[ Index ]
 

Code source de vtiger CRM 5.0.2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

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

   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  ?>


Généré le : Sun Feb 25 10:22:19 2007 par Balluche grâce à PHPXref 0.7