1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
18:
19: 20: 21: 22: 23: 24: 25:
26: abstract class ItemCollection extends cItemBaseAbstract {
27:
28: 29: 30: 31: 32: 33:
34: protected $objects;
35:
36: 37: 38: 39: 40:
41: protected $_driver;
42:
43: 44: 45: 46: 47:
48: protected $_collectionCache = array();
49:
50: 51: 52: 53: 54:
55: protected $_itemClass;
56:
57: 58: 59: 60: 61:
62: protected $_iteratorItem;
63:
64: 65: 66: 67: 68:
69: protected $_JoinPartners = array();
70:
71: 72: 73: 74: 75:
76: protected $_forwardJoinPartners;
77:
78: 79: 80: 81: 82:
83: protected $_whereRestriction;
84:
85: 86: 87: 88: 89:
90: protected $_innerGroupConditions = array();
91:
92: 93: 94: 95: 96:
97: protected $_groupConditions;
98:
99: 100: 101: 102: 103:
104: protected $_resultFields = array();
105:
106: 107: 108: 109: 110:
111: protected $_encoding;
112:
113: 114: 115: 116: 117:
118: protected $_itemClassInstance;
119:
120: 121: 122: 123: 124: 125:
126: protected $_aOperators;
127:
128: 129: 130: 131: 132: 133:
134: protected $_bAllMode = false;
135:
136: 137: 138: 139: 140:
141: protected $_where;
142:
143: 144: 145: 146: 147:
148: protected $_order;
149:
150: 151: 152: 153: 154:
155: protected $_limitStart;
156:
157: 158: 159: 160: 161:
162: protected $_limitCount;
163:
164: 165: 166: 167: 168:
169: protected $_lastSQL;
170:
171: 172: 173: 174: 175:
176: protected $_links;
177:
178: 179: 180: 181: 182: 183: 184: 185: 186: 187:
188: public function __construct($sTable, $sPrimaryKey) {
189: parent::__construct($sTable, $sPrimaryKey, get_parent_class($this));
190:
191: $this->resetQuery();
192:
193:
194: $this->_initializeDriver();
195:
196:
197: if (isset($GLOBALS['lang']) && isset($GLOBALS['aLanguageEncodings'])) {
198: $this->setEncoding($GLOBALS['aLanguageEncodings'][$GLOBALS['lang']]);
199: }
200:
201: $this->_aOperators = array(
202: '=',
203: '!=',
204: '<>',
205: '<',
206: '>',
207: '<=',
208: '>=',
209: 'LIKE',
210: 'DIACRITICS'
211: );
212: }
213:
214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225:
226: protected function _setJoinPartner($sForeignCollectionClass) {
227: if (class_exists($sForeignCollectionClass)) {
228:
229: if (!in_array($sForeignCollectionClass, $this->_JoinPartners)) {
230: $this->_JoinPartners[] = cString::toLowerCase($sForeignCollectionClass);
231: }
232: } else {
233: $msg = "Could not instantiate class [$sForeignCollectionClass] for use " . "with _setJoinPartner in class " . get_class($this);
234: throw new cInvalidArgumentException($msg);
235: }
236: }
237:
238: 239: 240: 241: 242: 243: 244: 245:
246: protected function _setItemClass($sClassName) {
247: if (class_exists($sClassName)) {
248: $this->_itemClass = $sClassName;
249: $this->_itemClassInstance = new $sClassName();
250:
251:
252:
253: $this->_initializeDriver();
254: $this->_driver->setItemClassInstance($this->_itemClassInstance);
255: } else {
256: $msg = "Could not instantiate class [$sClassName] for use with " . "_setItemClass in class " . get_class($this);
257: throw new cInvalidArgumentException($msg);
258: }
259: }
260:
261: 262: 263: 264: 265: 266:
267: protected function _initializeDriver($bForceInit = false) {
268: if (!is_object($this->_driver) || $bForceInit == true) {
269: $this->_driver = new cGenericDbDriverMysql();
270: }
271: }
272:
273: 274: 275: 276: 277:
278: public function setEncoding($sEncoding) {
279: $this->_encoding = $sEncoding;
280: $this->_driver->setEncoding($sEncoding);
281: }
282:
283: 284: 285: 286: 287: 288: 289: 290:
291: public function link($sForeignClass) {
292: if (class_exists($sForeignClass)) {
293: $this->_links[$sForeignClass] = new $sForeignClass();
294: } else {
295: $msg = "Could not find class [$sForeignClass] for use with link in class " . get_class($this);
296: throw new cInvalidArgumentException($msg);
297: }
298: }
299:
300: 301: 302: 303: 304: 305:
306: public function setLimit($iRowStart, $iRowCount) {
307: $this->_limitStart = $iRowStart;
308: $this->_limitCount = $iRowCount;
309: }
310:
311: 312: 313: 314: 315: 316: 317:
318: public function setWhere($sField, $mRestriction, $sOperator = '=') {
319: $sField = cString::toLowerCase($sField);
320: $this->_where['global'][$sField]['operator'] = $sOperator;
321: $this->_where['global'][$sField]['restriction'] = $mRestriction;
322: }
323:
324: 325: 326: 327: 328: 329: 330:
331: public function deleteWhere($sField, $mRestriction, $sOperator = '=') {
332: $sField = cString::toLowerCase($sField);
333: if (isset($this->_where['global'][$sField]) && is_array($this->_where['global'][$sField])) {
334: if ($this->_where['global'][$sField]['operator'] == $sOperator && $this->_where['global'][$sField]['restriction'] == $mRestriction) {
335: unset($this->_where['global'][$sField]);
336: }
337: }
338: }
339:
340: 341: 342: 343: 344: 345: 346: 347:
348: public function setWhereGroup($sGroup, $sField, $mRestriction, $sOperator = '=') {
349: $sField = cString::toLowerCase($sField);
350: $this->_where['groups'][$sGroup][$sField]['operator'] = $sOperator;
351: $this->_where['groups'][$sGroup][$sField]['restriction'] = $mRestriction;
352: }
353:
354: 355: 356: 357: 358: 359: 360: 361: 362:
363: public function deleteWhereGroup($sGroup, $sField, $mRestriction, $sOperator = '=') {
364: $sField = cString::toLowerCase($sField);
365: if (is_array($this->_where['groups'][$sGroup]) && isset($this->_where['groups'][$sGroup][$sField]) && is_array($this->_where['groups'][$sGroup][$sField])) {
366: if ($this->_where['groups'][$sGroup][$sField]['operator'] == $sOperator && $this->_where['groups'][$sGroup][$sField]['restriction'] == $mRestriction) {
367: unset($this->_where['groups'][$sGroup][$sField]);
368: }
369: }
370: }
371:
372: 373: 374: 375: 376: 377:
378: public function setInnerGroupCondition($sGroup, $sCondition = 'AND') {
379: $this->_innerGroupConditions[$sGroup] = $sCondition;
380: }
381:
382: 383: 384: 385: 386: 387: 388:
389: public function setGroupCondition($sGroup1, $sGroup2, $sCondition = 'AND') {
390: $this->_groupConditions[$sGroup1][$sGroup2] = $sCondition;
391: }
392:
393: 394: 395: 396: 397: 398:
399: protected function _buildGroupWhereStatements() {
400: $aWheres = array();
401: $aGroupWhere = array();
402:
403: $mLastGroup = false;
404: $sGroupWhereStatement = '';
405:
406:
407: if (count($this->_where['groups']) > 0) {
408:
409: foreach ($this->_where['groups'] as $groupname => $group) {
410: $aWheres = array();
411:
412:
413:
414:
415: foreach ($group as $field => $item) {
416: $aWheres[] = $this->_driver->buildOperator($field, $item['operator'], $item['restriction']);
417: }
418:
419:
420: $sOperator = 'AND';
421: if (isset($this->_innerGroupConditions[$groupname])) {
422: $sOperator = $this->_innerGroupConditions[$groupname];
423: }
424:
425: $aGroupWhere[$groupname] = implode(' ' . $sOperator . ' ', $aWheres);
426: }
427: }
428:
429:
430: foreach ($aGroupWhere as $groupname => $group) {
431: if ($mLastGroup != false) {
432: $sOperator = 'AND';
433:
434: if (isset($this->_groupConditions[$groupname])) {
435: if (isset($this->_groupConditions[$groupname][$mLastGroup])) {
436: $sOperator = $this->_groupConditions[$groupname][$mLastGroup];
437: }
438: }
439:
440:
441: if (isset($this->_groupConditions[$mLastGroup])) {
442: if (isset($this->_groupConditions[$mLastGroup][$groupname])) {
443: $sOperator = $this->_groupConditions[$mLastGroup][$groupname];
444: }
445: }
446:
447: $sGroupWhereStatement .= ' ' . $sOperator . ' (' . $group . ')';
448: } else {
449: $sGroupWhereStatement .= '(' . $group . ')';
450: }
451:
452: $mLastGroup = $groupname;
453: }
454:
455: return $sGroupWhereStatement;
456: }
457:
458: 459: 460: 461: 462: 463:
464: protected function _buildWhereStatements() {
465: $aWheres = array();
466:
467:
468: foreach ($this->_where['global'] as $field => $item) {
469: $aWheres[] = $this->_driver->buildOperator($field, $item['operator'], $item['restriction']);
470: }
471:
472: return implode(' AND ', $aWheres);
473: }
474:
475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498:
499: protected function _fetchJoinTables() {
500: $aParameters = array();
501: $aFields = array();
502: $aTables = array();
503: $aJoins = array();
504: $aWheres = array();
505:
506:
507: foreach ($this->_links as $link => $object) {
508: $matches = $this->_findReverseJoinPartner(cString::toLowerCase(get_class($this)), $link);
509: if ($matches !== false) {
510: if (isset($matches['desttable'])) {
511:
512: $aParameters[] = $this->_driver->buildJoinQuery($matches['desttable'], cString::toLowerCase($matches['destclass']), $matches['key'], cString::toLowerCase($matches['sourceclass']), $matches['key']);
513: } else {
514: foreach ($matches as $match) {
515: $aParameters[] = $this->_driver->buildJoinQuery($match['desttable'], cString::toLowerCase($match['destclass']), $match['key'], cString::toLowerCase($match['sourceclass']), $match['key']);
516: }
517: }
518: } else {
519: throw new cUnexpectedValueException("The join partner '" . get_class($this) . "' is not registered and can not be used with link().");
520: }
521: }
522:
523:
524: $aFields[] = cString::toLowerCase(cString::toLowerCase(get_class($this))) . '.' . $this->getPrimaryKeyName();
525:
526:
527: foreach ($aParameters as $parameter) {
528: array_unshift($aFields, $parameter['field']);
529: array_unshift($aTables, $parameter['table']);
530: array_unshift($aJoins, $parameter['join']);
531: array_unshift($aWheres, $parameter['where']);
532: }
533:
534: $aFields = array_filter(array_unique($aFields));
535: $aTables = array_filter(array_unique($aTables));
536: $aJoins = array_filter(array_unique($aJoins));
537: $aWheres = array_filter(array_unique($aWheres));
538:
539: return array(
540: 'fields' => $aFields,
541: 'tables' => $aTables,
542: 'joins' => $aJoins,
543: 'wheres' => $aWheres
544: );
545: }
546:
547: 548: 549: 550: 551:
552: protected function _resolveLinks() {
553: $aResolvedLinks = array();
554: $aResolvedLinks[] = cString::toLowerCase(get_class($this));
555:
556: foreach ($this->_JoinPartners as $link) {
557: $class = new $link();
558: $aResolvedLinks = array_merge($class->_resolveLinks(), $aResolvedLinks);
559: }
560: return $aResolvedLinks;
561: }
562:
563: 564: 565:
566: public function resetQuery() {
567: $this->setLimit(0, 0);
568: $this->_forwardJoinPartners = array();
569: $this->_links = array();
570: $this->_where['global'] = array();
571: $this->_where['groups'] = array();
572: $this->_groupConditions = array();
573: $this->_resultFields = array();
574: }
575:
576: 577: 578: 579: 580: 581: 582:
583: public function query() {
584: if (!isset($this->_itemClassInstance)) {
585: throw new cException('GenericDB can\'t use query() if no item class is set via setItemClass');
586: }
587:
588: $aGroupWhereStatements = $this->_buildGroupWhereStatements();
589: $sWhereStatements = $this->_buildWhereStatements();
590: $aParameters = $this->_fetchJoinTables();
591:
592: $aStatement = array(
593: 'SELECT',
594: implode(', ', (array_merge($aParameters['fields'], $this->_resultFields))),
595: 'FROM',
596: '`' . $this->table . '` AS ' . cString::toLowerCase(get_class($this))
597: );
598:
599: if (count($aParameters['tables']) > 0) {
600: $aStatement[] = implode(', ', $aParameters['tables']);
601: }
602:
603: if (count($aParameters['joins']) > 0) {
604: $aStatement[] = implode(' ', $aParameters['joins']);
605: }
606:
607: $aWheres = array();
608:
609: if (count($aParameters['wheres']) > 0) {
610: $aWheres[] = implode(', ', $aParameters['wheres']);
611: }
612:
613: if ($aGroupWhereStatements != '') {
614: $aWheres[] = $aGroupWhereStatements;
615: }
616:
617: if ($sWhereStatements != '') {
618: $aWheres[] = $sWhereStatements;
619: }
620:
621: if (count($aWheres) > 0) {
622: $aStatement[] = 'WHERE ' . implode(' AND ', $aWheres);
623: }
624:
625: if ($this->_order != '') {
626: $aStatement[] = 'ORDER BY ' . $this->_order;
627: }
628:
629: if ($this->_limitStart > 0 || $this->_limitCount > 0) {
630: $iRowStart = intval($this->_limitStart);
631: $iRowCount = intval($this->_limitCount);
632: $aStatement[] = "LIMIT $iRowStart, $iRowCount";
633: }
634:
635: $sql = implode(' ', $aStatement);
636:
637: $result = $this->db->query($sql);
638: $this->_lastSQL = $sql;
639:
640:
641:
642: $this->_bAllMode = false;
643: return ($result) ? true : false;
644: }
645:
646: 647: 648: 649: 650: 651: 652:
653: public function setOrder($order) {
654: $this->_order = cString::toLowerCase($order);
655: }
656:
657: 658: 659: 660: 661:
662: public function addResultField($sField) {
663: $sField = cString::toLowerCase($sField);
664: if (!in_array($sField, $this->_resultFields)) {
665: $this->_resultFields[] = $sField;
666: }
667: }
668:
669: 670: 671: 672: 673:
674: public function removeResultField($sField) {
675: $sField = cString::toLowerCase($sField);
676: $key = array_search($sField, $this->_resultFields);
677: if ($key !== false) {
678: unset($this->_resultFields[$key]);
679: }
680: }
681:
682: 683: 684: 685: 686: 687: 688:
689: protected function _findReverseJoinPartner($sParentClass, $sClassName) {
690:
691: $sClassName = cString::toLowerCase($sClassName);
692: $sParentClass = cString::toLowerCase($sParentClass);
693:
694:
695: if (in_array($sClassName, $this->_JoinPartners)) {
696: $obj = new $sClassName();
697: return array(
698: 'desttable' => $obj->table,
699: 'destclass' => $sClassName,
700: 'sourceclass' => $sParentClass,
701: 'key' => $obj->getPrimaryKeyName()
702: );
703: } else {
704:
705: foreach ($this->_JoinPartners as $join => $tmpClassname) {
706: $obj = new $tmpClassname();
707: $status = $obj->_findReverseJoinPartner($tmpClassname, $sClassName);
708:
709: if (is_array($status)) {
710: $returns = array();
711:
712: if (!isset($status['desttable'])) {
713: foreach ($status as $subitem) {
714: $returns[] = $subitem;
715: }
716: } else {
717: $returns[] = $status;
718: }
719:
720: $returns[] = array(
721: 'desttable' => $obj->table,
722: 'destclass' => $tmpClassname,
723: 'sourceclass' => $sParentClass,
724: 'key' => $obj->getPrimaryKeyName()
725: );
726: return $returns;
727: }
728: }
729: }
730: return false;
731: }
732:
733: 734: 735: 736: 737: 738: 739: 740: 741: 742: 743: 744: 745: 746: 747: 748: 749:
750: public function select($sWhere = '', $sGroupBy = '', $sOrderBy = '', $sLimit = '') {
751: unset($this->objects);
752:
753: if ($sWhere == '') {
754: $sWhere = '';
755: } else {
756: $sWhere = ' WHERE ' . $sWhere;
757: }
758:
759: if ($sGroupBy != '') {
760: $sGroupBy = ' GROUP BY ' . $sGroupBy;
761: }
762:
763: if ($sOrderBy != '') {
764: $sOrderBy = ' ORDER BY ' . $sOrderBy;
765: }
766:
767: if ($sLimit != '') {
768: $sLimit = ' LIMIT ' . $sLimit;
769: }
770:
771: $sFields = ($this->_settings['select_all_mode']) ? '*' : $this->getPrimaryKeyName();
772: $sql = 'SELECT ' . $sFields . ' FROM `' . $this->table . '`' . $sWhere . $sGroupBy . $sOrderBy . $sLimit;
773: $this->db->query($sql);
774: $this->_lastSQL = $sql;
775: $this->_bAllMode = $this->_settings['select_all_mode'];
776:
777: if ($this->db->numRows() == 0) {
778: return false;
779: } else {
780: return true;
781: }
782: }
783:
784: 785: 786: 787: 788: 789: 790: 791: 792: 793: 794: 795: 796: 797: 798: 799: 800: 801: 802: 803: 804: 805:
806: public function flexSelect($sDistinct = '', $sFrom = '', $sWhere = '', $sGroupBy = '', $sOrderBy = '', $sLimit = '') {
807: unset($this->objects);
808:
809: if ($sDistinct != '') {
810: $sDistinct = 'DISTINCT ';
811: }
812:
813: if ($sFrom != '') {
814: $sFrom = ', ' . $sFrom;
815: }
816:
817: if ($sWhere != '') {
818: $sWhere = ' WHERE ' . $sWhere;
819: }
820:
821: if ($sGroupBy != '') {
822: $sGroupBy = ' GROUP BY ' . $sGroupBy;
823: }
824:
825: if ($sOrderBy != '') {
826: $sOrderBy = ' ORDER BY ' . $sOrderBy;
827: }
828:
829: if ($sLimit != '') {
830: $sLimit = ' LIMIT ' . $sLimit;
831: }
832:
833: $sql = 'SELECT ' . $sDistinct . cString::toLowerCase(get_class($this)) . '.' . $this->getPrimaryKeyName() . ' AS ' . $this->getPrimaryKeyName() . ' FROM `' . $this->table . '` AS ' . cString::toLowerCase(get_class($this)) . $sFrom . $sWhere . $sGroupBy . $sOrderBy . $sLimit;
834:
835: $this->db->query($sql);
836: $this->_lastSQL = $sql;
837:
838: $this->_bAllMode = false;
839:
840: if ($this->db->numRows() == 0) {
841: return false;
842: } else {
843: return true;
844: }
845: }
846:
847: 848: 849: 850: 851: 852: 853: 854: 855:
856: public function exists($mId) {
857: $oDb = $this->_getSecondDBInstance();
858: $sql = "SELECT `%s` FROM %s WHERE %s='%s'";
859: $oDb->query($sql, $this->getPrimaryKeyName(), $this->table, $this->getPrimaryKeyName(), $mId);
860: return ($oDb->nextRecord()) ? true : false;
861: }
862:
863: 864: 865: 866: 867: 868: 869: 870:
871: public function next() {
872: $ret = false;
873: while ($this->db->nextRecord()) {
874: if ($this->_bAllMode) {
875: $aRs = $this->db->toArray(cDb::FETCH_BOTH);
876: $ret = $this->loadItem($aRs);
877: } else {
878: $ret = $this->loadItem($this->db->f($this->getPrimaryKeyName()));
879: }
880:
881: if ($ret->get($this->getPrimaryKeyName()) == "") {
882: continue;
883: } else {
884: break;
885: }
886: }
887: return $ret;
888: }
889:
890: 891: 892: 893: 894: 895: 896:
897: public function fetchObject($sClassName) {
898: $sKey = cString::toLowerCase($sClassName);
899:
900: if (!is_object($this->_collectionCache[$sKey])) {
901: $this->_collectionCache[$sKey] = new $sClassName();
902: }
903:
904: $obj = $this->_collectionCache[$sKey];
905: return $obj->loadItem($this->db->f($obj->getPrimaryKeyName()));
906: }
907:
908: 909: 910: 911: 912: 913: 914: 915: 916: 917: 918: 919: 920: 921: 922:
923: public function fetchTable(array $aFields = array(), array $aObjects = array()) {
924: $row = 1;
925: $aTable = array();
926:
927: if ($this->count() > 0) {
928:
929: $this->db->seek(0);
930:
931: while ($this->db->nextRecord()) {
932: foreach ($aFields as $alias => $field) {
933: if ($alias != '') {
934: $aTable[$row][$alias] = $this->db->f($field);
935: } else {
936: $aTable[$row][$field] = $this->db->f($field);
937: }
938: }
939:
940:
941: foreach ($aObjects as $alias => $object) {
942: if ($alias != '') {
943: if (isset($aTable[$row][$alias])) {
944:
945: if (is_array($aTable[$row][$alias])) {
946: $aTable[$row][$alias][] = $this->fetchObject($object);
947: } else {
948:
949: $aTable[$row][$alias] = array();
950: $aTable[$row][$alias][] = $this->fetchObject($object);
951: }
952: } else {
953: $aTable[$row][$alias] = $this->fetchObject($object);
954: }
955: } else {
956: $aTable[$row][$object] = $this->fetchObject($object);
957: }
958: }
959: $row++;
960: }
961:
962: $this->db->seek(0);
963:
964: }
965:
966: return $aTable;
967: }
968:
969: 970: 971: 972: 973: 974: 975: 976: 977: 978:
979: public function queryAndFetchStructured(array $aObjects) {
980: $aOrder = array();
981: $aFetchObjects = array();
982: $aResult = array();
983:
984: foreach ($aObjects as $object) {
985: $x = new $object();
986: $object = cString::toLowerCase($object);
987: $aOrder[] = $object . '.' . $x->getPrimaryKeyName() . ' ASC';
988: $aFetchObjects[] = $x;
989: }
990:
991: $this->setOrder(implode(', ', $aOrder));
992: $this->query();
993:
994: $this->db->seek(0);
995:
996: while ($this->db->nextRecord()) {
997: $aResult = $this->_recursiveStructuredFetch($aFetchObjects, $aResult);
998: }
999:
1000: return $aResult;
1001: }
1002:
1003: 1004: 1005: 1006: 1007: 1008:
1009: protected function _recursiveStructuredFetch(array $aObjects, array $aResult) {
1010: $i = array_shift($aObjects);
1011:
1012: $value = $this->db->f($i->getPrimaryKeyName());
1013:
1014: if (!is_null($value)) {
1015: $aResult[$value]['class'] = cString::toLowerCase(get_class($i));
1016: $aResult[$value]['object'] = $i->loadItem($value);
1017:
1018: if (count($aObjects) > 0) {
1019: $aResult[$value]['items'] = $this->_recursiveStructuredFetch($aObjects, $aResult[$value]['items']);
1020: }
1021: }
1022:
1023: return $aResult;
1024: }
1025:
1026: 1027: 1028: 1029: 1030: 1031:
1032: public function count() {
1033: return $this->db->numRows();
1034: }
1035:
1036: 1037: 1038: 1039: 1040: 1041: 1042: 1043: 1044:
1045: public function fetchById($id) {
1046: if (is_numeric($id)) {
1047: $id = (int) $id;
1048: } elseif (is_string($id)) {
1049: $id = $this->escape($id);
1050: }
1051: return $this->loadItem($id);
1052: }
1053:
1054: 1055: 1056: 1057: 1058: 1059: 1060: 1061: 1062: 1063: 1064:
1065: public function loadItem($mItem) {
1066: if (empty($this->_itemClass)) {
1067: $sMsg = "ItemClass has to be set in the constructor of class " . get_class($this) . ")";
1068: throw new cException($sMsg);
1069: }
1070:
1071: if (!is_object($this->_iteratorItem)) {
1072: $this->_iteratorItem = new $this->_itemClass();
1073: }
1074: $obj = clone $this->_iteratorItem;
1075:
1076: if (is_array($mItem)) {
1077: $obj->loadByRecordSet($mItem);
1078: } else {
1079: $obj->loadByPrimaryKey($mItem);
1080: }
1081:
1082: return $obj;
1083: }
1084:
1085: 1086: 1087: 1088: 1089: 1090: 1091: 1092: 1093: 1094: 1095: 1096: 1097:
1098: public function createNewItem($data = NULL) {
1099: $this->_executeCallbacks(self::CREATE_BEFORE, get_class($this), array());
1100:
1101: $db = $this->_getSecondDBInstance();
1102:
1103: $primaryKeyValue = NULL;
1104:
1105:
1106: if (is_array($data)) {
1107: if (array_key_exists($this->getPrimaryKeyName(), $data)) {
1108: $primaryKeyValue = $data[$this->getPrimaryKeyName()];
1109: }
1110: } else {
1111:
1112: $primaryKeyValue = $data;
1113: $data = array(
1114: $this->getPrimaryKeyName() => $data
1115: );
1116: }
1117:
1118:
1119: $sql = $db->buildInsert($this->table, $data);
1120:
1121: $db->query($sql);
1122:
1123: if ($primaryKeyValue === NULL) {
1124: $primaryKeyValue = $db->getLastInsertedId();
1125: }
1126:
1127: if ($db->affectedRows() == 0) {
1128: $this->_executeCallbacks(self::CREATE_FAILURE, $this->_itemClass, array());
1129: } else {
1130: $this->_executeCallbacks(self::CREATE_SUCCESS, $this->_itemClass, array(
1131: $primaryKeyValue
1132: ));
1133: }
1134:
1135: return $this->loadItem($primaryKeyValue);
1136: }
1137:
1138: 1139: 1140: 1141: 1142: 1143: 1144: 1145: 1146: 1147: 1148: 1149: 1150:
1151: public function copyItem($srcItem, array $fieldsToOverwrite = array()) {
1152: if (get_class($srcItem) !== $this->_itemClass) {
1153: throw new cInvalidArgumentException("Item class doesn't match");
1154: } elseif (!$srcItem->isLoaded()) {
1155: throw new cInvalidArgumentException("Item instance has no loaded recordset");
1156: }
1157:
1158: $destItem = self::createNewItem();
1159: if (!is_object($destItem)) {
1160: return NULL;
1161: }
1162:
1163: $rs = $srcItem->toArray();
1164:
1165: foreach ($rs as $field => $value) {
1166: if (is_numeric($field)) {
1167:
1168: continue;
1169: } elseif ($field == $this->getPrimaryKeyName()) {
1170:
1171: continue;
1172: }
1173:
1174: if (isset($fieldsToOverwrite[$field])) {
1175: $value = $fieldsToOverwrite[$field];
1176: }
1177:
1178: $destItem->set($field, $value);
1179: }
1180:
1181: $destItem->store();
1182: return $destItem;
1183: }
1184:
1185: 1186: 1187: 1188: 1189: 1190: 1191: 1192: 1193: 1194:
1195: public function getIdsByWhereClause($sWhere) {
1196: $oDb = $this->_getSecondDBInstance();
1197:
1198: $aIds = array();
1199:
1200:
1201: $sql = 'SELECT ' . $this->getPrimaryKeyName() . ' AS pk FROM `' . $this->table . '` WHERE ' . $sWhere;
1202: $oDb->query($sql);
1203: while ($oDb->nextRecord()) {
1204: $aIds[] = $oDb->f('pk');
1205: }
1206:
1207: return $aIds;
1208: }
1209:
1210: 1211: 1212: 1213: 1214: 1215: 1216: 1217: 1218: 1219: 1220: 1221:
1222: public function getFieldsByWhereClause(array $aFields, $sWhere) {
1223: $oDb = $this->_getSecondDBInstance();
1224:
1225: $aEntries = array();
1226:
1227: if (count($aFields) == 0) {
1228: return $aEntries;
1229: }
1230:
1231:
1232: $aEscapedFields = array_map(array(
1233: $oDb,
1234: 'escape'
1235: ), $aFields);
1236:
1237: $fields = implode(', ', $aEscapedFields);
1238:
1239:
1240: $sql = 'SELECT ' . $fields . ' FROM `' . $this->table . '` WHERE ' . $sWhere;
1241: $oDb->query($sql);
1242: while ($oDb->nextRecord()) {
1243: $data = array();
1244: foreach ($aFields as $field) {
1245: $data[$field] = $oDb->f($field);
1246: }
1247: $aEntries[] = $data;
1248: }
1249:
1250: return $aEntries;
1251: }
1252:
1253: 1254: 1255: 1256: 1257: 1258: 1259:
1260: public function getAllIds() {
1261: $oDb = $this->_getSecondDBInstance();
1262:
1263: $aIds = array();
1264:
1265:
1266: $sql = 'SELECT ' . $this->getPrimaryKeyName() . ' AS pk FROM `' . $this->table . '`';
1267: $oDb->query($sql);
1268: while ($oDb->nextRecord()) {
1269: $aIds[] = $oDb->f('pk');
1270: }
1271:
1272: return $aIds;
1273: }
1274:
1275: 1276: 1277: 1278: 1279: 1280: 1281: 1282: 1283: 1284: 1285: 1286:
1287: public function delete($mId) {
1288: $result = $this->_delete($mId);
1289: return $result;
1290: }
1291:
1292: 1293: 1294: 1295: 1296: 1297: 1298: 1299: 1300: 1301: 1302: 1303:
1304: public function deleteByWhereClause($sWhere) {
1305:
1306: $aIds = $this->getIdsByWhereClause($sWhere);
1307:
1308: if (!is_array($aIds) || 0 >= count($aIds)) {
1309: return 0;
1310: }
1311:
1312: $numDeleted = $this->_deleteMultiple($aIds);
1313: return $numDeleted;
1314: }
1315:
1316: 1317: 1318: 1319: 1320: 1321: 1322: 1323: 1324: 1325: 1326: 1327: 1328: 1329: 1330: 1331:
1332: public function deleteBy($sField, $mValue) {
1333: $where = (is_string($mValue)) ? "`%s` = '%s'" : "`%s` = %d";
1334: $where = $this->db->prepare($where, $sField, $mValue);
1335:
1336: return $this->deleteByWhereClause($where);
1337: }
1338:
1339: 1340: 1341: 1342: 1343: 1344: 1345: 1346: 1347: 1348: 1349:
1350: protected function _delete($mId) {
1351: $this->_executeCallbacks(self::DELETE_BEFORE, $this->_itemClass, array(
1352: $mId
1353: ));
1354:
1355: $oDb = $this->_getSecondDBInstance();
1356:
1357:
1358: $sql = "DELETE FROM `%s` WHERE %s = '%s'";
1359: $oDb->query($sql, $this->table, $this->getPrimaryKeyName(), $mId);
1360: $success = $oDb->affectedRows();
1361:
1362:
1363: $this->_oCache->removeItem($mId);
1364:
1365:
1366: $oProperties = $this->_getPropertiesCollectionInstance();
1367: $oProperties->deleteProperties($this->getPrimaryKeyName(), $mId);
1368:
1369: if ($success == 0) {
1370: $this->_executeCallbacks(self::DELETE_FAILURE, $this->_itemClass, array(
1371: $mId
1372: ));
1373: return false;
1374: } else {
1375: $this->_executeCallbacks(self::DELETE_SUCCESS, $this->_itemClass, array(
1376: $mId
1377: ));
1378: return true;
1379: }
1380: }
1381:
1382: 1383: 1384: 1385: 1386: 1387: 1388: 1389: 1390: 1391: 1392:
1393: protected function _deleteMultiple(array $aIds) {
1394: foreach ($aIds as $mId) {
1395: $this->_executeCallbacks(self::DELETE_BEFORE, $this->_itemClass, array(
1396: $mId
1397: ));
1398: }
1399:
1400: $oDb = $this->_getSecondDBInstance();
1401:
1402:
1403: $aEscapedIds = array_map(array(
1404: $oDb,
1405: 'escape'
1406: ), $aIds);
1407: $in = "'" . implode("', '", $aEscapedIds) . "'";
1408: $sql = "DELETE FROM `%s` WHERE %s IN (" . $in . ")";
1409: $oDb->query($sql, $this->table, $this->getPrimaryKeyName());
1410: $numAffected = $oDb->affectedRows();
1411:
1412:
1413: $this->_oCache->removeItems($aIds);
1414:
1415:
1416: $oProperties = $this->_getPropertiesCollectionInstance();
1417: $oProperties->deletePropertiesMultiple($this->getPrimaryKeyName(), $aIds);
1418:
1419:
1420:
1421: if ($numAffected == 0) {
1422: foreach ($aIds as $mId) {
1423: $this->_executeCallbacks(self::DELETE_FAILURE, $this->_itemClass, array(
1424: $mId
1425: ));
1426: }
1427: } else {
1428: foreach ($aIds as $mId) {
1429: $this->_executeCallbacks(self::DELETE_SUCCESS, $this->_itemClass, array(
1430: $mId
1431: ));
1432: }
1433: }
1434: return $numAffected;
1435: }
1436:
1437: 1438: 1439: 1440: 1441: 1442: 1443: 1444: 1445: 1446: 1447: 1448: 1449: 1450: 1451: 1452: 1453: 1454: 1455: 1456: 1457:
1458: public function fetchArray($sKey, $mFields) {
1459: $aResult = array();
1460:
1461: while (($item = $this->next()) !== false) {
1462: if (is_array($mFields)) {
1463: foreach ($mFields as $value) {
1464: $aResult[$item->get($sKey)][$value] = $item->get($value);
1465: }
1466: } else {
1467: $aResult[$item->get($sKey)] = $item->get($mFields);
1468: }
1469: }
1470:
1471: return $aResult;
1472: }
1473: }
1474: