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: public function create($itemtype, $itemid, $type, $name, $value, $bDontEscape = false) {
173: global $auth;
174:
175: $item = parent::createNewItem();
176:
177: if (!$bDontEscape) {
178: $itemtype = $this->db->escape($itemtype);
179: $itemid = $this->db->escape($itemid);
180: $value = $this->db->escape($value);
181: $type = $this->db->escape($type);
182: $name = $this->db->escape($name);
183: }
184:
185: $item->set('idclient', $this->client);
186: $item->set('itemtype', $itemtype, false);
187: $item->set('itemid', $itemid, false);
188: $item->set('type', $type);
189: $item->set('name', $name);
190: $item->set('value', $value);
191:
192: $item->set('created', date('Y-m-d H:i:s'), false);
193: $item->set('author', $this->db->escape($auth->auth['uid']));
194: $item->store();
195:
196: if ($this->_useCache($itemtype, $itemid)) {
197: $this->_addToCache($item);
198: }
199:
200: return ($item);
201: }
202:
203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218:
219: public function getValue($itemtype, $itemid, $type, $name, $default = false) {
220: if ($this->_useCache($itemtype, $itemid)) {
221: return $this->_getValueFromCache($itemtype, $itemid, $type, $name, $default);
222: }
223:
224: $itemtype = $this->db->escape($itemtype);
225: $itemid = $this->db->escape($itemid);
226: $type = $this->db->escape($type);
227: $name = $this->db->escape($name);
228:
229: if (isset($this->client)) {
230: $this->select("idclient = " . (int) $this->client . " AND itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "' AND type = '" . $type . "' AND name = '" . $name . "'");
231: } else {
232:
233: $this->select("itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "' AND type = '" . $type . "' AND name = '" . $name . "'");
234: }
235:
236: if (false !== $item = $this->next()) {
237: return cSecurity::unescapeDB($item->get('value'));
238: }
239:
240: return $default;
241: }
242:
243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257:
258: public function getValuesByType($itemtype, $itemid, $type) {
259: if ($this->_useCache($itemtype, $itemid)) {
260: return $this->_getValuesByTypeFromCache($itemtype, $itemid, $type);
261: }
262:
263: $aResult = array();
264: $itemtype = $this->db->escape($itemtype);
265: $itemid = $this->db->escape($itemid);
266: $type = $this->db->escape($type);
267:
268: if (isset($this->client)) {
269: $this->select("idclient = " . (int) $this->client . " AND itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "' AND type = '" . $type . "'");
270: } else {
271:
272: $this->select("itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "' AND type = '" . $type . "'");
273: }
274:
275: while (($item = $this->next()) !== false) {
276: $aResult[$item->get('name')] = cSecurity::unescapeDB($item->get('value'));
277: }
278:
279: return $aResult;
280: }
281:
282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295:
296: public function getValuesOnlyByTypeName($type, $name) {
297: $aResult = array();
298: $type = $this->db->escape($type);
299: $name = $this->db->escape($name);
300:
301: $this->select("type = '" . $type . "' AND name = '" . $name . "");
302:
303: while (($item = $this->next()) !== false) {
304: $aResult[] = cSecurity::unescapeDB($item->get('value'));
305: }
306:
307: return $aResult;
308: }
309:
310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328:
329: public function setValue($itemtype, $itemid, $type, $name, $value, $idProp = 0) {
330: $itemtype = $this->db->escape($itemtype);
331: $itemid = $this->db->escape($itemid);
332: $type = $this->db->escape($type);
333: $name = $this->db->escape($name);
334: $value = $this->db->escape($value);
335: $idProp = (int) $idProp;
336:
337: if ($idProp == 0) {
338: $this->select("idclient = " . (int) $this->client . " AND itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "' AND type = '" . $type . "' AND name = '" . $name . "'");
339: } else {
340: $this->select("idclient = " . (int) $this->client . " AND itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "' AND idproperty = " . $idProp);
341: }
342:
343: if (($item = $this->next()) !== false) {
344: $item->set('value', $value);
345: $item->set('name', $name);
346: $item->set('type', $type);
347: $item->store();
348:
349: if ($this->_useCache($itemtype, $itemid)) {
350: $this->_addToCache($item);
351: }
352: } else {
353: $this->create($itemtype, $itemid, $type, $name, $value, true);
354: }
355: }
356:
357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370:
371: public function deleteValue($itemtype, $itemid, $type, $name) {
372: $itemtype = $this->db->escape($itemtype);
373: $itemid = $this->db->escape($itemid);
374: $type = $this->db->escape($type);
375: $name = $this->db->escape($name);
376:
377: if (isset($this->client)) {
378: $where = "idclient = " . (int) $this->client . " AND itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "' AND type = '" . $type . "' AND name = '" . $name . "'";
379: } else {
380:
381: $where = "itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "' AND type = '" . $type . "' AND name = '" . $name . "'";
382: }
383:
384: $idproperties = $this->getIdsByWhereClause($where);
385:
386: $this->_deleteMultiple($idproperties);
387: if ($this->_useCache()) {
388: $this->_deleteFromCacheMultiple($idproperties);
389: }
390: }
391:
392: 393: 394: 395: 396: 397: 398:
399: public function getProperties($itemtype, $itemid) {
400: if ($this->_useCache($itemtype, $itemid)) {
401: return $this->_getPropertiesFromCache($itemtype, $itemid);
402: }
403:
404: $itemtype = $this->db->escape($itemtype);
405: $itemid = $this->db->escape($itemid);
406:
407: if (isset($this->client)) {
408: $this->select("idclient = " . (int) $this->client . " AND itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "'");
409: } else {
410:
411: $this->select("itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "'");
412: }
413:
414: $result[$itemid] = false;
415:
416: while (($item = $this->next()) !== false) {
417:
418: $result[$item->get('itemid')][$item->get('idproperty')] = array(
419: 0 => $item->get('type'),
420: 'type' => $item->get('type'),
421: 1 => $item->get('name'),
422: 'name' => $item->get('name'),
423: 2 => $item->get('value'),
424: 'value' => $item->get('value')
425: );
426: }
427: return $result;
428: }
429:
430: 431: 432: 433: 434: 435: 436: 437:
438: public function getAllValues($field, $fieldValue, $auth = NULL) {
439: $authString = '';
440: if (!is_null($auth) && sizeof($auth) > 0) {
441: $authString .= " AND author = '" . $auth->auth["uid"] . "'";
442: }
443:
444: if (isset($this->client)) {
445: $this->select("idclient = " . (int) $this->client . " AND " . $field . " = '" . $fieldValue . "'" . $authString, '', 'itemid');
446: } else {
447:
448: $this->select($field . " = '" . $fieldValue . "'" . $authString);
449: }
450:
451: $retValue = array();
452: while (($item = $this->next()) !== false) {
453: $dbLine = array(
454: 'idproperty' => $item->get('idproperty'),
455: 'idclient' => $item->get('idclient'),
456: 'itemtype' => $item->get('itemtype'),
457: 'itemid' => $item->get('itemid'),
458: 'type' => $item->get('type'),
459: 'name' => $item->get('name'),
460: 'value' => $item->get('value'),
461: 'author' => $item->get('author'),
462: 'created' => $item->get('created'),
463: 'modified' => $item->get('modified'),
464: 'modifiedby' => $item->get('modifiedby')
465: );
466: $retValue[] = $dbLine;
467: }
468: return $retValue;
469: }
470:
471: 472: 473: 474: 475: 476:
477: public function deleteProperties($itemtype, $itemid) {
478: $itemtype = $this->db->escape($itemtype);
479: $itemid = $this->db->escape($itemid);
480:
481: if (isset($this->client)) {
482: $where = "idclient = " . (int) $this->client . " AND itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "'";
483: } else {
484:
485: $where = "itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "'";
486: }
487:
488: $idproperties = $this->getIdsByWhereClause($where);
489:
490: $this->_deletePropertiesByIds($idproperties);
491: }
492:
493: 494: 495: 496: 497: 498:
499: public function deletePropertiesMultiple($itemtype, array $itemids) {
500: $itemtype = $this->db->escape($itemtype);
501: $itemids = array_map(array(
502: $this,
503: 'escape'
504: ), $itemids);
505:
506: $in = "'" . implode("', '", $itemids) . "'";
507:
508: if (isset($this->client)) {
509: $where = "idclient = " . (int) $this->client . " AND itemtype = '" . $itemtype . "' AND itemid IN (" . $in . ")";
510: } else {
511:
512: $where = "itemtype = '" . $itemtype . "' AND itemid IN (" . $in . ")";
513: }
514:
515: $idproperties = $this->getIdsByWhereClause($where);
516:
517: $this->_deletePropertiesByIds($idproperties);
518: }
519:
520: 521: 522: 523: 524:
525: public function changeClient($idclient) {
526: $this->client = (int) $idclient;
527: }
528:
529: 530: 531:
532: protected function _loadFromCache() {
533: global $client;
534: if (!isset(self::$_entries)) {
535: self::$_entries = array();
536: }
537:
538: $where = array();
539: foreach (self::$_cacheItemtypes as $itemtype => $itemid) {
540: if (is_numeric($itemid)) {
541: $where[] = "(itemtype = '" . $itemtype . "' AND itemid = " . $itemid . ")";
542: } else {
543: $where[] = "(itemtype = '" . $itemtype . "' AND itemid = '" . $itemid . "')";
544: }
545: }
546:
547: if (count($where) == 0) {
548: return;
549: }
550:
551: $where = "idclient = " . (int) $client . ' AND ' . implode(' OR ', $where);
552: $this->select($where);
553: while (($property = $this->next()) !== false) {
554: $this->_addToCache($property);
555: }
556: }
557:
558: 559: 560: 561: 562: 563:
564: protected function _useCache($itemtype = NULL, $itemid = NULL) {
565: global $client;
566: $ok = (self::$_enableCache && $this->client == $client);
567: if (!$ok) {
568: return $ok;
569: } elseif ($itemtype == NULL || $itemid == NULL) {
570: return $ok;
571: }
572:
573: foreach (self::$_cacheItemtypes as $name => $value) {
574: if ($itemtype == $value['itemtype'] || $itemid == $value['itemid']) {
575: return true;
576: }
577: }
578: }
579:
580: 581: 582: 583: 584: 585:
586: protected function _deletePropertiesByIds(array $ids) {
587: if (count($ids) > 0) {
588: $this->_deleteMultiple($ids);
589: if ($this->_useCache()) {
590: $this->_deleteFromCacheMultiple($ids);
591: }
592: }
593: }
594:
595: 596: 597: 598: 599:
600: protected function _addToCache($entry) {
601: global $client;
602: $data = $entry->toArray();
603: self::$_entries[$data['idproperty']] = $data;
604: }
605:
606: 607: 608: 609: 610:
611: protected function _deleteFromCache($id) {
612: if (isset(self::$_entries[$id])) {
613: unset(self::$_entries[$id]);
614: }
615: }
616:
617: 618: 619: 620: 621:
622: protected function _deleteFromCacheMultiple(array $ids) {
623: foreach ($ids as $id) {
624: if (isset(self::$_entries[$id])) {
625: unset(self::$_entries[$id]);
626: }
627: }
628: }
629:
630: 631: 632: 633: 634: 635: 636: 637: 638: 639:
640: protected function _getValueFromCache($itemtype, $itemid, $type, $name, $default = false) {
641: foreach (self::$_entries as $id => $entry) {
642: if ($entry['itemtype'] == $itemtype && $entry['itemid'] == $itemid && $entry['type'] == $type && $entry['name'] == $name) {
643: return cSecurity::unescapeDB($entry['value']);
644: }
645: }
646:
647: return $default;
648: }
649:
650: 651: 652: 653: 654: 655: 656: 657: 658:
659: protected function _getValuesByTypeFromCache($itemtype, $itemid, $type) {
660: $result = array();
661:
662: foreach (self::$_entries as $id => $entry) {
663: if ($entry['itemtype'] == $itemtype && $entry['itemid'] == $itemid && $entry['type'] == $type) {
664: $result[$entry['name']] = cSecurity::unescapeDB($entry['value']);
665: }
666: }
667:
668: return $result;
669: }
670:
671: 672: 673: 674: 675: 676: 677:
678: public function _getPropertiesFromCache($itemtype, $itemid) {
679: $result = array();
680: $result[$itemid] = false;
681:
682: foreach (self::$_entries as $id => $entry) {
683: if ($entry['itemtype'] == $itemtype && $entry['itemid'] == $itemid) {
684:
685: $result[$entry['itemid']][$entry['idproperty']] = array(
686: 0 => $entry['type'],
687: 'type' => $entry['type'],
688: 1 => $entry['name'],
689: 'name' => $entry['name'],
690: 2 => $entry['value'],
691: 'value' => $entry['value']
692: );
693: }
694: }
695:
696: return $result;
697: }
698:
699: }
700:
701: 702: 703: 704: 705: 706:
707: class cApiProperty extends Item {
708:
709: 710: 711: 712: 713:
714: public $maximumLength;
715:
716: 717: 718: 719: 720:
721: public function __construct($mId = false) {
722: global $cfg;
723: parent::__construct($cfg['tab']['properties'], 'idproperty');
724:
725:
726: $this->maximumLength = array();
727: $this->maximumLength['itemtype'] = 64;
728: $this->maximumLength['itemid'] = 255;
729: $this->maximumLength['type'] = 96;
730: $this->maximumLength['name'] = 96;
731:
732: if ($mId !== false) {
733: $this->loadByPrimaryKey($mId);
734: }
735: }
736:
737: 738: 739: 740: 741:
742: public function store() {
743: global $auth;
744:
745: $this->set('modified', date('Y-m-d H:i:s'), false);
746: $this->set('modifiedby', $auth->auth['uid']);
747:
748: return parent::store();
749: }
750:
751: 752: 753: 754: 755: 756: 757: 758: 759: 760:
761: public function setField($field, $value, $safe = true) {
762: if (array_key_exists($field, $this->maximumLength)) {
763: if (strlen($value) > $this->maximumLength[$field]) {
764: throw new cInvalidArgumentException("Tried to set field $field to value $value, but the field is too small. Truncated.");
765: }
766: }
767:
768: parent::setField($field, $value, $safe);
769: }
770:
771: }
772: