00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 global $_ADODB_ACTIVE_DBS;
00017
00018
00019 $_ADODB_ACTIVE_DBS = array();
00020
00021
00022 class ADODB_Active_DB {
00023 var $db;
00024 var $tables;
00025 }
00026
00027 class ADODB_Active_Table {
00028 var $name;
00029 var $flds;
00030 var $keys;
00031 }
00032
00033
00034 function ADODB_SetDatabaseAdapter(&$db)
00035 {
00036 global $_ADODB_ACTIVE_DBS;
00037
00038 foreach($_ADODB_ACTIVE_DBS as $k => $d) {
00039 if ($d->db == $db) return $k;
00040 }
00041
00042 $obj = new ADODB_Active_DB();
00043 $obj->db =& $db;
00044 $obj->tables = array();
00045
00046 $_ADODB_ACTIVE_DBS[] = $obj;
00047
00048 return sizeof($_ADODB_ACTIVE_DBS)-1;
00049 }
00050
00051 class ADODB_Active_Record {
00052 var $_dbat;
00053 var $_table;
00054 var $_tableat;
00055 var $_where;
00056 var $_saved = false;
00057 var $_lasterr = false;
00058
00059
00060 function SetDatabaseAdapter(&$db)
00061 {
00062 return ADODB_SetDatabaseAdapter($db);
00063 }
00064
00065
00066 function ADODB_Active_Record($table = false, $pkeyarr=false, $db=false)
00067 {
00068 ADODB_Active_Record::__construct($table,$pkeyarr,$db);
00069 }
00070
00071
00072 function __construct($table = false, $pkeyarr=false, $db=false)
00073 {
00074 global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS;
00075
00076 if ($db == false && is_object($pkeyarr)) {
00077 $db = $pkeyarr;
00078 $pkeyarr = false;
00079 }
00080
00081 if (!$table) $table = $this->_pluralize(get_class($this));
00082
00083 if ($db) {
00084 $this->_dbat = ADODB_Active_Record::SetDatabaseAdapter($db);
00085 } else
00086 $this->_dbat = sizeof($_ADODB_ACTIVE_DBS)-1;
00087
00088
00089 if ($this->_dbat < 0) $this->Error("No database connection set; use ADOdb_Active_Record::SetDatabaseAdapter(\$db)",'ADODB_Active_Record::__constructor');
00090
00091 $this->_table = $table;
00092 $this->_tableat = $table; # reserved for setting the assoc value to a non-table name, eg. the sql string in future
00093 $this->UpdateActiveTable($pkeyarr);
00094 }
00095
00096 function _pluralize($table)
00097 {
00098 $ut = strtoupper($table);
00099 $len = strlen($table);
00100 $lastc = $ut[$len-1];
00101 $lastc2 = substr($ut,$len-2);
00102 switch ($lastc) {
00103 case 'S':
00104 return $table.'es';
00105 case 'Y':
00106 return substr($table,0,$len-1).'ies';
00107 case 'X':
00108 return $table.'es';
00109 case 'H':
00110 if ($lastc2 == 'CH' || $lastc2 == 'SH')
00111 return $table.'es';
00112 default:
00113 return $table.'s';
00114 }
00115 }
00116
00118
00119
00120 function UpdateActiveTable($pkeys=false,$forceUpdate=false)
00121 {
00122 global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS;
00123
00124 $activedb =& $_ADODB_ACTIVE_DBS[$this->_dbat];
00125
00126 $table = $this->_table;
00127 $tables = $activedb->tables;
00128 $tableat = $this->_tableat;
00129 if (!$forceUpdate && !empty($tables[$tableat])) {
00130 $tobj =& $tables[$tableat];
00131 foreach($tobj->flds as $name => $fld)
00132 $this->$name = null;
00133 return;
00134 }
00135
00136 $activetab = new ADODB_Active_Table();
00137 $activetab->name = $table;
00138
00139 $db =& $activedb->db;
00140
00141 $cols = $db->MetaColumns($table);
00142 if (!$cols) {
00143 $this->Error("Invalid table name: $table",'UpdateActiveTable');
00144 return false;
00145 }
00146 $fld = reset($cols);
00147 if (!$pkeys) {
00148 if (isset($fld->primary_key)) {
00149 $pkeys = array();
00150 foreach($cols as $name => $fld) {
00151 if (!empty($fld->primary_key)) $pkeys[] = $name;
00152 }
00153 } else
00154 $pkeys = $this->GetPrimaryKeys($db, $table);
00155 }
00156 if (empty($pkeys)) {
00157 $this->Error("No primary key found for table $table",'UpdateActiveTable');
00158 return false;
00159 }
00160
00161 $attr = array();
00162 $keys = array();
00163
00164 switch($ADODB_ASSOC_CASE) {
00165 case 0:
00166 foreach($cols as $name => $fldobj) {
00167 $name = strtolower($name);
00168 $this->$name = null;
00169 $attr[$name] = $fldobj;
00170 }
00171 foreach($pkeys as $k => $name) {
00172 $keys[strtolower($name)] = strtolower($name);
00173 }
00174 break;
00175
00176 case 1:
00177 foreach($cols as $name => $fldobj) {
00178 $name = strtoupper($name);
00179 $this->$name = null;
00180 $attr[$name] = $fldobj;
00181 }
00182
00183 foreach($pkeys as $k => $name) {
00184 $keys[strtoupper($name)] = strtoupper($name);
00185 }
00186 break;
00187 default:
00188 foreach($cols as $name => $fldobj) {
00189 $name = ($name);
00190 $this->$name = null;
00191 $attr[$name] = $fldobj;
00192 }
00193 foreach($pkeys as $k => $name) {
00194 $keys[$name] = ($name);
00195 }
00196 break;
00197 }
00198
00199 $activetab->keys = $keys;
00200 $activetab->flds = $attr;
00201 $activedb->tables[$table] = $activetab;
00202 }
00203
00204 function GetPrimaryKeys(&$db, $table)
00205 {
00206 return $db->MetaPrimaryKeys($table);
00207 }
00208
00209
00210 function Error($err,$fn)
00211 {
00212 global $_ADODB_ACTIVE_DBS;
00213
00214 $fn = get_class($this).'::'.$fn;
00215 $this->_lasterr = $fn.': '.$err;
00216
00217 if ($this->_dbat < 0) $db = false;
00218 else {
00219 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
00220 $db =& $activedb->db;
00221 }
00222
00223 if (function_exists('adodb_throw')) {
00224 if (!$db) adodb_throw('ADOdb_Active_Record', $fn, -1, $err, 0, 0, false);
00225 else adodb_throw($db->databaseType, $fn, -1, $err, 0, 0, $db);
00226 } else
00227 if (!$db || $db->debug) ADOConnection::outp($this->_lasterr);
00228
00229 }
00230
00231
00232 function ErrorMsg()
00233 {
00234 if (!function_exists('adodb_throw')) {
00235 if ($this->_dbat < 0) $db = false;
00236 else $db = $this->DB();
00237
00238
00239 if ($db && $db->ErrorMsg()) return $db->ErrorMsg();
00240 }
00241 return $this->_lasterr;
00242 }
00243
00244
00245 function &DB()
00246 {
00247 global $_ADODB_ACTIVE_DBS;
00248
00249 if ($this->_dbat < 0) {
00250 $false = false;
00251 $this->Error("No database connection set: use ADOdb_Active_Record::SetDatabaseAdaptor(\$db)", "DB");
00252 return $false;
00253 }
00254 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
00255 $db =& $activedb->db;
00256 return $db;
00257 }
00258
00259
00260 function &TableInfo()
00261 {
00262 global $_ADODB_ACTIVE_DBS;
00263
00264 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
00265 $table =& $activedb->tables[$this->_tableat];
00266 return $table;
00267 }
00268
00269
00270 function Set(&$row)
00271 {
00272 $db =& $this->DB();
00273
00274 if (!$row) {
00275 $this->_saved = false;
00276 return false;
00277 }
00278
00279 $this->_saved = true;
00280
00281 $table =& $this->TableInfo();
00282 if (sizeof($table->flds) != sizeof($row)) {
00283 $this->Error("Table structure of $this->_table has changed","Load");
00284 return false;
00285 }
00286
00287 $cnt = 0;
00288 foreach($table->flds as $name=>$fld) {
00289 $this->$name = $row[$cnt];
00290 $cnt += 1;
00291 }
00292 #$this->_original =& $row;
00293 return true;
00294 }
00295
00296
00297 function LastInsertID(&$db,$fieldname)
00298 {
00299 if ($db->hasInsertID)
00300 $val = $db->Insert_ID($this->_table,$fieldname);
00301 else
00302 $val = false;
00303
00304 if (is_null($val) || $val === false) {
00305
00306 return $db->GetOne("select max(".$fieldname.") from ".$this->_table);
00307 }
00308 return $val;
00309 }
00310
00311
00312 function doquote(&$db, $val,$t)
00313 {
00314 switch($t) {
00315 case 'D':
00316 case 'T':
00317 if (empty($val)) return 'null';
00318
00319 case 'C':
00320 case 'X':
00321 if (is_null($val)) return 'null';
00322
00323 if (strncmp($val,"'",1) != 0 && substr($val,strlen($val)-1,1) != "'") {
00324 return $db->qstr($val);
00325 break;
00326 }
00327 default:
00328 return $val;
00329 break;
00330 }
00331 }
00332
00333
00334 function GenWhere(&$db, &$table)
00335 {
00336 $keys = $table->keys;
00337 $parr = array();
00338
00339 foreach($keys as $k) {
00340 $f = $table->flds[$k];
00341 if ($f) {
00342 $parr[] = $k.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type));
00343 }
00344 }
00345 return implode(' and ', $parr);
00346 }
00347
00348
00349
00350
00351 function Load($where,$bindarr=false)
00352 {
00353 $db =& $this->DB(); if (!$db) return false;
00354 $this->_where = $where;
00355
00356 $save = $db->SetFetchMode(ADODB_FETCH_NUM);
00357 $row = $db->GetRow("select * from ".$this->_table.' WHERE '.$where,$bindarr);
00358 $db->SetFetchMode($save);
00359
00360 return $this->Set($row);
00361 }
00362
00363
00364 function Save()
00365 {
00366 if ($this->_saved) $ok = $this->Update();
00367 else $ok = $this->Insert();
00368
00369 return $ok;
00370 }
00371
00372
00373 function Insert()
00374 {
00375 $db =& $this->DB(); if (!$db) return false;
00376 $cnt = 0;
00377 $table =& $this->TableInfo();
00378
00379 foreach($table->flds as $name=>$fld) {
00380 $val = $this->$name;
00381
00382
00383
00384
00385
00386
00387
00388
00389 $valarr[] = $val;
00390 $names[] = $name;
00391 $valstr[] = $db->Param($cnt);
00392 $cnt += 1;
00393 }
00394
00395 $sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')';
00396 $ok = $db->Execute($sql,$valarr);
00397
00398 if ($ok) {
00399 $this->_saved = true;
00400 $autoinc = false;
00401 foreach($table->keys as $k) {
00402 if (is_null($this->$k)) {
00403 $autoinc = true;
00404 break;
00405 }
00406 }
00407 if ($autoinc && sizeof($table->keys) == 1) {
00408 $k = reset($table->keys);
00409 $this->$k = $this->LastInsertID($db,$k);
00410 }
00411 }
00412
00413 #$this->_original =& $valarr;
00414 return !empty($ok);
00415 }
00416
00417 function Delete()
00418 {
00419 $db =& $this->DB(); if (!$db) return false;
00420 $table =& $this->TableInfo();
00421
00422 $where = $this->GenWhere($db,$table);
00423 $sql = 'DELETE FROM '.$this->_table.' WHERE '.$where;
00424 $db->Execute($sql);
00425 }
00426
00427
00428
00429 function Replace()
00430 {
00431 global $ADODB_ASSOC_CASE;
00432
00433 $db =& $this->DB(); if (!$db) return false;
00434 $table =& $this->TableInfo();
00435
00436 $pkey = $table->keys;
00437
00438 foreach($table->flds as $name=>$fld) {
00439 $val = $this->$name;
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 $t = $db->MetaType($fld->type);
00451 $arr[$name] = $this->doquote($db,$val,$t);
00452 $valarr[] = $val;
00453 }
00454
00455 if (!is_array($pkey)) $pkey = array($pkey);
00456
00457
00458 if ($ADODB_ASSOC_CASE == 0)
00459 foreach($pkey as $k => $v)
00460 $pkey[$k] = strtolower($v);
00461 elseif ($ADODB_ASSOC_CASE == 0)
00462 foreach($pkey as $k => $v)
00463 $pkey[$k] = strtoupper($v);
00464
00465 $ok = $db->Replace($this->_table,$arr,$pkey);
00466 if ($ok) {
00467 $this->_saved = true;
00468 if ($ok == 2) {
00469 $autoinc = false;
00470 foreach($table->keys as $k) {
00471 if (is_null($this->$k)) {
00472 $autoinc = true;
00473 break;
00474 }
00475 }
00476 if ($autoinc && sizeof($table->keys) == 1) {
00477 $k = reset($table->keys);
00478 $this->$k = $this->LastInsertID($db,$k);
00479 }
00480 }
00481
00482 #$this->_original =& $valarr;
00483 }
00484 return $ok;
00485 }
00486
00487
00488 function Update()
00489 {
00490 $db =& $this->DB(); if (!$db) return false;
00491 $table =& $this->TableInfo();
00492
00493 $where = $this->GenWhere($db, $table);
00494
00495 if (!$where) {
00496 $this->error("Where missing for table $table", "Update");
00497 return false;
00498 }
00499 $cnt = 0;
00500 foreach($table->flds as $name=>$fld) {
00501 if (isset($table->keys[$name])) continue;
00502
00503 $val = $this->$name;
00504
00505 if (is_null($val)) {
00506 if (isset($fld->not_null) && $fld->not_null) {
00507 if (isset($fld->default_value) && strlen($fld->default_value)) continue;
00508 else {
00509 $this->Error("Cannot set field $name to NULL","Update");
00510 return false;
00511 }
00512 }
00513 }
00514 $valarr[] = $val;
00515 $pairs[] = $name.'='.$db->Param($cnt);
00516 $cnt += 1;
00517 }
00518
00519 #$this->_original =& $valarr;
00520
00521 $sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where;
00522 $ok = $db->Execute($sql,$valarr);
00523
00524 return !empty($ok);
00525 }
00526
00527 function GetAttributeNames()
00528 {
00529 $table =& $this->TableInfo();
00530 if (!$table) return false;
00531 return array_keys($table->flds);
00532 }
00533
00534 };
00535
00536 ?>