b2evolution PHP Cross Reference Blogging Systems

Source: /inc/collections/model/_category.funcs.php - 559 lines - 16159 bytes - Summary - Text - Print

Description: This file implements Category handling functions. This file is part of the evoCore framework - {@link http://evocore.net/} See also {@link http://sourceforge.net/projects/evocms/}.

   1  <?php
   2  /**
   3   * This file implements Category handling functions.
   4   *
   5   * This file is part of the evoCore framework - {@link http://evocore.net/}
   6   * See also {@link http://sourceforge.net/projects/evocms/}.
   7   *
   8   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}
   9   * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
  10   * Parts of this file are copyright (c)2004 by The University of North Carolina at Charlotte as
  11   * contributed by Jason Edgecombe {@link http://tst.uncc.edu/team/members/jason_bio.php}.
  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   * Daniel HAHLER grants Francois PLANQUE the right to license
  24   * Daniel HAHLER's contributions to this file and the b2evolution project
  25   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  26   *
  27   * The University of North Carolina at Charlotte grants Francois PLANQUE the right to license
  28   * Jason EDGECOMBE's contributions to this file and the b2evolution project
  29   * under the GNU General Public License (http://www.opensource.org/licenses/gpl-license.php)
  30   * and the Mozilla Public License (http://www.opensource.org/licenses/mozilla1.1.php).
  31   * }}
  32   *
  33   * @package evocore
  34   *
  35   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  36   * @author blueyed: Daniel HAHLER.
  37   * @author fplanque: Francois PLANQUE.
  38   * @author jwedgeco: Jason EDGECOMBE (for hire by UNC-Charlotte)
  39   * @author edgester: Jason EDGECOMBE (personal contributions, not for hire)
  40   *
  41   * @todo implement CategoryCache based on LinkCache
  42   *
  43   * @version $Id: _category.funcs.php 6136 2014-03-08 07:59:48Z manuel $
  44   */
  45  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  46  
  47  
  48  /**
  49   * Create a new category
  50   *
  51   * This funtion has to handle all needed DB dependencies!
  52   *
  53   * @param string Category name
  54   * @param string Category ID ('NULL' as string(!) for root)
  55   * @param integer|NULL Blog ID (will be taken from parent cat, if empty)
  56   * @param string Category description
  57   * @param boolean Set to true if the new object needs to be added into the ChapterCache after it was created
  58   * @param integer Category order
  59   */
  60  function cat_create( $cat_name, $cat_parent_ID, $cat_blog_ID = NULL, $cat_description = NULL, $add_to_cache = false, $cat_order = NULL )
  61  {
  62      global $DB;
  63  
  64      load_class('chapters/model/_chapter.class.php', 'Chapter');
  65  
  66      if( ! $cat_blog_ID )
  67      {
  68          if( empty($cat_parent_ID) ) debug_die ( 'cat_create(-) missing parameters (cat_parent_ID)!' );
  69  
  70          $ChapterCache = & get_ChapterCache();
  71          $Chapter = $ChapterCache->get_by_ID($cat_parent_ID);
  72          $cat_blog_ID = $Chapter->blog_ID;
  73      }
  74  
  75      if( $cat_parent_ID === 'NULL' )
  76          // fix old use case
  77          $cat_parent_ID = NULL;
  78  
  79      $new_Chapter = new Chapter(NULL, $cat_blog_ID);
  80      $new_Chapter->set('name', $cat_name);
  81      $new_Chapter->set('parent_ID', $cat_parent_ID);
  82      if( !empty( $cat_description ) )
  83      {    // Set decription
  84          $new_Chapter->set('description', $cat_description);
  85      }
  86      $new_Chapter->set('order', $cat_order);
  87  
  88  
  89      if( ! $new_Chapter->dbinsert() )
  90          return 0;
  91  
  92      if( $add_to_cache )
  93      { // add new Category into the Cache
  94          $ChapterCache = & get_ChapterCache();
  95          $ChapterCache->add( $new_Chapter );
  96      }
  97  
  98      return $new_Chapter->ID;
  99  }
 100  
 101  
 102  /**
 103   * Get category name+blog_id for specified cat ID
 104   *
 105   * fplanque: reused "R. U. Serious" optimization here
 106   * fplanque: added blog ID stuff
 107   *
 108   * @deprecated since 3.1.0-alpha. Use ChapterCache instead.
 109   * @param integer category ID
 110   * @param boolean die() if category does not exist? (default: true)
 111   *
 112   */
 113  function get_the_category_by_ID( $cat_ID, $die = true )
 114  {
 115      global $cache_categories;
 116      if( empty($cache_categories[$cat_ID]) )
 117      {
 118          cat_load_cache( 'none' );
 119      }
 120      if( !isset( $cache_categories[$cat_ID] ) )
 121      {
 122          if( $die )
 123          {
 124              debug_die( sprintf( T_('Requested category %s does not exist!'),  $cat_ID ) );
 125          }
 126          else return false;
 127      }
 128      return $cache_categories[$cat_ID];
 129  }
 130  
 131  
 132  /**
 133   * Get blog ID for a given cat.
 134   * This halts on error.
 135   * @return integer
 136   */
 137  function get_catblog( $cat_ID )
 138  {
 139      $ChapterCache = & get_ChapterCache();
 140      $Chapter = $ChapterCache->get_by_ID($cat_ID);
 141  
 142      return $Chapter->blog_ID;
 143  }
 144  
 145  
 146  /**
 147   * Get category permanent url by category ID
 148   *
 149   * @param integer category ID
 150   */
 151  function get_caturl( $cat_ID )
 152  {
 153      $ChapterCache = & get_ChapterCache();
 154      $Chapter = $ChapterCache->get_by_ID($cat_ID);
 155  
 156      return $Chapter->get_permanent_url();
 157  }
 158  
 159  
 160  /**
 161   * Load cache for category definitions.
 162   *
 163   * Warning: this loads all categories for ALL blogs
 164   */
 165  function cat_load_cache()
 166  {
 167      global $DB, $cache_categories;
 168      global $Settings;
 169      global $Timer;
 170  
 171      if( isset($cache_categories))
 172      {
 173          return;
 174      }
 175  
 176      $Timer->resume( 'cat_load_cache' );
 177  
 178      // echo "loading CAT cache";
 179      if( $Settings->get('chapter_ordering') == 'manual' )
 180      {    // Manual order
 181          $select_temp_order = ', IF( cat_order IS NULL, 999999999, cat_order ) AS temp_order';
 182          $sql_order = ' ORDER BY temp_order';
 183      }
 184      else
 185      {    // Alphabetic order
 186          $select_temp_order = '';
 187          $sql_order = ' ORDER BY cat_name';
 188      }
 189      $sql = 'SELECT cat_ID, cat_parent_ID, cat_name, cat_blog_ID'.$select_temp_order.'
 190                      FROM T_categories'
 191                      .$sql_order;
 192  
 193  
 194      foreach( $DB->get_results( $sql, ARRAY_A, 'loading CAT cache' ) as $myrow )
 195      {
 196          $this_cat['cat_name'] = $myrow['cat_name'];
 197          $this_cat['cat_blog_ID'] = $myrow['cat_blog_ID'];
 198          $this_cat['cat_parent_ID'] = $myrow['cat_parent_ID'];
 199          $this_cat['cat_postcount'] = 0;                    // Will be increased later
 200          $this_cat['cat_children'] = array();
 201          $cache_categories[$myrow['cat_ID']] = $this_cat;
 202          // echo 'just cached:',$myrow['cat_ID'],':',$cache_categories[$myrow['cat_ID']]['cat_name'], ' parent:',$cache_categories[$myrow['cat_ID']]['cat_parent_ID'],'<br />';
 203      }
 204  
 205      // echo 'Number of cats=', count($cache_categories);
 206  
 207      // Reveal children:
 208      if( ! empty( $cache_categories ) )
 209      {
 210          foreach( $cache_categories as $icat_ID => $i_cat )
 211          {
 212              // echo '<br>handling cat ', $icat_ID, ' ', $i_cat['cat_name'];
 213              $cat_parent_ID = $i_cat['cat_parent_ID'];
 214              if( $cat_parent_ID )
 215              {
 216                  if( isset( $cache_categories[$cat_parent_ID] ) )
 217                  { // If the parent exists!
 218                      $cache_categories[$cat_parent_ID]['cat_children'][] = $icat_ID;
 219                  }
 220                  else
 221                  {
 222                      echo( "Category #$icat_ID is orphan of non existant parent #$cat_parent_ID!<br />" );
 223                  }
 224              }
 225          }
 226      }
 227  
 228      // echo 'Number of cats=', count($cache_categories);
 229  
 230      $Timer->pause( 'cat_load_cache' );
 231  }
 232  
 233  
 234  /**
 235   * Get # of posts for each category in a blog
 236   *
 237   * @param integer Category ID
 238   * @param integer Blog ID
 239   */
 240  function get_postcount_in_category( $cat_ID, $blog_ID = NULL )
 241  {
 242      if( is_null( $blog_ID ) )
 243      {
 244          global $blog;
 245          $blog_ID = $blog;
 246      }
 247  
 248      global $DB, $number_of_posts_in_cat;
 249  
 250      if( !isset( $number_of_posts_in_cat[ (string) $blog_ID ] ) )
 251      {
 252          $SQL = new SQL( 'Get # of posts for each category in a blog' );
 253          $SQL->SELECT( 'cat_ID, count( postcat_post_ID ) c' );
 254          $SQL->FROM( 'T_categories' );
 255          $SQL->FROM_add( 'INNER JOIN T_postcats ON postcat_cat_ID = cat_id' );
 256          $SQL->FROM_add( 'INNER JOIN T_items__item ON postcat_post_ID = post_id' );
 257          $SQL->WHERE( 'cat_blog_ID = '.$DB->quote( $blog_ID ) );
 258          // fp> TODO: the following probably needs to be ALL except $posttypes_specialtypes
 259          $SQL->WHERE_and( 'post_ptyp_ID IN ( '.$DB->quote( array( 1, 2000 ) ).' )' );
 260          $SQL->WHERE_and( statuses_where_clause( get_inskin_statuses(), 'post_', $blog_ID, 'blog_post!', true ) );
 261          $SQL->GROUP_BY( 'cat_ID' );
 262          $number_of_posts_in_cat[ (string) $blog_ID ] = $DB->get_assoc( $SQL->get() );
 263      }
 264  
 265      return isset( $number_of_posts_in_cat[(string) $blog_ID][$cat_ID] ) ? (int) $number_of_posts_in_cat[(string) $blog_ID][$cat_ID] : 0;
 266  }
 267  
 268  
 269  /**
 270   * Get # of comments for each category in a blog
 271   *
 272   * @param integer Category ID
 273   * @param integer Blog ID
 274   */
 275  function get_commentcount_in_category( $cat_ID, $blog_ID = NULL )
 276  {
 277      if( is_null( $blog_ID ) )
 278      {
 279          global $blog;
 280          $blog_ID = $blog;
 281      }
 282  
 283      global $DB, $number_of_comments_in_cat;
 284  
 285      if( !isset( $number_of_comments_in_cat[(string) $blog_ID] ) )
 286      {
 287          $SQL = new SQL();
 288          $SQL->SELECT( 'cat_ID, COUNT( comment_ID ) c' );
 289          $SQL->FROM( 'T_comments' );
 290          $SQL->FROM_add( 'LEFT JOIN T_postcats ON comment_post_ID = postcat_post_ID' );
 291          $SQL->FROM_add( 'LEFT JOIN T_categories ON postcat_cat_ID = cat_id' );
 292          $SQL->FROM_add( 'LEFT JOIN T_items__item ON comment_post_ID = post_id' );
 293          $SQL->WHERE( 'cat_blog_ID = '.$DB->quote( $blog_ID ) );
 294          $SQL->WHERE_and( statuses_where_clause( get_inskin_statuses(), 'comment_', $blog_ID, 'blog_comment!', true ) );
 295          // add where condition to show only those posts commetns which are visible for the current User
 296          $SQL->WHERE_and( statuses_where_clause( get_inskin_statuses(), 'post_', $blog_ID, 'blog_post!', true ) );
 297          $SQL->GROUP_BY( 'cat_ID' );
 298  
 299          $number_of_comments_in_cat[(string) $blog_ID] = $DB->get_assoc( $SQL->get() );
 300      }
 301  
 302      return isset( $number_of_comments_in_cat[(string) $blog_ID][$cat_ID] ) ? (int) $number_of_comments_in_cat[(string) $blog_ID][$cat_ID] : 0;
 303  }
 304  
 305  
 306  /**
 307   * Get category associations with given item
 308   *
 309   * sam2kb> TODO: Cache item cat IDs into Item::categories property instead of global $cache_postcats
 310   */
 311  function postcats_get_byID( $post_ID )
 312  {
 313      global $DB, $cache_postcats;
 314  
 315      if( ! isset($cache_postcats[$post_ID]) )
 316      {
 317          $sql = 'SELECT postcat_cat_ID
 318                  FROM T_postcats
 319                  WHERE postcat_post_ID = '.$DB->quote($post_ID).'
 320                  ORDER BY postcat_cat_ID';
 321  
 322          $cache_postcats[$post_ID] = $DB->get_col( $sql, 0, 'Get category associations with given item' );
 323      }
 324  
 325      return $cache_postcats[$post_ID];
 326  }
 327  
 328  
 329  /**
 330   * Taking a recursive walk in the category park...
 331   *
 332   * @param array PHP requires this stupid cloning of the cache_categories array in order to be able to perform foreach on it
 333   * @param integer
 334   * @param integer
 335   * @param string|array Callback for first category
 336   * @param string|array Callback before each category
 337   * @param string|array Callback after each category
 338   * @param string|array Callback after last category
 339   * @param integer Caller nesting level, just to keep track of how far we go :)
 340   * @return string
 341   */
 342  function cat_children( $ccats, $blog_ID, $parent_ID, $callback_before_first, $callback_before_each, $callback_after_each, $callback_after_last, $level = 0, $root_call = true )
 343  {
 344      static $total_count = 0;
 345  
 346      $r = '';
 347  
 348      // echo 'Number of cats=', count($ccats);
 349      if( empty( $ccats ) )
 350      { // this can happen if there are no cats at all!
 351          return '';
 352      }
 353  
 354      if( $root_call )
 355      { // Init:
 356          $total_count = 0;
 357      }
 358  
 359      $child_count = 0;
 360      foreach( $ccats as $icat_ID => $i_cat )
 361      {
 362          if( empty( $icat_ID )
 363              || ! ( /* TODO: check ($blog_ID == 0) || */ ($i_cat['cat_blog_ID'] == $blog_ID))
 364              || ! ($i_cat['cat_parent_ID'] == $parent_ID) )
 365          { // this cat is not in the blog and or is not a child of the parent
 366              continue;
 367          }
 368  
 369          // this cat is in the blog and is a child of the parent...
 370          $total_count++;
 371  
 372  
 373          // "before first":
 374          if( $child_count++ == 0 )
 375          { // this is the first child
 376              if( is_array( $callback_before_first ) )
 377              { // object callback:
 378                  $r .= $callback_before_first[0]->{$callback_before_first[1]}( $parent_ID, $level, $total_count, 1 );
 379              }
 380              else
 381                  $r .= $callback_before_first( $parent_ID, $level, $total_count, 1 );
 382          }
 383  
 384          // "before each":
 385          if( is_array( $callback_before_each ) )
 386          { // object callback:
 387              $r2 = $callback_before_each[0]->{$callback_before_each[1]}( $icat_ID, $level, $total_count, $child_count );
 388          }
 389          else
 390              $r2 = $callback_before_each( $icat_ID, $level, $total_count, $child_count );
 391          if( $r2 === true )
 392          {    // callback function has requested that we stop recursing for this branch
 393              continue;
 394          }
 395          $r .= $r2;
 396  
 397          // Recursion:
 398          $r .= cat_children( $ccats, $blog_ID, $icat_ID, $callback_before_first, $callback_before_each, $callback_after_each, $callback_after_last, $level+1, false );
 399  
 400          // "after each":
 401          if( is_array( $callback_after_each ) )
 402          { // object callback:
 403              $r .= $callback_after_each[0]->{$callback_after_each[1]}( $icat_ID, $level, $total_count, $child_count );
 404          }
 405          else
 406          {
 407              $r .= $callback_after_each( $icat_ID, $level, $total_count, $child_count );
 408          }
 409      }
 410      if( $child_count )
 411      { // There have been children
 412          if( is_array( $callback_after_last ) )
 413              $r .= $callback_after_last[0]->{$callback_after_last[1]}( $parent_ID, $level, $total_count, $child_count );
 414          else
 415              $r .= $callback_after_last( $parent_ID, $level, $total_count, $child_count );
 416      }
 417  
 418      return $r;
 419  }
 420  
 421  
 422  /**
 423   * Does a given blog have categories?
 424   *
 425   * @param integer Blog ID
 426   * @return boolean
 427   */
 428  function blog_has_cats( $blog_ID )
 429  {
 430      global $cache_categories;
 431  
 432      cat_load_cache( 'none' );
 433  
 434      foreach( $cache_categories as $icat_ID => $i_cat )
 435      {
 436          if( $icat_ID && $i_cat['cat_blog_ID'] == $blog_ID )
 437          { // this cat is in the blog
 438              return true;
 439          }
 440      }
 441  
 442      return false;
 443  }
 444  
 445  
 446  /**
 447   * Compiles the cat array from $cat (recursive + optional modifiers) and $catsel[] (non recursive)
 448   *
 449   * @param string
 450   * @param array
 451   * @param array by ref, will be modified
 452   * @param string by ref, will be modified
 453   * @param integer blog number to restrict to
 454   */
 455  function compile_cat_array( $cat, $catsel, & $cat_array, & $cat_modifier, $restrict_to_blog = 0  )
 456  {
 457      global $cache_categories;
 458  
 459      // echo '$cat='.$cat;
 460      // pre_dump( $catsel );
 461      // echo '$restrict_to_blog'.$restrict_to_blog;
 462  
 463      $cat_array = array();
 464      $cat_modifier = '';
 465  
 466      // Check for cat string (which will be handled recursively)
 467      if( $cat != 'all' && !empty($cat) )
 468      { // specified a category string:
 469          $cat_modifier = substr($cat, 0, 1 );
 470          // echo 'cats['.$first_char.']';
 471          if( ( $cat_modifier == '*' ) ||
 472              ( $cat_modifier == '-' ) ||
 473              ( $cat_modifier == '|' ) )
 474          {
 475              $cat = substr( $cat, 1 );
 476          }
 477          else
 478          {
 479              $cat_modifier = '';
 480          }
 481  
 482          if( strlen( $cat ) )
 483          {    // There are some values to explode...
 484              $req_cat_array = explode(',', $cat);
 485  
 486              // Getting required sub-categories:
 487              // and add everything to cat array
 488              // ----------------- START RECURSIVE CAT LIST ----------------
 489              cat_load_cache();    // make sure the caches are loaded
 490              foreach( $req_cat_array as $cat_ID )
 491              { // run recursively through the cats
 492                  if( ! in_array( $cat_ID, $cat_array ) )
 493                  { // Not already in list
 494                      $cat_array[] = $cat_ID;
 495                      cat_children( $cache_categories, $restrict_to_blog, $cat_ID, 'cat_req_dummy', 'cat_req',
 496                                                  'cat_req_dummy', 'cat_req_dummy', 1 );
 497                  }
 498              }
 499              // ----------------- END RECURSIVE CAT LIST ----------------
 500          }
 501      }
 502  
 503      // Add explicit selections:
 504      if( ! empty( $catsel ))
 505      {
 506          // echo "Explicit selections!<br />";
 507          $cat_array = array_merge( $cat_array, $catsel );
 508          $cat_array = array_unique( $cat_array );
 509      }
 510  
 511      // echo '$cat_modifier='.$cat_modifier;
 512      // pre_dump( $cat_array );
 513  
 514  }
 515  
 516  
 517  /**
 518   * Callback used in compile_cat_array()
 519   */
 520  function cat_req( $parent_cat_ID, $level )
 521  {
 522      global $cat_array;
 523      // echo "[$parent_cat_ID] ";
 524      if( ! in_array( $parent_cat_ID, $cat_array ) )
 525      { // Not already visited
 526          $cat_array[] = $parent_cat_ID;
 527      }
 528      else
 529      {
 530          // echo "STOP! ALREADY VISITED THIS ONE!";
 531          return -1;        // STOP going through that branch
 532      }
 533  }
 534  
 535  
 536  /**
 537   * Get global cross posting settings -- (cross posting = 1 post in multiple blogs)
 538   *
 539   * @return int
 540   *         0 - cross posting disabled
 541   *         1 - cross posting enabled for extra categories
 542   *         2 - cross posting enabled for main categories
 543   *         3 - cross posting enabled for main and extracats
 544   */
 545  function get_allow_cross_posting()
 546  {
 547      global $Settings;
 548      return $Settings->get( 'cross_posting' ) + ( 2 *  $Settings->get( 'cross_posting_blogs' ) );
 549  }
 550  
 551  
 552  /**
 553   * Callback used in compile_cat_array()
 554   */
 555  function cat_req_dummy()
 556  {
 557  }
 558  
 559  ?>

title

Description

title

Description

title

Description

title

title

Body