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