* modifications related to enabling memcache and adding some expire headers
[vsc.git] / _res / _libs / tdoabstract.class.php
bloba7d1b60952dd39b573de49a9c56896211681f4dd
1 <?php
2 /**
3 * @desc The Abstract Data Objects series
5 * @author Marius Orcsik <marius.orcsik@gmail.com>
6 * @version 0.0.1
7 */
9 class tdoAbstract {
10 /**
11 * @var mySqlIm $db
13 public $db,
14 $wheres = array(),
15 $groups,
16 // $orders,
17 $limit,
18 $refers = array();
20 protected $id, // public to allow debugging outside the class
21 $name,
22 $alias,
23 $fields;
25 /**
26 * @desc function to implement get_ | set_ virtual methods
28 * @param string $method
29 * @param array $args
30 * @return bool|mixed
32 * @see http://www.ibm.com/developerworks/xml/library/os-php-flexobj/ by Jack Herrington <jherr@pobox.com>
34 function __call ( $method, $args) {
35 $diff = $this->get_members();
36 $all = get_object_vars($this);
38 if ( preg_match( '/set_(.*)/', $method, $found ) ) {
39 // check for fields with $found[1] name
40 if ( array_key_exists( $found[1], $diff) ) {
41 $this->fields[$found[1]]->setValue($args[0]);
42 return true;
43 // check for obj members with $found[1] name
44 } elseif (array_key_exists( $found[1], $all)){
45 $this->$found[1] = $args[0];
46 return true;
48 } else if ( preg_match( '/get_(.*)/', $method, $found ) ) {
49 if ( array_key_exists( $found[1], $diff ) ) {
50 return $this->fields[$found[1]]->getValue();
51 } elseif (array_key_exists( $found[1], $all)){
52 return $this->$found[1];
55 return false;
58 /**
59 * @desc A function to implement a virtual getter member of the class
61 * @param string $key
62 * @return mixed
64 * @see http://www.ibm.com/developerworks/xml/library/os-php-flexobj/ by Jack Herrington <jherr@pobox.com>
66 function __get ( $key ) {
67 return $this->fields[$key];
70 /**
71 * @desc A function to implement a virtual setter member for this class
73 * @param string $key
74 * @param mixed $value
75 * @return bool
77 * @see http://www.ibm.com/developerworks/xml/library/os-php-flexobj/ by Jack Herrington <jherr@pobox.com>
79 function __set ( $key, $value ) {
80 if (
81 array_key_exists ($key, $this->get_members()) /*&&
82 $this->isValidMember($this->fields[$key])*/
83 ) {
84 $this->fields[$key]->set_value ($value);
85 return true;
86 } else {
87 $this->fields[$key] = new tdoAbstractField ($key, $this->alias);
88 $this->fields[$key]->set_value ($value);
92 public function __construct(&$db) {
93 $this->db = &$db;
94 $this->alias = 'm1';
96 $this->instantiateMembers();
99 public function __destruct() {}
102 * gets the members we consider table fields
104 * @return array ('fieldName' => tdoAbstractField)
106 public function &get_members () {
107 return $this->fields;
111 * checks if a field is a valid member of the current object
113 * @param tdoAbstractField $incMember
114 * @return bool
116 public function isValidMember ($incMember) {
117 if (
118 ! ($incMember instanceof tdoAbstractField ) ||
119 // this prevents an error in php > 5.2 object comparison
120 ! in_array ($incMember, $this->get_members() /**/, true/**/)
122 return false;
123 } else
124 return true;
128 * instantiating the object's members
130 public function instantiateMembers () {
131 foreach ($this->get_members() as $key => $field) {
132 if ( is_int ($key) && is_string ($field) ) {
133 $this->fields[$field] = new tdoAbstractField ($field, $this->alias);
135 // FIXME: this is so bad :D - it implies that the primary key must be the first field containing _id :D
136 if (stristr ($field,'_id') && !isset ($this->id) && $this->isValidMember ($this->fields[$field])) {
137 $this->id = &$this->fields[$field];
139 unset ($this->fields[$key]);
143 $this->wheres = array();
144 $this->groups = '';
145 // $this->orders = '';
146 $this->refers = array();
149 * setting the table's index field
151 * @param tdoAbstractField $obj
153 public function set_index (&$obj) {
154 if ($this->isValidMember($obj)) {
155 $this->id = &$obj;
156 $this->id->flags = PRIMARY;
161 * setting an alias for the table in case of joins.
162 * this method also sets the alias on all the fields of the current object
164 * @param string $alias
166 public function set_alias ($alias) {
167 foreach ($this->get_members() as $field){
168 if ($field->table == $this->alias) {
169 $field->table = 't'.$alias;
172 $this->alias = 't'.$alias;
176 * For adding custom sql functions for certain fields
178 * @param string $modif
179 * @param tdoAbstractField $field
181 public function set_fieldModifier ($modif, &$field) {
182 if ($this->isValidMember ($field) && stristr ($modif, '%'))
183 $field->set_modifier ($modif);
187 * method used in join cases to add the joined object's fields
188 * to the current one
190 * @param array ('fieldName' => tdoAbstractField) $incArr
192 public function addFields (&$incArr) {
193 if (is_array($incArr)) {
194 foreach ($incArr as $fieldName => $field) {
195 $this->fields[$fieldName] = $field;
201 * Based on field values, we get the _first_ row in the table that matches
203 * TODO: maybe we can have a function that returns _all_ the rows that match
205 * @return bool
207 public function buildObj () {
208 $sql = $this->buildSql(1);
209 $this->db->query( $sql );
211 $arr = $this->db->getAssoc();
212 if (is_array($arr)) {
213 foreach ($arr as $field => $var) {
214 $this->fields[$field]->set_value ($var);
216 return true;
218 return false;
222 * Gets the row in the table for $id
224 * @param mixed $id
227 public function get ($id) {
228 $id = $this->db->escape($id);
230 $this->instantiateMembers();
232 $this->id->set_value ($id);
233 $this->buildObj ();
236 * Returns the last id of the table
237 * OBS: this assumes that we didn't delete any rows from the table.
239 * @return int
241 public function getLastInsertedId () {
242 $sql = $this->db->_SELECT ($this->id->name)
243 .$this->db->_FROM ($this->name) . $this->db->_AS ($this->alias);
245 $this->addOrder ($this->id, false);
247 $sql .= $this->db->_ORDER ($this->outputOrders ());
249 $sql .= ' LIMIT 1';
251 $this->db->query ($sql);
252 return $this->db->getScalar ();
256 * encapsulating the $this->db->escape() method
258 * @param mixed $value
259 * @return mixed
261 public function escape ($value) {
262 if (is_numeric ($value)) {
263 return $value;
264 } else {
265 return '"'.$this->db->escape ($value).'"';
269 * inserting into the database
270 * TODO: multiple inserts to use with loadFromArray
272 * @return int
274 public function insert () {
275 $sql = $this->db->_INSERT ($this->name);//`'INSERT INTO '.$this->name;
277 $fieldStr = '';
278 $valueStr = '';
279 $f = $this->get_members();
281 // $sql .= ' '.$this->outputRefers().' SET';
283 foreach ($f as $fieldName => $field) {
284 if ($this->isValidMember ($field) && ($field != $this->id) && !is_null ($field->value)) {
285 $value = $this->escape ($field->value);
287 $fieldStr.= (!empty ($fieldStr) ? ', ' : ' ') . $fieldName;
288 $valueStr.= (!empty ($valueStr) ? ', ' : ' ') . $value;
292 $sql.= ' ('.$fieldStr.') VALUES ('.$valueStr.')';
293 if ($fieldStr) {
294 $this->db->query($sql);
296 return $this->getLastInsertedId();
300 public function update ($id = null) {
301 if (is_null ($id)) {
302 $id = $this->id->value;
305 if (is_null ($id)) {
306 throw new Exception('Cannot update record in table '.$this->name.' because an id hasn\'t been provided');
307 return false;
310 $sql = $this->db->_UPDATE (array ($this->name, $this->alias) );
312 if (is_array ($this->refers) && !empty ($this->refers)){
313 $this->refers = array_reverse ($this->refers);
315 foreach ($this->refers as $ref)
316 $sql .= $ref;
319 $sql .= $this->db->_SET();
321 $fields = $this->get_members();
323 foreach ($fields as $fieldName => $field) {
324 if (($field instanceof tdoAbstractField) && $field != $this->id) { // TODO: make a more real check for field is an id
325 $value = $field->value;
328 if ((isset($value) && !is_null($value))) {
329 $sql.= $field->table.'.'.$fieldName.' = '.$this->escape ($value).', ';
333 $sql = substr ($sql, 0, -2);
335 $sql.= $this->db->_WHERE($this->alias.'.'.$this->id->name.' = '.$this->escape($id));
337 // var_dump($sql);die ('<br/>update');
338 $this->db->query($sql);
340 return $id;
343 public function replace ( $id = null ) {
344 if (is_null($id)) {
345 $id = $this->id->value;
348 if (is_null($id) || !$this->idExists ($id) ) {
349 return $this->insert ();
350 } else {
351 return $this->update ($id);
355 // TODO: make this the same way the find first method works
356 public function delete ($id = null) {
357 $id = (!is_null ($id) ? $id :$this->id->value);
359 if (!is_null ($id)) {
360 // no need for other wheres
361 $this->wheres = array();
362 $this->addWhere ($this->id, '=', $id);
365 if (empty($this->wheres)) {
366 return false;
369 $temp = $this->alias;
370 $this->set_alias(null);
373 $sql = 'DELETE FROM '.$this->name.' WHERE '; //$this->id->name.' = '.$this->escape($value).' LIMIT 1';
374 $sql.= $this->outputWheres();
375 // echo $sql;die;
376 $affRows = $this->db->query($sql);
378 $this->set_alias($temp);
379 return $affRows;
382 public function reset () {
383 foreach ($this->fields as $key => $field) {
384 if ($field instanceof tdoAbstractField) {
385 $this->fields[$key] = new tdoAbstractField($key, $this->alias);
389 $this->wheres = array();
390 $this->groups = array();
391 // $this->orders = array();
392 $this->refers = array();
393 return true;
396 public function idExists ($id = null) {
397 if (is_null($id)) {
398 $id = $this->id->value;
400 if (is_null($id))
401 return false;
403 $this->id->set_modifier ('COUNT(%s)');
405 $t = sprintf ($this->id->modifier, $this->id->name);
407 $sql = $this->db->_SELECT ($t).
408 $this->db->_FROM ($this->name).
409 $this->db->_WHERE ($this->id->name.' = '.$this->escape($id));
411 $this->db->query($sql);
413 if ($this->db->getScalar()) {
414 return true;
415 } else {
416 return false;
420 protected function outputFieldList () {
421 $fields = '';
422 $f = $this->get_members();
423 // var_dump($f);
424 foreach ($f as $fieldName => $field) {
425 if ($this->isValidMember ($field)) {
427 if (!is_null ($field->modifier)) {
428 // i replaced str_replace ('%s', $curField, '%s', $curField)
429 // as sometimes I might need it for something else than %s
430 $fields .= sprintf ($field->modifier, (!is_null ($field->table) ? $field->table . '.' : '') . $field->name) .
431 $this->db->_AS($field->name) . ', ';
432 } elseif ( !$field->inWhere ()) {
433 $fields .= (!is_null ($field->table) ? $field->table.'.' : '') . $field->name . ', ';
436 } else {
437 trigger_error ($fieldName . ' is not a valid member of ' . get_class($this));
438 // throw new Exception ($fieldName . ' is not a valid member of ' . get_class($this));
439 return false;
442 return substr ($fields,0,-2);//$fields;
445 protected function outputWheres ($bIW = true) {
446 // var_dump($this->wheres);
447 return implode ($this->db->_AND(), $this->wheres);
450 protected function outputGroups () {
451 // groups
452 $groups = '';
453 $f = $this->get_members ();
454 foreach ($f as $field) {
455 if (!is_null ($field->group) ) {
456 $groups .= (!empty($groups) ? ', ' : '') .
457 $field->table . '.' . $field->name;
461 return $groups;
464 protected function outputOrders () {
465 $orders = '';
466 $f = $this->get_members();
467 foreach ($f as $field)
468 if (!is_null($field->order)) {
469 $orders .= (!empty($orders) ? ', ': '') .
470 $field->table . '.' . $field->name .
471 ($field->order == true ? ' ASC' : ' DESC');
473 return $orders;
476 protected function outputRefers () {
477 $refers= '';
478 if (!empty($this->refers) && is_array($this->refers)){
479 $rs = array_reverse ($this->refers);
480 foreach ($rs as $ref) // using the __toString magic function
481 $refers .= $ref;
483 return $refers;
486 protected function buildInherentWheres () {
487 $diff = $this->get_members();
488 // let's hope this doesn't break stuff.
489 // it's needed when we use more queries on the same instance of the object :D
491 if (is_array ($diff)) {
492 foreach ($diff as $fieldName => $field) {
493 if ( $this->isValidMember ($field) ) {
494 if (!is_null($field->value))
495 $this->addWhere ($field, '=', $this->escape($field->value));
496 } else {
497 trigger_error ($fieldName . ' is not a valid member of ' . get_class($this));
498 // throw new Exception ($fieldName . ' is not a valid member of ' . get_class($this));
503 if (empty ($this->wheres)) {
504 $t = '1';
505 $this->wheres[] = new tdoAbstractClause ($t);
510 * function to add an abstract clause to the current object if it doesn't exist
512 * @param tdoAbstractField|tdoAbstractClause $field1
513 * @param string $condition
514 * @param string $field2
516 public function addWhere (&$field1, $condition = null, $field2 = null) {
517 if (($field1 instanceof tdoAbstractClause) && ($condition == null || $field2 == null)) {
518 $w = &$field1;
519 } else {
520 $w = new tdoAbstractClause ($field1, $condition, $field2);
522 // this might generate an infinite recursion error on some PHP > 5.2 due to object comparison
523 if (!in_array ($w, $this->wheres /*, true */))
524 $this->wheres[] = &$w;
527 public function addOrder (&$orderField, $asc = true) {
528 if (!($orderField instanceof tdoAbstractField) && is_string ($orderField)) {
529 $orderField = &$this->fields[$orderField];
531 if ($this->isValidMember ($orderField))
532 $orderField->set_order ($asc);
535 public function addGroup (&$groupField) {
536 if (!($groupField instanceof tdoAbstractField) && is_string ($groupField)) {
537 $groupField = &$this->fields[$groupField];
539 if (($groupField instanceof tdoAbstractField)) {
540 $groupField->set_group (true);
545 * @param int $start
546 * @param int $count
549 public function addLimit ($start = 0, $count=null) {
550 if (empty($this->limit))
551 $this->limit = $this->db->_LIMIT ($start, $count);
555 * building a normal SELECT query
557 * @param int $start
558 * @param int $end
559 * @return string
561 protected function buildSql ($start = 0, $count = 0) {
562 $sql = $this->db->_SELECT($this->outputFieldList()). ' FROM '.$this->name.' AS '.$this->alias.' ';
564 $this->buildInherentWheres(); // will it work
566 $sql .= $this->outputRefers();
568 $sql .= $this->db->_WHERE ($this->outputWheres());
570 $sql .= $this->db->_GROUP ($this->outputGroups());
572 $sql .= $this->db->_ORDER ($this->outputOrders());
574 if (empty ($this->limit)) {
575 $this->addLimit ($start, $count);
577 $sql .= $this->limit;
578 return $sql;
581 public function find ($start = 0, $count = 0) {
582 $result = $this->db->query ($this->buildSql(), $start, $count);
583 return $result;
586 public function findFirst () {
587 $this->buildInherentWheres();
589 $this->db->query($this->buildSql(), 0, 1);
590 $row = $this->db->getAssoc();
591 if (is_array($row))
592 foreach ($row as $field => $value){
593 $this->fields[$field]->value = $value;
597 public function getArray ($start = 0, $count = 0, $orderBy = null) {
598 $this->buildInherentWheres ();
600 $sql = $this->buildSql ($start, $count, $orderBy);
602 $this->db->query ($sql);
603 return $this->db->getArray ();
607 * execute a select count () on the current object
609 * @return null
611 public function getCount1() {
612 $this->set_fieldModifier('COUNT(%s)', $this->id);
613 $this->db->query($this->buildSql());
614 return $this->db->getScalar();
617 public function getCount() {
618 // this is bad:
619 // it takes into account the counting rows in many2many table relationshit
620 // but it does not for more than one group by
621 foreach ($this->get_members() as $fieldName => $field) {
622 if ($field->get_group() == true) {
623 $what = 'DISTINCT(' . $field->table .'.' . $fieldName . ')';
627 if (empty ($what))
628 $what = '*';
630 // made it a bit more clean and less sql portable by adding hard coded
631 // MY SQL stuff
632 $sql = $this->db->_SELECT (' COUNT(' . $what . ') ');
634 $sql .= $this->db->_FROM( $this->name. $this->db->_AS($this->alias) );
636 $this->buildInherentWheres();
638 $sql .= $this->outputRefers();
640 $sql .= $this->db->_WHERE ($this->outputWheres());
642 // this would need to be replaced with a count(distinct(group by column))
643 // because we're using many2many relations
644 // also I do not know how this behaves for:
645 // 1. multiple group by's
646 // 2. !many2many relations.
647 // $sql .= $this->db->_GROUP ($this->outputGroups());
649 $this->db->query($sql);
650 return $this->db->getScalar();
653 public function getVector() {
654 // I really don't see why we need this. ?
658 * Function to load the values of current object from an array
659 * of type field_name => field_value
660 * If strict is false, the current object can have fields that are not already
661 * present in $this->fields[]
663 * @param array $valArray
664 * @param bool $strict
666 public function loadFromArray ($valArray, $strict = true) {
667 foreach ($valArray as $fieldName => $value) {
668 if (array_key_exists ($fieldName, $this->fields)) {
669 $this->fields[$fieldName]->set_value($value);
670 } elseif (!$strict) {
671 // if the field name is not in the field list of the current object
672 // it means that the valArray object is got from an JOIN sql
673 $this->fields[$fieldName] = new tdoAbstractField ($value,'j1');
674 $this->fields[$fieldName]->set_value ($value);
680 * FIXME: make it work when composing with the same object
682 * @param tdoAbstract $incOb
683 * @return void
685 private function composeObj ($incOb) {
686 if (!($incOb instanceof tdoAbstract))
687 return false;
688 $refs = count($this->refers);
690 foreach ($incOb->refers as $alias => $ref) {
691 $tAl = $refs++;
693 $this->refers[$tAl] = $ref;//str_replace(array($alias, $aliases[$alias][1]), array($tAl, $aliases[$alias][2]), $ref);
694 $this->refers[$tAl]->set_state ($tAl);
699 * Function to execute a join between two tdoAbstract objects
701 * @param string $jType
702 * @param tdoAbstractField $thisJField
703 * @param tdoAbstract $incOb
704 * @param tdoAbstractField $incObJField
705 * @return unknown
707 public function joinWith ($jType = null, &$thisJField = null, &$incOb = null, &$incObJField = null) {
708 if (
709 !tdoAbstractJoin::isValidType ($jType) ||
710 !$this->isValidMember ($thisJField)
711 ) return false;
713 $this->composeObj ($incOb);
715 $tAl = (count($this->refers));
716 if ($tAl > 59) {
717 trigger_error('Join aborted for table '.$this->name.': Too many tables; MySQL can only use 61 tables in a join', E_USER_NOTICE);
718 return;
719 } else {
720 $incOb->set_alias($tAl);
722 if($thisJField == null || !($thisJField instanceof tdoAbstractField))
723 $thisJField = $this->id;
725 if($incObJField == null || !($incObJField instanceof tdoAbstractField))
726 $incObJField = $incOb->id;
728 $this->refers[$tAl] = new tdoAbstractJoin ($jType, $this, $incOb, $thisJField, $incObJField, $tAl);
729 $this->refers[$tAl]->set_state ($tAl);
731 // var_dump ($this->refers);
735 * function to dump a <type>Sql
736 * problem with the field types. :D
738 * @param tdoAbstract $obj
740 static public function dumpSchema ($obj) {
741 if ($obj instanceof tdoAbstract)
742 throw new Exception('Can\'t generate sql dump');
744 $sql = 'CREATE TABLE '. $obj->name . ' (';
746 foreach ($obj->getFields() as $fieldName => $data) {
747 $sql .= $fieldName.' '.$data[0].', ';
749 $sql .= ')';
750 return $sql;
756 * class to abstract a where clause in a SQL query
757 * TODO: add possibility of complex wheres: (t1 condition1 OR|AND|XOR t2.condition2)
758 * TODO: abstract the condition part of a where clause - currently string based :D
760 class tdoAbstractClause {
761 protected $subject, $predicate, $predicative;
764 * initializing a WHERE|ON clause
766 * @param tdoAbstractClause|tdoAbstractField $subject
767 * @param string $predicate
768 * @param tdoAbstractClause|tdoAbstractField|null $complement
770 public function __construct ($subject, $predicate = null, $predicative = null) {
771 // I must be careful with the $subject == 1 because (int)object == 1
772 if (($subject === 1 || is_string($subject)) && $predicate == null && $predicative == null) {
773 $this->subject = $subject;
774 $this->predicate = '';
775 $this->predicative = '';
776 return;
779 if (($subject instanceof tdoAbstractField ) || ($subject instanceof tdoAbstractClause )) {
780 $this->subject = &$subject;
782 $subject->set_where = true;
784 $this->predicative = &$predicative;
786 if ($this->validPredicative ($predicate))
787 $this->predicate = $predicate;
789 } else {
790 $this->subject = '';
791 $this->predicate = '';
792 $this->predicative = '';
794 return;
797 public function __destruct () {}
799 public function __toString () {
800 // var_dump($this->subject, $this->predicate, $this->predicative);
801 // echo '<br/>';
802 if ($this->subject === '1' || is_string($this->subject)) {
803 // var_dump($this->subject);
804 return (string)$this->subject;
805 } elseif ($this->subject instanceof tdoAbstractClause) {
806 $subStr = (string)$this->subject;
807 } elseif ($this->subject instanceof tdoAbstractField) {
808 // without $this->subject->table != 't' we have a bug in the delete op
809 $subStr = ($this->subject->table != 't' ? $this->subject->table.'.': '').$this->subject->name;
810 } else {
811 return '';
814 if (is_null($this->predicative)) {
815 if ($this->validPredicative ($this->predicate)) {
816 $preStr = 'NULL';
817 } else
818 $preStr = '';
819 } elseif (is_numeric($this->predicative)) {
820 $preStr = $this->predicative;
821 } elseif (is_string($this->predicative)) {
822 $preStr = $this->predicative;
824 if ($this->predicate == 'LIKE') {
825 $preStr = '%'.$this->predicate.'%';
828 $preStr = (stripos($preStr, '"') !== 0 ? '"'.$preStr.'"' : $preStr);//'"'.$preStr.'"';
829 } elseif (is_array($this->predicative)) {
830 $preStr = '("'.implode('", "',$this->predicative).'")';
831 } elseif ($this->predicative instanceof tdoAbstractfield) {
832 $preStr = ($this->predicative->table != 't' ? $this->predicative->table.'.': '').$this->predicative->name;
833 } elseif ($this->predicative instanceof tdoAbstractClause) {
834 $subStr = $subStr;
835 $preStr = $this->predicative;
838 $retStr = $subStr.' '.$this->predicate.' '.$preStr;
839 if (($this->subject instanceof tdoAbstractClause) && ($this->predicative instanceof tdoAbstractClause))
840 return '('.$retStr.')';
842 return $retStr;
845 private function validPredicative ($predicate) {
846 // need to find a way to abstract these
847 // $validPredicates = array (
848 // 'AND',
849 // '&&',
850 // 'OR',
851 // '||',
852 // 'XOR',
853 // 'IS',
854 // 'IS NOT',
855 // '!',
856 // 'IN',
857 // 'LIKE',
858 // '=',
859 // '!=',
860 // '<>'
861 // );
862 if ($this->predicative instanceof tdoAbstractClause) {
863 // we'll have Subject AND|OR|XOR Predicative
864 $validPredicates = array (
865 'AND',
866 '&&',
867 'OR',
868 '||',
869 'XOR'
871 } elseif (($this->predicative instanceof tdoAbstractField) || is_numeric($this->predicative)) {
872 // we'll have Subject =|!= Predicative
873 $validPredicates = array (
874 '=',
875 '!=',
876 '>',
877 '<',
878 '>=',
879 '<='
881 } elseif (is_array($this->predicative)) {
882 $validPredicates = array (
883 'IN',
884 'NOT IN'
886 } elseif (is_string($this->predicative)) {
887 $validPredicates = array (
888 '=',
889 'LIKE',
890 // dates
891 '>',
892 '<',
893 '>=',
894 '<='
896 } elseif (is_null($this->predicative)) {
897 $validPredicates = array (
898 'IS',
899 'IS NOT'
903 return in_array($predicate, $validPredicates);
905 // if (in_array($predicate, $validPredicates) && (($predicative instanceof tdoAbstractClause) || ($predicative instanceof tdoAbstractField)))
906 // return true;
907 // return false;
911 class tdoAbstractJoin {
912 static public $validTypes = array (
913 'INNER',
914 'LEFT',
915 'RIGHT',
916 'OUTER'
918 protected $state,
919 $type,
921 $leftTable,
922 $rightTable,
924 $leftField,
925 $rightField;
927 public function __construct ($type, &$lt, &$rt, &$lf, &$rf, $state) {
928 if ($rt instanceof tdoAbstract ||
929 $lt instanceof tdoAbstract
931 $this->leftTable = &$lt;
932 $this->rightTable = &$rt;
934 if (tdoAbstractJoin::isValidType($type))
935 $this->type = $type;
937 if (
938 $lf instanceof tdoAbstractField &&
939 $rf instanceof tdoAbstractField
941 $this->rightField = &$rf;
942 $this->leftField = &$lf;
945 $this->state = $state;
948 $this->composeFields ();
949 $this->composeWheres ();
953 public function __destruct () {}
955 public function __toString() {
956 $lAlias = $this->leftTable->get_alias();
958 return (string)$this->type.' JOIN '.$this->rightTable->get_name().
959 ' AS t'.$this->state.' ON '.(isset($lAlias) ? $lAlias : $this->leftTable->get_name()).
960 '.'.$this->leftField->name.
961 ' = t'.$this->state.'.'.$this->rightField->name.' ';
965 * Will compose the $rightTable and $leftTable fields
966 * @return void
968 public function composeFields () {
969 $leftFields = $this->leftTable->get_members();
971 $this->rightTable->set_alias($this->state);
972 $rightFields = $this->rightTable->get_members();
975 $this->leftTable->addFields($rightFields);
979 * Will compose the $rightTable and $leftTable WHERE clauses
980 * @return void
982 public function composeWheres () {
983 if (!is_array($this->leftTable->wheres))
984 $this->leftTable->wheres = array();
985 if (!is_array($this->rightTable->wheres))
986 $this->rightTable->wheres = array();
988 // var_dump($this->rightTable->wheres, $this->leftTable );die;
989 foreach ($this->rightTable->wheres as $where) {
990 $this->leftTable->addWhere ($where);
992 $this->leftTable->wheres = array_merge($this->rightTable->wheres, $this->leftTable->wheres);
995 public function set_state ($st) {
996 $this->state = $st;
999 static public function isValidType ($inc) {
1000 if (in_array($inc, tdoAbstractJoin::$validTypes))
1001 return true;
1002 return false;
1006 define ('INDEX', 1);
1007 define ('PRIMARY', 2);
1008 define ('UNIQUE', 4);
1009 define ('FULLTEXT', 8);
1011 class tdoAbstractField {
1012 static public $validTypes = array (
1013 'VARCHAR',
1014 'INT',
1015 'DATE',
1016 'TEXT',
1017 'FLOAT',
1018 'TIMESTAMP',
1019 'ENUM'
1022 protected $name, $type, $flags, $value, $table, $modifier = null, $order = null, $group = null, $where = false;
1024 public function __construct ($incName, $incTable, $incType='INT', $incFlags=0) {
1025 $this->name = $incName;
1026 $this->table = $incTable;
1027 $this->type = $incType;
1028 $this->flags = $incFlags;
1031 public function __set ( $key, $value ) {
1032 if ( array_key_exists ($key, get_object_vars($this)) ) {
1033 $this->$key = $value;
1035 // if ($key == 'where')
1036 // var_dump($this);
1038 if ( is_null ($this->type) )
1039 $this->setType();
1041 return true;
1042 } else
1043 return false;
1046 public function __get ( $key ) {
1047 return $this->$key;
1050 public function __call ( $method, $args) {
1051 $all = get_object_vars($this);
1053 if ( preg_match( '/set_(.*)/', $method, $found ) ) {
1054 if (array_key_exists( $found[1], $all)){
1055 $this->$found[1] = $args[0];
1056 return true;
1058 } elseif ( preg_match( '/get_(.*)/', $method, $found ) ) {
1059 if (array_key_exists( $found[1], $all)){
1060 return $this->$found[1];
1063 return false;
1066 public function __destruct () {}
1068 public function __toString () {
1069 return (string)$this->value;
1072 // public function inWhere () {
1073 // return $this->where;
1074 // }
1076 static public function isValidType ($inc) {
1077 if (in_array($inc, tdoAbstractField::$validTypes)){
1078 return true;
1080 return false;
1083 public function set_modifier ($modif) {
1084 // if (stristr($modif, '%'))
1085 $this->modifier = $modif;
1088 public function set_value ($value) {
1089 $this->value = $value;
1092 public function set_group ($true = true) {
1093 $this->group = (bool)$true;
1096 public function set_order ($asc = true) {
1097 $this->order = (bool)$asc;
1100 public function isIndex() {
1101 return (($this->flags & INDEX) == INDEX);
1104 public function isPrimary() {
1105 return (($this->flags & PRIMARY) == PRIMARY);
1108 public function isFullText() {
1109 return (($this->flags & FULLTEXT) == FULLTEXT);
1111 public function isUnique () {
1112 return (($this->flags & UNIQUE) == UNIQUE);
1114 public function setType () {
1115 $incValue = $this->value;
1116 // TODO : enums
1117 if (is_int($incValue)) {
1118 $this->type = 'INT';
1119 } elseif (is_float($incValue)) {
1120 $this->type = 'FLOAT';
1121 } elseif (is_string($incValue)) {
1122 if (strtotime($this->value)){
1123 $this->type = 'DATE';
1124 }elseif (strlen($incValue) > 255)
1125 $this->type = 'TEXT';
1126 else
1127 $this->type = 'VARCHAR';