[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/adodb/ -> adodb-active-record.inc.php (source)

   1  <?php
   2  /*
   3  
   4  @version V5.19  23-Apr-2014  (c) 2000-2014 John Lim (jlim#natsoft.com). All rights reserved.
   5    Latest version is available at http://adodb.sourceforge.net
   6  
   7    Released under both BSD license and Lesser GPL library license.
   8    Whenever there is any discrepancy between the two licenses,
   9    the BSD license will take precedence.
  10  
  11    Active Record implementation. Superset of Zend Framework's.
  12  
  13    Version 0.92
  14  
  15    See http://www-128.ibm.com/developerworks/java/library/j-cb03076/?ca=dgr-lnxw01ActiveRecord
  16        for info on Ruby on Rails Active Record implementation
  17  */
  18  
  19  
  20  global $_ADODB_ACTIVE_DBS;
  21  global $ADODB_ACTIVE_CACHESECS; // set to true to enable caching of metadata such as field info
  22  global $ACTIVE_RECORD_SAFETY; // set to false to disable safety checks
  23  global $ADODB_ACTIVE_DEFVALS; // use default values of table definition when creating new active record.
  24  
  25  // array of ADODB_Active_DB's, indexed by ADODB_Active_Record->_dbat
  26  $_ADODB_ACTIVE_DBS = array();
  27  $ACTIVE_RECORD_SAFETY = true;
  28  $ADODB_ACTIVE_DEFVALS = false;
  29  $ADODB_ACTIVE_CACHESECS = 0;
  30  
  31  class ADODB_Active_DB {
  32      var $db; // ADOConnection
  33      var $tables; // assoc array of ADODB_Active_Table objects, indexed by tablename
  34  }
  35  
  36  class ADODB_Active_Table {
  37      var $name; // table name
  38      var $flds; // assoc array of adofieldobjs, indexed by fieldname
  39      var $keys; // assoc array of primary keys, indexed by fieldname
  40      var $_created; // only used when stored as a cached file
  41      var $_belongsTo = array();
  42      var $_hasMany = array();
  43  }
  44  
  45  // $db = database connection
  46  // $index = name of index - can be associative, for an example see
  47  //    http://phplens.com/lens/lensforum/msgs.php?id=17790
  48  // returns index into $_ADODB_ACTIVE_DBS
  49  function ADODB_SetDatabaseAdapter(&$db, $index=false)
  50  {
  51      global $_ADODB_ACTIVE_DBS;
  52  
  53          foreach($_ADODB_ACTIVE_DBS as $k => $d) {
  54              if (PHP_VERSION >= 5) {
  55                  if ($d->db === $db) return $k;
  56              } else {
  57                  if ($d->db->_connectionID === $db->_connectionID && $db->database == $d->db->database)
  58                      return $k;
  59              }
  60          }
  61  
  62          $obj = new ADODB_Active_DB();
  63          $obj->db = $db;
  64          $obj->tables = array();
  65  
  66          if ($index == false) $index = sizeof($_ADODB_ACTIVE_DBS);
  67  
  68  
  69          $_ADODB_ACTIVE_DBS[$index] = $obj;
  70  
  71          return sizeof($_ADODB_ACTIVE_DBS)-1;
  72  }
  73  
  74  
  75  class ADODB_Active_Record {
  76      static $_changeNames = true; // dynamically pluralize table names
  77      static $_quoteNames = false;
  78  
  79      static $_foreignSuffix = '_id'; //
  80      var $_dbat; // associative index pointing to ADODB_Active_DB eg. $ADODB_Active_DBS[_dbat]
  81      var $_table; // tablename, if set in class definition then use it as table name
  82      var $_tableat; // associative index pointing to ADODB_Active_Table, eg $ADODB_Active_DBS[_dbat]->tables[$this->_tableat]
  83      var $_where; // where clause set in Load()
  84      var $_saved = false; // indicates whether data is already inserted.
  85      var $_lasterr = false; // last error message
  86      var $_original = false; // the original values loaded or inserted, refreshed on update
  87  
  88      var $foreignName; // CFR: class name when in a relationship
  89  
  90      var $lockMode = ' for update '; // you might want to change to
  91  
  92  	static function UseDefaultValues($bool=null)
  93      {
  94      global $ADODB_ACTIVE_DEFVALS;
  95          if (isset($bool)) $ADODB_ACTIVE_DEFVALS = $bool;
  96          return $ADODB_ACTIVE_DEFVALS;
  97      }
  98  
  99      // should be static
 100  	static function SetDatabaseAdapter(&$db, $index=false)
 101      {
 102          return ADODB_SetDatabaseAdapter($db, $index);
 103      }
 104  
 105  
 106  	public function __set($name, $value)
 107      {
 108          $name = str_replace(' ', '_', $name);
 109          $this->$name = $value;
 110      }
 111  
 112      // php5 constructor
 113  	function __construct($table = false, $pkeyarr=false, $db=false)
 114      {
 115      global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS;
 116  
 117          if ($db == false && is_object($pkeyarr)) {
 118              $db = $pkeyarr;
 119              $pkeyarr = false;
 120          }
 121  
 122          if (!$table) {
 123              if (!empty($this->_table)) $table = $this->_table;
 124              else $table = $this->_pluralize(get_class($this));
 125          }
 126          $this->foreignName = strtolower(get_class($this)); // CFR: default foreign name
 127          if ($db) {
 128              $this->_dbat = ADODB_Active_Record::SetDatabaseAdapter($db);
 129          } else if (!isset($this->_dbat)) {
 130              if (sizeof($_ADODB_ACTIVE_DBS) == 0) $this->Error("No database connection set; use ADOdb_Active_Record::SetDatabaseAdapter(\$db)",'ADODB_Active_Record::__constructor');
 131              end($_ADODB_ACTIVE_DBS);
 132              $this->_dbat = key($_ADODB_ACTIVE_DBS);
 133          }
 134  
 135          $this->_table = $table;
 136          $this->_tableat = $table; # reserved for setting the assoc value to a non-table name, eg. the sql string in future
 137  
 138          $this->UpdateActiveTable($pkeyarr);
 139      }
 140  
 141  	function __wakeup()
 142      {
 143            $class = get_class($this);
 144            new $class;
 145      }
 146  
 147  	function _pluralize($table)
 148      {
 149          if (!ADODB_Active_Record::$_changeNames) return $table;
 150  
 151          $ut = strtoupper($table);
 152          $len = strlen($table);
 153          $lastc = $ut[$len-1];
 154          $lastc2 = substr($ut,$len-2);
 155          switch ($lastc) {
 156          case 'S':
 157              return $table.'es';
 158          case 'Y':
 159              return substr($table,0,$len-1).'ies';
 160          case 'X':
 161              return $table.'es';
 162          case 'H':
 163              if ($lastc2 == 'CH' || $lastc2 == 'SH')
 164                  return $table.'es';
 165          default:
 166              return $table.'s';
 167          }
 168      }
 169  
 170      // CFR Lamest singular inflector ever - @todo Make it real!
 171      // Note: There is an assumption here...and it is that the argument's length >= 4
 172  	function _singularize($tables)
 173      {
 174  
 175          if (!ADODB_Active_Record::$_changeNames) return $table;
 176  
 177          $ut = strtoupper($tables);
 178          $len = strlen($tables);
 179          if($ut[$len-1] != 'S')
 180              return $tables; // I know...forget oxen
 181          if($ut[$len-2] != 'E')
 182              return substr($tables, 0, $len-1);
 183          switch($ut[$len-3])
 184          {
 185              case 'S':
 186              case 'X':
 187                  return substr($tables, 0, $len-2);
 188              case 'I':
 189                  return substr($tables, 0, $len-3) . 'y';
 190              case 'H';
 191                  if($ut[$len-4] == 'C' || $ut[$len-4] == 'S')
 192                      return substr($tables, 0, $len-2);
 193              default:
 194                  return substr($tables, 0, $len-1); // ?
 195          }
 196      }
 197  
 198  	function hasMany($foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
 199      {
 200          $ar = new $foreignClass($foreignRef);
 201          $ar->foreignName = $foreignRef;
 202          $ar->UpdateActiveTable();
 203          $ar->foreignKey = ($foreignKey) ? $foreignKey : $foreignRef.ADODB_Active_Record::$_foreignSuffix;
 204          $table =& $this->TableInfo();
 205          $table->_hasMany[$foreignRef] = $ar;
 206      #    $this->$foreignRef = $this->_hasMany[$foreignRef]; // WATCHME Removed assignment by ref. to please __get()
 207      }
 208  
 209      // use when you don't want ADOdb to auto-pluralize tablename
 210  	static function TableHasMany($table, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
 211      {
 212          $ar = new ADODB_Active_Record($table);
 213          $ar->hasMany($foreignRef, $foreignKey, $foreignClass);
 214      }
 215  
 216      // use when you don't want ADOdb to auto-pluralize tablename
 217  	static function TableKeyHasMany($table, $tablePKey, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
 218      {
 219          if (!is_array($tablePKey)) $tablePKey = array($tablePKey);
 220          $ar = new ADODB_Active_Record($table,$tablePKey);
 221          $ar->hasMany($foreignRef, $foreignKey, $foreignClass);
 222      }
 223  
 224  
 225      // use when you want ADOdb to auto-pluralize tablename for you. Note that the class must already be defined.
 226      // e.g. class Person will generate relationship for table Persons
 227  	static function ClassHasMany($parentclass, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
 228      {
 229          $ar = new $parentclass();
 230          $ar->hasMany($foreignRef, $foreignKey, $foreignClass);
 231      }
 232  
 233  
 234  	function belongsTo($foreignRef,$foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
 235      {
 236          global $inflector;
 237  
 238          $ar = new $parentClass($this->_pluralize($foreignRef));
 239          $ar->foreignName = $foreignRef;
 240          $ar->parentKey = $parentKey;
 241          $ar->UpdateActiveTable();
 242          $ar->foreignKey = ($foreignKey) ? $foreignKey : $foreignRef.ADODB_Active_Record::$_foreignSuffix;
 243  
 244          $table =& $this->TableInfo();
 245          $table->_belongsTo[$foreignRef] = $ar;
 246      #    $this->$foreignRef = $this->_belongsTo[$foreignRef];
 247      }
 248  
 249  	static function ClassBelongsTo($class, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
 250      {
 251          $ar = new $class();
 252          $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
 253      }
 254  
 255  	static function TableBelongsTo($table, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
 256      {
 257          $ar = new ADOdb_Active_Record($table);
 258          $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
 259      }
 260  
 261  	static function TableKeyBelongsTo($table, $tablePKey, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
 262      {
 263          if (!is_array($tablePKey)) $tablePKey = array($tablePKey);
 264          $ar = new ADOdb_Active_Record($table, $tablePKey);
 265          $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
 266      }
 267  
 268  
 269      /**
 270       * __get Access properties - used for lazy loading
 271       *
 272       * @param mixed $name
 273       * @access protected
 274       * @return mixed
 275       */
 276  	 function __get($name)
 277      {
 278          return $this->LoadRelations($name, '', -1, -1);
 279      }
 280  
 281      /**
 282       * @param string $name
 283       * @param string $whereOrderBy : eg. ' AND field1 = value ORDER BY field2'
 284       * @param offset
 285       * @param limit
 286       * @return mixed
 287       */
 288  	function LoadRelations($name, $whereOrderBy='', $offset=-1,$limit=-1)
 289      {
 290          $extras = array();
 291          $table = $this->TableInfo();
 292          if ($limit >= 0) $extras['limit'] = $limit;
 293          if ($offset >= 0) $extras['offset'] = $offset;
 294  
 295          if (strlen($whereOrderBy))
 296              if (!preg_match('/^[ \n\r]*AND/i',$whereOrderBy))
 297                  if (!preg_match('/^[ \n\r]*ORDER[ \n\r]/i',$whereOrderBy))
 298                      $whereOrderBy = 'AND '.$whereOrderBy;
 299  
 300          if(!empty($table->_belongsTo[$name]))
 301          {
 302              $obj = $table->_belongsTo[$name];
 303              $columnName = $obj->foreignKey;
 304              if(empty($this->$columnName))
 305                  $this->$name = null;
 306              else
 307              {
 308                  if ($obj->parentKey) $key = $obj->parentKey;
 309                  else $key = reset($table->keys);
 310  
 311                  $arrayOfOne = $obj->Find($key.'='.$this->$columnName.' '.$whereOrderBy,false,false,$extras);
 312                  if ($arrayOfOne) {
 313                      $this->$name = $arrayOfOne[0];
 314                      return $arrayOfOne[0];
 315                  }
 316              }
 317          }
 318          if(!empty($table->_hasMany[$name]))
 319          {
 320              $obj = $table->_hasMany[$name];
 321              $key = reset($table->keys);
 322              $id = @$this->$key;
 323              if (!is_numeric($id)) {
 324                  $db = $this->DB();
 325                  $id = $db->qstr($id);
 326              }
 327              $objs = $obj->Find($obj->foreignKey.'='.$id. ' '.$whereOrderBy,false,false,$extras);
 328              if (!$objs) $objs = array();
 329              $this->$name = $objs;
 330              return $objs;
 331          }
 332  
 333          return array();
 334      }
 335      //////////////////////////////////
 336  
 337      // update metadata
 338  	function UpdateActiveTable($pkeys=false,$forceUpdate=false)
 339      {
 340      global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS , $ADODB_CACHE_DIR, $ADODB_ACTIVE_CACHESECS;
 341      global $ADODB_ACTIVE_DEFVALS,$ADODB_FETCH_MODE;
 342  
 343          $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
 344  
 345          $table = $this->_table;
 346          $tables = $activedb->tables;
 347          $tableat = $this->_tableat;
 348          if (!$forceUpdate && !empty($tables[$tableat])) {
 349  
 350              $acttab = $tables[$tableat];
 351              foreach($acttab->flds as $name => $fld) {
 352              if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value))
 353                  $this->$name = $fld->default_value;
 354              else
 355                  $this->$name = null;
 356              }
 357              return;
 358          }
 359          $db = $activedb->db;
 360          $fname = $ADODB_CACHE_DIR . '/adodb_' . $db->databaseType . '_active_'. $table . '.cache';
 361          if (!$forceUpdate && $ADODB_ACTIVE_CACHESECS && $ADODB_CACHE_DIR && file_exists($fname)) {
 362              $fp = fopen($fname,'r');
 363              @flock($fp, LOCK_SH);
 364              $acttab = unserialize(fread($fp,100000));
 365              fclose($fp);
 366              if ($acttab->_created + $ADODB_ACTIVE_CACHESECS - (abs(rand()) % 16) > time()) {
 367                  // abs(rand()) randomizes deletion, reducing contention to delete/refresh file
 368                  // ideally, you should cache at least 32 secs
 369  
 370                  foreach($acttab->flds as $name => $fld) {
 371                      if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value))
 372                          $this->$name = $fld->default_value;
 373                      else
 374                          $this->$name = null;
 375                  }
 376  
 377                  $activedb->tables[$table] = $acttab;
 378  
 379                  //if ($db->debug) ADOConnection::outp("Reading cached active record file: $fname");
 380                    return;
 381              } else if ($db->debug) {
 382                  ADOConnection::outp("Refreshing cached active record file: $fname");
 383              }
 384          }
 385          $activetab = new ADODB_Active_Table();
 386          $activetab->name = $table;
 387  
 388          $save = $ADODB_FETCH_MODE;
 389          $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
 390          if ($db->fetchMode !== false) $savem = $db->SetFetchMode(false);
 391  
 392          $cols = $db->MetaColumns($table);
 393  
 394          if (isset($savem)) $db->SetFetchMode($savem);
 395          $ADODB_FETCH_MODE = $save;
 396  
 397          if (!$cols) {
 398              $this->Error("Invalid table name: $table",'UpdateActiveTable');
 399              return false;
 400          }
 401          $fld = reset($cols);
 402          if (!$pkeys) {
 403              if (isset($fld->primary_key)) {
 404                  $pkeys = array();
 405                  foreach($cols as $name => $fld) {
 406                      if (!empty($fld->primary_key)) $pkeys[] = $name;
 407                  }
 408              } else
 409                  $pkeys = $this->GetPrimaryKeys($db, $table);
 410          }
 411          if (empty($pkeys)) {
 412              $this->Error("No primary key found for table $table",'UpdateActiveTable');
 413              return false;
 414          }
 415  
 416          $attr = array();
 417          $keys = array();
 418  
 419          switch($ADODB_ASSOC_CASE) {
 420          case 0:
 421              foreach($cols as $name => $fldobj) {
 422                  $name = strtolower($name);
 423                  if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value))
 424                      $this->$name = $fldobj->default_value;
 425                  else
 426                      $this->$name = null;
 427                  $attr[$name] = $fldobj;
 428              }
 429              foreach($pkeys as $k => $name) {
 430                  $keys[strtolower($name)] = strtolower($name);
 431              }
 432              break;
 433  
 434          case 1:
 435              foreach($cols as $name => $fldobj) {
 436                  $name = strtoupper($name);
 437  
 438                  if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value))
 439                      $this->$name = $fldobj->default_value;
 440                  else
 441                      $this->$name = null;
 442                  $attr[$name] = $fldobj;
 443              }
 444  
 445              foreach($pkeys as $k => $name) {
 446                  $keys[strtoupper($name)] = strtoupper($name);
 447              }
 448              break;
 449          default:
 450              foreach($cols as $name => $fldobj) {
 451                  $name = ($fldobj->name);
 452  
 453                  if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value))
 454                      $this->$name = $fldobj->default_value;
 455                  else
 456                      $this->$name = null;
 457                  $attr[$name] = $fldobj;
 458              }
 459              foreach($pkeys as $k => $name) {
 460                  $keys[$name] = $cols[$name]->name;
 461              }
 462              break;
 463          }
 464  
 465          $activetab->keys = $keys;
 466          $activetab->flds = $attr;
 467  
 468          if ($ADODB_ACTIVE_CACHESECS && $ADODB_CACHE_DIR) {
 469              $activetab->_created = time();
 470              $s = serialize($activetab);
 471              if (!function_exists('adodb_write_file')) include (ADODB_DIR.'/adodb-csvlib.inc.php');
 472              adodb_write_file($fname,$s);
 473          }
 474          if (isset($activedb->tables[$table])) {
 475              $oldtab = $activedb->tables[$table];
 476  
 477              if ($oldtab) $activetab->_belongsTo = $oldtab->_belongsTo;
 478              if ($oldtab) $activetab->_hasMany = $oldtab->_hasMany;
 479          }
 480          $activedb->tables[$table] = $activetab;
 481      }
 482  
 483  	function GetPrimaryKeys(&$db, $table)
 484      {
 485          return $db->MetaPrimaryKeys($table);
 486      }
 487  
 488      // error handler for both PHP4+5.
 489  	function Error($err,$fn)
 490      {
 491      global $_ADODB_ACTIVE_DBS;
 492  
 493          $fn = get_class($this).'::'.$fn;
 494          $this->_lasterr = $fn.': '.$err;
 495  
 496          if ($this->_dbat < 0) $db = false;
 497          else {
 498              $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
 499              $db = $activedb->db;
 500          }
 501  
 502          if (function_exists('adodb_throw')) {
 503              if (!$db) adodb_throw('ADOdb_Active_Record', $fn, -1, $err, 0, 0, false);
 504              else adodb_throw($db->databaseType, $fn, -1, $err, 0, 0, $db);
 505          } else
 506              if (!$db || $db->debug) ADOConnection::outp($this->_lasterr);
 507  
 508      }
 509  
 510      // return last error message
 511  	function ErrorMsg()
 512      {
 513          if (!function_exists('adodb_throw')) {
 514              if ($this->_dbat < 0) $db = false;
 515              else $db = $this->DB();
 516  
 517              // last error could be database error too
 518              if ($db && $db->ErrorMsg()) return $db->ErrorMsg();
 519          }
 520          return $this->_lasterr;
 521      }
 522  
 523  	function ErrorNo()
 524      {
 525          if ($this->_dbat < 0) return -9999; // no database connection...
 526          $db = $this->DB();
 527  
 528          return (int) $db->ErrorNo();
 529      }
 530  
 531  
 532      // retrieve ADOConnection from _ADODB_Active_DBs
 533      function DB()
 534      {
 535      global $_ADODB_ACTIVE_DBS;
 536  
 537          if ($this->_dbat < 0) {
 538              $false = false;
 539              $this->Error("No database connection set: use ADOdb_Active_Record::SetDatabaseAdaptor(\$db)", "DB");
 540              return $false;
 541          }
 542          $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
 543          $db = $activedb->db;
 544          return $db;
 545      }
 546  
 547      // retrieve ADODB_Active_Table
 548      function &TableInfo()
 549      {
 550      global $_ADODB_ACTIVE_DBS;
 551          $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
 552          $table = $activedb->tables[$this->_tableat];
 553          return $table;
 554      }
 555  
 556  
 557      // I have an ON INSERT trigger on a table that sets other columns in the table.
 558      // So, I find that for myTable, I want to reload an active record after saving it. -- Malcolm Cook
 559  	function Reload()
 560      {
 561          $db =& $this->DB(); if (!$db) return false;
 562          $table =& $this->TableInfo();
 563          $where = $this->GenWhere($db, $table);
 564          return($this->Load($where));
 565      }
 566  
 567  
 568      // set a numeric array (using natural table field ordering) as object properties
 569  	function Set(&$row)
 570      {
 571      global $ACTIVE_RECORD_SAFETY;
 572  
 573          $db = $this->DB();
 574  
 575          if (!$row) {
 576              $this->_saved = false;
 577              return false;
 578          }
 579  
 580          $this->_saved = true;
 581  
 582          $table = $this->TableInfo();
 583          if ($ACTIVE_RECORD_SAFETY && sizeof($table->flds) != sizeof($row)) {
 584              # <AP>
 585              $bad_size = TRUE;
 586              if (sizeof($row) == 2 * sizeof($table->flds)) {
 587                  // Only keep string keys
 588                  $keys = array_filter(array_keys($row), 'is_string');
 589                  if (sizeof($keys) == sizeof($table->flds))
 590                      $bad_size = FALSE;
 591              }
 592              if ($bad_size) {
 593              $this->Error("Table structure of $this->_table has changed","Load");
 594              return false;
 595          }
 596              # </AP>
 597          }
 598          else
 599              $keys = array_keys($row);
 600  
 601          # <AP>
 602          reset($keys);
 603          $this->_original = array();
 604          foreach($table->flds as $name=>$fld) {
 605              $value = $row[current($keys)];
 606              $this->$name = $value;
 607              $this->_original[] = $value;
 608              next($keys);
 609          }
 610  
 611          # </AP>
 612          return true;
 613      }
 614  
 615      // get last inserted id for INSERT
 616  	function LastInsertID(&$db,$fieldname)
 617      {
 618          if ($db->hasInsertID)
 619              $val = $db->Insert_ID($this->_table,$fieldname);
 620          else
 621              $val = false;
 622  
 623          if (is_null($val) || $val === false) {
 624              // this might not work reliably in multi-user environment
 625              return $db->GetOne("select max(".$fieldname.") from ".$this->_table);
 626          }
 627          return $val;
 628      }
 629  
 630      // quote data in where clause
 631  	function doquote(&$db, $val,$t)
 632      {
 633          switch($t) {
 634          case 'L':
 635              if (strpos($db->databaseType,'postgres') !== false) return $db->qstr($val);
 636          case 'D':
 637          case 'T':
 638              if (empty($val)) return 'null';
 639  
 640          case 'B':
 641          case 'N':
 642          case 'C':
 643          case 'X':
 644              if (is_null($val)) return 'null';
 645  
 646              if (strlen($val)>0 &&
 647                  (strncmp($val,"'",1) != 0 || substr($val,strlen($val)-1,1) != "'")) {
 648                  return $db->qstr($val);
 649                  break;
 650              }
 651          default:
 652              return $val;
 653              break;
 654          }
 655      }
 656  
 657      // generate where clause for an UPDATE/SELECT
 658  	function GenWhere(&$db, &$table)
 659      {
 660          $keys = $table->keys;
 661          $parr = array();
 662  
 663          foreach($keys as $k) {
 664              $f = $table->flds[$k];
 665              if ($f) {
 666                  $parr[] = $k.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type));
 667              }
 668          }
 669          return implode(' and ', $parr);
 670      }
 671  
 672  
 673  	function _QName($n,$db=false)
 674      {
 675          if (!ADODB_Active_Record::$_quoteNames) return $n;
 676          if (!$db) $db = $this->DB(); if (!$db) return false;
 677          return $db->nameQuote.$n.$db->nameQuote;
 678      }
 679  
 680      //------------------------------------------------------------ Public functions below
 681  
 682  	function Load($where=null,$bindarr=false, $lock = false)
 683      {
 684      global $ADODB_FETCH_MODE;
 685  
 686          $db = $this->DB(); if (!$db) return false;
 687          $this->_where = $where;
 688  
 689          $save = $ADODB_FETCH_MODE;
 690          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 691          if ($db->fetchMode !== false) $savem = $db->SetFetchMode(false);
 692  
 693          $qry = "select * from ".$this->_table;
 694  
 695          if($where) {
 696              $qry .= ' WHERE '.$where;
 697          }
 698          if ($lock) $qry .= $this->lockMode;
 699  
 700          $row = $db->GetRow($qry,$bindarr);
 701  
 702          if (isset($savem)) $db->SetFetchMode($savem);
 703          $ADODB_FETCH_MODE = $save;
 704  
 705          return $this->Set($row);
 706      }
 707  
 708  	function LoadLocked($where=null, $bindarr=false)
 709      {
 710          $this->Load($where,$bindarr,true);
 711      }
 712  
 713      # useful for multiple record inserts
 714      # see http://phplens.com/lens/lensforum/msgs.php?id=17795
 715  	function Reset()
 716      {
 717          $this->_where=null;
 718          $this->_saved = false;
 719          $this->_lasterr = false;
 720          $this->_original = false;
 721          $vars=get_object_vars($this);
 722          foreach($vars as $k=>$v){
 723              if(substr($k,0,1)!=='_'){
 724                  $this->{$k}=null;
 725              }
 726          }
 727          $this->foreignName=strtolower(get_class($this));
 728          return true;
 729      }
 730  
 731      // false on error
 732  	function Save()
 733      {
 734          if ($this->_saved) $ok = $this->Update();
 735          else $ok = $this->Insert();
 736  
 737          return $ok;
 738      }
 739  
 740  
 741      // false on error
 742  	function Insert()
 743      {
 744          $db = $this->DB(); if (!$db) return false;
 745          $cnt = 0;
 746          $table = $this->TableInfo();
 747  
 748          $valarr = array();
 749          $names = array();
 750          $valstr = array();
 751  
 752          foreach($table->flds as $name=>$fld) {
 753              $val = $this->$name;
 754              if(!is_array($val) || !is_null($val) || !array_key_exists($name, $table->keys)) {
 755                  $valarr[] = $val;
 756                  $names[] = $this->_QName($name,$db);
 757                  $valstr[] = $db->Param($cnt);
 758                  $cnt += 1;
 759              }
 760          }
 761  
 762          if (empty($names)){
 763              foreach($table->flds as $name=>$fld) {
 764                  $valarr[] = null;
 765                  $names[] = $name;
 766                  $valstr[] = $db->Param($cnt);
 767                  $cnt += 1;
 768              }
 769          }
 770          $sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')';
 771          $ok = $db->Execute($sql,$valarr);
 772  
 773          if ($ok) {
 774              $this->_saved = true;
 775              $autoinc = false;
 776              foreach($table->keys as $k) {
 777                  if (is_null($this->$k)) {
 778                      $autoinc = true;
 779                      break;
 780                  }
 781              }
 782              if ($autoinc && sizeof($table->keys) == 1) {
 783                  $k = reset($table->keys);
 784                  $this->$k = $this->LastInsertID($db,$k);
 785              }
 786          }
 787  
 788          $this->_original = $valarr;
 789          return !empty($ok);
 790      }
 791  
 792  	function Delete()
 793      {
 794          $db = $this->DB(); if (!$db) return false;
 795          $table = $this->TableInfo();
 796  
 797          $where = $this->GenWhere($db,$table);
 798          $sql = 'DELETE FROM '.$this->_table.' WHERE '.$where;
 799          $ok = $db->Execute($sql);
 800  
 801          return $ok ? true : false;
 802      }
 803  
 804      // returns an array of active record objects
 805  	function Find($whereOrderBy,$bindarr=false,$pkeysArr=false,$extra=array())
 806      {
 807          $db = $this->DB(); if (!$db || empty($this->_table)) return false;
 808          $arr = $db->GetActiveRecordsClass(get_class($this),$this->_table, $whereOrderBy,$bindarr,$pkeysArr,$extra);
 809          return $arr;
 810      }
 811  
 812      // returns 0 on error, 1 on update, 2 on insert
 813  	function Replace()
 814      {
 815      global $ADODB_ASSOC_CASE;
 816  
 817          $db = $this->DB(); if (!$db) return false;
 818          $table = $this->TableInfo();
 819  
 820          $pkey = $table->keys;
 821  
 822          foreach($table->flds as $name=>$fld) {
 823              $val = $this->$name;
 824              /*
 825              if (is_null($val)) {
 826                  if (isset($fld->not_null) && $fld->not_null) {
 827                      if (isset($fld->default_value) && strlen($fld->default_value)) continue;
 828                      else {
 829                          $this->Error("Cannot update null into $name","Replace");
 830                          return false;
 831                      }
 832                  }
 833              }*/
 834              if (is_null($val) && !empty($fld->auto_increment)) {
 835                  continue;
 836              }
 837  
 838              if (is_array($val)) continue;
 839  
 840              $t = $db->MetaType($fld->type);
 841              $arr[$name] = $this->doquote($db,$val,$t);
 842              $valarr[] = $val;
 843          }
 844  
 845          if (!is_array($pkey)) $pkey = array($pkey);
 846  
 847  
 848          if ($ADODB_ASSOC_CASE == 0)
 849              foreach($pkey as $k => $v)
 850                  $pkey[$k] = strtolower($v);
 851          elseif ($ADODB_ASSOC_CASE == 1)
 852              foreach($pkey as $k => $v)
 853                  $pkey[$k] = strtoupper($v);
 854  
 855          $ok = $db->Replace($this->_table,$arr,$pkey);
 856          if ($ok) {
 857              $this->_saved = true; // 1= update 2=insert
 858              if ($ok == 2) {
 859                  $autoinc = false;
 860                  foreach($table->keys as $k) {
 861                      if (is_null($this->$k)) {
 862                          $autoinc = true;
 863                          break;
 864                      }
 865                  }
 866                  if ($autoinc && sizeof($table->keys) == 1) {
 867                      $k = reset($table->keys);
 868                      $this->$k = $this->LastInsertID($db,$k);
 869                  }
 870              }
 871  
 872              $this->_original = $valarr;
 873          }
 874          return $ok;
 875      }
 876  
 877      // returns 0 on error, 1 on update, -1 if no change in data (no update)
 878  	function Update()
 879      {
 880          $db = $this->DB(); if (!$db) return false;
 881          $table = $this->TableInfo();
 882  
 883          $where = $this->GenWhere($db, $table);
 884  
 885          if (!$where) {
 886              $this->error("Where missing for table $table", "Update");
 887              return false;
 888          }
 889          $valarr = array();
 890          $neworig = array();
 891          $pairs = array();
 892          $i = -1;
 893          $cnt = 0;
 894          foreach($table->flds as $name=>$fld) {
 895              $i += 1;
 896              $val = $this->$name;
 897              $neworig[] = $val;
 898  
 899              if (isset($table->keys[$name]) || is_array($val))
 900                  continue;
 901  
 902              if (is_null($val)) {
 903                  if (isset($fld->not_null) && $fld->not_null) {
 904                      if (isset($fld->default_value) && strlen($fld->default_value)) continue;
 905                      else {
 906                          $this->Error("Cannot set field $name to NULL","Update");
 907                          return false;
 908                      }
 909                  }
 910              }
 911  
 912              if (isset($this->_original[$i]) && strcmp($val,$this->_original[$i]) == 0) continue;
 913  
 914              if (is_null($this->_original[$i]) && is_null($val)) continue;
 915  
 916              $valarr[] = $val;
 917              $pairs[] = $this->_QName($name,$db).'='.$db->Param($cnt);
 918              $cnt += 1;
 919          }
 920  
 921  
 922          if (!$cnt) return -1;
 923          $sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where;
 924          $ok = $db->Execute($sql,$valarr);
 925          if ($ok) {
 926              $this->_original = $neworig;
 927              return 1;
 928          }
 929          return 0;
 930      }
 931  
 932  	function GetAttributeNames()
 933      {
 934          $table = $this->TableInfo();
 935          if (!$table) return false;
 936          return array_keys($table->flds);
 937      }
 938  
 939  };
 940  
 941  function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr, $primkeyArr,
 942              $extra)
 943  {
 944  global $_ADODB_ACTIVE_DBS;
 945  
 946  
 947      $save = $db->SetFetchMode(ADODB_FETCH_NUM);
 948      $qry = "select * from ".$table;
 949  
 950      if (!empty($whereOrderBy))
 951          $qry .= ' WHERE '.$whereOrderBy;
 952      if(isset($extra['limit']))
 953      {
 954          $rows = false;
 955          if(isset($extra['offset'])) {
 956              $rs = $db->SelectLimit($qry, $extra['limit'], $extra['offset'],$bindarr);
 957          } else {
 958              $rs = $db->SelectLimit($qry, $extra['limit'],-1,$bindarr);
 959          }
 960          if ($rs) {
 961              while (!$rs->EOF) {
 962                  $rows[] = $rs->fields;
 963                  $rs->MoveNext();
 964              }
 965          }
 966      } else
 967          $rows = $db->GetAll($qry,$bindarr);
 968  
 969      $db->SetFetchMode($save);
 970  
 971      $false = false;
 972  
 973      if ($rows === false) {
 974          return $false;
 975      }
 976  
 977  
 978      if (!class_exists($class)) {
 979          $db->outp_throw("Unknown class $class in GetActiveRecordsClass()",'GetActiveRecordsClass');
 980          return $false;
 981      }
 982      $arr = array();
 983      // arrRef will be the structure that knows about our objects.
 984      // It is an associative array.
 985      // We will, however, return arr, preserving regular 0.. order so that
 986      // obj[0] can be used by app developpers.
 987      $arrRef = array();
 988      $bTos = array(); // Will store belongTo's indices if any
 989      foreach($rows as $row) {
 990  
 991          $obj = new $class($table,$primkeyArr,$db);
 992          if ($obj->ErrorNo()){
 993              $db->_errorMsg = $obj->ErrorMsg();
 994              return $false;
 995          }
 996          $obj->Set($row);
 997          $arr[] = $obj;
 998      } // foreach($rows as $row)
 999  
1000      return $arr;
1001  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1