1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58:
59:
60: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
61:
62:
63: 64: 65: 66: 67: 68:
69: class cApiPropertyCollection extends ItemCollection {
70:
71: 72: 73: 74: 75:
76: public $client;
77:
78: 79: 80: 81: 82:
83: protected static $_entries;
84:
85: 86: 87: 88: 89:
90: protected static $_enableCache;
91:
92: 93: 94: 95: 96:
97: protected static $_cacheItemtypes;
98:
99: 100: 101: 102:
103: public function __construct($idclient = 0) {
104: global $cfg, $client, $lang;
105:
106: if (0 === $idclient) {
107:
108:
109: $idclient = $client;
110: }
111:
112: $this->client = cSecurity::toInteger($idclient);
113: parent::__construct($cfg['tab']['properties'], 'idproperty');
114: $this->_setItemClass('cApiProperty');
115:
116:
117: $this->_setJoinPartner('cApiClientCollection');
118:
119: if (!isset(self::$_enableCache)) {
120: if (isset($cfg['properties']) && isset($cfg['properties']['properties']) && isset($cfg['properties']['properties']['enable_cache'])) {
121: self::$_enableCache = (bool) $cfg['properties']['properties']['enable_cache'];
122:
123: if (isset($cfg['properties']['properties']['itemtypes']) && is_array($cfg['properties']['properties']['itemtypes'])) {
124: self::$_cacheItemtypes = $cfg['properties']['properties']['itemtypes'];
125: foreach (self::$_cacheItemtypes as $name => $value) {
126: if ('%client%' == $value) {
127: self::$_cacheItemtypes[$name] = (int) $idclient;
128: } elseif ('%lang%' == $value) {
129: self::$_cacheItemtypes[$name] = (int) $lang;
130: } else {
131: unset(self::$_cacheItemtypes[$name]);
132: }
133: }
134: }
135: } else {
136: self::$_enableCache = false;
137: }
138: }
139:
140: if (self::$_enableCache && !isset(self::$_entries)) {
141: $this->_loadFromCache();
142: }
143: }
144:
145: 146: 147:
148: public static function reset() {
149: self::$_enableCache = false;
150: self::$_entries = array();
151: self::$_cacheItemtypes = array();
152: }
153:
154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172:
173: public function create($itemtype, $itemid, $type, $name, $value, $bDontEscape = false) {
174: global $auth;
175:
176: $item = parent::createNewItem();
177:
178: $item->set('idclient', $this->client);
179: $item->set('itemtype', $itemtype, false);
180: $item->set('itemid', $itemid, false);
181: $item->set('type', $type);
182: $item->set('name', $name);
183: $item->set('value', $value);
184:
185: $item->set('created', date('Y-m-d H:i:s'), false);
186: $item->set('author', $auth->auth['uid']);
187: $item->store();
188:
189: if ($this->_useCache($itemtype, $itemid)) {
190: $this->_addToCache($item);
191: }
192:
193: return $item;
194: }
195:
196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211:
212: public function getValue($itemtype, $itemid, $type, $name, $default = false) {
213: if ($this->_useCache($itemtype, $itemid)) {
214: return $this->_getValueFromCache($itemtype, $itemid, $type, $name, $default);
215: }
216:
217: if (isset($this->client)) {
218: $sql = $this->db->prepare("idclient = %d AND itemtype = '%s' AND itemid = '%s' AND type = '%s' AND name = '%s'", $this->client, $itemtype, $itemid, $type, $name);
219: } else {
220:
221: $sql = $this->db->prepare("itemtype = '%s' AND itemid = '%s' AND type = '%s' AND name = '%s'", $itemtype, $itemid, $type, $name);
222: }
223: $this->select($sql);
224:
225: if (false !== $item = $this->next()) {
226: return cSecurity::unescapeDB($item->get('value'));
227: }
228:
229: return $default;
230: }
231:
232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246:
247: public function getValuesByType($itemtype, $itemid, $type) {
248: if ($this->_useCache($itemtype, $itemid)) {
249: return $this->_getValuesByTypeFromCache($itemtype, $itemid, $type);
250: }
251:
252: $aResult = array();
253:
254: if (isset($this->client)) {
255: $sql = $this->db->prepare("idclient = %d AND itemtype = '%s' AND itemid = '%s' AND type = '%s'", $this->client, $itemtype, $itemid, $type);
256: } else {
257:
258: $sql = $this->db->prepare("itemtype = '%s' AND itemid = '%s' AND type = '%s'", $itemtype, $itemid, $type);
259: }
260: $this->select($sql);
261:
262: while (($item = $this->next()) !== false) {
263: $aResult[$item->get('name')] = cSecurity::unescapeDB($item->get('value'));
264: }
265:
266: return $aResult;
267: }
268:
269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282:
283: public function getValuesOnlyByTypeName($type, $name) {
284: $aResult = array();
285:
286: $sql = $this->db->prepare("type = '%s' AND name = '%s'", $type, $name);
287:
288: while (($item = $this->next()) !== false) {
289: $aResult[] = cSecurity::unescapeDB($item->get('value'));
290: }
291:
292: return $aResult;
293: }
294:
295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313:
314: public function setValue($itemtype, $itemid, $type, $name, $value, $idProp = 0) {
315: $idProp = (int) $idProp;
316:
317: if ($idProp == 0) {
318: $sql = $this->db->prepare("idclient = %d AND itemtype = '%s' AND itemid = '%s' AND type = '%s' AND name = '%s'", $this->client, $itemtype, $itemid, $type, $name);
319: } else {
320: $sql = $this->db->prepare("idclient = %d AND itemtype = '%s' AND itemid = '%s' AND idproperty = %d", $this->client, $itemtype, $itemid, $idProp);
321: }
322: $this->select($sql);
323:
324: if (($item = $this->next()) !== false) {
325: $item->set('value', $value);
326: $item->set('name', $name);
327: $item->set('type', $type);
328: $item->store();
329:
330: if ($this->_useCache($itemtype, $itemid)) {
331: $this->_addToCache($item);
332: }
333: } else {
334: $this->create($itemtype, $itemid, $type, $name, $value, true);
335: }
336: }
337:
338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351:
352: public function deleteValue($itemtype, $itemid, $type, $name) {
353: if (isset($this->client)) {
354: $where = $this->db->prepare("idclient = %d AND itemtype = '%s' AND itemid = '%s' AND type = '%s' AND name = '%s'", $this->client, $itemtype, $itemid, $type, $name);
355: } else {
356:
357: $where = $this->db->prepare("itemtype = '%s' AND itemid = '%s' AND type = '%s' AND name = '%s'", $itemtype, $itemid, $type, $name);
358: }
359:
360: $idproperties = $this->getIdsByWhereClause($where);
361:
362: $this->_deleteMultiple($idproperties);
363: if ($this->_useCache()) {
364: $this->_deleteFromCacheMultiple($idproperties);
365: }
366: }
367:
368: 369: 370: 371: 372: 373: 374:
375: public function getProperties($itemtype, $itemid) {
376: if ($this->_useCache($itemtype, $itemid)) {
377: return $this->_getPropertiesFromCache($itemtype, $itemid);
378: }
379:
380: if (isset($this->client)) {
381: $sql = $this->db->prepare("idclient = %d AND itemtype = '%s' AND itemid = '%s'", $this->client, $itemtype, $itemid);
382: } else {
383:
384: $sql = $this->db->prepare("itemtype = '%s' AND itemid = '%s'", $itemtype, $itemid);
385: }
386: $this->select($sql);
387:
388: $result[$itemid] = false;
389:
390: while (($item = $this->next()) !== false) {
391:
392: $result[$item->get('itemid')][$item->get('idproperty')] = array(
393: 0 => $item->get('type'),
394: 'type' => $item->get('type'),
395: 1 => $item->get('name'),
396: 'name' => $item->get('name'),
397: 2 => $item->get('value'),
398: 'value' => $item->get('value')
399: );
400: }
401: return $result;
402: }
403:
404: 405: 406: 407: 408: 409: 410: 411:
412: public function getAllValues($field, $fieldValue, $auth = NULL) {
413: $authString = '';
414: if (!is_null($auth) && sizeof($auth) > 0) {
415: $authString .= " AND author = '" . $this->db->escape($auth->auth["uid"]) . "'";
416: }
417:
418: $field = $this->db->escape($field);
419: $fieldValue = $this->db->escape($fieldValue);
420:
421: if (isset($this->client)) {
422: $this->select("idclient = " . (int) $this->client . " AND " . $field . " = '" . $fieldValue . "'" . $authString, '', 'itemid');
423: } else {
424:
425: $this->select($field . " = '" . $fieldValue . "'" . $authString);
426: }
427:
428: $retValue = array();
429: while (($item = $this->next()) !== false) {
430: $dbLine = array(
431: 'idproperty' => $item->get('idproperty'),
432: 'idclient' => $item->get('idclient'),
433: 'itemtype' => $item->get('itemtype'),
434: 'itemid' => $item->get('itemid'),
435: 'type' => $item->get('type'),
436: 'name' => $item->get('name'),
437: 'value' => $item->get('value'),
438: 'author' => $item->get('author'),
439: 'created' => $item->get('created'),
440: 'modified' => $item->get('modified'),
441: 'modifiedby' => $item->get('modifiedby')
442: );
443: $retValue[] = $dbLine;
444: }
445: return $retValue;
446: }
447:
448: 449: 450: 451: 452: 453:
454: public function deleteProperties($itemtype, $itemid) {
455: if (isset($this->client)) {
456: $where = $this->db->prepare("idclient = %d AND itemtype = '%s' AND itemid = '%s'", $this->client, $itemtype, $itemid);
457: } else {
458:
459: $where = $this->db->prepare("itemtype = '%s' AND itemid = '%s'", $itemtype, $itemid);
460: }
461:
462: $idproperties = $this->getIdsByWhereClause($where);
463:
464: $this->_deletePropertiesByIds($idproperties);
465: }
466:
467: 468: 469: 470: 471: 472:
473: public function deletePropertiesMultiple($itemtype, array $itemids) {
474: $itemtype = $this->db->escape($itemtype);
475: $itemids = array_map(array($this, 'escape'), $itemids);
476: $in = "'" . implode("', '", $itemids) . "'";
477:
478: if (isset($this->client)) {
479: $where = "idclient = " . (int) $this->client . " AND itemtype = '" . $itemtype . "' AND itemid IN (" . $in . ")";
480: } else {
481:
482: $where = "itemtype = '" . $itemtype . "' AND itemid IN (" . $in . ")";
483: }
484:
485: $idproperties = $this->getIdsByWhereClause($where);
486:
487: $this->_deletePropertiesByIds($idproperties);
488: }
489:
490: 491: 492: 493: 494:
495: public function changeClient($idclient) {
496: $this->client = (int) $idclient;
497: }
498:
499: 500: 501: 502: 503:
504: protected function _loadFromCache() {
505: global $client;
506: if (!isset(self::$_entries)) {
507: self::$_entries = array();
508: }
509:
510: $where = array();
511: foreach (self::$_cacheItemtypes as $itemtype => $itemid) {
512: if (is_numeric($itemid)) {
513: $where[] = "(itemtype = '" . $itemtype . "' AND itemid = " . $itemid . ")";
514: } else {
515: $where[] = "(itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "')";
516: }
517: }
518:
519: if (count($where) == 0) {
520: return;
521: }
522:
523: $where = "idclient = " . (int) $client . ' AND ' . implode(' OR ', $where);
524: $this->select($where);
525: while (($property = $this->next()) !== false) {
526: $this->_addToCache($property);
527: }
528: }
529:
530: 531: 532: 533: 534: 535:
536: protected function _useCache($itemtype = NULL, $itemid = NULL) {
537: global $client;
538: $ok = (self::$_enableCache && $this->client == $client);
539: if (!$ok) {
540: return $ok;
541: } elseif ($itemtype == NULL || $itemid == NULL) {
542: return $ok;
543: }
544:
545: foreach (self::$_cacheItemtypes as $name => $value) {
546: if ($itemtype == $value['itemtype'] || $itemid == $value['itemid']) {
547: return true;
548: }
549: }
550: }
551:
552: 553: 554: 555: 556: 557:
558: protected function _deletePropertiesByIds(array $ids) {
559: if (count($ids) > 0) {
560: $this->_deleteMultiple($ids);
561: if ($this->_useCache()) {
562: $this->_deleteFromCacheMultiple($ids);
563: }
564: }
565: }
566:
567: 568: 569: 570: 571:
572: protected function _addToCache($entry) {
573: $data = $entry->toArray();
574: self::$_entries[$data['idproperty']] = $data;
575: }
576:
577: 578: 579: 580: 581:
582: protected function _deleteFromCache($id) {
583: if (isset(self::$_entries[$id])) {
584: unset(self::$_entries[$id]);
585: }
586: }
587:
588: 589: 590: 591: 592:
593: protected function _deleteFromCacheMultiple(array $ids) {
594: foreach ($ids as $id) {
595: if (isset(self::$_entries[$id])) {
596: unset(self::$_entries[$id]);
597: }
598: }
599: }
600:
601: 602: 603: 604: 605: 606: 607: 608: 609: 610:
611: protected function _getValueFromCache($itemtype, $itemid, $type, $name, $default = false) {
612: foreach (self::$_entries as $id => $entry) {
613: if ($entry['itemtype'] == $itemtype && $entry['itemid'] == $itemid && $entry['type'] == $type && $entry['name'] == $name) {
614: return cSecurity::unescapeDB($entry['value']);
615: }
616: }
617:
618: return $default;
619: }
620:
621: 622: 623: 624: 625: 626: 627: 628: 629:
630: protected function _getValuesByTypeFromCache($itemtype, $itemid, $type) {
631: $result = array();
632:
633: foreach (self::$_entries as $id => $entry) {
634: if ($entry['itemtype'] == $itemtype && $entry['itemid'] == $itemid && $entry['type'] == $type) {
635: $result[$entry['name']] = cSecurity::unescapeDB($entry['value']);
636: }
637: }
638:
639: return $result;
640: }
641:
642: 643: 644: 645: 646: 647: 648:
649: public function _getPropertiesFromCache($itemtype, $itemid) {
650: $result = array();
651: $result[$itemid] = false;
652:
653: foreach (self::$_entries as $id => $entry) {
654: if ($entry['itemtype'] == $itemtype && $entry['itemid'] == $itemid) {
655:
656: $result[$entry['itemid']][$entry['idproperty']] = array(
657: 0 => $entry['type'],
658: 'type' => $entry['type'],
659: 1 => $entry['name'],
660: 'name' => $entry['name'],
661: 2 => $entry['value'],
662: 'value' => $entry['value']
663: );
664: }
665: }
666:
667: return $result;
668: }
669:
670: }
671:
672: 673: 674: 675: 676: 677:
678: class cApiProperty extends Item {
679:
680: 681: 682: 683: 684:
685: public $maximumLength;
686:
687: 688: 689: 690: 691:
692: public function __construct($mId = false) {
693: global $cfg;
694: parent::__construct($cfg['tab']['properties'], 'idproperty');
695:
696:
697: $this->maximumLength = array(
698: 'itemtype' => 64,
699: 'itemid' => 255,
700: 'type' => 96,
701: 'name' => 96
702: );
703:
704: if ($mId !== false) {
705: $this->loadByPrimaryKey($mId);
706: }
707: }
708:
709: 710: 711: 712: 713:
714: public function store() {
715: global $auth;
716:
717: $this->set('modified', date('Y-m-d H:i:s'), false);
718: $this->set('modifiedby', $auth->auth['uid']);
719:
720: return parent::store();
721: }
722:
723: 724: 725: 726: 727: 728: 729: 730: 731: 732:
733: public function setField($field, $value, $safe = true) {
734: if (array_key_exists($field, $this->maximumLength)) {
735: if (strlen($value) > $this->maximumLength[$field]) {
736: throw new cInvalidArgumentException("Tried to set field $field to value $value, but the field is too small. Truncated.");
737: }
738: }
739:
740: parent::setField($field, $value, $safe);
741: }
742:
743: }
744: