Source for file _dataobjectcache.class.php
Documentation is available at _dataobjectcache.class.php
* This file implements the DataObjectCache class.
* This file is part of Quam Plures - {@link http://quamplures.net/}
* See also {@link https://launchpad.net/quam-plures}.
* @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}
* @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}
* Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
* Parts of this file are copyright (c)2005-2006 by PROGIDISTRI - {@link http://progidistri.com/}.
* {@internal License choice
* - If you have received this file as part of a package, please find the license.txt file in
* the same folder or the closest folder above for complete license terms.
* - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
* then you must choose one of the following licenses before using the file:
* - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
* - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
* {@internal Open Source relicensing agreement:
* Daniel HAHLER grants Francois PLANQUE the right to license
* Daniel HAHLER's contributions to this file and the b2evolution project
* under any OSI approved OSS license (http://www.opensource.org/licenses/).
* PROGIDISTRI S.A.S. grants Francois PLANQUE the right to license
* PROGIDISTRI S.A.S.'s contributions to this file and the b2evolution project
* under any OSI approved OSS license (http://www.opensource.org/licenses/).
* {@internal Below is a list of authors who have contributed to design/coding of this file: }}
* @author blueyed: Daniel HAHLER.
* @author fplanque: Francois PLANQUE
if( !defined('QP_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
* Data Object Cache Class
* @todo dh> Provide iteration "interface"!
* Class name of objects in this cache:
* Copy of previous object array
* @see DataObjectCache::clear()
* NON indexed object array
* @var array of DataObjects
* Index of current iteration
* @see DataObjectCache::get_next()
* The text that gets used for the "None" option in the objects options list.
* This is especially useful for i18n, because there are several "None"s!
* The value that gets used for the "None" option in the objects options list.
* @param string Name of DataObject class we are cacheing
* @param boolean true if it's OK to just load all items!
* @param string Name of table in database
* @param string Prefix of fields in the table
* @param string Name of the ID field (including prefix)
* @param string Name of the name field (including prefix)
* @param string field names or NULL to use name field
* @param string The text that gets used for the "None" option in the objects options list (Default: T_('None')).
* @param mixed The value that gets used for the "None" option in the objects options list.
function DataObjectCache( $objtype, $load_all, $tablename, $prefix = '', $dbIDname, $name_field = NULL, $order_by = '', $allow_none_text = NULL, $allow_none_value = '' )
if( empty( $name_field ) )
if( isset ($allow_none_text) )
$this->none_option_text = /* TRANS: the default value for option lists where "None" is allowed */ T_('None');
* Instanciate a new object within this cache
// Instantiate a custom object
$obj = new $objtype( $row ); // COPY !!
* Load the cache **extensively**
$Debuglog->add( get_class($this). ' - Loading <strong>'. $this->objtype. '(ALL)</strong> into cache', 'dataobjects' );
foreach( $DB->get_results( $sql, OBJECT, 'Loading '. $this->objtype. '(ALL) into cache' ) as $row )
// Instantiate a custom object
* Load a list of objects into the cache
* @param string list of IDs of objects to load
* @param boolean Invert list: Load all objects except those listed in the first parameter
function load_list( $req_list, $invert = false )
$Debuglog->add( 'Loading <strong>'. $this->objtype. '('. ( $invert ? 'ALL except ' : '' ). $req_list. ')</strong> into cache', 'dataobjects' );
WHERE $this->dbIDname ". ( $invert ? 'NOT ' : '' ). "IN ($req_list)";
foreach( $DB->get_results( $sql ) as $row )
// Instantiate a custom object
* Get an array of all (loaded) IDs.
foreach( $this->cache as $obj )
* Add a dataobject to the cache
if( is_null($Obj->ID) ) // value 0 is used by item preview
$Debuglog->add( 'No object to add!', 'dataobjects' );
// fplanque: I don't want an extra (and expensive) comparison here. $this->cache[$Obj->ID] === $Obj.
// If you need this you're probably misusing the cache.
if( isset ($this->cache[$Obj->ID]) )
$Debuglog->add( $this->objtype. ': Object with ID '. $Obj->ID. ' is already cached', 'dataobjects' );
// If the object is valid and not already cached:
$this->cache[$Obj->ID] = & $Obj;
// Add a reference in the object list:
* Instantiate a DataObject from a table row and then cache it.
* @param Object Database row
{ // we can't access NULL as an object
// Get ID of the object we'ere preparing to instantiate...
if( is_null($obj_ID) ) // value 0 is used for item preview
if( isset ( $this->cache[$obj_ID] ) )
{ // Already in cache, do nothing!
{ // Already in shadow, recycle object:
{ // Not already cached, add new object:
return $this->cache[$obj_ID];
* Clear the cache **extensively**
function clear( $keep_shadow = false )
{ // Keep copy of cache in case we try to re instantiate previous object:
* This provides a simple interface for looping over the contents of the Cache.
* This should only be used for basic enumeration.
* If you need complex filtering of the cache contents, you should probablt use a DataObjectList instead.
* @see DataObject::get_next()
* This provides a simple interface for looping over the contents of the Cache.
* This should only be used for basic enumeration.
* If you need complex filtering of the cache contents, you should probablt use a DataObjectList instead.
* @see DataObject::get_first()
* Get an object from cache by ID
* Load the cache if necessary (all at once if allowed).
* @param integer ID of object to load
* @param boolean true if function should die on error
* @param boolean true if function should die on empty/null
* @return DataObject reference on cached object
function & get_by_ID( $req_ID, $halt_on_error = true, $halt_on_empty = true )
if( !empty( $this->cache[ $req_ID ] ) )
// $Debuglog->add( "Accessing $this->objtype($req_ID) from cache", 'dataobjects' );
return $this->cache[ $req_ID ];
{ // Not in cache, but not everything is loaded yet
{ // It's ok to just load everything:
{ // Load just the requested object:
$Debuglog->add( "Loading <strong>$this->objtype($req_ID)</strong> into cache", 'dataobjects' );
// Note: $req_ID MUST be an unsigned integer. This is how DataObject works.
if( $row = $DB->get_row( $sql, OBJECT, 0, 'DataObjectCache::get_by_ID()' ) )
$Debuglog->add( 'Could not add() object to cache!', 'dataobjects' );
$Debuglog->add( 'Could not get DataObject by ID. Query: '. $sql, 'dataobjects' );
if( empty( $this->cache[ $req_ID ] ) )
{ // Requested object does not exist
// $Debuglog->add( 'failure', 'dataobjects' );
return $this->cache[ $req_ID ];
* Get an object from cache by name
* Load the cache if necessary (all at once if allowed).
* @param integer ID of object to load
* @param boolean true if function should die on error
* @param boolean true if function should die on empty/null
* @return reference on cached object
function & get_by_name( $req_name, $halt_on_error = true, $halt_on_empty = true )
debug_die( 'DataObjectCache::get_by_name() : No name field to query on' );
// Load just the requested object:
$Debuglog->add( "Loading <strong>$this->objtype($req_name)</strong>", 'dataobjects' );
WHERE $this->name_field = ". $DB->quote($req_name);
if( $db_row = $DB->get_row( $sql, OBJECT, 0, 'DataObjectCache::get_by_name()' ) )
$resolved_ID = $db_row->{$this->dbIDname};
$Debuglog->add( 'success; ID = '. $resolved_ID, 'dataobjects' );
if( ! isset ( $this->cache[$resolved_ID] ) )
{ // Object is not already in cache:
$Debuglog->add( 'Adding to cache...', 'dataobjects' );
//$Obj = new $this->objtype( $row ); // COPY !!
//if( ! $this->add( $this->new_obj( $db_row ) ) )
$Debuglog->add( 'Could not add() object to cache!', 'dataobjects' );
return $this->cache[$resolved_ID];
$Debuglog->add( 'Could not get DataObject by name.', 'dataobjects' );
* Remove an object from cache by ID
* @param integer ID of object to remove
unset ( $this->cache[$req_ID] );
* Delete an object from DB by ID.
* @param integer ID of object to delete
if( isset ( $this->cache[$req_ID] ) )
$this->cache[$req_ID]->dbdelete();
* Returns form option list with cache contents
* Load the cache if necessary
* @param integer selected ID
* @param boolean provide a choice for "none" with ID ''
* @param string Callback method name
* @param array IDs to ignore.
function get_option_list( $default = 0, $allow_none = false, $method = 'get_name', $ignore_IDs = array() )
$default = array( $default );
{ // We have not loaded all items so far, but we're allowed to.
if ( empty( $ignore_IDs ) )
{ // only load those items not listed in $ignore_IDs
if( empty($default) ) $r .= ' selected="selected"';
foreach( $this->cache as $loop_Obj )
if ( in_array( $loop_Obj->ID, $ignore_IDs ) )
$r .= '<option value="'. $loop_Obj->ID. '"';
if( in_array( $loop_Obj->ID, $default ) ) $r .= ' selected="selected"';
* Returns option array with cache contents
* Load the cache if necessary
* @param string Callback method name
* @param array IDs to ignore.
{ // We have not loaded all items so far, but we're allowed to.
if ( empty( $ignore_IDs ) )
{ // only load those items not listed in $ignore_IDs
foreach( $this->cache as $loop_Obj )
if( in_array( $loop_Obj->ID, $ignore_IDs ) )
$r[$loop_Obj->ID] = $loop_Obj->$method();
|