PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/concreteOLD/libraries/3rdparty/adodb/adodb-active-record.inc.php

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