[ Index ] |
|
Code source de vtiger CRM 5.0.2 |
1 <?php 2 /* 3 4 @version V4.90 8 June 2006 (c) 2000-2006 John Lim (jlim#natsoft.com.my). 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.04 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 global $_ADODB_ACTIVE_DBS; 20 global $ADODB_ACTIVE_CACHESECS; // set to true to enable caching of metadata such as field info 21 22 // array of ADODB_Active_DB's, indexed by ADODB_Active_Record->_dbat 23 $_ADODB_ACTIVE_DBS = array(); 24 25 26 class ADODB_Active_DB { 27 var $db; // ADOConnection 28 var $tables; // assoc array of ADODB_Active_Table objects, indexed by tablename 29 } 30 31 class ADODB_Active_Table { 32 var $name; // table name 33 var $flds; // assoc array of adofieldobjs, indexed by fieldname 34 var $keys; // assoc array of primary keys, indexed by fieldname 35 var $_created; // only used when stored as a cached file 36 } 37 38 // returns index into $_ADODB_ACTIVE_DBS 39 function ADODB_SetDatabaseAdapter(&$db) 40 { 41 global $_ADODB_ACTIVE_DBS; 42 43 foreach($_ADODB_ACTIVE_DBS as $k => $d) { 44 if ($d->db == $db) return $k; 45 } 46 47 $obj = new ADODB_Active_DB(); 48 $obj->db =& $db; 49 $obj->tables = array(); 50 51 $_ADODB_ACTIVE_DBS[] = $obj; 52 53 return sizeof($_ADODB_ACTIVE_DBS)-1; 54 } 55 56 57 class ADODB_Active_Record { 58 var $_dbat; // associative index pointing to ADODB_Active_DB eg. $ADODB_Active_DBS[_dbat] 59 var $_table; // tablename, if set in class definition then use it as table name 60 var $_tableat; // associative index pointing to ADODB_Active_Table, eg $ADODB_Active_DBS[_dbat]->tables[$this->_tableat] 61 var $_where; // where clause set in Load() 62 var $_saved = false; // indicates whether data is already inserted. 63 var $_lasterr = false; // last error message 64 var $_original = false; // the original values loaded or inserted, refreshed on update 65 66 // should be static 67 function SetDatabaseAdapter(&$db) 68 { 69 return ADODB_SetDatabaseAdapter($db); 70 } 71 72 // php4 constructor 73 function ADODB_Active_Record($table = false, $pkeyarr=false, $db=false) 74 { 75 ADODB_Active_Record::__construct($table,$pkeyarr,$db); 76 } 77 78 // php5 constructor 79 function __construct($table = false, $pkeyarr=false, $db=false) 80 { 81 global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS; 82 83 if ($db == false && is_object($pkeyarr)) { 84 $db = $pkeyarr; 85 $pkeyarr = false; 86 } 87 88 if (!$table) { 89 if (!empty($this->_table)) $table = $this->_table; 90 else $table = $this->_pluralize(get_class($this)); 91 } 92 if ($db) { 93 $this->_dbat = ADODB_Active_Record::SetDatabaseAdapter($db); 94 } else 95 $this->_dbat = sizeof($_ADODB_ACTIVE_DBS)-1; 96 97 98 if ($this->_dbat < 0) $this->Error("No database connection set; use ADOdb_Active_Record::SetDatabaseAdapter(\$db)",'ADODB_Active_Record::__constructor'); 99 100 $this->_table = $table; 101 $this->_tableat = $table; # reserved for setting the assoc value to a non-table name, eg. the sql string in future 102 $this->UpdateActiveTable($pkeyarr); 103 } 104 105 function _pluralize($table) 106 { 107 $ut = strtoupper($table); 108 $len = strlen($table); 109 $lastc = $ut[$len-1]; 110 $lastc2 = substr($ut,$len-2); 111 switch ($lastc) { 112 case 'S': 113 return $table.'es'; 114 case 'Y': 115 return substr($table,0,$len-1).'ies'; 116 case 'X': 117 return $table.'es'; 118 case 'H': 119 if ($lastc2 == 'CH' || $lastc2 == 'SH') 120 return $table.'es'; 121 default: 122 return $table.'s'; 123 } 124 } 125 126 ////////////////////////////////// 127 128 // update metadata 129 function UpdateActiveTable($pkeys=false,$forceUpdate=false) 130 { 131 global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS , $ADODB_CACHE_DIR, $ADODB_ACTIVE_CACHESECS; 132 133 $activedb =& $_ADODB_ACTIVE_DBS[$this->_dbat]; 134 135 $table = $this->_table; 136 $tables = $activedb->tables; 137 $tableat = $this->_tableat; 138 if (!$forceUpdate && !empty($tables[$tableat])) { 139 $tobj =& $tables[$tableat]; 140 foreach($tobj->flds as $name => $fld) 141 $this->$name = null; 142 return; 143 } 144 145 $db =& $activedb->db; 146 $fname = $ADODB_CACHE_DIR . '/adodb_' . $db->databaseType . '_active_'. $table . '.cache'; 147 if (!$forceUpdate && $ADODB_ACTIVE_CACHESECS && $ADODB_CACHE_DIR && file_exists($fname)) { 148 $fp = fopen($fname,'r'); 149 @flock($fp, LOCK_SH); 150 $acttab = unserialize(fread($fp,100000)); 151 fclose($fp); 152 if ($acttab->_created + $ADODB_ACTIVE_CACHESECS - (abs(rand()) % 16) > time()) { 153 // abs(rand()) randomizes deletion, reducing contention to delete/refresh file 154 // ideally, you should cache at least 32 secs 155 $activedb->tables[$table] = $acttab; 156 157 //if ($db->debug) ADOConnection::outp("Reading cached active record file: $fname"); 158 return; 159 } else if ($db->debug) { 160 ADOConnection::outp("Refreshing cached active record file: $fname"); 161 } 162 } 163 $activetab = new ADODB_Active_Table(); 164 $activetab->name = $table; 165 166 167 $cols = $db->MetaColumns($table); 168 if (!$cols) { 169 $this->Error("Invalid table name: $table",'UpdateActiveTable'); 170 return false; 171 } 172 $fld = reset($cols); 173 if (!$pkeys) { 174 if (isset($fld->primary_key)) { 175 $pkeys = array(); 176 foreach($cols as $name => $fld) { 177 if (!empty($fld->primary_key)) $pkeys[] = $name; 178 } 179 } else 180 $pkeys = $this->GetPrimaryKeys($db, $table); 181 } 182 if (empty($pkeys)) { 183 $this->Error("No primary key found for table $table",'UpdateActiveTable'); 184 return false; 185 } 186 187 $attr = array(); 188 $keys = array(); 189 190 switch($ADODB_ASSOC_CASE) { 191 case 0: 192 foreach($cols as $name => $fldobj) { 193 $name = strtolower($name); 194 $this->$name = null; 195 $attr[$name] = $fldobj; 196 } 197 foreach($pkeys as $k => $name) { 198 $keys[strtolower($name)] = strtolower($name); 199 } 200 break; 201 202 case 1: 203 foreach($cols as $name => $fldobj) { 204 $name = strtoupper($name); 205 $this->$name = null; 206 $attr[$name] = $fldobj; 207 } 208 209 foreach($pkeys as $k => $name) { 210 $keys[strtoupper($name)] = strtoupper($name); 211 } 212 break; 213 default: 214 foreach($cols as $name => $fldobj) { 215 $name = ($name); 216 $this->$name = null; 217 $attr[$name] = $fldobj; 218 } 219 foreach($pkeys as $k => $name) { 220 $keys[$name] = ($name); 221 } 222 break; 223 } 224 225 $activetab->keys = $keys; 226 $activetab->flds = $attr; 227 228 if ($ADODB_ACTIVE_CACHESECS && $ADODB_CACHE_DIR) { 229 $activetab->_created = time(); 230 $s = serialize($activetab); 231 if (!function_exists('adodb_write_file')) include (ADODB_DIR.'/adodb-csvlib.inc.php'); 232 adodb_write_file($fname,$s); 233 } 234 $activedb->tables[$table] = $activetab; 235 } 236 237 function GetPrimaryKeys(&$db, $table) 238 { 239 return $db->MetaPrimaryKeys($table); 240 } 241 242 // error handler for both PHP4+5. 243 function Error($err,$fn) 244 { 245 global $_ADODB_ACTIVE_DBS; 246 247 $fn = get_class($this).'::'.$fn; 248 $this->_lasterr = $fn.': '.$err; 249 250 if ($this->_dbat < 0) $db = false; 251 else { 252 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 253 $db =& $activedb->db; 254 } 255 256 if (function_exists('adodb_throw')) { 257 if (!$db) adodb_throw('ADOdb_Active_Record', $fn, -1, $err, 0, 0, false); 258 else adodb_throw($db->databaseType, $fn, -1, $err, 0, 0, $db); 259 } else 260 if (!$db || $db->debug) ADOConnection::outp($this->_lasterr); 261 262 } 263 264 // return last error message 265 function ErrorMsg() 266 { 267 if (!function_exists('adodb_throw')) { 268 if ($this->_dbat < 0) $db = false; 269 else $db = $this->DB(); 270 271 // last error could be database error too 272 if ($db && $db->ErrorMsg()) return $db->ErrorMsg(); 273 } 274 return $this->_lasterr; 275 } 276 277 // retrieve ADOConnection from _ADODB_Active_DBs 278 function &DB() 279 { 280 global $_ADODB_ACTIVE_DBS; 281 282 if ($this->_dbat < 0) { 283 $false = false; 284 $this->Error("No database connection set: use ADOdb_Active_Record::SetDatabaseAdaptor(\$db)", "DB"); 285 return $false; 286 } 287 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 288 $db =& $activedb->db; 289 return $db; 290 } 291 292 // retrieve ADODB_Active_Table 293 function &TableInfo() 294 { 295 global $_ADODB_ACTIVE_DBS; 296 297 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 298 $table =& $activedb->tables[$this->_tableat]; 299 return $table; 300 } 301 302 // set a numeric array (using natural table field ordering) as object properties 303 function Set(&$row) 304 { 305 $db =& $this->DB(); 306 307 if (!$row) { 308 $this->_saved = false; 309 return false; 310 } 311 312 $this->_saved = true; 313 314 $table =& $this->TableInfo(); 315 if (sizeof($table->flds) != sizeof($row)) { 316 $this->Error("Table structure of $this->_table has changed","Load"); 317 return false; 318 } 319 320 $cnt = 0; 321 foreach($table->flds as $name=>$fld) { 322 $this->$name = $row[$cnt]; 323 $cnt += 1; 324 } 325 $this->_original = $row; 326 return true; 327 } 328 329 // get last inserted id for INSERT 330 function LastInsertID(&$db,$fieldname) 331 { 332 if ($db->hasInsertID) 333 $val = $db->Insert_ID($this->_table,$fieldname); 334 else 335 $val = false; 336 337 if (is_null($val) || $val === false) { 338 // this might not work reliably in multi-user environment 339 return $db->GetOne("select max(".$fieldname.") from ".$this->_table); 340 } 341 return $val; 342 } 343 344 // quote data in where clause 345 function doquote(&$db, $val,$t) 346 { 347 switch($t) { 348 case 'D': 349 case 'T': 350 if (empty($val)) return 'null'; 351 352 case 'C': 353 case 'X': 354 if (is_null($val)) return 'null'; 355 356 if (strncmp($val,"'",1) != 0 && substr($val,strlen($val)-1,1) != "'") { 357 return $db->qstr($val); 358 break; 359 } 360 default: 361 return $val; 362 break; 363 } 364 } 365 366 // generate where clause for an UPDATE/SELECT 367 function GenWhere(&$db, &$table) 368 { 369 $keys = $table->keys; 370 $parr = array(); 371 372 foreach($keys as $k) { 373 $f = $table->flds[$k]; 374 if ($f) { 375 $parr[] = $k.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type)); 376 } 377 } 378 return implode(' and ', $parr); 379 } 380 381 382 //------------------------------------------------------------ Public functions below 383 384 function Load($where,$bindarr=false) 385 { 386 $db =& $this->DB(); if (!$db) return false; 387 $this->_where = $where; 388 389 $save = $db->SetFetchMode(ADODB_FETCH_NUM); 390 $row = $db->GetRow("select * from ".$this->_table.' WHERE '.$where,$bindarr); 391 $db->SetFetchMode($save); 392 393 return $this->Set($row); 394 } 395 396 // false on error 397 function Save() 398 { 399 if ($this->_saved) $ok = $this->Update(); 400 else $ok = $this->Insert(); 401 402 return $ok; 403 } 404 405 // false on error 406 function Insert() 407 { 408 $db =& $this->DB(); if (!$db) return false; 409 $cnt = 0; 410 $table =& $this->TableInfo(); 411 412 foreach($table->flds as $name=>$fld) { 413 $val = $this->$name; 414 /* 415 if (is_null($val)) { 416 if (isset($fld->not_null) && $fld->not_null) { 417 if (isset($fld->default_value) && strlen($fld->default_value)) continue; 418 else $this->Error("Cannot insert null into $name","Insert"); 419 } 420 }*/ 421 422 $valarr[] = $val; 423 $names[] = $name; 424 $valstr[] = $db->Param($cnt); 425 $cnt += 1; 426 } 427 428 $sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')'; 429 $ok = $db->Execute($sql,$valarr); 430 431 if ($ok) { 432 $this->_saved = true; 433 $autoinc = false; 434 foreach($table->keys as $k) { 435 if (is_null($this->$k)) { 436 $autoinc = true; 437 break; 438 } 439 } 440 if ($autoinc && sizeof($table->keys) == 1) { 441 $k = reset($table->keys); 442 $this->$k = $this->LastInsertID($db,$k); 443 } 444 } 445 446 $this->_original = $valarr; 447 return !empty($ok); 448 } 449 450 function Delete() 451 { 452 $db =& $this->DB(); if (!$db) return false; 453 $table =& $this->TableInfo(); 454 455 $where = $this->GenWhere($db,$table); 456 $sql = 'DELETE FROM '.$this->_table.' WHERE '.$where; 457 $db->Execute($sql); 458 } 459 460 // returns an array of active record objects 461 function &Find($whereOrderBy,$bindarr=false,$pkeysArr=false) 462 { 463 $db =& $this->DB(); if (!$db || empty($this->_table)) return false; 464 $arr =& $db->GetActiveRecordsClass(get_class($this),$this->_table, $whereOrderBy,$bindarr,$pkeysArr); 465 return $arr; 466 } 467 468 // returns 0 on error, 1 on update, 2 on insert 469 function Replace() 470 { 471 global $ADODB_ASSOC_CASE; 472 473 $db =& $this->DB(); if (!$db) return false; 474 $table =& $this->TableInfo(); 475 476 $pkey = $table->keys; 477 478 foreach($table->flds as $name=>$fld) { 479 $val = $this->$name; 480 /* 481 if (is_null($val)) { 482 if (isset($fld->not_null) && $fld->not_null) { 483 if (isset($fld->default_value) && strlen($fld->default_value)) continue; 484 else { 485 $this->Error("Cannot update null into $name","Replace"); 486 return false; 487 } 488 } 489 }*/ 490 if (is_null($val) && !empty($fld->auto_increment)) { 491 continue; 492 } 493 $t = $db->MetaType($fld->type); 494 $arr[$name] = $this->doquote($db,$val,$t); 495 $valarr[] = $val; 496 } 497 498 if (!is_array($pkey)) $pkey = array($pkey); 499 500 501 if ($ADODB_ASSOC_CASE == 0) 502 foreach($pkey as $k => $v) 503 $pkey[$k] = strtolower($v); 504 elseif ($ADODB_ASSOC_CASE == 0) 505 foreach($pkey as $k => $v) 506 $pkey[$k] = strtoupper($v); 507 508 $ok = $db->Replace($this->_table,$arr,$pkey); 509 if ($ok) { 510 $this->_saved = true; // 1= update 2=insert 511 if ($ok == 2) { 512 $autoinc = false; 513 foreach($table->keys as $k) { 514 if (is_null($this->$k)) { 515 $autoinc = true; 516 break; 517 } 518 } 519 if ($autoinc && sizeof($table->keys) == 1) { 520 $k = reset($table->keys); 521 $this->$k = $this->LastInsertID($db,$k); 522 } 523 } 524 525 $this->_original =& $valarr; 526 } 527 return $ok; 528 } 529 530 // returns 0 on error, 1 on update, -1 if no change in data (no update) 531 function Update() 532 { 533 $db =& $this->DB(); if (!$db) return false; 534 $table =& $this->TableInfo(); 535 536 $where = $this->GenWhere($db, $table); 537 538 if (!$where) { 539 $this->error("Where missing for table $table", "Update"); 540 return false; 541 } 542 $valarr = array(); 543 $neworig = array(); 544 $pairs = array(); 545 $i = -1; 546 $cnt = 0; 547 foreach($table->flds as $name=>$fld) { 548 $i += 1; 549 $val = $this->$name; 550 $neworig[] = $val; 551 552 if (isset($table->keys[$name])) { 553 continue; 554 } 555 556 557 if (is_null($val)) { 558 if (isset($fld->not_null) && $fld->not_null) { 559 if (isset($fld->default_value) && strlen($fld->default_value)) continue; 560 else { 561 $this->Error("Cannot set field $name to NULL","Update"); 562 return false; 563 } 564 } 565 } 566 567 if ( $val == $this->_original[$i]) { 568 continue; 569 } 570 $valarr[] = $val; 571 $pairs[] = $name.'='.$db->Param($cnt); 572 $cnt += 1; 573 } 574 575 576 if (!$cnt) return -1; 577 $sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where; 578 $ok = $db->Execute($sql,$valarr); 579 if ($ok) { 580 $this->_original =& $neworig; 581 return 1; 582 } 583 return 0; 584 } 585 586 function GetAttributeNames() 587 { 588 $table =& $this->TableInfo(); 589 if (!$table) return false; 590 return array_keys($table->flds); 591 } 592 593 }; 594 595 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 10:22:19 2007 | par Balluche grâce à PHPXref 0.7 |