[ Index ] |
|
Code source de b2evolution 2.1.0-beta |
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-2007 by Francois PLANQUE - {@link http://fplanque.net/} 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,v 1.1 2007/06/25 10:59:32 fplanque Exp $ 44 */ 45 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 46 47 /** 48 * Create a new category 49 * 50 * This funtion has to handle all needed DB dependencies! 51 * 52 * @param string Category name 53 * @param string Category ID ('NULL' as string(!) for root) 54 * @param integer|NULL Blog ID (will be taken from parent cat, if empty) 55 */ 56 function cat_create( 57 $cat_name, 58 $cat_parent_ID, 59 $cat_blog_ID = NULL) 60 { 61 global $DB; 62 63 if( $cat_blog_ID == NULL ) 64 { 65 if( empty($cat_parent_ID) ) debug_die ( 'cat_create(-) missing parameters!' ); 66 $parent_cat = get_the_category_by_ID($cat_parent_ID); 67 $cat_blog_ID = $parent_cat['cat_blog_ID']; 68 } 69 70 // Dirty temporary fix: 71 $cat_urlname = preg_replace( '/[^a-z0-9]/', '-', strtolower($cat_name) ); 72 73 $sql = "INSERT INTO T_categories( cat_parent_ID, cat_name, cat_blog_ID, cat_urlname ) 74 VALUES ( $cat_parent_ID, ".$DB->quote($cat_name).", $cat_blog_ID, ".$DB->quote($cat_urlname)." )"; 75 if( ! $DB->query( $sql ) ) 76 return 0; 77 78 return $DB->insert_id; 79 } 80 81 82 /** 83 * get_the_category_by_ID(-) 84 * 85 * Get category name+blog_id for specified cat ID 86 * 87 * fplanque: reused "R. U. Serious" optimization here 88 * fplanque: added blog ID stuff 89 * TODO: move. dis is not a template tag 90 * 91 * @param integer category ID 92 * @param boolean die() if category does not exist? (default: true) 93 * 94 */ 95 function get_the_category_by_ID( $cat_ID, $die = true ) 96 { 97 global $cache_categories; 98 if( empty($cache_categories[$cat_ID]) ) 99 { 100 cat_load_cache( 'none' ); 101 } 102 if( !isset( $cache_categories[$cat_ID] ) ) 103 { 104 if( $die ) 105 { 106 debug_die( sprintf( T_('Requested category %s does not exist!'), $cat_ID ) ); 107 } 108 else return false; 109 } 110 return $cache_categories[$cat_ID]; 111 } 112 113 114 115 /** 116 * Get blog for a given cat 117 */ 118 function get_catblog( $cat_ID ) 119 { 120 $cat = get_the_category_by_ID( $cat_ID ); 121 return $cat['cat_blog_ID']; 122 } 123 124 125 /** 126 * Load cache for category definitions. 127 */ 128 function cat_load_cache() 129 { 130 global $DB, $cache_categories; 131 global $timestamp_min, $timestamp_max; 132 global $Settings; 133 global $Timer; 134 135 if( isset($cache_categories)) 136 { 137 return; 138 } 139 140 $Timer->resume( 'cat_load_cache' ); 141 142 // echo "loading CAT cache"; 143 $sql = "SELECT cat_ID, cat_parent_ID, cat_name, cat_blog_ID 144 FROM T_categories 145 ORDER BY cat_name"; 146 147 foreach( $DB->get_results( $sql, ARRAY_A, 'loading CAT cache' ) as $myrow ) 148 { 149 $this_cat['cat_name'] = $myrow['cat_name']; 150 $this_cat['cat_blog_ID'] = $myrow['cat_blog_ID']; 151 $this_cat['cat_parent_ID'] = $myrow['cat_parent_ID']; 152 $this_cat['cat_postcount'] = 0; // Will be increased later 153 $this_cat['cat_children'] = array(); 154 $cache_categories[$myrow['cat_ID']] = $this_cat; 155 // echo 'just cached:',$myrow['cat_ID'],':',$cache_categories[$myrow['cat_ID']]['cat_name'], ' parent:',$cache_categories[$myrow['cat_ID']]['cat_parent_ID'],'<br />'; 156 } 157 158 // echo 'Number of cats=', count($cache_categories); 159 160 // Reveal children: 161 if( ! empty( $cache_categories ) ) 162 { 163 foreach( $cache_categories as $icat_ID => $i_cat ) 164 { 165 // echo '<br>handling cat ', $icat_ID, ' ', $i_cat['cat_name']; 166 $cat_parent_ID = $i_cat['cat_parent_ID']; 167 if( $cat_parent_ID ) 168 { 169 if( isset( $cache_categories[$cat_parent_ID] ) ) 170 { // If the parent exists! 171 $cache_categories[$cat_parent_ID]['cat_children'][] = $icat_ID; 172 } 173 else 174 { 175 echo( "Category #$icat_ID is orphan of non existant parent #$cat_parent_ID!<br />" ); 176 } 177 } 178 } 179 } 180 181 // echo 'Number of cats=', count($cache_categories); 182 183 $Timer->pause( 'cat_load_cache' ); 184 } 185 186 187 /** 188 * Load cache for category associations with current posts 189 * 190 * @todo put this into main post query when MySQL 4.0 commonly available 191 * @todo dh> why is this limited to the _global_ $postIDlist?! 192 * Really ridiculous, trying to get a list of category names for an Item (which is not in $postIDlist for example.. :/) 193 * fp> This is legacy from a quick b2/cafelog hack. This will de deprecated. 194 */ 195 function cat_load_postcats_cache() 196 { 197 global $DB, $cache_postcats, $postIDlist, $preview; 198 199 if( isset($cache_postcats) ) 200 { // already done! 201 return; 202 } 203 204 if( $preview ) 205 { // Preview mode 206 global $extracats, $post_category; 207 param( 'extracats', 'array', array() ); 208 if( !in_array( $post_category, $extracats ) ) 209 $extracats[] = $post_category; 210 $cache_postcats[0] = $extracats; 211 return; 212 } 213 214 if( !empty($postIDlist) ) 215 { 216 $sql = "SELECT postcat_post_ID, postcat_cat_ID 217 FROM T_postcats 218 WHERE postcat_post_ID IN ($postIDlist) 219 ORDER BY postcat_post_ID, postcat_cat_ID"; 220 221 foreach( $DB->get_results( $sql, ARRAY_A ) as $myrow ) 222 { 223 $postcat_post_ID = $myrow["postcat_post_ID"]; 224 if( ! isset( $cache_postcats[$postcat_post_ID] ) ) 225 { 226 $cache_postcats[$postcat_post_ID] = array(); 227 } 228 $cache_postcats[$postcat_post_ID][] = $myrow["postcat_cat_ID"]; 229 // echo "just cached: post=$postcat_post_ID cat=".$myrow["postcat_cat_ID"]."<br />"; 230 } 231 } 232 } 233 234 235 /** 236 * Get category associations with given post 237 */ 238 function postcats_get_byID( $post_ID ) 239 { 240 global $DB; 241 242 //echo "looking up cats for post $post_ID "; 243 244 $sql = "SELECT postcat_cat_ID 245 FROM T_postcats 246 WHERE postcat_post_ID = $post_ID 247 ORDER BY postcat_cat_ID"; 248 return $DB->get_col( $sql ); 249 } 250 251 252 /** 253 * Taking a recursive walk in the category park... 254 * 255 * @param array PHP requires this stupid cloning of the cache_categories array in order to be able to perform foreach on it 256 * @param integer 257 * @param integer 258 * @param string|array Callback for first category 259 * @param string|array Callback before each category 260 * @param string|array Callback after each category 261 * @param string|array Callback after last category 262 * @param integer Caller nesting level, just to keep track of how far we go :) 263 * @return string 264 */ 265 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 ) 266 { 267 static $total_count = 0; 268 269 $r = ''; 270 271 // echo 'Number of cats=', count($ccats); 272 if( empty( $ccats ) ) 273 { // this can happen if there are no cats at all! 274 return ''; 275 } 276 277 if( $root_call ) 278 { // Init: 279 $total_count = 0; 280 } 281 282 $child_count = 0; 283 foreach( $ccats as $icat_ID => $i_cat ) 284 { 285 if( empty( $icat_ID ) 286 || ! ( /* TODO: check ($blog_ID == 0) || */ ($i_cat['cat_blog_ID'] == $blog_ID)) 287 || ! ($i_cat['cat_parent_ID'] == $parent_ID) ) 288 { // this cat is not in the blog and or is not a child of the parent 289 continue; 290 } 291 292 // this cat is in the blog and is a child of the parent... 293 $total_count++; 294 295 296 // "before first": 297 if( $child_count++ == 0 ) 298 { // this is the first child 299 if( is_array( $callback_before_first ) ) 300 { // object callback: 301 $r .= $callback_before_first[0]->{$callback_before_first[1]}( $parent_ID, $level, $total_count, 1 ); 302 } 303 else 304 $r .= $callback_before_first( $parent_ID, $level, $total_count, 1 ); 305 } 306 307 // "before each": 308 if( is_array( $callback_before_each ) ) 309 { // object callback: 310 $r2 = $callback_before_each[0]->{$callback_before_each[1]}( $icat_ID, $level, $total_count, $child_count ); 311 } 312 else 313 $r2 = $callback_before_each( $icat_ID, $level, $total_count, $child_count ); 314 if( $r2 === true ) 315 { // callback function has requested that we stop recursing for this branch 316 continue; 317 } 318 $r .= $r2; 319 320 // Recursion: 321 $r .= cat_children( $ccats, $blog_ID, $icat_ID, $callback_before_first, $callback_before_each, $callback_after_each, $callback_after_last, $level+1, false ); 322 323 // "after each": 324 if( is_array( $callback_after_each ) ) 325 { // object callback: 326 $r .= $callback_after_each[0]->{$callback_after_each[1]}( $icat_ID, $level, $total_count, $child_count ); 327 } 328 else 329 { 330 $r .= $callback_after_each( $icat_ID, $level, $total_count, $child_count ); 331 } 332 } 333 if( $child_count ) 334 { // There have been children 335 if( is_array( $callback_after_last ) ) 336 $r .= $callback_after_last[0]->{$callback_after_last[1]}( $parent_ID, $level, $total_count, $child_count ); 337 else 338 $r .= $callback_after_last( $parent_ID, $level, $total_count, $child_count ); 339 } 340 341 return $r; 342 } 343 344 345 /** 346 * Does a given blog have categories? 347 * 348 * @param integer Blog ID 349 * @return boolean 350 */ 351 function blog_has_cats( $blog_ID ) 352 { 353 global $cache_categories; 354 355 cat_load_cache( 'none' ); 356 357 if( count($cache_categories) ) foreach( $cache_categories as $icat_ID => $i_cat ) 358 { 359 if( $icat_ID && $i_cat['cat_blog_ID'] == $blog_ID ) 360 { // this cat is in the blog 361 return true; 362 } 363 } 364 365 return false; 366 } 367 368 369 /** 370 * Compiles the cat array from $cat (recursive + optional modifiers) and $catsel[] (non recursive) 371 * 372 * @param string 373 * @param array 374 * @param array by ref, will be modified 375 * @param string by ref, will be modified 376 * @param integer blog number to restrict to 377 */ 378 function compile_cat_array( $cat, $catsel, & $cat_array, & $cat_modifier, $restrict_to_blog = 0 ) 379 { 380 global $cache_categories; 381 382 // echo '$cat='.$cat; 383 // pre_dump( $catsel ); 384 // echo '$restrict_to_blog'.$restrict_to_blog; 385 386 $cat_array = array(); 387 $cat_modifier = ''; 388 389 // Check for cat string (which will be handled recursively) 390 if( $cat != 'all' && !empty($cat) ) 391 { // specified a category string: 392 $cat_modifier = substr($cat, 0, 1 ); 393 // echo 'cats['.$first_char.']'; 394 if( ($cat_modifier == '*') 395 || ($cat_modifier == '-') ) 396 { 397 $cat = substr( $cat, 1 ); 398 } 399 else 400 { 401 $cat_modifier = ''; 402 } 403 404 if( strlen( $cat ) ) 405 { // There are some values to explode... 406 $req_cat_array = explode(',', $cat); 407 408 // Getting required sub-categories: 409 // and add everything to cat array 410 // ----------------- START RECURSIVE CAT LIST ---------------- 411 cat_load_cache(); // make sure the caches are loaded 412 foreach( $req_cat_array as $cat_ID ) 413 { // run recursively through the cats 414 if( ! in_array( $cat_ID, $cat_array ) ) 415 { // Not already in list 416 $cat_array[] = $cat_ID; 417 cat_children( $cache_categories, $restrict_to_blog, $cat_ID, 'cat_req_dummy', 'cat_req', 418 'cat_req_dummy', 'cat_req_dummy', 1 ); 419 } 420 } 421 // ----------------- END RECURSIVE CAT LIST ---------------- 422 } 423 } 424 425 // Add explicit selections: 426 if( ! empty( $catsel )) 427 { 428 // echo "Explicit selections!<br />"; 429 $cat_array = array_merge( $cat_array, $catsel ); 430 $cat_array = array_unique( $cat_array ); 431 } 432 433 // echo '$cat_modifier='.$cat_modifier; 434 // pre_dump( $cat_array ); 435 436 } 437 438 439 /** 440 * Callback used in compile_cat_array() 441 */ 442 function cat_req( $parent_cat_ID, $level ) 443 { 444 global $cat_array; 445 // echo "[$parent_cat_ID] "; 446 if( ! in_array( $parent_cat_ID, $cat_array ) ) 447 { // Not already visited 448 $cat_array[] = $parent_cat_ID; 449 } 450 else 451 { 452 // echo "STOP! ALREADY VISITED THIS ONE!"; 453 return -1; // STOP going through that branch 454 } 455 } 456 457 /** 458 * Callback used in compile_cat_array() 459 */ 460 function cat_req_dummy() 461 { 462 } 463 464 /* 465 * $Log: _category.funcs.php,v $ 466 * Revision 1.1 2007/06/25 10:59:32 fplanque 467 * MODULES (refactored MVC) 468 * 469 * Revision 1.29 2007/05/28 01:33:22 fplanque 470 * permissions/fixes 471 * 472 * Revision 1.28 2007/05/09 00:58:55 fplanque 473 * massive cleanup of old functions 474 * 475 * Revision 1.27 2007/04/26 00:11:06 fplanque 476 * (c) 2007 477 * 478 * Revision 1.26 2007/03/24 20:41:16 fplanque 479 * Refactored a lot of the link junk. 480 * Made options blog specific. 481 * Some junk still needs to be cleaned out. Will do asap. 482 * 483 * Revision 1.25 2006/12/17 23:42:38 fplanque 484 * Removed special behavior of blog #1. Any blog can now aggregate any other combination of blogs. 485 * Look into Advanced Settings for the aggregating blog. 486 * There may be side effects and new bugs created by this. Please report them :] 487 * 488 * Revision 1.24 2006/11/26 02:30:39 fplanque 489 * doc / todo 490 * 491 * Revision 1.23 2006/11/24 18:27:23 blueyed 492 * Fixed link to b2evo CVS browsing interface in file docblocks 493 * 494 * Revision 1.22 2006/11/22 20:38:17 blueyed 495 * todo 496 */ 497 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 23:58:50 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |