b2evolution

Multilingual multiuser multiblog engine

b2evolution Technical Documentation (CVS HEAD) [ class tree: evocore ] [ index: evocore ] [ all elements ]

Source for file _genericcategorycache.class.php

Documentation is available at _genericcategorycache.class.php

  1. <?php
  2. /**
  3.  * This file implements the GenericCategoryCache class.
  4.  *
  5.  * This is the object handling genreric category lists.
  6.  *
  7.  * This file is part of the evoCore framework - {@link http://evocore.net/}
  8.  * See also {@link http://sourceforge.net/projects/evocms/}.
  9.  *
  10.  * @copyright (c)2003-2010 by Francois PLANQUE - {@link http://fplanque.net/}
  11.  *  Parts of this file are copyright (c)2005-2006 by PROGIDISTRI - {@link http://progidistri.com/}.
  12.  *
  13.  *  {@internal License choice
  14.  *  - If you have received this file as part of a package, please find the license.txt file in
  15.  *    the same folder or the closest folder above for complete license terms.
  16.  *  - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
  17.  *    then you must choose one of the following licenses before using the file:
  18.  *    - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
  19.  *    - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
  20.  *  }}}
  21.  *
  22.  *  {@internal Open Source relicensing agreement:
  23.  *  PROGIDISTRI S.A.S. grants Francois PLANQUE the right to license
  24.  *  PROGIDISTRI S.A.S.'s contributions to this file and the b2evolution project
  25.  *  under any OSI approved OSS license (http://www.opensource.org/licenses/).
  26.  *  }}}
  27.  *
  28.  * @package evocore
  29.  *
  30.  *  {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  31.  * @author fplanque: Francois PLANQUE.
  32.  * @author mbruneau: Marc BRUNEAU / PROGIDISTRI
  33.  *
  34.  * @version $Id: _genericcategorycache.class.php,v 1.10 2010/02/08 17:53:03 efy-yury Exp $
  35.  */
  36. if!defined('EVO_MAIN_INIT') ) die'Please, do not access this page directly.' );
  37.  
  38.  
  39. load_class'generic/model/_genericcache.class.php''GenericCache' );
  40.  
  41.  
  42. // DEBUG: (Turn switch on or off to log debug info for specified category)
  43. $GLOBALS['debug_CategoryCache'false;
  44.  
  45.  
  46. /**
  47.  * GenericCategoryCache class
  48.  *
  49.  *
  50.  * @package evocore
  51.  */
  52. {
  53.  
  54.     var $subset_cache = array();
  55.  
  56.     /**
  57.      * Which property of the objects defines the subset
  58.      */
  59.     var $subset_property;
  60.  
  61.     /**
  62.      * Which subsets have been loaded
  63.      */
  64.     var $loaded_subsets = array();
  65.  
  66.     /**
  67.      * These are the level 0 categories (which have no parent)
  68.      */
  69.     var $root_cats = array();
  70.  
  71.     /**
  72.      * These are the level 0 categories (which have no parent) for each subset
  73.      */
  74.     var $subset_root_cats = array();
  75.  
  76.     /**
  77.      * Have the children been revealed for all subsets yet?
  78.      */
  79.     var $revealed_all_children = false;
  80.     /**
  81.      * Have the children been revealed for all subsets yet?
  82.      */
  83.     var $revealed_subsets = array();
  84.  
  85.  
  86.     /**
  87.      * Constructor
  88.      */
  89.     function GenericCategoryCache$objtype$load_all$tablename$prefix ''$dbIDname 'ID'$name_field NULL$subset_property NULL$order_by '' )
  90.     {
  91.         parent::GenericCache$objtype$load_all$tablename$prefix$dbIDname$name_field$order_by );
  92.  
  93.         $this->subset_property = $subset_property;
  94.     }
  95.  
  96.  
  97.     /**
  98.      * Empty/reset the cache
  99.      */
  100.     function clear()
  101.     {
  102.          $this->subset_cache = array();
  103.          $this->loaded_subsets = array();
  104.         $this->root_cats = array();
  105.         $this->subset_root_cats = array();
  106.         $this->revealed_all_children = false;
  107.         $this->revealed_subsets = array();
  108.         parent::clear();
  109.      }
  110.  
  111.  
  112.     /**
  113.      * Add a dataobject to the cache
  114.      */
  115.     function add$Obj )
  116.     {
  117.         global $Debuglog;
  118.  
  119.         ifparent::add$Obj ) )
  120.         {    // Successfuly added
  121.  
  122.             if!empty($this->subset_property) )
  123.             {    // Also add to subset cache:
  124.                 $this->subset_cache[$Obj->{$this->subset_property}][$Obj->ID$Obj;
  125.             }
  126.             return true;
  127.         }
  128.  
  129.         return false;
  130.     }
  131.  
  132.  
  133.     /**
  134.      * Reveal children
  135.      *
  136.      * After this each Category will have an array pointing to its direct children
  137.      *
  138.      * @param integer|NULLNULL for all subsets
  139.      */
  140.     function reveal_children$subset_ID NULL )
  141.     {
  142.         global $Debuglog;
  143.         global $Timer;
  144.  
  145.         if$this->revealed_all_children )
  146.         {    // ALL Children have already been revealed: (can happen even if we require a subset *now*)
  147.             return;
  148.             /* RETURN */
  149.         }
  150.  
  151.         ifempty($this->subset_property) )
  152.         {    // We are not handling subsets
  153.  
  154.             echo 'Revealing all children -- this is not yet handling all edge cases that the subset version can handle';
  155.  
  156.             // Make sure everything has been loaded:
  157.         $this->load_all();
  158.  
  159.             // Reveal children:
  160.             if!empty$this->cache ) )
  161.             {    // There are loaded categories, so loop on all loaded categories to set their children list if it has:
  162.                 foreach$this->cache as $cat_ID => $GenericCategory )
  163.                 {
  164.                     // echo $GenericCategory->name;
  165.                     ifis_null$GenericCategory->parent_ID ) )
  166.                     {    // This category has a parent, so add it to its parent children list:
  167.                         $this->cache[$GenericCategory->parent_ID]->add_children$this->cache[$cat_ID);
  168.                     }
  169.                     else
  170.                     {    // This category has no parent, so add it to the parent categories list
  171.                         $this->root_cats[$this->cache[$cat_ID];
  172.                     }
  173.                 }
  174.             }
  175.  
  176.             $this->revealed_all_children = true;
  177.         }
  178.         else
  179.         {    // We are handling subsets
  180.  
  181.             ifis_null$subset_ID ) )
  182.             {    // No specific subset requested, we are going to reveal all subsets
  183.  
  184.                 // Make sure everything has been loaded:
  185.                 $this->load_all();
  186.  
  187.             echo 'REVEALING ALL SUBSETS in a row. Is this needed?';
  188.  
  189.                 foreach$this->subset_cache as $subset_ID => $dummy )
  190.                 {
  191.                     $this->reveal_children$subset_ID );
  192.                 }
  193.  
  194.                 $this->revealed_all_children = true;
  195.             }
  196.             else
  197.             {    // We're interested in a specific subset
  198.                 if!empty$this->revealed_subsets[$subset_ID) )
  199.                 {    // Children have already been revealed:
  200.                     return;
  201.                     /* RETURN */
  202.                 }
  203.  
  204.                 $Timer->resume('reveal_children'false );
  205.  
  206.                 $Debuglog->add'Revealing subset of children''CategoryCache' );
  207.  
  208.                 // Make sure the requested subset has been loaded:
  209.             $this->load_subset($subset_ID);
  210.  
  211.                 // Reveal children:
  212.                 if!empty$this->subset_cache[$subset_ID) )
  213.                 {    // There are loaded categories
  214.  
  215.                     // Now check that each category has a path to the root:
  216.                     foreach$this->subset_cache[$subset_IDas $cat_ID => $dummy )    // "as" would give a freakin copy of the object :(((
  217.                     {
  218.                         $this->check_path_to_root$subset_ID$cat_ID );
  219.                     }
  220.  
  221.                     // loop on all loaded categories to set their children list if it has some:
  222.                     foreach$this->subset_cache[$subset_IDas $cat_ID => $dummy )    // "as" would give a freakin copy of the object :(((
  223.                     {
  224.                         $GenericCategory $this->subset_cache[$subset_ID][$cat_ID];
  225.                         // echo '<br>'.$cat_ID;
  226.                         // echo $GenericCategory->name;
  227.                         ifis_null$GenericCategory->parent_ID ) )
  228.                         {    // This category has a parent, so add it to its parent children list:
  229.                             $Debuglog->add'adding child with ID='.$cat_ID.' to parent ID='.$GenericCategory->parent_ID'CategoryCache' );
  230.                             $this->cache[$GenericCategory->parent_ID]->add_children$this->cache[$cat_ID);
  231.                         }
  232.                         else
  233.                         {    // This category has no parent, so add it to the parent categories list
  234.                             $Debuglog->add'adding parent with ID='.$cat_ID'CategoryCache' );
  235.                             $this->root_cats[$GenericCategory// $this->cache[$cat_ID];
  236.                             $this->subset_root_cats[$this->cache[$cat_ID]->{$this->subset_property}][$GenericCategory// $this->cache[$cat_ID];
  237.                         }
  238.                     }
  239.  
  240.                     $Timer->pause('reveal_children'false );
  241.  
  242.                 }
  243.  
  244.                 // Children have been revealed.
  245.                 $this->revealed_subsets[$subset_IDtrue;
  246.             }
  247.         }
  248.  
  249.     }
  250.  
  251.  
  252.     /**
  253.      * Support function for reveal_children()
  254.      *
  255.      * @param integer 
  256.      * @param integer 
  257.      * @return true if root parent
  258.      */
  259.     function check_path_to_root$subset_ID$cat_ID$path_array array() )
  260.     {
  261.         global $Debuglog;
  262.         $padding str_pad('',count($path_array),'*');
  263.         $Debuglog->add$padding.'Checking path to root for cat ID='.$cat_ID.' with path:'.implode(',',$path_array)'CategoryCache' );
  264.         $GenericCategory $this->subset_cache[$subset_ID][$cat_ID];
  265.         ifis_null$GenericCategory->parent_ID ) )
  266.         {    // Found root parent
  267.             $Debuglog->add$padding.'*OK''CategoryCache' );
  268.             return true;
  269.         }
  270.         // This is not the last parent...
  271.         // Record path...
  272.         $path_array[$GenericCategory->ID;
  273.  
  274.         ifin_array$GenericCategory->parent_ID$path_array ) )
  275.         {    // We are about to enter an infinite loop
  276.             $Debuglog->add$padding.'*LOOP! -> assign to root''CategoryCache' );
  277.             $GenericCategory->parent_ID NULL;
  278.             return false;
  279.         }
  280.         elseifisset($this->cache[$GenericCategory->parent_ID) )
  281.         {
  282.             $Debuglog->add$padding.'*Missing parent ID('.$GenericCategory->parent_ID.')! -> assign to root''CategoryCache' );
  283.             $GenericCategory->parent_ID NULL;
  284.             return false;
  285.         }
  286.  
  287.         // Recurse!
  288.         return $this->check_path_to_root$subset_ID$GenericCategory->parent_ID$path_array );
  289.     }
  290.  
  291.     /**
  292.      * Return recursive display of loaded categories
  293.      *
  294.      * @param array callback funtions (to format the display)
  295.      * @param integer|NULLNULL for all subsets
  296.      * @param array categories list to display
  297.      * @param int depth of  categories list
  298.      *
  299.      * @return string recursive list of all loaded categories
  300.      */
  301.     function recurse$callbacks$subset_ID NULL$cat_array NULL$level )
  302.     {
  303.         // Make sure children have been revealed for specific subset:
  304.         $this->reveal_children$subset_ID );
  305.  
  306.         ifis_null$cat_array ) )
  307.         {    // Get all parent categories:
  308.             ifis_null$subset_ID ) )
  309.             {
  310.                 $cat_array $this->root_cats;
  311.             }
  312.             elseifisset$this->subset_root_cats[$subset_ID) )
  313.             {    // We have root cats for the requested subset:
  314.                 $cat_array $this->subset_root_cats[$subset_ID];
  315.             }
  316.             else
  317.             {
  318.                 $cat_array array();
  319.             }
  320.         }
  321.  
  322.         $r '';
  323.  
  324.         ifis_array$callbacks['before_level') )
  325.         // object callback:
  326.             $r .= $callbacks['before_level'][0]->{$callbacks['before_level'][1]}$level )// <ul>
  327.         }
  328.         else
  329.         {
  330.             $r .= $callbacks['before_level']$level )// <ul>
  331.         }
  332.  
  333.         foreach$cat_array as $cat )
  334.         {
  335.             ifis_array$callbacks['line') )
  336.             // object callback:
  337.                 $r .= $callbacks['line'][0]->{$callbacks['line'][1]}$cat$level )// <li> Category  - or - <tr><td>Category</td></tr> ...
  338.             }
  339.             else
  340.             {
  341.                 $r .= $callbacks['line']$cat$level )// <li> Category  - or - <tr><td>Category</td></tr> ...
  342.             }
  343.  
  344.             if!empty$cat->children ) )
  345.             {    // Add children categories:
  346.                 $r .= $this->recurse$callbacks$subset_ID$cat->children$level+);
  347.             }
  348.             elseifis_array$callbacks['no_children') )
  349.             // object callback:
  350.                 $r .= $callbacks['no_children'][0]->{$callbacks['no_children'][1]}$cat$level )// </li>
  351.             }
  352.             else
  353.             {
  354.                 $r .= $callbacks['no_children']$cat$level )// </li>
  355.             }
  356.  
  357.         }
  358.  
  359.         ifis_array$callbacks['after_level') )
  360.         // object callback:
  361.             $r .= $callbacks['after_level'][0]->{$callbacks['after_level'][1]}$level )// </ul>
  362.         }
  363.         else
  364.         {
  365.             $r .= $callbacks['after_level']$level )// </ul>
  366.         }
  367.  
  368.         return $r;
  369.     }
  370.  
  371.  
  372.     /**
  373.      * Return recursive select options list of all loaded categories
  374.      *
  375.      * @param integer selected category in the select input
  376.      * @param integer NULL for all subsets
  377.      * @param boolean Include the root element?
  378.      * @param array GenercCategory objects to display (will recurse from those starting points)
  379.      * @param integer depth of categories list
  380.      * @param array IDs of categories to exclude (their children will be ignored to)
  381.      *
  382.      * @return string select options list of all loaded categories
  383.      */
  384.     function recurse_select$selected NULL$subset_ID NULL$include_root false$Cat_array NULL,
  385.                             $level 0$exclude_array array() )
  386.     {
  387.         // pre_dump( $exclude_array );
  388.  
  389.         // Make sure children have been revealed for specific subset:
  390.         $this->reveal_children$subset_ID );
  391.  
  392.         ifis_null$Cat_array ) )
  393.         {    // Get all parent categorie:
  394.             $Cat_array $this->root_cats;
  395.         }
  396.  
  397.         $r '';
  398.  
  399.         if$include_root )
  400.         {
  401.             $r .= '<option value="">'.T_('Root').'</option>';
  402.             $level++;
  403.         }
  404.  
  405.         foreach$Cat_array as $GenericCategory )
  406.         {
  407.             ifin_array$GenericCategory->ID$exclude_array ) )
  408.             {    // We want to exclude that cat.
  409.                 continue;
  410.             }
  411.  
  412.             // Set category indentation in the select:
  413.             $indent '';
  414.             for($i 0$i $level$i++)
  415.             {
  416.                 $indent .='&nbsp;&nbsp;';
  417.             }
  418.             // Set category option:
  419.             $r .= '<option value="'.$GenericCategory->ID.'" ';
  420.             if$GenericCategory->ID == $selected $r .= ' selected="selected"';
  421.             $r .= ' >'.$indent.$GenericCategory->name.'</option>';
  422.  
  423.             if!empty$GenericCategory->children ) )
  424.             {    // Add children categories:
  425.                 $r .= $this->recurse_select$selected$subset_IDfalse$GenericCategory->children$level+1$exclude_array );
  426.             }
  427.         }
  428.  
  429.         return $r;
  430.     }
  431.  
  432. }
  433.  
  434. /*
  435.  * $Log: _genericcategorycache.class.php,v $
  436.  * Revision 1.10  2010/02/08 17:53:03  efy-yury
  437.  * copyright 2009 -> 2010
  438.  *
  439.  * Revision 1.9  2009/11/30 00:22:05  fplanque
  440.  * clean up debug info
  441.  * show more timers in view of block caching
  442.  *
  443.  * Revision 1.8  2009/09/14 13:11:37  efy-arrin
  444.  * Included the ClassName in load_class() call with proper UpperCase
  445.  *
  446.  * Revision 1.7  2009/03/08 23:57:43  fplanque
  447.  * 2009
  448.  *
  449.  * Revision 1.6  2009/01/28 21:23:23  fplanque
  450.  * Manual ordering of categories
  451.  *
  452.  * Revision 1.5  2008/12/28 19:00:14  fplanque
  453.  * Fixed multiple category parent/child recursion issues. It should no longer be possible to "lose" categories by creating loops.
  454.  *
  455.  * Revision 1.4  2008/01/21 09:35:30  fplanque
  456.  * (c) 2008
  457.  *
  458.  * Revision 1.3  2007/10/08 08:33:15  fplanque
  459.  * rollback until needed
  460.  *
  461.  * Revision 1.1  2007/06/25 11:00:16  fplanque
  462.  * MODULES (refactored MVC)
  463.  *
  464.  * Revision 1.15  2007/04/26 00:11:11  fplanque
  465.  * (c) 2007
  466.  *
  467.  * Revision 1.14  2006/12/10 02:01:11  fplanque
  468.  * doc
  469.  *
  470.  * Revision 1.13  2006/12/10 01:52:27  fplanque
  471.  * old cats are now officially dead :>
  472.  *
  473.  * Revision 1.12  2006/12/09 02:37:44  fplanque
  474.  * Prevent user from creating loops in the chapter tree
  475.  * (still needs a check before writing to DB though)
  476.  *
  477.  * Revision 1.11  2006/11/26 01:42:09  fplanque
  478.  * doc
  479.  */
  480. ?>

Documentation generated on Sat, 06 Mar 2010 04:11:42 +0100 by phpDocumentor 1.4.2. This site is hosted and maintained by Daniel HAHLER (Contact).