b2evolution PHP Cross Reference Blogging Systems

Source: /inc/generic/model/_genericcategorycache.class.php - 447 lines - 13071 bytes - Summary - Text - Print

Description: This file implements the GenericCategoryCache class. This is the object handling genreric category lists.

   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-2014 by Francois Planque - {@link http://fplanque.com/}
  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 6136 2014-03-08 07:59:48Z manuel $
  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  class GenericCategoryCache extends GenericCache
  53  {
  54  
  55      var $subset_cache = array();
  56  
  57      /**
  58       * Which property of the objects defines the subset
  59       */
  60      var $subset_property;
  61  
  62      /**
  63       * Which subsets have been loaded
  64       */
  65      var $loaded_subsets = array();
  66  
  67      /**
  68       * These are the level 0 categories (which have no parent)
  69       */
  70      var $root_cats = array();
  71  
  72      /**
  73       * These are the level 0 categories (which have no parent) for each subset
  74       */
  75      var $subset_root_cats = array();
  76  
  77      /**
  78       * Have the children been revealed for all subsets yet?
  79       */
  80      var $revealed_all_children = false;
  81      /**
  82       * Have the children been revealed for all subsets yet?
  83       */
  84      var $revealed_subsets = array();
  85  
  86  
  87      /**
  88       * Constructor
  89       */
  90  	function GenericCategoryCache( $objtype, $load_all, $tablename, $prefix = '', $dbIDname = 'ID', $name_field = NULL, $subset_property = NULL, $order_by = '', $allow_none_text = NULL, $allow_none_value = '', $select = '' )
  91      {
  92          parent::GenericCache( $objtype, $load_all, $tablename, $prefix, $dbIDname, $name_field, $order_by, $allow_none_text, $allow_none_value, $select );
  93  
  94          $this->subset_property = $subset_property;
  95      }
  96  
  97  
  98      /**
  99       * Empty/reset the cache
 100       */
 101  	function clear()
 102      {
 103          $this->subset_cache = array();
 104          $this->loaded_subsets = array();
 105          $this->root_cats = array();
 106          $this->subset_root_cats = array();
 107          $this->revealed_all_children = false;
 108          $this->revealed_subsets = array();
 109          parent::clear();
 110       }
 111  
 112  
 113      /**
 114       * Add a dataobject to the cache
 115       */
 116  	function add( & $Obj )
 117      {
 118          global $Debuglog;
 119  
 120          if( parent::add( $Obj ) )
 121          {    // Successfully added
 122  
 123              if( !empty($this->subset_property) )
 124              {    // Also add to subset cache:
 125                  $this->subset_cache[$Obj->{$this->subset_property}][$Obj->ID] = & $Obj;
 126              }
 127              return true;
 128          }
 129  
 130          return false;
 131      }
 132  
 133  
 134      /**
 135       * Reveal children
 136       *
 137       * After this each Category will have an array pointing to its direct children
 138       *
 139       * @param integer|NULL NULL for all subsets
 140       */
 141  	function reveal_children( $subset_ID = NULL )
 142      {
 143          global $Debuglog;
 144          global $Timer;
 145  
 146          if( $this->revealed_all_children )
 147          {    // ALL Children have already been revealed: (can happen even if we require a subset *now*)
 148              return;
 149              /* RETURN */
 150          }
 151  
 152          if( empty($this->subset_property) )
 153          {    // We are not handling subsets
 154  
 155              echo 'Revealing all children -- this is not yet handling all edge cases that the subset version can handle';
 156  
 157              // Make sure everything has been loaded:
 158              $this->load_all();
 159  
 160              // Reveal children:
 161              if( !empty( $this->cache ) )
 162              {    // There are loaded categories, so loop on all loaded categories to set their children list if it has:
 163                  foreach( $this->cache as $cat_ID => $GenericCategory )
 164                  {
 165                      // echo $GenericCategory->name;
 166                      if( ! is_null( $GenericCategory->parent_ID ) )
 167                      {    // This category has a parent, so add it to its parent children list:
 168                          $this->cache[$GenericCategory->parent_ID]->add_child_category( $this->cache[$cat_ID] );
 169                      }
 170                      else
 171                      {    // This category has no parent, so add it to the parent categories list
 172                          $this->root_cats[] = & $this->cache[$cat_ID];
 173                      }
 174                  }
 175              }
 176  
 177              $this->revealed_all_children = true;
 178          }
 179          else
 180          {    // We are handling subsets
 181  
 182              if( is_null( $subset_ID ) )
 183              {    // No specific subset requested, we are going to reveal all subsets
 184  
 185                  // Make sure everything has been loaded:
 186                  $this->load_all();
 187  
 188                  echo 'REVEALING ALL SUBSETS in a row. Is this needed?';
 189  
 190                  foreach( $this->subset_cache as $subset_ID => $dummy )
 191                  {
 192                      $this->reveal_children( $subset_ID );
 193                  }
 194  
 195                  $this->revealed_all_children = true;
 196              }
 197              else
 198              {    // We're interested in a specific subset
 199                  if( !empty( $this->revealed_subsets[$subset_ID] ) )
 200                  {    // Children have already been revealed:
 201                      return;
 202                      /* RETURN */
 203                  }
 204  
 205                  $Timer->resume('reveal_children', false );
 206  
 207                  $Debuglog->add( 'Revealing subset of children', 'CategoryCache' );
 208  
 209                  // Make sure the requested subset has been loaded:
 210                  $this->load_subset($subset_ID);
 211  
 212                  // Reveal children:
 213                  if( !empty( $this->subset_cache[$subset_ID] ) )
 214                  {    // There are loaded categories
 215  
 216                      // Now check that each category has a path to the root:
 217                      foreach( $this->subset_cache[$subset_ID] as $cat_ID => $dummy )    // "as" would give a freakin copy of the object :(((
 218                      {
 219                          $this->check_path_to_root( $subset_ID, $cat_ID );
 220                      }
 221  
 222                      // loop on all loaded categories to set their children list if it has some:
 223                      foreach( $this->subset_cache[$subset_ID] as $cat_ID => $dummy )    // "as" would give a freakin copy of the object :(((
 224                      {
 225                          $GenericCategory = & $this->subset_cache[$subset_ID][$cat_ID];
 226                          // echo '<br>'.$cat_ID;
 227                          // echo $GenericCategory->name;
 228                          if( ! is_null( $GenericCategory->parent_ID ) )
 229                          {    // This category has a parent, so add it to its parent children list:
 230                              $Debuglog->add( 'adding child with ID='.$cat_ID.' to parent ID='.$GenericCategory->parent_ID, 'CategoryCache' );
 231                              $this->cache[$GenericCategory->parent_ID]->add_child_category( $this->cache[$cat_ID] );
 232                          }
 233                          else
 234                          {    // This category has no parent, so add it to the parent categories list
 235                              $Debuglog->add( 'adding parent with ID='.$cat_ID, 'CategoryCache' );
 236                              $this->root_cats[] = & $GenericCategory; // $this->cache[$cat_ID];
 237                              $this->subset_root_cats[$this->cache[$cat_ID]->{$this->subset_property}][] = & $GenericCategory; // $this->cache[$cat_ID];
 238                          }
 239                      }
 240  
 241                      $Timer->pause('reveal_children', false );
 242  
 243                  }
 244  
 245                  // Children have been revealed.
 246                  $this->revealed_subsets[$subset_ID] = true;
 247              }
 248          }
 249  
 250      }
 251  
 252  
 253      /**
 254       * Support function for reveal_children()
 255       *
 256       * @param integer
 257       * @param integer
 258       * @return true if root parent
 259       */
 260  	function check_path_to_root( $subset_ID, $cat_ID, $path_array = array() )
 261      {
 262          global $Debuglog;
 263          $padding = str_pad('',count($path_array),'*');
 264          $Debuglog->add( $padding.'Checking path to root for cat ID='.$cat_ID.' with path:'.implode(',',$path_array), 'CategoryCache' );
 265          $GenericCategory = & $this->subset_cache[$subset_ID][$cat_ID];
 266          if( is_null( $GenericCategory->parent_ID ) )
 267          {    // Found root parent
 268              $Debuglog->add( $padding.'*OK', 'CategoryCache' );
 269              return true;
 270          }
 271          // This is not the last parent...
 272          // Record path...
 273          $path_array[] = $GenericCategory->ID;
 274  
 275          if( in_array( $GenericCategory->parent_ID, $path_array ) )
 276          {    // We are about to enter an infinite loop
 277              $Debuglog->add( $padding.'*LOOP! -> assign to root', 'CategoryCache' );
 278              $GenericCategory->parent_ID = NULL;
 279              return false;
 280          }
 281          elseif( ! isset($this->cache[$GenericCategory->parent_ID] ) )
 282          {
 283              $Debuglog->add( $padding.'*Missing parent ID('.$GenericCategory->parent_ID.')! -> assign to root', 'CategoryCache' );
 284              $GenericCategory->parent_ID = NULL;
 285              return false;
 286          }
 287  
 288          // Recurse!
 289          return $this->check_path_to_root( $subset_ID, $GenericCategory->parent_ID, $path_array );
 290      }
 291  
 292      /**
 293       * Return recursive display of loaded categories
 294       *
 295       * @param array callback funtions (to format the display)
 296       * @param integer|NULL NULL for all subsets
 297       * @param array categories list to display
 298       * @param int depth of  categories list
 299       *
 300       * @return string recursive list of all loaded categories
 301       */
 302  	function recurse( $callbacks, $subset_ID = NULL, $cat_array = NULL, $level = 0 )
 303      {
 304          // Make sure children have been revealed for specific subset:
 305          $this->reveal_children( $subset_ID );
 306  
 307          if( is_null( $cat_array ) )
 308          {    // Get all parent categories:
 309              if( is_null( $subset_ID ) )
 310              {
 311                  $cat_array = $this->root_cats;
 312              }
 313              elseif( isset( $this->subset_root_cats[$subset_ID] ) )
 314              {    // We have root cats for the requested subset:
 315                  $cat_array = $this->subset_root_cats[$subset_ID];
 316              }
 317              else
 318              {
 319                  $cat_array = array();
 320              }
 321          }
 322  
 323          $r = '';
 324  
 325          if( is_array( $callbacks['before_level'] ) )
 326          { // object callback:
 327              $r .= $callbacks['before_level'][0]->{$callbacks['before_level'][1]}( $level ); // <ul>
 328          }
 329          else
 330          {
 331              $r .= $callbacks['before_level']( $level ); // <ul>
 332          }
 333  
 334          foreach( $cat_array as $cat )
 335          {
 336              if( is_array( $callbacks['line'] ) )
 337              { // object callback:
 338                  $r .= $callbacks['line'][0]->{$callbacks['line'][1]}( $cat, $level ); // <li> Category  - or - <tr><td>Category</td></tr> ...
 339              }
 340              else
 341              {
 342                  $r .= $callbacks['line']( $cat, $level ); // <li> Category  - or - <tr><td>Category</td></tr> ...
 343              }
 344  
 345              if( !empty( $cat->children ) )
 346              {    // Add children categories:
 347                  $r .= $this->recurse( $callbacks, $subset_ID, $cat->children, $level+1 );
 348              }
 349              elseif( is_array( $callbacks['no_children'] ) )
 350              { // object callback:
 351                  $r .= $callbacks['no_children'][0]->{$callbacks['no_children'][1]}( $cat, $level ); // </li>
 352              }
 353              else
 354              {
 355                  $r .= $callbacks['no_children']( $cat, $level ); // </li>
 356              }
 357  
 358          }
 359  
 360          if( !empty( $cat->parent_ID ) && !empty( $callbacks['posts'] ) )
 361          {    // Callback to display the posts under subchapters
 362              if( is_array( $callbacks['posts'] ) )
 363              {    // object callback:
 364                  $r .= $callbacks['posts'][0]->{$callbacks['posts'][1]}( $cat->parent_ID );
 365              }
 366              else
 367              {
 368                  $r .= $callbacks['posts']( $cat->parent_ID );
 369              }
 370          }
 371  
 372          if( is_array( $callbacks['after_level'] ) )
 373          { // object callback:
 374              $r .= $callbacks['after_level'][0]->{$callbacks['after_level'][1]}( $level ); // </ul>
 375          }
 376          else
 377          {
 378              $r .= $callbacks['after_level']( $level ); // </ul>
 379          }
 380  
 381          return $r;
 382      }
 383  
 384  
 385      /**
 386       * Return recursive select options list of all loaded categories
 387       *
 388       * @param integer selected category in the select input
 389       * @param integer NULL for all subsets
 390       * @param boolean Include the root element?
 391       * @param array GenercCategory objects to display (will recurse from those starting points)
 392       * @param integer depth of categories list
 393       * @param array IDs of categories to exclude (their children will be ignored to)
 394       *
 395       * @return string select options list of all loaded categories
 396       */
 397  	function recurse_select( $selected = NULL, $subset_ID = NULL, $include_root = false, $Cat_array = NULL,
 398                              $level = 0, $exclude_array = array() )
 399      {
 400          // pre_dump( $exclude_array );
 401  
 402          // Make sure children have been revealed for specific subset:
 403          $this->reveal_children( $subset_ID );
 404  
 405          if( is_null( $Cat_array ) )
 406          {    // Get all parent categorie:
 407              $Cat_array = $this->root_cats;
 408          }
 409  
 410          $r = '';
 411  
 412          if( $include_root )
 413          {
 414              $r .= '<option value="">'.T_('Root').'</option>';
 415              $level++;
 416          }
 417  
 418          foreach( $Cat_array as $GenericCategory )
 419          {
 420              if( in_array( $GenericCategory->ID, $exclude_array ) )
 421              {    // We want to exclude that cat.
 422                  continue;
 423              }
 424  
 425              // Set category indentation in the select:
 426              $indent = '';
 427              for($i = 0; $i < $level; $i++)
 428              {
 429                  $indent .='&nbsp;&nbsp;';
 430              }
 431              // Set category option:
 432              $r .= '<option value="'.$GenericCategory->ID.'" ';
 433              if( $GenericCategory->ID == $selected ) $r .= ' selected="selected"';
 434              $r .= ' >'.$indent.$GenericCategory->name.'</option>';
 435  
 436              if( !empty( $GenericCategory->children ) )
 437              {    // Add children categories:
 438                  $r .= $this->recurse_select( $selected, $subset_ID, false, $GenericCategory->children, $level+1, $exclude_array );
 439              }
 440          }
 441  
 442          return $r;
 443      }
 444  
 445  }
 446  
 447  ?>

title

Description

title

Description

title

Description

title

title

Body