[ Index ]
 

Code source de Mantis 1.1.0rc3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

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

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


Généré le : Thu Nov 29 09:42:17 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics