| [ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * This file implements the DataObjectCache class. 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)2005-2006 by PROGIDISTRI - {@link http://progidistri.com/}. 11 * 12 * {@internal License choice 13 * - If you have received this file as part of a package, please find the license.txt file in 14 * the same folder or the closest folder above for complete license terms. 15 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/) 16 * then you must choose one of the following licenses before using the file: 17 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php 18 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php 19 * }} 20 * 21 * {@internal Open Source relicensing agreement: 22 * Daniel HAHLER grants Francois PLANQUE the right to license 23 * Daniel HAHLER's contributions to this file and the b2evolution project 24 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 25 * 26 * PROGIDISTRI S.A.S. grants Francois PLANQUE the right to license 27 * PROGIDISTRI S.A.S.'s contributions to this file and the b2evolution project 28 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 29 * }} 30 * 31 * @package evocore 32 * 33 * {@internal Below is a list of authors who have contributed to design/coding of this file: }} 34 * @author blueyed: Daniel HAHLER. 35 * @author fplanque: Francois PLANQUE 36 * 37 * @version $Id: _dataobjectcache.class.php,v 1.1 2007/06/25 10:58:56 fplanque Exp $ 38 */ 39 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 40 41 /** 42 * Data Object Cache Class 43 * 44 * @todo dh> Provide iteration "interface"! 45 * 46 * @package evocore 47 * @version beta 48 */ 49 class DataObjectCache 50 { 51 var $dbtablename; 52 var $dbprefix; 53 var $dbIDname; 54 55 /** 56 * Class name of objects in this cache: 57 */ 58 var $objtype; 59 60 /** 61 * Object array by ID 62 */ 63 var $cache = array(); 64 65 /** 66 * Copy of previous object array 67 * @see DataObjectCache::clear() 68 */ 69 var $shadow_cache = NULL; 70 71 /** 72 * NON indexed object array 73 * @var array of DataObjects 74 */ 75 var $DataObject_array = array(); 76 77 /** 78 * Index of current iteration 79 * @see DataObjectCache::get_next() 80 */ 81 var $current_idx = NULL; 82 83 var $load_all = false; 84 var $all_loaded = false; 85 86 87 var $name_field; 88 var $order_by; 89 90 /** 91 * The text that gets used for the "None" option in the objects options list. 92 * 93 * This is especially useful for i18n, because there are several "None"s! 94 * 95 * @var string 96 */ 97 var $none_option_text; 98 99 100 /** 101 * Constructor 102 * 103 * @param string Name of DataObject class we are cacheing 104 * @param boolean true if it's OK to just load all items! 105 * @param string Name of table in database 106 * @param string Prefix of fields in the table 107 * @param string Name of the ID field (including prefix) 108 * @param string Name of the name field (including prefix) 109 * @param string field names or NULL to use name field 110 * @param string The text that gets used for the "None" option in the objects options list (Default: T_('None')). 111 */ 112 function DataObjectCache( $objtype, $load_all, $tablename, $prefix = '', $dbIDname, $name_field = NULL, $order_by = '', $allow_none_text = NULL ) 113 { 114 $this->objtype = $objtype; 115 $this->load_all = $load_all; 116 $this->dbtablename = $tablename; 117 $this->dbprefix = $prefix; 118 $this->dbIDname = $dbIDname; 119 $this->name_field = $name_field; 120 121 if( empty( $order_by ) ) 122 { 123 if( empty( $name_field ) ) 124 { 125 $this->order_by = $dbIDname; 126 } 127 else 128 { 129 $this->order_by = $name_field; 130 } 131 } 132 else 133 { 134 $this->order_by = $order_by; 135 } 136 137 if( isset($allow_none_text) ) 138 { 139 $this->none_option_text = $allow_none_text; 140 } 141 else 142 { 143 $this->none_option_text = /* TRANS: the default value for option lists where "None" is allowed */ T_('None'); 144 } 145 } 146 147 148 /** 149 * Instanciate a new object within this cache 150 */ 151 function & new_obj( $row = NULL ) 152 { 153 $objtype = $this->objtype; 154 155 // Instantiate a custom object 156 $obj = new $objtype( $row ); // COPY !! 157 158 return $obj; 159 } 160 161 162 /** 163 * Load the cache **extensively** 164 */ 165 function load_all() 166 { 167 /** 168 * @var DB 169 */ 170 global $DB; 171 global $Debuglog; 172 173 if( $this->all_loaded ) 174 { // Already loaded 175 return false; 176 } 177 178 $this->clear( true ); 179 180 $Debuglog->add( get_class($this).' - Loading <strong>'.$this->objtype.'(ALL)</strong> into cache', 'dataobjects' ); 181 $sql = 'SELECT * 182 FROM '.$this->dbtablename.' 183 ORDER BY '.$this->order_by; 184 185 foreach( $DB->get_results( $sql, OBJECT, 'Loading '.$this->objtype.'(ALL) into cache' ) as $row ) 186 { 187 // Instantiate a custom object 188 $this->instantiate( $row ); 189 } 190 191 $this->all_loaded = true; 192 193 return true; 194 } 195 196 197 /** 198 * Load a list of objects into the cache 199 * 200 * @param string list of IDs of objects to load 201 */ 202 function load_list( $req_list ) 203 { 204 global $DB, $Debuglog; 205 206 $Debuglog->add( "Loading <strong>$this->objtype($req_list)</strong> into cache", 'dataobjects' ); 207 208 if( empty( $req_list ) ) 209 { 210 return false; 211 } 212 213 $sql = "SELECT * 214 FROM $this->dbtablename 215 WHERE $this->dbIDname IN ($req_list)"; 216 217 foreach( $DB->get_results( $sql ) as $row ) 218 { 219 // Instantiate a custom object 220 $this->instantiate( $row ); 221 } 222 } 223 224 225 /** 226 * Get an array of all (loaded) IDs. 227 * 228 * @return array 229 */ 230 function get_ID_array() 231 { 232 $IDs = array(); 233 234 foreach( $this->cache as $obj ) 235 { 236 $IDs[] = $obj->ID; 237 } 238 239 return $IDs; 240 } 241 242 243 /** 244 * Add a dataobject to the cache 245 */ 246 function add( & $Obj ) 247 { 248 global $Debuglog; 249 250 if( is_null($Obj->ID) ) // value 0 is used by item preview 251 { 252 $Debuglog->add( 'No object to add!', 'dataobjects' ); 253 return false; 254 } 255 256 // fplanque: I don't want an extra (and expensive) comparison here. $this->cache[$Obj->ID] === $Obj. 257 // If you need this you're probably misusing the cache. 258 if( isset($this->cache[$Obj->ID]) ) 259 { 260 $Debuglog->add( $this->objtype.': Object with ID '.$Obj->ID.' is already cached', 'dataobjects' ); 261 return false; 262 } 263 264 // If the object is valid and not already cached: 265 // Add object to cache: 266 $this->cache[$Obj->ID] = & $Obj; 267 // Add a reference in the object list: 268 $this->DataObject_array[] = & $Obj; 269 270 return true; 271 } 272 273 274 /** 275 * Instantiate a DataObject from a table row and then cache it. 276 * 277 * @param Object Database row 278 * @return Object 279 */ 280 function & instantiate( & $db_row ) 281 { 282 // Get ID of the object we'ere preparing to instantiate... 283 $obj_ID = $db_row->{$this->dbIDname}; 284 285 if( is_null($obj_ID) ) // value 0 is used for item preview 286 { 287 $Obj = NULL; 288 return $Obj; 289 } 290 291 if( isset( $this->cache[$obj_ID] ) ) 292 { // Already in cache, do nothing! 293 } 294 elseif( isset( $this->shadow_cache[$obj_ID] ) ) 295 { // Already in shadow, recycle object: 296 // echo "adding shadow {$this->objtype} $obj_ID "; 297 $this->add( $this->shadow_cache[$obj_ID] ); 298 } 299 else 300 { // Not already cached, add new object: 301 // echo "adding new {$this->objtype} $obj_ID "; 302 $this->add( $this->new_obj( $db_row ) ); 303 } 304 305 return $this->cache[$obj_ID]; 306 } 307 308 309 /** 310 * Clear the cache **extensively** 311 * 312 */ 313 function clear( $keep_shadow = false ) 314 { 315 if( $keep_shadow ) 316 { // Keep copy of cache in case we try to re instantiate previous object: 317 $this->shadow_cache = $this->cache; 318 } 319 else 320 { 321 $this->shadow_cache = NULL; 322 } 323 324 $this->cache = array(); 325 $this->DataObject_array = array(); 326 $this->all_loaded = false; 327 $this->current_idx = NULL; 328 } 329 330 331 /** 332 * This provides a simple interface for looping over the contents of the Cache. 333 * 334 * This should only be used for basic enumeration. 335 * If you need complex filtering of the cache contents, you should probablt use a DataObjectList instead. 336 * 337 * @see DataObject::get_next() 338 * 339 * @return DataObject 340 */ 341 function & get_first() 342 { 343 $this->load_all(); 344 345 $this->current_idx = -1; 346 return $this->get_next(); 347 } 348 349 350 /** 351 * This provides a simple interface for looping over the contents of the Cache. 352 * 353 * This should only be used for basic enumeration. 354 * If you need complex filtering of the cache contents, you should probablt use a DataObjectList instead. 355 * 356 * @see DataObject::get_first() 357 * 358 * @return DataObject 359 */ 360 function & get_next() 361 { 362 $this->current_idx++; 363 // echo 'getting idx:'.$this->current_idx; 364 365 if( ! isset( $this->DataObject_array[$this->current_idx] ) ) 366 { 367 $this->current_idx = NULL; 368 $r = NULL; 369 return $r; 370 } 371 372 return $this->DataObject_array[$this->current_idx]; 373 } 374 375 376 /** 377 * Get an object from cache by ID 378 * 379 * Load the cache if necessary (all at once if allowed). 380 * 381 * @param integer ID of object to load 382 * @param boolean true if function should die on error 383 * @param boolean true if function should die on empty/null 384 * @return DataObject reference on cached object 385 */ 386 function & get_by_ID( $req_ID, $halt_on_error = true, $halt_on_empty = true ) 387 { 388 global $DB, $Debuglog; 389 390 if( empty($req_ID) ) 391 { 392 if($halt_on_empty) 393 { 394 debug_die( "Requested $this->objtype from $this->dbtablename without ID!" ); 395 } 396 $r = NULL; 397 return $r; 398 } 399 400 if( !empty( $this->cache[ $req_ID ] ) ) 401 { // Already in cache 402 // $Debuglog->add( "Accessing $this->objtype($req_ID) from cache", 'dataobjects' ); 403 return $this->cache[ $req_ID ]; 404 } 405 elseif( !$this->all_loaded ) 406 { // Not in cache, but not everything is loaded yet 407 if( $this->load_all ) 408 { // It's ok to just load everything: 409 $this->load_all(); 410 } 411 else 412 { // Load just the requested object: 413 $Debuglog->add( "Loading <strong>$this->objtype($req_ID)</strong> into cache", 'dataobjects' ); 414 // Note: $req_ID MUST be an unsigned integer. This is how DataObject works. 415 $sql = "SELECT * 416 FROM $this->dbtablename 417 WHERE $this->dbIDname = $req_ID"; 418 if( $row = $DB->get_row( $sql, OBJECT, 0, 'DataObjectCache::get_by_ID()' ) ) 419 { 420 if( ! $this->instantiate( $row ) ) 421 { 422 $Debuglog->add( 'Could not add() object to cache!', 'dataobjects' ); 423 } 424 } 425 else 426 { 427 $Debuglog->add( 'Could not get DataObject by ID. Query: '.$sql, 'dataobjects' ); 428 } 429 } 430 } 431 432 if( empty( $this->cache[ $req_ID ] ) ) 433 { // Requested object does not exist 434 // $Debuglog->add( 'failure', 'dataobjects' ); 435 if( $halt_on_error ) 436 { 437 debug_die( "Requested $this->objtype does not exist!" ); 438 } 439 $r = false; 440 return $r; 441 } 442 443 return $this->cache[ $req_ID ]; 444 } 445 446 447 /** 448 * Get an object from cache by name 449 * 450 * Load the cache if necessary (all at once if allowed). 451 * 452 * @param integer ID of object to load 453 * @param boolean true if function should die on error 454 * @param boolean true if function should die on empty/null 455 * @return reference on cached object 456 */ 457 function & get_by_name( $req_name, $halt_on_error = true, $halt_on_empty = true ) 458 { 459 global $DB, $Debuglog; 460 461 if( empty( $this->name_field ) ) 462 { 463 debug_die( 'DataObjectCache::get_by_name() : No name field to query on' ); 464 } 465 466 if( empty($req_name) ) 467 { 468 if($halt_on_empty) { debug_die( "Requested $this->objtype from $this->dbtablename without name!" ); } 469 $r = NULL; 470 return $r; 471 } 472 473 // Load just the requested object: 474 $Debuglog->add( "Loading <strong>$this->objtype($req_name)</strong>", 'dataobjects' ); 475 $sql = "SELECT * 476 FROM $this->dbtablename 477 WHERE $this->name_field = ".$DB->quote($req_name); 478 479 if( $db_row = $DB->get_row( $sql, OBJECT, 0, 'DataObjectCache::get_by_name()' ) ) 480 { 481 $resolved_ID = $db_row->{$this->dbIDname}; 482 $Debuglog->add( 'success; ID = '.$resolved_ID, 'dataobjects' ); 483 if( ! isset( $this->cache[$resolved_ID] ) ) 484 { // Object is not already in cache: 485 $Debuglog->add( 'Adding to cache...', 'dataobjects' ); 486 //$Obj = new $this->objtype( $row ); // COPY !! 487 //if( ! $this->add( $this->new_obj( $db_row ) ) ) 488 if( ! $this->add( $this->new_obj( $db_row ) ) ) 489 { // could not add 490 $Debuglog->add( 'Could not add() object to cache!', 'dataobjects' ); 491 } 492 } 493 return $this->cache[$resolved_ID]; 494 } 495 else 496 { 497 $Debuglog->add( 'Could not get DataObject by name.', 'dataobjects' ); 498 if( $halt_on_error ) 499 { 500 debug_die( "Requested $this->objtype does not exist!" ); 501 } 502 $r = NULL; 503 return $r; 504 } 505 } 506 507 508 /** 509 * Remove an object from cache by ID 510 * 511 * @param integer ID of object to remove 512 */ 513 function remove_by_ID( $req_ID ) 514 { 515 unset( $this->cache[$req_ID] ); 516 } 517 518 519 /** 520 * Delete an object from DB by ID. 521 * 522 * @param integer ID of object to delete 523 * @return boolean 524 */ 525 function dbdelete_by_ID( $req_ID ) 526 { 527 if( isset( $this->cache[$req_ID] ) ) 528 { 529 // Delete from db 530 $this->cache[$req_ID]->dbdelete(); 531 532 // Remove from cache 533 $this->remove_by_ID( $req_ID ); 534 535 return true; 536 } 537 else 538 { 539 return false; 540 } 541 } 542 543 544 /** 545 * Returns form option list with cache contents 546 * 547 * Load the cache if necessary 548 * 549 * @param integer selected ID 550 * @param boolean provide a choice for "none" with ID '' 551 * @param string Callback method name 552 * @return string 553 */ 554 function get_option_list( $default = 0, $allow_none = false, $method = 'get_name' ) 555 { 556 if( (! $this->all_loaded) && $this->load_all ) 557 { // We have not loaded all items so far, but we're allowed to... so let's go: 558 $this->load_all(); 559 } 560 561 $r = ''; 562 563 if( $allow_none ) 564 { 565 $r .= '<option value=""'; 566 if( empty($default) ) $r .= ' selected="selected"'; 567 $r .= '>'.format_to_output($this->none_option_text).'</option>'."\n"; 568 } 569 570 foreach( $this->cache as $loop_Obj ) 571 { 572 $r .= '<option value="'.$loop_Obj->ID.'"'; 573 if( $loop_Obj->ID == $default ) $r .= ' selected="selected"'; 574 $r .= '>'; 575 $r .= format_to_output( $loop_Obj->$method(), 'htmlbody' ); 576 $r .= '</option>'."\n"; 577 } 578 579 return $r; 580 } 581 582 } 583 584 585 /* 586 * $Log: _dataobjectcache.class.php,v $ 587 * Revision 1.1 2007/06/25 10:58:56 fplanque 588 * MODULES (refactored MVC) 589 * 590 * Revision 1.31 2007/05/09 01:00:39 fplanque 591 * minor 592 * 593 * Revision 1.30 2007/04/26 00:11:09 fplanque 594 * (c) 2007 595 * 596 * Revision 1.29 2007/02/12 15:42:40 fplanque 597 * public interface for looping over a cache 598 * 599 * Revision 1.28 2006/12/29 01:10:06 fplanque 600 * basic skin registering 601 * 602 * Revision 1.27 2006/12/24 01:09:55 fplanque 603 * Rollback. Non geeks do not know how to use select multiple. 604 * Checkbox lists should be used instead. 605 * The core does. There is not reason for plugins not to do so also. 606 * 607 * Revision 1.24 2006/12/12 02:53:56 fplanque 608 * Activated new item/comments controllers + new editing navigation 609 * Some things are unfinished yet. Other things may need more testing. 610 * 611 * Revision 1.23 2006/12/05 01:35:27 blueyed 612 * Hooray for less complexity and the 8th param for DataObjectCache() 613 * 614 * Revision 1.22 2006/12/05 00:59:46 fplanque 615 * doc 616 * 617 * Revision 1.21 2006/12/05 00:34:39 blueyed 618 * Implemented custom "None" option text in DataObjectCache; Added for $ItemStatusCache, $GroupCache, UserCache and BlogCache; Added custom text for Item::priority_options() 619 * 620 * Revision 1.20 2006/11/24 18:27:24 blueyed 621 * Fixed link to b2evo CVS browsing interface in file docblocks 622 * 623 * Revision 1.19 2006/11/10 20:14:42 blueyed 624 * TODO 625 * 626 * Revision 1.18 2006/10/13 09:58:53 blueyed 627 * Removed bogus unset() 628 */ 629 ?>
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 |
|