Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
entity.php
1<?php
9namespace Bitrix\Main\ORM;
10
11use Bitrix\Main;
21
25class Entity
26{
28 protected $className;
29
30 protected
37
38 protected
42
44 protected $fields;
45
46 protected $fieldsMap;
47
49 protected $u_fields;
50
52 protected $code;
53
54 protected $references;
55
57 protected static $instances;
58
60 protected static $ufIdIndex = [];
61
63 protected $isClone = false;
64
65 const DEFAULT_OBJECT_PREFIX = 'EO_';
66
76 public static function get($entityName)
77 {
78 return static::getInstance($entityName);
79 }
80
88 public static function has($entityName)
89 {
90 $entityClass = static::normalizeEntityClass($entityName);
91 return class_exists($entityClass);
92 }
93
103 public static function getInstance($entityName)
104 {
105 $entityName = static::normalizeEntityClass($entityName);
106
107 return self::getInstanceDirect($entityName);
108 }
109
117 protected static function getInstanceDirect($className)
118 {
119 if (empty(self::$instances[$className]))
120 {
122 $entityClass = $className::getEntityClass();
123
124 // in case of calling Table class was not ended with entity initialization
125 if (empty(self::$instances[$className]))
126 {
127 $entity = new $entityClass;
128 $entity->initialize($className);
129 $entity->postInitialize();
130
131 // call user-defined postInitialize
132 $className::postInitialize($entity);
133
134 self::$instances[$className] = $entity;
135 }
136 }
137
138 return self::$instances[$className];
139 }
140
151 public function initializeField($fieldName, $fieldInfo)
152 {
153 if ($fieldInfo instanceof Field)
154 {
155 $field = $fieldInfo;
156
157 // rewrite name
158 if (!empty($fieldName) && !is_numeric($fieldName))
159 {
160 $field->setName($fieldName);
161 }
162 }
163 elseif (is_array($fieldInfo))
164 {
165 if (!empty($fieldInfo['reference']))
166 {
167 if (is_string($fieldInfo['data_type']) && strpos($fieldInfo['data_type'], '\\') === false)
168 {
169 // if reference has no namespace, then it'is in the same namespace
170 $fieldInfo['data_type'] = $this->getNamespace().$fieldInfo['data_type'];
171 }
172
173 //$refEntity = Base::getInstance($fieldInfo['data_type']."Table");
174 $field = new Reference($fieldName, $fieldInfo['data_type'], $fieldInfo['reference'], $fieldInfo);
175 }
176 elseif (!empty($fieldInfo['expression']))
177 {
178 $expression = array_shift($fieldInfo['expression']);
179 $buildFrom = $fieldInfo['expression'];
180
181 $field = new ExpressionField($fieldName, $expression, $buildFrom, $fieldInfo);
182 }
183 elseif (!empty($fieldInfo['USER_TYPE_ID']))
184 {
185 $field = new UField($fieldInfo);
186 }
187 else
188 {
189 $fieldClass = StringHelper::snake2camel($fieldInfo['data_type']) . 'Field';
190 $fieldClass = '\\Bitrix\\Main\\Entity\\'.$fieldClass;
191
192 if (strlen($fieldInfo['data_type']) && class_exists($fieldClass))
193 {
194 $field = new $fieldClass($fieldName, $fieldInfo);
195 }
196 elseif (strlen($fieldInfo['data_type']) && class_exists($fieldInfo['data_type']))
197 {
198 $fieldClass = $fieldInfo['data_type'];
199 $field = new $fieldClass($fieldName, $fieldInfo);
200 }
201 else
202 {
203 throw new Main\ArgumentException(sprintf(
204 'Unknown data type "%s" found for `%s` field in %s Entity.',
205 $fieldInfo['data_type'], $fieldName, $this->getName()
206 ));
207 }
208 }
209 }
210 else
211 {
212 throw new Main\ArgumentException(sprintf('Unknown field type `%s`',
213 is_object($fieldInfo) ? get_class($fieldInfo) : gettype($fieldInfo)
214 ));
215 }
216
217 $field->setEntity($this);
218 $field->postInitialize();
219
220 return $field;
221 }
222
223 public function initialize($className)
224 {
226 $this->className = $className;
227
229 $this->connectionName = $className::getConnectionName();
230 $this->dbTableName = $className::getTableName();
231 $this->fieldsMap = $className::getMap();
232 $this->uf_id = $className::getUfId();
233 $this->isUts = $className::isUts();
234 $this->isUtm = $className::isUtm();
235
236 // object & collection classes
237 // Loader::registerObjectClass($className::getObjectClass(), $className);
238 // Loader::registerCollectionClass($className::getCollectionClass(), $className);
239 }
240
249 public function reinitialize($className)
250 {
251 // reset class
252 $this->className = static::normalizeEntityClass($className);
253
254 $classPath = explode('\\', ltrim($this->className, '\\'));
255 $this->name = substr(end($classPath), 0, -5);
256 }
257
262 public function postInitialize()
263 {
264 // basic properties
265 $classPath = explode('\\', ltrim($this->className, '\\'));
266 $this->name = substr(end($classPath), 0, -5);
267
268 // default db table name
269 if (is_null($this->dbTableName))
270 {
271 $_classPath = array_slice($classPath, 0, -1);
272
273 $this->dbTableName = 'b_';
274
275 foreach ($_classPath as $i => $_pathElem)
276 {
277 if ($i == 0 && $_pathElem == 'Bitrix')
278 {
279 // skip bitrix namespace
280 continue;
281 }
282
283 if ($i == 1 && $_pathElem == 'Main')
284 {
285 // also skip Main module
286 continue;
287 }
288
289 $this->dbTableName .= strtolower($_pathElem).'_';
290 }
291
292 // add class
293 if ($this->name !== end($_classPath))
294 {
295 $this->dbTableName .= StringHelper::camel2snake($this->name);
296 }
297 else
298 {
299 $this->dbTableName = substr($this->dbTableName, 0, -1);
300 }
301 }
302
303 $this->primary = array();
304 $this->references = array();
305
306 // attributes
307 foreach ($this->fieldsMap as $fieldName => &$fieldInfo)
308 {
309 $this->addField($fieldInfo, $fieldName);
310 }
311
312 if (!empty($this->fieldsMap) && empty($this->primary))
313 {
314 throw new Main\SystemException(sprintf('Primary not found for %s Entity', $this->name));
315 }
316
317 // attach userfields
318 if (empty($this->uf_id))
319 {
320 // try to find ENTITY_ID by map
321 $userTypeManager = Main\Application::getUserTypeManager();
322 if($userTypeManager instanceof \CUserTypeManager)
323 {
324 $entityList = $userTypeManager->getEntityList();
325 $ufId = is_array($entityList) ? array_search($this->className, $entityList) : false;
326 if ($ufId !== false)
327 {
328 $this->uf_id = $ufId;
329 }
330 }
331 }
332
333 if (!empty($this->uf_id))
334 {
335 // attach uf fields and create uts/utm entities
336 Main\UserFieldTable::attachFields($this, $this->uf_id);
337
338 // save index
339 static::$ufIdIndex[$this->uf_id] = $this->className;
340 }
341 }
342
348 public function getObjectClass()
349 {
350 $dataManagerClass = $this->className;
351 return static::normalizeName($dataManagerClass::getObjectClass());
352 }
353
359 public function getObjectClassName()
360 {
361 $dataManagerClass = $this->className;
362 return $dataManagerClass::getObjectClassName();
363 }
364
365 public static function getDefaultObjectClassName($entityName)
366 {
367 $className = $entityName;
368
369 if ($className == '')
370 {
371 // entity without name
372 $className = 'NNM_Object';
373 }
374
375 $className = static::DEFAULT_OBJECT_PREFIX.$className;
376
377 return $className;
378 }
379
383 public function getCollectionClass()
384 {
385 $dataClass = $this->getDataClass();
386 return static::normalizeName($dataClass::getCollectionClass());
387 }
388
392 public function getCollectionClassName()
393 {
394 $dataClass = $this->getDataClass();
395 return $dataClass::getCollectionClassName();
396 }
397
398 public static function getDefaultCollectionClassName($entityName)
399 {
400 $className = static::DEFAULT_OBJECT_PREFIX.$entityName.'_Collection';
401
402 return $className;
403 }
404
410 public function createObject($setDefaultValues = true)
411 {
412 $objectClass = $this->getObjectClass();
413 return new $objectClass($setDefaultValues);
414 }
415
419 public function createCollection()
420 {
421 $collectionClass = $this->getCollectionClass();
422 return new $collectionClass($this);
423 }
424
434 public function wakeUpObject($row)
435 {
436 $objectClass = $this->getObjectClass();
437 return $objectClass::wakeUp($row);
438 }
439
449 public function wakeUpCollection($rows)
450 {
451 $collectionClass = $this->getCollectionClass();
452 return $collectionClass::wakeUp($rows);
453 }
454
462 protected function appendField(Field $field)
463 {
464 if (isset($this->fields[StringHelper::strtoupper($field->getName())]) && !$this->isClone)
465 {
466 trigger_error(sprintf(
467 'Entity `%s` already has Field with name `%s`.', $this->getFullName(), $field->getName()
468 ), E_USER_WARNING);
469
470 return false;
471 }
472
473 if ($field instanceof Reference)
474 {
475 // references cache
476 $this->references[$field->getRefEntityName()][] = $field;
477 }
478
479 $this->fields[StringHelper::strtoupper($field->getName())] = $field;
480
481 if ($field instanceof ScalarField && $field->isPrimary())
482 {
483 $this->primary[] = $field->getName();
484
485 if($field->isAutocomplete())
486 {
487 $this->autoIncrement = $field->getName();
488 }
489 }
490
491 // add reference field for UField iblock_section
492 if ($field instanceof UField && $field->getTypeId() == 'iblock_section')
493 {
494 $refFieldName = $field->getName().'_BY';
495
496 if ($field->isMultiple())
497 {
498 $localFieldName = $field->getValueFieldName();
499 }
500 else
501 {
502 $localFieldName = $field->getName();
503 }
504
505 $newFieldInfo = array(
506 'data_type' => 'Bitrix\Iblock\Section',
507 'reference' => array($localFieldName, 'ID')
508 );
509
510 $newRefField = new Reference($refFieldName, $newFieldInfo['data_type'], $newFieldInfo['reference'][0], $newFieldInfo['reference'][1]);
511 $newRefField->setEntity($this);
512
513 $this->fields[StringHelper::strtoupper($refFieldName)] = $newRefField;
514 }
515
516 return true;
517 }
518
527 public function addField($fieldInfo, $fieldName = null)
528 {
529 $field = $this->initializeField($fieldName, $fieldInfo);
530
531 return $this->appendField($field) ? $field : false;
532 }
533
534 public function getReferencesCountTo($refEntityName)
535 {
536 if (array_key_exists($key = strtolower($refEntityName), $this->references))
537 {
538 return count($this->references[$key]);
539 }
540
541 return 0;
542 }
543
544
545 public function getReferencesTo($refEntityName)
546 {
547 if (array_key_exists($key = strtolower($refEntityName), $this->references))
548 {
549 return $this->references[$key];
550 }
551
552 return array();
553 }
554
555 // getters
556 public function getFields()
557 {
558 return $this->fields;
559 }
560
567 public function getField($name)
568 {
569 if ($this->hasField($name))
570 {
571 return $this->fields[StringHelper::strtoupper($name)];
572 }
573
574 throw new Main\ArgumentException(sprintf(
575 '%s Entity has no `%s` field.', $this->getName(), $name
576 ));
577 }
578
579 public function hasField($name)
580 {
581 return isset($this->fields[StringHelper::strtoupper($name)]);
582 }
583
587 public function getScalarFields()
588 {
589 $scalarFields = array();
590
591 foreach ($this->getFields() as $field)
592 {
593 if ($field instanceof ScalarField)
594 {
595 $scalarFields[$field->getName()] = $field;
596 }
597 }
598
599 return $scalarFields;
600 }
601
611 public function getUField($name)
612 {
613 if ($this->hasUField($name))
614 {
615 return $this->u_fields[$name];
616 }
617
618 throw new Main\ArgumentException(sprintf(
619 '%s Entity has no `%s` userfield.', $this->getName(), $name
620 ));
621 }
622
631 public function hasUField($name)
632 {
633 if (is_null($this->u_fields))
634 {
635 $this->u_fields = array();
636
637 if($this->uf_id <> '')
638 {
640 global $USER_FIELD_MANAGER;
641
642 foreach($USER_FIELD_MANAGER->getUserFields($this->uf_id) as $info)
643 {
644 $this->u_fields[$info['FIELD_NAME']] = new UField($info);
645 $this->u_fields[$info['FIELD_NAME']]->setEntity($this);
646
647 // add references for ufield (UF_DEPARTMENT_BY)
648 if($info['USER_TYPE_ID'] == 'iblock_section')
649 {
650 $info['FIELD_NAME'] .= '_BY';
651 $this->u_fields[$info['FIELD_NAME']] = new UField($info);
652 $this->u_fields[$info['FIELD_NAME']]->setEntity($this);
653 }
654 }
655 }
656 }
657
658 return isset($this->u_fields[$name]);
659 }
660
661 public function getName()
662 {
663 return $this->name;
664 }
665
666 public function getFullName()
667 {
668 return substr($this->className, 0, -5);
669 }
670
671 public function getNamespace()
672 {
673 return substr($this->className, 0, strrpos($this->className, '\\') + 1);
674 }
675
676 public function getModule()
677 {
678 if($this->module === null)
679 {
680 // \Bitrix\Main\Site -> "main"
681 // \Partner\Module\Thing -> "partner.module"
682 // \Thing -> ""
683 $parts = explode("\\", $this->className);
684 if($parts[1] == "Bitrix")
685 $this->module = strtolower($parts[2]);
686 elseif(!empty($parts[1]) && isset($parts[2]))
687 $this->module = strtolower($parts[1].".".$parts[2]);
688 else
689 $this->module = "";
690 }
691 return $this->module;
692 }
693
697 public function getDataClass()
698 {
699 return $this->className;
700 }
701
706 public function getConnection()
707 {
709 $conn = Main\Application::getInstance()->getConnectionPool()->getConnection($this->connectionName);
710 return $conn;
711 }
712
713 public function getDBTableName()
714 {
715 return $this->dbTableName;
716 }
717
718 public function getPrimary()
719 {
720 return count($this->primary) == 1 ? $this->primary[0] : $this->primary;
721 }
722
723 public function getPrimaryArray()
724 {
725 return $this->primary;
726 }
727
728 public function getAutoIncrement()
729 {
730 return $this->autoIncrement;
731 }
732
733 public function isUts()
734 {
735 return $this->isUts;
736 }
737
738 public function isUtm()
739 {
740 return $this->isUtm;
741 }
742
743 public function getUfId()
744 {
745 return $this->uf_id;
746 }
747
753 public function setDefaultScope($query)
754 {
755 $dataClass = $this->className;
756 return $dataClass::setDefaultScope($query);
757 }
758
759 public static function isExists($name)
760 {
761 return class_exists(static::normalizeEntityClass($name));
762 }
763
769 public static function normalizeEntityClass($entityName)
770 {
771 if (strtolower(substr($entityName, -5)) !== 'table')
772 {
773 $entityName .= 'Table';
774 }
775
776 if (substr($entityName, 0, 1) !== '\\')
777 {
778 $entityName = '\\'.$entityName;
779 }
780
781 return $entityName;
782 }
783
784 public static function getEntityClassParts($class)
785 {
786 $class = static::normalizeEntityClass($class);
787 $lastPos = strrpos($class, '\\');
788
789 if($lastPos === 0)
790 {
791 //global namespace
792 $namespace = "";
793 }
794 else
795 {
796 $namespace = substr($class, 1, $lastPos - 1);
797 }
798 $name = substr($class, $lastPos + 1, -5);
799
800 return compact('namespace', 'name');
801 }
802
803 public function getCode()
804 {
805 if ($this->code === null)
806 {
807 $this->code = '';
808
809 // get absolute path to class
810 $class_path = explode('\\', strtoupper(ltrim($this->className, '\\')));
811
812 // cut class name to leave namespace only
813 $class_path = array_slice($class_path, 0, -1);
814
815 // cut Bitrix namespace
816 if (count($class_path) && $class_path[0] === 'BITRIX')
817 {
818 $class_path = array_slice($class_path, 1);
819 }
820
821 // glue module name
822 if (!empty($class_path))
823 {
824 $this->code = join('_', $class_path).'_';
825 }
826
827 // glue entity name
828 $this->code .= strtoupper(StringHelper::camel2snake($this->getName()));
829 }
830
831 return $this->code;
832 }
833
834 public function getLangCode()
835 {
836 return $this->getCode().'_ENTITY';
837 }
838
839 public function getTitle()
840 {
841 $dataClass = $this->getDataClass();
842 $title = $dataClass::getTitle();
843
844 if ($title === null)
845 {
846 $title = Main\Localization\Loc::getMessage($this->getLangCode());
847 }
848
849 return $title;
850 }
851
859 public static function camel2snake($str)
860 {
861 return StringHelper::camel2snake($str);
862 }
863
871 public static function snake2camel($str)
872 {
873 return StringHelper::snake2camel($str);
874 }
875
876 public static function normalizeName($entityName)
877 {
878 if (substr($entityName, 0, 1) !== '\\')
879 {
880 $entityName = '\\'.$entityName;
881 }
882
883 if (strtolower(substr($entityName, -5)) === 'table')
884 {
885 $entityName = substr($entityName, 0, -5);
886 }
887
888 return $entityName;
889 }
890
891 public function __clone()
892 {
893 $this->isClone = true;
894
895 // reset entity in fields
896 foreach ($this->fields as $field)
897 {
898 $field->resetEntity();
899 $field->setEntity($this);
900 }
901 }
902
911 public static function getInstanceByQuery(Query $query, &$entity_name = null)
912 {
913 if ($entity_name === null)
914 {
915 $entity_name = 'Tmp'.randString().'x';
916 }
917 elseif (!preg_match('/^[a-z0-9_]+$/i', $entity_name))
918 {
919 throw new Main\ArgumentException(sprintf(
920 'Invalid entity name `%s`.', $entity_name
921 ));
922 }
923
924 $query_string = '('.$query->getQuery().')';
925 $query_chains = $query->getChains();
926
927 $replaced_aliases = array_flip($query->getReplacedAliases());
928
929 // generate fieldsMap
930 $fieldsMap = array();
931
932 foreach ($query->getSelect() as $k => $v)
933 {
934 // convert expressions to regular field, clone in case of regular scalar field
935 if (is_array($v))
936 {
937 // expression
938 $fieldsMap[$k] = array('data_type' => $v['data_type']);
939 }
940 else
941 {
942 if ($v instanceof ExpressionField)
943 {
944 $fieldDefinition = $v->getName();
945
946 // better to initialize fields as objects after entity is created
947 $dataType = Field::getOldDataTypeByField($query_chains[$fieldDefinition]->getLastElement()->getValue());
948 $fieldsMap[$fieldDefinition] = array('data_type' => $dataType);
949 }
950 else
951 {
952 $fieldDefinition = is_numeric($k) ? $v : $k;
953
955 $field = $query_chains[$fieldDefinition]->getLastElement()->getValue();
956
957 if ($field instanceof ExpressionField)
958 {
959 $dataType = Field::getOldDataTypeByField($query_chains[$fieldDefinition]->getLastElement()->getValue());
960 $fieldsMap[$fieldDefinition] = array('data_type' => $dataType);
961 }
962 else
963 {
965 $fieldsMap[$fieldDefinition] = clone $field;
966 $fieldsMap[$fieldDefinition]->setName($fieldDefinition);
967 $fieldsMap[$fieldDefinition]->setColumnName($fieldDefinition);
968 $fieldsMap[$fieldDefinition]->resetEntity();
969 }
970 }
971 }
972
973 if (isset($replaced_aliases[$k]))
974 {
975 if (is_array($fieldsMap[$k]))
976 {
977 $fieldsMap[$k]['column_name'] = $replaced_aliases[$k];
978 }
979 elseif ($fieldsMap[$k] instanceof ScalarField)
980 {
982 $fieldsMap[$k]->setColumnName($replaced_aliases[$k]);
983 }
984 }
985 }
986
987 // generate class content
988 $eval = 'class '.$entity_name.'Table extends '.DataManager::class.' {'.PHP_EOL;
989 $eval .= 'public static function getMap() {'.PHP_EOL;
990 $eval .= 'return '.var_export(['TMP_ID' => ['data_type' => 'integer', 'primary' => true, 'auto_generated' => true]], true).';'.PHP_EOL;
991 $eval .= '}';
992 $eval .= 'public static function getTableName() {'.PHP_EOL;
993 $eval .= 'return '.var_export($query_string, true).';'.PHP_EOL;
994 $eval .= '}';
995 $eval .= '}';
996
997 eval($eval);
998
999 $entity = self::getInstance($entity_name);
1000
1001 foreach ($fieldsMap as $k => $v)
1002 {
1003 $entity->addField($v, $k);
1004 }
1005
1006 return $entity;
1007 }
1008
1019 public static function compileEntity($entityName, $fields = null, $parameters = array())
1020 {
1021 $classCode = '';
1022 $classCodeEnd = '';
1023
1024 if (strtolower(substr($entityName, -5)) !== 'table')
1025 {
1026 $entityName .= 'Table';
1027 }
1028
1029 // validation
1030 if (!preg_match('/^[a-z0-9_]+$/i', $entityName))
1031 {
1032 throw new Main\ArgumentException(sprintf(
1033 'Invalid entity className `%s`.', $entityName
1034 ));
1035 }
1036
1038 $fullEntityName = $entityName;
1039
1040 // namespace configuration
1041 if (!empty($parameters['namespace']) && $parameters['namespace'] !== '\\')
1042 {
1043 $namespace = $parameters['namespace'];
1044
1045 if (!preg_match('/^[a-z0-9_\\\\]+$/i', $namespace))
1046 {
1047 throw new Main\ArgumentException(sprintf(
1048 'Invalid namespace name `%s`', $namespace
1049 ));
1050 }
1051
1052 $classCode = $classCode."namespace {$namespace} "."{";
1053 $classCodeEnd = '}'.$classCodeEnd;
1054
1055 $fullEntityName = '\\'.$namespace.'\\'.$fullEntityName;
1056 }
1057
1058 $parentClass = !empty($parameters['parent']) ? $parameters['parent'] : DataManager::class;
1059
1060 // build entity code
1061 $classCode = $classCode."class {$entityName} extends \\".$parentClass." {";
1062 $classCodeEnd = '}'.$classCodeEnd;
1063
1064 if (!empty($parameters['table_name']))
1065 {
1066 $classCode .= 'public static function getTableName(){return '.var_export($parameters['table_name'], true).';}';
1067 }
1068
1069 if (!empty($parameters['uf_id']))
1070 {
1071 $classCode .= 'public static function getUfId(){return '.var_export($parameters['uf_id'], true).';}';
1072 }
1073
1074 if (!empty($parameters['default_scope']))
1075 {
1076 $classCode .= 'public static function setDefaultScope($query){'.$parameters['default_scope'].'}';
1077 }
1078
1079 if (isset($parameters['parent_map']) && $parameters['parent_map'] == false)
1080 {
1081 $classCode .= 'public static function getMap(){return [];}';
1082 }
1083
1084 if(isset($parameters['object_parent']) && is_a($parameters['object_parent'], EntityObject::class, true))
1085 {
1086 $classCode .= 'public static function getObjectParentClass(){return '.var_export($parameters['object_parent'], true).';}';
1087 }
1088
1089 // create entity
1090 eval($classCode.$classCodeEnd);
1091
1092 $entity = $fullEntityName::getEntity();
1093
1094 // add fields
1095 if (!empty($fields))
1096 {
1097 foreach ($fields as $fieldName => $field)
1098 {
1099 $entity->addField($field, $fieldName);
1100 }
1101 }
1102
1103 return $entity;
1104 }
1105
1110 public function compileDbTableStructureDump()
1111 {
1112 $fields = $this->getScalarFields();
1113
1115 $connection = $this->getConnection();
1116
1117 $autocomplete = [];
1118 $unique = [];
1119
1120 foreach ($fields as $field)
1121 {
1122 if ($field->isAutocomplete())
1123 {
1124 $autocomplete[] = $field->getName();
1125 }
1126
1127 if ($field->isUnique())
1128 {
1129 $unique[] = $field->getName();
1130 }
1131 }
1132
1133 // start collecting queries
1134 $connection->disableQueryExecuting();
1135
1136 // create table
1137 $connection->createTable($this->getDBTableName(), $fields, $this->getPrimaryArray(), $autocomplete);
1138
1139 // create indexes
1140 foreach ($unique as $fieldName)
1141 {
1142 $connection->createIndex($this->getDBTableName(), $fieldName, [$fieldName], null,
1143 Main\DB\MysqlCommonConnection::INDEX_UNIQUE);
1144 }
1145
1146 // stop collecting queries
1147 $connection->enableQueryExecuting();
1148
1149 return $connection->getDisabledQueryExecutingDump();
1150 }
1151
1157 public static function compileObjectClass($dataClass)
1158 {
1159 $dataClass = static::normalizeEntityClass($dataClass);
1160 $classParts = static::getEntityClassParts($dataClass);
1161
1162 if (class_exists($dataClass::getObjectClass(), false)
1163 && is_subclass_of($dataClass::getObjectClass(), EntityObject::class))
1164 {
1165 // class is already defined
1166 return $dataClass::getObjectClass();
1167 }
1168
1169 $baseObjectClass = '\\'.$dataClass::getObjectParentClass();
1170 $objectClassName = static::getDefaultObjectClassName($classParts['name']);
1171
1172 $eval = "";
1173 if($classParts['namespace'] <> '')
1174 {
1175 $eval .= "namespace {$classParts['namespace']} {";
1176 }
1177 $eval .= "class {$objectClassName} extends {$baseObjectClass} {";
1178 $eval .= "static public \$dataClass = '{$dataClass}';";
1179 $eval .= "}"; // end class
1180 if($classParts['namespace'] <> '')
1181 {
1182 $eval .= "}"; // end namespace
1183 }
1184
1185 eval($eval);
1186
1187 return $dataClass::getObjectClass();
1188 }
1189
1195 public static function compileCollectionClass($dataClass)
1196 {
1197 $dataClass = static::normalizeEntityClass($dataClass);
1198 $classParts = static::getEntityClassParts($dataClass);
1199
1200 if (class_exists($dataClass::getCollectionClass(), false)
1201 && is_subclass_of($dataClass::getCollectionClass(), Collection::class))
1202 {
1203 // class is already defined
1204 return $dataClass::getCollectionClass();
1205 }
1206
1207 $baseCollectionClass = '\\'.$dataClass::getCollectionParentClass();
1208 $collectionClassName = static::getDefaultCollectionClassName($classParts['name']);
1209
1210 $eval = "";
1211 if($classParts['namespace'] <> '')
1212 {
1213 $eval .= "namespace {$classParts['namespace']} {";
1214 }
1215 $eval .= "class {$collectionClassName} extends {$baseCollectionClass} {";
1216 $eval .= "static public \$dataClass = '{$dataClass}';";
1217 $eval .= "}"; // end class
1218 if($classParts['namespace'] <> '')
1219 {
1220 $eval .= "}"; // end namespace
1221 }
1222
1223 eval($eval);
1224
1225 return $dataClass::getCollectionClass();
1226 }
1227
1234 public function createDbTable()
1235 {
1236 foreach ($this->compileDbTableStructureDump() as $sqlQuery)
1237 {
1238 $this->getConnection()->query($sqlQuery);
1239 }
1240 }
1241
1247 public static function destroy($entity)
1248 {
1249 if ($entity instanceof Entity)
1250 {
1251 $entityName = $entity->getDataClass();
1252 }
1253 else
1254 {
1255 $entityName = static::normalizeEntityClass($entity);
1256 }
1257
1258 if (isset(self::$instances[$entityName]))
1259 {
1260 unset(self::$instances[$entityName]);
1261 DataManager::unsetEntity($entityName);
1262
1263 return true;
1264 }
1265
1266 return false;
1267 }
1268
1269 public static function onUserTypeChange($userfield, $id = null)
1270 {
1271 // resolve UF ENTITY_ID
1272 if (!empty($userfield['ENTITY_ID']))
1273 {
1274 $ufEntityId = $userfield['ENTITY_ID'];
1275 }
1276 elseif (!empty($id))
1277 {
1278 $usertype = new \CUserTypeEntity();
1279 $userfield = $usertype->GetList([], ["ID" => $id])->Fetch();
1280
1281 if ($userfield)
1282 {
1283 $ufEntityId = $userfield['ENTITY_ID'];
1284 }
1285 }
1286
1287 if (empty($ufEntityId))
1288 {
1289 throw new Main\ArgumentException('Invalid ENTITY_ID');
1290 }
1291
1292 // find orm entity with uf ENTITY_ID
1293 if (!empty(static::$ufIdIndex[$ufEntityId]))
1294 {
1295 if (!empty(static::$instances[static::$ufIdIndex[$ufEntityId]]))
1296 {
1297 // clear for further reinitialization
1298 static::destroy(static::$instances[static::$ufIdIndex[$ufEntityId]]);
1299 }
1300 }
1301 }
1302
1313 public function readFromCache($ttl, $cacheId, $countTotal = false)
1314 {
1315 if($ttl > 0)
1316 {
1317 $cache = Main\Application::getInstance()->getManagedCache();
1318 $cacheDir = $this->getCacheDir();
1319
1320 $count = null;
1321 if($countTotal)
1322 {
1323 if ($cache->read($ttl, $cacheId.".total", $cacheDir))
1324 {
1325 $count = $cache->get($cacheId.".total");
1326 }
1327 else
1328 {
1329 // invalidate cache
1330 return null;
1331 }
1332 }
1333 if($cache->read($ttl, $cacheId, $cacheDir))
1334 {
1335 $result = new Main\DB\ArrayResult($cache->get($cacheId));
1336 if($count !== null)
1337 {
1338 $result->setCount($count);
1339 }
1340 return $result;
1341 }
1342 }
1343 return null;
1344 }
1345
1355 public function writeToCache(Main\DB\Result $result, $cacheId, $countTotal = false)
1356 {
1357 $rows = $result->fetchAll();
1358 $arrayResult = new Main\DB\ArrayResult($rows);
1359
1360 $cache = Main\Application::getInstance()->getManagedCache();
1361 $cache->set($cacheId, $rows);
1362
1363 if($countTotal)
1364 {
1365 $count = $result->getCount();
1366 $cache->set($cacheId.".total", $count);
1367 $arrayResult->setCount($count);
1368 }
1369 return $arrayResult;
1370 }
1371
1382 public function getCacheTtl($ttl)
1383 {
1384 $table = $this->getDBTableName();
1385 $cacheFlags = Main\Config\Configuration::getValue("cache_flags");
1386 if(isset($cacheFlags[$table."_min_ttl"]))
1387 {
1388 $ttl = (int)max($ttl, $cacheFlags[$table."_min_ttl"]);
1389 }
1390 if(isset($cacheFlags[$table."_max_ttl"]))
1391 {
1392 $ttl = (int)min($ttl, $cacheFlags[$table."_max_ttl"]);
1393 }
1394 return $ttl;
1395 }
1396
1397 protected function getCacheDir()
1398 {
1399 return "orm_".$this->getDBTableName();
1400 }
1401
1405 public function cleanCache()
1406 {
1407 if($this->getCacheTtl(100) > 0)
1408 {
1409 //cache might be disabled in .settings.php via *_max_ttl = 0 option
1410 $cache = Main\Application::getInstance()->getManagedCache();
1411 $cache->cleanDir($this->getCacheDir());
1412 }
1413 }
1414
1422 public function enableFullTextIndex($field, $mode = true)
1423 {
1424 }
1425
1433 public function fullTextIndexEnabled($field)
1434 {
1435 return true;
1436 }
1437}
static normalizeEntityClass($entityName)
Definition entity.php:769
readFromCache($ttl, $cacheId, $countTotal=false)
Definition entity.php:1313
static destroy($entity)
Definition entity.php:1247
static onUserTypeChange($userfield, $id=null)
Definition entity.php:1269
static compileObjectClass($dataClass)
Definition entity.php:1157
static normalizeName($entityName)
Definition entity.php:876
appendField(Field $field)
Definition entity.php:462
writeToCache(Main\DB\Result $result, $cacheId, $countTotal=false)
Definition entity.php:1355
static getDefaultObjectClassName($entityName)
Definition entity.php:365
static isExists($name)
Definition entity.php:759
static snake2camel($str)
Definition entity.php:871
initializeField($fieldName, $fieldInfo)
Definition entity.php:151
static getEntityClassParts($class)
Definition entity.php:784
fullTextIndexEnabled($field)
Definition entity.php:1433
static camel2snake($str)
Definition entity.php:859
static getDefaultCollectionClassName($entityName)
Definition entity.php:398
reinitialize($className)
Definition entity.php:249
createObject($setDefaultValues=true)
Definition entity.php:410
static getInstance($entityName)
Definition entity.php:103
static has($entityName)
Definition entity.php:88
static compileCollectionClass($dataClass)
Definition entity.php:1195
enableFullTextIndex($field, $mode=true)
Definition entity.php:1422
const DEFAULT_OBJECT_PREFIX
Definition entity.php:65
addField($fieldInfo, $fieldName=null)
Definition entity.php:527
getReferencesTo($refEntityName)
Definition entity.php:545
getReferencesCountTo($refEntityName)
Definition entity.php:534