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