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