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