b2evolution PHP Cross Reference Blogging Systems

Source: /inc/_core/model/dataobjects/_dataobjectcache.class.php - 951 lines - 23760 bytes - Summary - Text - Print

Description: This file implements the DataObjectCache class. 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 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-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)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 6136 2014-03-08 07:59:48Z manuel $
  38   */
  39  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  40  
  41  
  42  // DEBUG: (Turn switch on or off to log debug info for specified category)
  43  $GLOBALS['debug_dataobjects'] = false;
  44  
  45  
  46  load_class( '_core/model/db/_sql.class.php', 'SQL' );
  47  
  48  
  49  /**
  50   * Data Object Cache Class
  51   *
  52   * @todo dh> Provide iteration "interface"!
  53   *
  54   * @package evocore
  55   * @version beta
  56   */
  57  class DataObjectCache
  58  {
  59      var $dbtablename;
  60      var $dbprefix;
  61      var $dbIDname;
  62  
  63      /**
  64       * Class name of objects in this cache:
  65       */
  66      var $objtype;
  67  
  68      /**
  69       * Object array by ID
  70       */
  71      var $cache = array();
  72  
  73      /**
  74       * Copy of previous object array
  75       * @see DataObjectCache::clear()
  76       */
  77      var $shadow_cache = NULL;
  78  
  79      /**
  80       * NON indexed object array
  81       * @var array of DataObjects
  82       */
  83      var $DataObject_array = array();
  84  
  85      /**
  86       * Index of current iteration
  87       * @see DataObjectCache::get_next()
  88       */
  89      var $current_idx = 0;
  90  
  91      var $load_all = false;
  92      var $all_loaded = false;
  93  
  94  
  95      /**
  96       * @var string SQL name field (not necessarily with the object).
  97       */
  98      var $name_field;
  99  
 100      /**
 101       * @var string SQL ORDER BY.
 102       */
 103      var $order_by;
 104  
 105      /**
 106       * @var string SQL additional SELECT fields.
 107       */
 108      var $select;
 109  
 110      /**
 111       * The text that gets used for the "None" option in the objects options list.
 112       *
 113       * This is especially useful for i18n, because there are several "None"s!
 114       *
 115       * @var string
 116       */
 117      var $none_option_text;
 118  
 119      /**
 120       * The value that gets used for the "None" option in the objects options list.
 121       *
 122       * @var mixed
 123       */
 124      var $none_option_value;
 125  
 126      /**
 127       * List of object IDs.
 128       * @see get_ID_array()
 129       * @access protected
 130       */
 131      var $ID_array;
 132  
 133  
 134      /**
 135       * Constructor
 136       *
 137       * @param string Name of DataObject class we are caching
 138       * @param boolean true if it's OK to just load all items!
 139       * @param string Name of table in database
 140       * @param string Prefix of fields in the table
 141       * @param string Name of the ID field (including prefix)
 142       * @param string Name of the name field (including prefix)
 143       * @param string field names or NULL to use name field
 144       * @param string The text that gets used for the "None" option in the objects options list (Default: T_('None')).
 145       * @param mixed  The value that gets used for the "None" option in the objects options list.
 146       * @param string Additional part for SELECT clause of sql query
 147       */
 148  	function DataObjectCache( $objtype, $load_all, $tablename, $prefix = '', $dbIDname, $name_field = NULL, $order_by = '', $allow_none_text = NULL, $allow_none_value = '', $select = '' )
 149      {
 150          $this->objtype = $objtype;
 151          $this->load_all = $load_all;
 152          $this->dbtablename = $tablename;
 153          $this->dbprefix = $prefix;
 154          $this->dbIDname = $dbIDname;
 155          $this->name_field = $name_field;
 156          $this->none_option_value = $allow_none_value;
 157          $this->select = $select;
 158  
 159          if( empty( $order_by ) )
 160          {
 161              if( empty( $name_field ) )
 162              {
 163                  $this->order_by = $dbIDname;
 164              }
 165              else
 166              {
 167                  $this->order_by = $name_field;
 168              }
 169          }
 170          else
 171          {
 172              $this->order_by = $order_by;
 173          }
 174  
 175          if( isset($allow_none_text) )
 176          {
 177              $this->none_option_text = $allow_none_text;
 178          }
 179          else
 180          {
 181              $this->none_option_text = /* TRANS: the default value for option lists where "None" is allowed */ T_('None');
 182          }
 183      }
 184  
 185  
 186      /**
 187       * Instanciate a new object within this cache.
 188       *
 189       * This is used by {@link instantiate()} to get the object which then gets passed to {@link add()}.
 190       *
 191       * @param object DB row
 192       */
 193      function & new_obj( $row = NULL )
 194      {
 195          $objtype = $this->objtype;
 196  
 197          // Instantiate a custom object
 198          $obj = new $objtype( $row ); // COPY !!
 199  
 200          return $obj;
 201      }
 202  
 203  
 204      /**
 205       * Load the cache **extensively**
 206       */
 207  	function load_all()
 208      {
 209          /**
 210           * @var DB
 211           */
 212          global $DB;
 213          global $Debuglog;
 214  
 215          if( $this->all_loaded )
 216          { // Already loaded
 217              return false;
 218          }
 219  
 220          $this->clear( true );
 221  
 222          $Debuglog->add( get_class($this).' - Loading <strong>'.$this->objtype.'(ALL)</strong> into cache', 'dataobjects' );
 223  
 224          $SQL = $this->get_SQL_object('Loading '.$this->objtype.'(ALL) into cache');
 225          $this->load_by_sql($SQL);
 226  
 227          $this->all_loaded = true;
 228  
 229          return true;
 230      }
 231  
 232  
 233      /**
 234       * Load a list of objects into the cache.
 235       *
 236       * @param array List of IDs of objects to load
 237       * @param boolean Invert list: Load all objects except those listed in the first parameter
 238       */
 239  	function load_list( $req_list, $invert = false )
 240      {
 241          global $Debuglog;
 242  
 243          if( ! $invert )
 244              $req_list = array_diff($req_list, $this->get_ID_array());
 245  
 246          if( empty( $req_list ) )
 247              return false;
 248  
 249          $SQL = $this->get_SQL_object();
 250          $SQL->WHERE_and($this->dbIDname.( $invert ? ' NOT' : '' ).' IN ('.implode(',', $req_list).')');
 251  
 252          return $this->load_by_sql($SQL);
 253      }
 254  
 255  
 256      /**
 257       * Load a set of objects into the cache.
 258       *
 259       * @param string SQL where expression
 260       */
 261  	function load_where( $sql_where )
 262      {
 263          $SQL = $this->get_SQL_object();
 264          $SQL->WHERE($sql_where);
 265          return $this->load_by_sql($SQL);
 266      }
 267  
 268  
 269      /**
 270       * Load a set of objects into the cache.
 271       * Already loaded objects get excluded via "NOT IN()"
 272       *
 273       * @param SQL SQL object
 274       * @return array List of DataObjects
 275       */
 276  	function load_by_sql( $SQL )
 277      {
 278          global $DB, $Debuglog;
 279  
 280          if( is_a($Debuglog, 'Log') )
 281          {
 282              $sql_where = trim($SQL->get_where(''));
 283              if( empty($sql_where) )
 284                  $sql_where = 'ALL';
 285              $Debuglog->add( 'Loading <strong>'.$this->objtype.'('.$sql_where.')</strong> into cache', 'dataobjects' );
 286          }
 287  
 288          // Do not request already loaded objects
 289          if( $loaded_IDs = $this->get_ID_array() )
 290          {
 291              $SQL->WHERE_and($this->dbIDname.' NOT IN ('.implode(',', $loaded_IDs).')');
 292          }
 293  
 294          return $this->instantiate_list($DB->get_results( $SQL->get(), OBJECT, $SQL->title ));
 295      }
 296  
 297  
 298      /**
 299       * Get base SQL object for queries.
 300       * This gets used internally and is a convenient method for derived caches to override SELECT behaviour.
 301       * @param string Optional query title
 302       * @return SQL
 303       */
 304  	function get_SQL_object($title = NULL)
 305      {
 306          $select = '';
 307          if( !empty( $this->select ) )
 308          {    // Additional select fields
 309              $select = ', '.$this->select;
 310          }
 311          $SQL = new SQL( $title );
 312          $SQL->SELECT( '*'.$select );
 313          $SQL->FROM( $this->dbtablename );
 314          $SQL->ORDER_BY( $this->order_by );
 315          return $SQL;
 316      }
 317  
 318  
 319      /**
 320       * Get list of objects, referenced by list of IDs.
 321       * @param array
 322       * @return array
 323       */
 324  	function get_list( $ids )
 325      {
 326          $this->load_list($ids);
 327          $r = array();
 328          foreach( $ids as $id )
 329          {
 330              $r[] = $this->get_by_ID($id);
 331          }
 332          return $r;
 333      }
 334  
 335  
 336      /**
 337       * Get an array of all (loaded) IDs.
 338       *
 339       * @return array
 340       */
 341  	function get_ID_array()
 342      {
 343          if( ! isset($this->ID_array) )
 344          {
 345              $this->ID_array = array();
 346              foreach( $this->cache as $obj )
 347              {
 348                  $this->ID_array[] = $obj->ID;
 349              }
 350          }
 351  
 352          return $this->ID_array;
 353      }
 354  
 355  
 356      /**
 357       * Add a dataobject to the cache
 358       */
 359  	function add( & $Obj )
 360      {
 361          global $Debuglog;
 362  
 363          if( is_null($Obj->ID) )    // value 0 is used by item preview
 364          {
 365              $Debuglog->add( 'No object to add!', 'dataobjects' );
 366              return false;
 367          }
 368  
 369          // fplanque: I don't want an extra (and expensive) comparison here. $this->cache[$Obj->ID] === $Obj.
 370          // If you need this you're probably misusing the cache.
 371          if( isset($this->cache[$Obj->ID]) )
 372          {
 373              $Debuglog->add( $this->objtype.': Object with ID '.$Obj->ID.' is already cached', 'dataobjects' );
 374              return false;
 375          }
 376  
 377          // If the object is valid and not already cached:
 378          // Add object to cache:
 379          $this->cache[$Obj->ID] = & $Obj;
 380          // Add a reference in the object list:
 381          $this->DataObject_array[] = & $Obj;
 382          // Add the ID to the list of IDs
 383          $this->ID_array[] = $Obj->ID;
 384  
 385          return true;
 386      }
 387  
 388  
 389      /**
 390       * Instantiate a DataObject from a table row and then cache it.
 391       *
 392       * @param Object Database row
 393       * @return Object
 394       */
 395      function & instantiate( & $db_row )
 396      {
 397          if( is_null($db_row) )
 398          {    // we can't access NULL as an object
 399              return $db_row;
 400          }
 401  
 402          // Get ID of the object we'ere preparing to instantiate...
 403          $obj_ID = $db_row->{$this->dbIDname};
 404  
 405          if( is_null($obj_ID) )    // value 0 is used for item preview
 406          {
 407              $Obj = NULL;
 408              return $Obj;
 409          }
 410  
 411          if( isset( $this->cache[$obj_ID] ) )
 412          { // Already in cache, do nothing!
 413          }
 414          elseif( isset( $this->shadow_cache[$obj_ID] ) )
 415          {    // Already in shadow, recycle object:
 416              // echo "adding shadow {$this->objtype} $obj_ID ";
 417              $this->add( $this->shadow_cache[$obj_ID] );
 418          }
 419          else
 420          { // Not already cached, add new object:
 421              // echo "adding new {$this->objtype} $obj_ID ";
 422              $this->add( $this->new_obj( $db_row ) );
 423          }
 424  
 425  /* fp>blueyed: yes move that to add()!
 426          // Add to named cache:
 427          if( ! empty($this->name_field) )
 428          { // NOTE: this should get done in add() really, but there the mapping of $name_field => object property is not given.
 429              //       (handled by DataObject constructors).
 430              $this->cache_name[$db_row->{$this->name_field}] = & $this->cache[$obj_ID];
 431          }
 432  */
 433  
 434          return $this->cache[$obj_ID];
 435      }
 436  
 437  
 438      /**
 439       * @access public
 440       * @param array List of DB rows
 441       * @return array List of DataObjects
 442       */
 443  	function instantiate_list($db_rows)
 444      {
 445          $r = array();
 446          foreach( $db_rows as $db_row )
 447          {
 448              $r[] = $this->instantiate($db_row);
 449          }
 450          return $r;
 451      }
 452  
 453  
 454      /**
 455       * Clear the cache **extensively**
 456       *
 457       */
 458  	function clear( $keep_shadow = false )
 459      {
 460          if( $keep_shadow )
 461          {    // Keep copy of cache in case we try to re instantiate previous object:
 462              $this->shadow_cache = $this->cache;
 463          }
 464          else
 465          {
 466              $this->shadow_cache = NULL;
 467          }
 468  
 469          $this->cache = array();
 470          $this->DataObject_array = array();
 471          $this->all_loaded = false;
 472          $this->ID_array = NULL;
 473          $this->rewind();
 474      }
 475  
 476  
 477    /**
 478       * This provides a simple interface for looping over the contents of the Cache.
 479       *
 480       * This should only be used for basic enumeration.
 481       * If you need complex filtering of the cache contents, you should probably use a DataObjectList instead.
 482       *
 483       * @see DataObject::get_next()
 484       *
 485       * @return DataObject
 486       */
 487      function & get_first()
 488      {
 489          $this->load_all();
 490  
 491          $this->rewind();
 492          return $this->get_next();
 493      }
 494  
 495  
 496      /**
 497       * Rewind internal index to first position.
 498       * @access public
 499       */
 500  	function rewind()
 501      {
 502          $this->current_idx = 0;
 503      }
 504  
 505  
 506    /**
 507       * This provides a simple interface for looping over the contents of the Cache.
 508       *
 509       * This should only be used for basic enumeration.
 510       * If you need complex filtering of the cache contents, you should probably use a DataObjectList instead.
 511       *
 512       * @see DataObject::get_first()
 513       *
 514       * @return DataObject
 515       */
 516      function & get_next()
 517      {
 518          // echo 'getting idx:'.$this->current_idx;
 519  
 520          if( ! isset( $this->DataObject_array[$this->current_idx] ) )
 521          {
 522              $this->rewind();
 523              $r = NULL;
 524              return $r;
 525          }
 526  
 527          return $this->DataObject_array[$this->current_idx++];
 528      }
 529  
 530  
 531      /**
 532       * Get an object from cache by ID
 533       *
 534       * Load the cache if necessary (all at once if allowed).
 535       *
 536       * @param integer ID of object to load
 537       * @param boolean true if function should die on error
 538       * @param boolean true if function should die on empty/null
 539       * @return DataObject reference on cached object or NULL if not found
 540       */
 541      function & get_by_ID( $req_ID, $halt_on_error = true, $halt_on_empty = true )
 542      {
 543          global $DB, $Debuglog;
 544  
 545          if( empty($req_ID) )
 546          {
 547              if($halt_on_empty)
 548              {
 549                  debug_die( "Requested $this->objtype from $this->dbtablename without ID!" );
 550              }
 551              $r = NULL;
 552              return $r;
 553          }
 554  
 555          if( !empty( $this->cache[ $req_ID ] ) )
 556          { // Already in cache
 557              // $Debuglog->add( "Accessing $this->objtype($req_ID) from cache", 'dataobjects' );
 558              return $this->cache[ $req_ID ];
 559          }
 560          elseif( !$this->all_loaded )
 561          { // Not in cache, but not everything is loaded yet
 562              if( $this->load_all )
 563              { // It's ok to just load everything:
 564                  $this->load_all();
 565              }
 566              else
 567              { // Load just the requested object:
 568                  $Debuglog->add( "Loading <strong>$this->objtype($req_ID)</strong> into cache", 'dataobjects' );
 569                  // Note: $req_ID MUST be an unsigned integer. This is how DataObject works.
 570                  $SQL = $this->get_SQL_object();
 571                  $SQL->WHERE_and("$this->dbIDname = $req_ID");
 572                  if( $row = $DB->get_row( $SQL->get(), OBJECT, 0, 'DataObjectCache::get_by_ID()' ) )
 573                  {
 574                      if( ! $this->instantiate( $row ) )
 575                      {
 576                          $Debuglog->add( 'Could not add() object to cache!', 'dataobjects' );
 577                      }
 578                  }
 579                  else
 580                  {
 581                      $Debuglog->add( 'Could not get DataObject by ID. Query: '.$SQL->get(), 'dataobjects' );
 582                  }
 583              }
 584          }
 585  
 586          if( empty( $this->cache[ $req_ID ] ) )
 587          { // Requested object does not exist
 588              // $Debuglog->add( 'failure', 'dataobjects' );
 589              if( $halt_on_error )
 590              {
 591                  debug_die( "Requested $this->objtype does not exist!" );
 592              }
 593              $r = false;
 594              return $r;
 595          }
 596  
 597          return $this->cache[ $req_ID ];
 598      }
 599  
 600  
 601      /**
 602       * Get an object from cache by name
 603       *
 604       * Load the cache if necessary (all at once if allowed).
 605       *
 606       * @param integer ID of object to load
 607       * @param boolean true if function should die on error
 608       * @param boolean true if function should die on empty/null
 609       * @return reference on cached object
 610       */
 611      function & get_by_name( $req_name, $halt_on_error = true, $halt_on_empty = true )
 612      {
 613          global $DB, $Debuglog;
 614  
 615          if( empty( $this->name_field ) )
 616          {
 617              debug_die( 'DataObjectCache::get_by_name() : No name field to query on' );
 618          }
 619  
 620          if( empty($req_name) )
 621          {
 622              if($halt_on_empty) { debug_die( "Requested $this->objtype from $this->dbtablename without name!" ); }
 623              $r = NULL;
 624              return $r;
 625          }
 626  
 627          // Load just the requested object:
 628          $Debuglog->add( "Loading <strong>$this->objtype($req_name)</strong>", 'dataobjects' );
 629          $SQL = $this->get_SQL_object();
 630          $SQL->WHERE_and($this->name_field.' = '.$DB->quote($req_name));
 631  
 632          if( $db_row = $DB->get_row( $SQL->get(), OBJECT, 0, 'DataObjectCache::get_by_name()' ) )
 633          {
 634              $resolved_ID = $db_row->{$this->dbIDname};
 635              $Debuglog->add( 'success; ID = '.$resolved_ID, 'dataobjects' );
 636              if( ! isset( $this->cache[$resolved_ID] ) )
 637              {    // Object is not already in cache:
 638                  $Debuglog->add( 'Adding to cache...', 'dataobjects' );
 639                  //$Obj = new $this->objtype( $row ); // COPY !!
 640                  //if( ! $this->add( $this->new_obj( $db_row ) ) )
 641                  if( ! $this->add( $this->new_obj( $db_row ) ) )
 642                  {    // could not add
 643                      $Debuglog->add( 'Could not add() object to cache!', 'dataobjects' );
 644                  }
 645              }
 646              return $this->cache[$resolved_ID];
 647          }
 648          else
 649          {
 650              $Debuglog->add( 'Could not get DataObject by name.', 'dataobjects' );
 651              if( $halt_on_error )
 652              {
 653                  debug_die( "Requested $this->objtype does not exist!" );
 654              }
 655              $r = NULL;
 656              return $r;
 657          }
 658  
 659  /* fp> code below  by blueyed, undocumented, except for cache insertion in instantiate which is self labeled as dirty
 660          if( isset($this->cache_name[$req_name]) )
 661          {
 662              return $this->cache_name[$req_name];
 663          }
 664  
 665          if( ! $this->all_loaded )
 666          {
 667              // Load just the requested object:
 668              $Debuglog->add( "Loading <strong>$this->objtype($req_name)</strong>", 'dataobjects' );
 669              $SQL = $this->get_SQL_object();
 670              $SQL->WHERE_and($this->name_field.' = '.$DB->quote($req_name));
 671  
 672              if( $db_row = $DB->get_row( $SQL->get(), OBJECT, 0, 'DataObjectCache::get_by_name()' ) )
 673              {
 674                  $resolved_ID = $db_row->{$this->dbIDname};
 675                  $Debuglog->add( 'success; ID = '.$resolved_ID, 'dataobjects' );
 676                  if( ! isset( $this->cache[$resolved_ID] ) )
 677                  {    // Object is not already in cache:
 678                      $Debuglog->add( 'Adding to cache...', 'dataobjects' );
 679                      //$Obj = new $this->objtype( $row ); // COPY !!
 680                      //if( ! $this->add( $this->new_obj( $db_row ) ) )
 681                      if( ! $this->add( $this->new_obj( $db_row ) ) )
 682                      {    // could not add
 683                          $Debuglog->add( 'Could not add() object to cache!', 'dataobjects' );
 684                      }
 685                  }
 686                  $this->cache_name[$req_name] = $this->cache[$resolved_ID];
 687                  return $this->cache[$resolved_ID];
 688              }
 689          }
 690  
 691          $Debuglog->add( 'Could not get DataObject by name.', 'dataobjects' );
 692          if( $halt_on_error )
 693          {
 694              debug_die( "Requested $this->objtype does not exist!" );
 695          }
 696          $r = NULL;
 697          return $r;
 698  */
 699      }
 700  
 701  
 702      /**
 703       * Remove an object from cache by ID
 704       *
 705       * @param integer ID of object to remove
 706       */
 707  	function remove_by_ID( $req_ID )
 708      {
 709          # if( ($k = array_search($this->ID_array, $req_ID)) !== false )
 710          #     unset($this->ID_array[$k]);
 711          $this->ID_array = NULL;
 712          unset( $this->cache[$req_ID] );
 713          // remove Obj with req_ID from DataObject_array
 714          $remove_index = 0;
 715          foreach( $this->DataObject_array as $DataObject )
 716          {
 717              if( $DataObject->ID == $req_ID )
 718              {
 719                  break;
 720              }
 721              $remove_index++;
 722          }
 723          unset( $this->DataObject_array[$remove_index] );
 724      }
 725  
 726  
 727      /**
 728       * Delete an object from DB by ID.
 729       *
 730       * @param integer ID of object to delete
 731       * @return boolean
 732       */
 733  	function dbdelete_by_ID( $req_ID )
 734      {
 735          if( isset( $this->cache[$req_ID] ) )
 736          {
 737              // Delete from db
 738              $this->cache[$req_ID]->dbdelete();
 739  
 740              // Remove from cache
 741              $this->remove_by_ID( $req_ID );
 742  
 743              return true;
 744          }
 745          else
 746          {
 747              return false;
 748          }
 749      }
 750  
 751  
 752      /**
 753       * Returns form option list with cache contents
 754       *
 755       * Load the cache if necessary
 756       *
 757       * @param integer|array selected ID(s) (list for multi-selects)
 758       * @param boolean provide a choice for "none" with ID ''
 759       * @param string Callback method name
 760       * @param array IDs to ignore.
 761       * @return string
 762       */
 763  	function get_option_list( $default = 0, $allow_none = false, $method = 'get_name', $ignore_IDs = array() )
 764      {
 765          if( !is_array( $default ) )
 766          {
 767              $default = array( $default );
 768          }
 769  
 770          if( ! $this->all_loaded && $this->load_all )
 771          { // We have not loaded all items so far, but we're allowed to.
 772              if ( empty( $ignore_IDs ) )
 773              {    // just load all items
 774                  $this->load_all();
 775              }
 776              else
 777              {    // only load those items not listed in $ignore_IDs
 778                  $this->load_list( $ignore_IDs, true );
 779              }
 780          }
 781  
 782          $r = '';
 783  
 784          if( $allow_none )
 785          {
 786              $r .= '<option value="'.$this->none_option_value.'"';
 787              if( empty($default) ) $r .= ' selected="selected"';
 788              $r .= '>'.format_to_output($this->none_option_text).'</option>'."\n";
 789          }
 790  
 791          foreach( $this->cache as $loop_Obj )
 792          {
 793              if ( in_array( $loop_Obj->ID, $ignore_IDs ) )
 794              {    // Ignore this ID
 795                  continue;
 796              }
 797  
 798              $r .=  '<option value="'.$loop_Obj->ID.'"';
 799              if( in_array( $loop_Obj->ID, $default ) ) $r .= ' selected="selected"';
 800              $r .= '>';
 801              $r .= format_to_output( $loop_Obj->$method(), 'htmlbody' );
 802              $r .=  '</option>'."\n";
 803          }
 804  
 805          return $r;
 806      }
 807  
 808      /**
 809       * Returns form option list with cache contents grouped by country preference
 810       *
 811       * Load the cache if necessary
 812       *
 813       * @param integer|array selected ID(s) (list for multi-selects)
 814       * @param boolean provide a choice for "none" with ID ''
 815       * @param string Callback method name
 816       * @param array IDs to ignore.
 817       * @return string
 818       */
 819  	function get_group_country_option_list( $default = 0, $allow_none = false, $method = 'get_name', $ignore_IDs = array() )
 820      {
 821          if( !is_array( $default ) )
 822          {
 823              $default = array( $default );
 824          }
 825  
 826          if( ! $this->all_loaded && $this->load_all )
 827          { // We have not loaded all items so far, but we're allowed to.
 828              if ( empty( $ignore_IDs ) )
 829              {    // just load all items
 830                  $this->load_all();
 831              }
 832              else
 833              {    // only load those items not listed in $ignore_IDs
 834                  $this->load_list( $ignore_IDs, true );
 835              }
 836          }
 837  
 838          $r = '';
 839  
 840          if( $allow_none )
 841          {    // we set current value of a country if it is sent to function
 842              $r .= '<option value="'.$this->none_option_value.'"';
 843              if( empty($default) ) $r .= ' selected="selected"';
 844              $r .= '>'.format_to_output($this->none_option_text).'</option>'."\n";
 845          }
 846  
 847          $pref_countries = array(); //preferred countries.
 848          $rest_countries = array(); // not preffered countries (the rest)
 849  
 850          foreach( $this->cache as $loop_Obj )
 851          {
 852              if ( in_array( $loop_Obj->ID, $ignore_IDs ) )
 853              {    // if we have ID of countries that we have to ignore we just do not include them here. 
 854                  //Ignore this ID
 855                  continue;
 856              }
 857  
 858              if($loop_Obj->preferred == 1)
 859              {  // if the country is preferred we add it to selected array.
 860                  $pref_countries[] = $loop_Obj;
 861              }
 862              $rest_countries[] = $loop_Obj;
 863  
 864          }
 865  
 866          if(count($pref_countries))
 867          {    // if we don't have preferred countries in this case we don't have to show optgroup
 868              // in option list
 869              $r .= '<optgroup label="'.T_('Frequent countries').'">';
 870              foreach( $pref_countries as $loop_Obj )
 871              {
 872                  $r .=  '<option value="'.$loop_Obj->ID.'"';
 873                  if( in_array( $loop_Obj->ID, $default ) ) $r .= ' selected="selected"';
 874                  $r .= '>';
 875                  $r .= format_to_output( $loop_Obj->$method(), 'htmlbody' );
 876                  $r .=  '</option>'."\n";
 877              }
 878              $r .= '</optgroup>';
 879  
 880              if(count($rest_countries))
 881              { // if we don't have rest countries we do not create optgroup for them
 882                  $r .= '<optgroup label="'.T_('Other countries').'">';
 883                  foreach( $rest_countries as $loop_Obj )
 884                  {
 885                      $r .=  '<option value="'.$loop_Obj->ID.'"';
 886                      if( in_array( $loop_Obj->ID, $default ) ) $r .= ' selected="selected"';
 887                      $r .= '>';
 888                      $r .= format_to_output( $loop_Obj->$method(), 'htmlbody' );
 889                      $r .=  '</option>'."\n";
 890                  }
 891                  $r .= '</optgroup>';
 892              }
 893          }
 894          else
 895          {    // if we have only rest countries we get here
 896              foreach( $rest_countries as $loop_Obj )
 897              {
 898                  $r .=  '<option value="'.$loop_Obj->ID.'"';
 899                  if( in_array( $loop_Obj->ID, $default ) ) $r .= ' selected="selected"';
 900                  $r .= '>';
 901                  $r .= format_to_output( $loop_Obj->$method(), 'htmlbody' );
 902                  $r .=  '</option>'."\n";
 903              }
 904          }
 905  
 906          return $r;
 907      }
 908  
 909  
 910  
 911      /**
 912       * Returns option array with cache contents
 913       *
 914       * Load the cache if necessary
 915       *
 916       * @param string Callback method name
 917       * @param array IDs to ignore.
 918       * @return string
 919       */
 920  	function get_option_array( $method = 'get_name', $ignore_IDs = array() )
 921      {
 922          if( ! $this->all_loaded && $this->load_all )
 923          { // We have not loaded all items so far, but we're allowed to.
 924              if ( empty( $ignore_IDs ) )
 925              {    // just load all items
 926                  $this->load_all();
 927              }
 928              else
 929              {    // only load those items not listed in $ignore_IDs
 930                  $this->load_list( $ignore_IDs, true );
 931              }
 932          }
 933  
 934          $r = array();
 935  
 936          foreach( $this->cache as $loop_Obj )
 937          {
 938              if( in_array( $loop_Obj->ID, $ignore_IDs ) )
 939              {    // Ignore this ID
 940                  continue;
 941              }
 942  
 943              $r[$loop_Obj->ID] = $loop_Obj->$method();
 944          }
 945  
 946          return $r;
 947      }
 948  
 949  }
 950  
 951  ?>

title

Description

title

Description

title

Description

title

title

Body