source: sandbox/2.5.1-evolucao/phpgwapi/inc/adodb/adodb-active-record.inc.php @ 8222

Revision 8222, 26.1 KB checked in by angelo, 11 years ago (diff)

Ticket #3491 - Compatibilizar Expresso com novas versoes do PHP

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