Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
userfield.php
1<?php
9namespace Bitrix\Main;
10
15
35{
36 // to use in uts serialized fields
37 const MULTIPLE_DATE_FORMAT = 'Y-m-d';
38 const MULTIPLE_DATETIME_FORMAT = 'Y-m-d H:i:s';
39
40 public static function getMap()
41 {
42 return array(
43 'ID' => array(
44 'data_type' => 'integer',
45 'primary' => true,
46 'autocomplete' => true,
47 ),
48 'ENTITY_ID' => array(
49 'data_type' => 'string',
50 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_ENTITY_ID_TITLE'),
51 ),
52 'FIELD_NAME' => array(
53 'data_type' => 'string',
54 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_FIELD_NAME_TITLE'),
55 ),
56 'USER_TYPE_ID' => array(
57 'data_type' => 'string',
58 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_USER_TYPE_ID_TITLE'),
59 ),
60 'XML_ID' => array(
61 'data_type' => 'string',
62 ),
63 'SORT' => array(
64 'data_type' => 'integer',
65 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_SORT_TITLE'),
66 ),
67 'MULTIPLE' => array(
68 'data_type' => 'boolean',
69 'values' => array('N', 'Y'),
70 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_MULTIPLE_TITLE'),
71 ),
72 'MANDATORY' => array(
73 'data_type' => 'boolean',
74 'values' => array('N', 'Y'),
75 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_MANDATORY_TITLE'),
76 ),
77 'SHOW_FILTER' => array(
78 'data_type' => 'boolean',
79 'values' => array('N', 'Y'),
80 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_SHOW_FILTER_TITLE'),
81 ),
82 'SHOW_IN_LIST' => array(
83 'data_type' => 'boolean',
84 'values' => array('N', 'Y'),
85 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_SHOW_IN_LIST_TITLE'),
86 ),
87 'EDIT_IN_LIST' => array(
88 'data_type' => 'boolean',
89 'values' => array('N', 'Y'),
90 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_EDIT_IN_LIST_TITLE'),
91 ),
92 'IS_SEARCHABLE' => array(
93 'data_type' => 'boolean',
94 'values' => array('N', 'Y'),
95 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_IS_SEARCHABLE_TITLE'),
96 ),
97 'SETTINGS' => array(
98 'data_type' => 'text',
99 'serialized' => true,
100 'title' => Loc::getMessage('MAIN_USER_FIELD_TABLE_SETTINGS_TITLE'),
101 ),
102 );
103 }
104
105 public static function getLabelsReference(string $referenceName = null, string $languageId = null): ORM\Fields\Relations\Reference
106 {
107 if(!$referenceName)
108 {
109 $referenceName = 'LABELS';
110 }
111
112 $filter = [
113 '=this.ID' => 'ref.USER_FIELD_ID',
114 ];
115
116 if($languageId)
117 {
118 $filter['=ref.LANGUAGE_ID'] = new SqlExpression('?s', $languageId);
119 }
120
122 $referenceName,
123 UserFieldLangTable::class,
124 $filter
125 );
126 }
127
128 public static function getLabelFields(): array
129 {
130 return [
131 'LANGUAGE_ID',
132 'EDIT_FORM_LABEL',
133 'LIST_COLUMN_LABEL',
134 'LIST_FILTER_LABEL',
135 'ERROR_MESSAGE',
136 'HELP_MESSAGE',
137 ];
138 }
139
140 public static function getLabelsSelect(string $referenceName = null): array
141 {
142 if(!$referenceName)
143 {
144 $referenceName = 'LABELS';
145 }
146
147 $result = [];
148 foreach(static::getLabelFields() as $labelField)
149 {
150 $result[$labelField] = $referenceName . '.' . $labelField;
151 }
152
153 return $result;
154 }
155
156 public static function getFieldData(int $id): ?array
157 {
158 $labelFields = static::getLabelFields();
159 $field = [];
160 $list = static::getList([
161 'select' => array_merge(['*'], UserFieldTable::getLabelsSelect()),
162 'filter' => [
163 '=ID' => $id,
164 ],
165 'runtime' => [
166 static::getLabelsReference(),
167 ]
168 ]);
169 foreach($list as $data)
170 {
171 if(empty($field))
172 {
173 $field = $data;
174 unset(
175 $field['LANGUAGE_ID'],
176 $field['EDIT_FORM_LABEL'],
177 $field['LIST_COLUMN_LABEL'],
178 $field['LIST_FILTER_LABEL'],
179 $field['ERROR_MESSAGE'],
180 $field['HELP_MESSAGE'],
181 $field['UALIAS_0']
182 );
183 }
184
185 foreach($labelFields as $labelField)
186 {
187 $field[$labelField][$data['LANGUAGE_ID']] = $data[$labelField];
188 }
189 }
190
191 if(empty($field))
192 {
193 return null;
194 }
195
196 if($field['USER_TYPE_ID'] === 'enumeration')
197 {
198 $field['ENUM'] = [];
199 $enumEntity = new \CUserFieldEnum();
200 $enumList = $enumEntity->GetList(
201 [
202 'SORT' => 'ASC'
203 ], [
204 'USER_FIELD_ID' => $field['ID'],
205 ]
206 );
207 while($enum = $enumList->Fetch())
208 {
209 $field['ENUM'][] = $enum;
210 }
211 }
212
213 return $field;
214 }
215
222 public static function add(array $data)
223 {
224 throw new NotImplementedException('Use \CUserTypeEntity API instead.');
225 }
226
234 public static function update($primary, array $data)
235 {
236 throw new NotImplementedException('Use \CUserTypeEntity API instead.');
237 }
238
245 public static function delete($primary)
246 {
247 throw new NotImplementedException('Use \CUserTypeEntity API instead.');
248 }
249
257 public static function attachFields(ORM\Entity $entity, $ufId)
258 {
259 global $USER_FIELD_MANAGER;
260
261 $utsFields = array();
262 $utsFieldNames = array();
263
264 $utmFields = array();
265 $utmFieldNames = array();
266
267 $fields = $USER_FIELD_MANAGER->getUserFields($ufId);
268
269 foreach ($fields as $field)
270 {
271 if ($field['MULTIPLE'] === 'Y')
272 {
273 $utmFields[] = $field;
274 $utmFieldNames[$field['FIELD_NAME']] = true;
275 }
276 else
277 {
278 $utsFields[] = $field;
279 $utsFieldNames[$field['FIELD_NAME']] = true;
280 }
281 }
282
283 if (!empty($utsFields) || !empty($utmFields))
284 {
285 // create uts entity & put fields into it
286 $utsEntity = static::createUtsEntity($entity, $utsFields, $utmFields, $ufId);
287
288 // create reference to uts entity
289 $utsReference = new ORM\Fields\Relations\Reference('UTS_OBJECT', $utsEntity->getDataClass(), array(
290 '=this.ID' => 'ref.VALUE_ID'
291 ));
292
293 $entity->addField($utsReference);
294
295 // add UF_* aliases
296 foreach ($fields as $userfield)
297 {
298 $utsFieldName = $userfield['FIELD_NAME'];
299
301 $utsField = $utsEntity->getField($utsFieldName);
302
303 $aliasField = new ORM\Fields\UserTypeField(
304 $utsFieldName,
305 '%s',
306 'UTS_OBJECT.'.$utsFieldName,
307 array('data_type' => get_class($utsField))
308 );
309
310 $aliasField->configureValueField($utsField);
311
312 if ($userfield['MULTIPLE'] == 'Y')
313 {
314 $aliasField->configureMultiple();
315 }
316
317 $entity->addField($aliasField);
318 }
319
320
321 if (!empty($utsFields))
322 {
323 foreach ($utsFields as $utsField)
324 {
326 $utsEntityField = $utsEntity->getField($utsField['FIELD_NAME']);
327
328 foreach ($USER_FIELD_MANAGER->getEntityReferences($utsField, $utsEntityField) as $reference)
329 {
330 // rewrite reference from this.field to this.uts_object.field
331 $referenceDesc = static::rewriteUtsReference($reference->getReference());
332
333 $aliasReference = new ORM\Fields\Relations\Reference(
334 $reference->getName(),
335 $reference->getRefEntityName(),
336 $referenceDesc
337 );
338
339 $entity->addField($aliasReference);
340 }
341 }
342 }
343
344 if (!empty($utmFields))
345 {
346 // create utm entity & put base fields into it
347 $utmEntity = static::createUtmEntity($entity, $utmFields, $ufId);
348
349 // add UF_* aliases
350 foreach ($utmFieldNames as $utmFieldName => $true)
351 {
353 $utmField = $utmEntity->getField($utmFieldName);
354
355 $aliasField = new ORM\Fields\ExpressionField(
356 $utmFieldName.'_SINGLE',
357 '%s',
358 $utmEntity->getFullName().':PARENT_'.$utmFieldName.'.'.$utmField->getColumnName(),
359 array('data_type' => get_class($utmField))
360 );
361
362 $entity->addField($aliasField);
363 }
364 }
365 }
366 }
367
378 protected static function createUtsEntity(ORM\Entity $srcEntity, array $utsFields, array $utmFields, $ufId = null)
379 {
380 global $USER_FIELD_MANAGER;
381
382 // get namespace & class
384 $utsClassFull = static::getUtsEntityClassNameBySrcEntity($srcEntity);
385 $utsClassPath = explode('\\', ltrim($utsClassFull, '\\'));
386
387 $utsNamespace = join('\\', array_slice($utsClassPath, 0, -1));
388 $utsClass = end($utsClassPath);
389
390 // get table name
391 $utsTable = static::getUtsEntityTableNameBySrcEntity($srcEntity, $ufId);
392
393 // base fields
394 $fieldsMap = array(
395 'VALUE_ID' => array(
396 'data_type' => 'integer',
397 'primary' => true
398 ),
399 'PARENT' => array(
400 'data_type' => $srcEntity->getDataClass(),
401 'reference' => array(
402 '=this.VALUE_ID' => 'ref.ID'
403 )
404 )
405 );
406
407 // initialize entity
408 if (class_exists($utsNamespace."\\".$utsClass))
409 {
410 ORM\Entity::destroy($utsNamespace."\\".$utsClass);
411 $entity = ORM\Entity::getInstance($utsNamespace."\\".$utsClass);
412
413 foreach ($fieldsMap as $fieldName => $field)
414 {
415 $entity->addField($field, $fieldName);
416 }
417 }
418 else
419 {
420 $entity = ORM\Entity::compileEntity($utsClass, $fieldsMap, array(
421 'namespace' => $utsNamespace, 'table_name' => $utsTable
422 ));
423 }
424
425 foreach ($utsFields as $utsField)
426 {
427 $field = $USER_FIELD_MANAGER->getEntityField($utsField);
428 $entity->addField($field);
429
430 foreach ($USER_FIELD_MANAGER->getEntityReferences($utsField, $field) as $reference)
431 {
432 $entity->addField($reference);
433 }
434 }
435
436 foreach ($utmFields as $utmFieldMeta)
437 {
438 // better to get field from UtmEntity
439 $utmField = $USER_FIELD_MANAGER->getEntityField($utmFieldMeta);
440
441 // add serialized utm cache-fields
442 $cacheField = (new ORM\Fields\UserTypeUtsMultipleField($utmField->getName()))
443 ->configureUtmField($utmField);
444
445 static::setMultipleFieldSerialization($cacheField, $utmField);
446 $entity->addField($cacheField);
447 }
448
449 return $entity;
450 }
451
458 public static function setMultipleFieldSerialization(ORM\Fields\Field $entityField, $fieldAsType)
459 {
460 global $USER_FIELD_MANAGER;
461
462 if (!($fieldAsType instanceof ORM\Fields\Field))
463 {
464 $fieldAsType = $USER_FIELD_MANAGER->getEntityField($fieldAsType);
465 }
466
467 if ($fieldAsType instanceof ORM\Fields\DatetimeField)
468 {
469 if ($entityField instanceof ORM\Fields\ArrayField)
470 {
471 $entityField->configureSerializeCallback([__CLASS__, 'serializeMultipleDatetime']);
472 $entityField->configureUnserializeCallback([__CLASS__, 'unserializeMultipleDatetime']);
473 }
474 else
475 {
476 $entityField->addSaveDataModifier([__CLASS__, 'serializeMultipleDatetime']);
477 $entityField->addFetchDataModifier([__CLASS__, 'unserializeMultipleDatetime']);
478 }
479 }
480 elseif ($fieldAsType instanceof ORM\Fields\DateField)
481 {
482 if ($entityField instanceof ORM\Fields\ArrayField)
483 {
484 $entityField->configureSerializeCallback([__CLASS__, 'serializeMultipleDate']);
485 $entityField->configureUnserializeCallback([__CLASS__, 'unserializeMultipleDate']);
486 }
487 else
488 {
489 $entityField->addSaveDataModifier([__CLASS__, 'serializeMultipleDate']);
490 $entityField->addFetchDataModifier([__CLASS__, 'unserializeMultipleDate']);
491 }
492 }
493 else
494 {
495 if ($entityField instanceof ORM\Fields\ArrayField)
496 {
497 $entityField->configureSerializationPhp();
498 }
499 else
500 {
501 $entityField->setSerialized();
502 }
503 }
504 }
505
506 public static function rewriteUtsReference($referenceDesc)
507 {
508 $new = array();
509
510 foreach ($referenceDesc as $k => $v)
511 {
512 if (is_array($v))
513 {
514 $new[$k] = static::rewriteUtsReference($v);
515 }
516 else
517 {
518 $k = str_replace('this.', 'this.UTS_OBJECT.', $k);
519 $new[$k] = $v;
520 }
521 }
522
523 return $new;
524 }
525
526 protected static function getUtsEntityClassNameBySrcEntity(ORM\Entity $srcEntity)
527 {
528 return $srcEntity->getFullName().'UtsTable';
529 }
530
531 protected static function getUtsEntityTableNameBySrcEntity(ORM\Entity $srcEntity, $ufId = null)
532 {
533 return 'b_uts_'.mb_strtolower($ufId ?: $srcEntity->getUfId());
534 }
535
545 protected static function createUtmEntity(ORM\Entity $srcEntity, array $utmFields, $ufId = null)
546 {
547 global $USER_FIELD_MANAGER;
548
550 $utmClassFull = static::getUtmEntityClassNameBySrcEntity($srcEntity);
551 $utmClassPath = explode('\\', ltrim($utmClassFull, '\\'));
552
553 $utmNamespace = join('\\', array_slice($utmClassPath, 0, -1));
554 $utmClass = end($utmClassPath);
555
556 // get table name
557 $utmTable = static::getUtmEntityTableNameBySrcEntity($srcEntity, $ufId);
558
559 // collect fields
560 $fieldsMap = array(
561 'ID' => array(
562 'data_type' => 'integer',
563 'primary' => true,
564 'autocomplete' => true
565 ),
566 'VALUE_ID' => array(
567 'data_type' => 'integer',
568 'primary' => true
569 ),
570 'PARENT' => array(
571 'data_type' => $srcEntity->getDataClass(),
572 'reference' => array(
573 '=this.VALUE_ID' => 'ref.ID'
574 )
575 ),
576 'FIELD_ID' => array(
577 'data_type' => 'integer'
578 ),
579
580 // base values fields
581 'VALUE' => array(
582 'data_type' => 'text'
583 ),
584 'VALUE_INT' => array(
585 'data_type' => 'integer'
586 ),
587 'VALUE_DOUBLE' => array(
588 'data_type' => 'float'
589 ),
590 'VALUE_DATE' => array(
591 'data_type' => 'datetime'
592 )
593 );
594
595 // initialize entity
596 if (class_exists($utmNamespace."\\".$utmClass))
597 {
598 ORM\Entity::destroy($utmNamespace."\\".$utmClass);
599 $entity = ORM\Entity::getInstance($utmNamespace."\\".$utmClass);
600
601 foreach ($fieldsMap as $fieldName => $field)
602 {
603 $entity->addField($field, $fieldName);
604 }
605 }
606 else
607 {
608 $entity = ORM\Entity::compileEntity($utmClass, $fieldsMap, array(
609 'namespace' => $utmNamespace, 'table_name' => $utmTable
610 ));
611 }
612
613 // add utm fields being mapped on real column name
614 foreach ($utmFields as $utmField)
615 {
616 $field = $USER_FIELD_MANAGER->getEntityField($utmField);
617
618 if ($field instanceof ORM\Fields\IntegerField)
619 {
620 $columnName = 'VALUE_INT';
621 }
622 elseif ($field instanceof ORM\Fields\FloatField)
623 {
624 $columnName = 'VALUE_DOUBLE';
625 }
626 elseif ($field instanceof ORM\Fields\DateField)
627 {
628 $columnName = 'VALUE_DATE';
629 }
630 else
631 {
632 $columnName = 'VALUE';
633 }
634
635 $field->setColumnName($columnName);
636
637 $entity->addField($field);
638
639 foreach ($USER_FIELD_MANAGER->getEntityReferences($utmField, $field) as $reference)
640 {
641 $entity->addField($reference);
642 }
643
644 // add back-reference
645 $refField = new ORM\Fields\Relations\Reference(
646 'PARENT_'.$utmField['FIELD_NAME'],
647 $srcEntity->getDataClass(),
648 array('=this.VALUE_ID' => 'ref.ID', '=this.FIELD_ID' => array('?i', $utmField['ID']))
649 );
650
651 $entity->addField($refField);
652 }
653
654 return $entity;
655 }
656
657 protected static function getUtmEntityClassNameBySrcEntity(ORM\Entity $srcEntity)
658 {
659 return $srcEntity->getFullName().'UtmTable';
660 }
661
662 protected static function getUtmEntityTableNameBySrcEntity(ORM\Entity $srcEntity, $ufId = null)
663 {
664 return 'b_utm_'.mb_strtolower($ufId ?: $srcEntity->getUfId());
665 }
666
672 public static function serializeMultipleDatetime($value)
673 {
674 if (is_array($value) || $value instanceof \Traversable)
675 {
676 $tmpValue = array();
677
678 foreach ($value as $k => $singleValue)
679 {
681 $tmpValue[$k] = $singleValue->format(static::MULTIPLE_DATETIME_FORMAT);
682 }
683
684 return serialize($tmpValue);
685 }
686
687 return $value;
688 }
689
696 public static function unserializeMultipleDatetime($value)
697 {
698 if($value <> '')
699 {
700 $value = unserialize($value, ["allowed_classes" => false]);
701
702 foreach($value as &$singleValue)
703 {
704 try
705 {
706 //try new independent datetime format
707 $singleValue = new Type\DateTime($singleValue, static::MULTIPLE_DATETIME_FORMAT);
708 }
709 catch(ObjectException $e)
710 {
711 //try site format
712 $singleValue = new Type\DateTime($singleValue);
713 }
714 }
715 }
716
717 return $value;
718 }
719
725 public static function serializeMultipleDate($value)
726 {
727 if (is_array($value) || $value instanceof \Traversable)
728 {
729 $tmpValue = array();
730
731 foreach ($value as $k => $singleValue)
732 {
734 $tmpValue[$k] = $singleValue->format(static::MULTIPLE_DATE_FORMAT);
735 }
736
737 return serialize($tmpValue);
738 }
739
740 return $value;
741 }
742
749 public static function unserializeMultipleDate($value)
750 {
751 if($value <> '')
752 {
753 $value = unserialize($value, ["allowed_classes" => false]);
754
755 foreach($value as &$singleValue)
756 {
757 try
758 {
759 //try new independent datetime format
760 $singleValue = new Type\Date($singleValue, static::MULTIPLE_DATE_FORMAT);
761 }
762 catch(ObjectException $e)
763 {
764 //try site format
765 $singleValue = new Type\Date($singleValue);
766 }
767 }
768 }
769
770 return $value;
771 }
772}
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static unserializeMultipleDate($value)
static getLabelsSelect(string $referenceName=null)
static getUtsEntityClassNameBySrcEntity(ORM\Entity $srcEntity)
static getLabelsReference(string $referenceName=null, string $languageId=null)
static getUtmEntityTableNameBySrcEntity(ORM\Entity $srcEntity, $ufId=null)
static setMultipleFieldSerialization(ORM\Fields\Field $entityField, $fieldAsType)
static add(array $data)
static rewriteUtsReference($referenceDesc)
static unserializeMultipleDatetime($value)
static getUtsEntityTableNameBySrcEntity(ORM\Entity $srcEntity, $ufId=null)
static getFieldData(int $id)
static getUtmEntityClassNameBySrcEntity(ORM\Entity $srcEntity)
static update($primary, array $data)