Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
base.php
1<?php
2
3
5
6
14
15abstract class Base
16{
17 abstract public function getFields();
18
19 final public function prepareFieldInfos($fields): array
20 {
21 $result = [];
22 foreach($fields as $name => $info)
23 {
24 $attributs = isset($info['ATTRIBUTES']) ? $info['ATTRIBUTES'] : [];
25
26 if(in_array(Attributes::HIDDEN, $attributs, true))
27 {
28 continue;
29 }
30
31 $result[$name] = $this->prepareFieldAttributs($info, $attributs);
32 }
33
34 return $result;
35 }
36
37 protected function prepareFieldAttributs($info, $attributs): array
38 {
39 $intersectRequired = array_intersect([
43 ], $attributs);
44
45 return array(
46 'TYPE' => $info['TYPE'],
47 'IS_REQUIRED' => count($intersectRequired) > 0,
48 'IS_READ_ONLY' => in_array(Attributes::READONLY, $attributs, true),
49 'IS_IMMUTABLE' => in_array(Attributes::IMMUTABLE, $attributs, true)
50 );
51 }
52
53 final public function getListFieldInfo(array $fieldsInfo, $params=[]): array
54 {
55 $list = [];
56
57 $filter = isset($params['filter'])?$params['filter']:[];
58 $ignoredAttributes = isset($filter['ignoredAttributes'])?$filter['ignoredAttributes']:[];
59 $ignoredFields = isset($filter['ignoredFields'])?$filter['ignoredFields']:[];
60 $skipFields = isset($filter['skipFields'])?$filter['skipFields']:[];
61
62 foreach ($fieldsInfo as $name=>$info)
63 {
64 if(in_array($name, $ignoredFields))
65 {
66 continue;
67 }
68 elseif(in_array($name, $skipFields) == false)
69 {
70 if(isset($info['ATTRIBUTES']))
71 {
72 $skipAttr = array_intersect($ignoredAttributes, $info['ATTRIBUTES']);
73 if(!empty($skipAttr))
74 {
75 continue;
76 }
77 }
78 }
79
80 $list[$name] = $info;
81 }
82
83 return $list;
84 }
85
86 //region convert keys to snake case
87 final public function convertKeysToSnakeCaseFields($fields)
88 {
89 return $this->convertKeysToSnakeCase($fields);
90 }
91
92 final public function convertKeysToSnakeCaseSelect($fields)
93 {
94 $converter = new Converter(Converter::VALUES | Converter::TO_SNAKE | Converter::TO_SNAKE_DIGIT | Converter::TO_UPPER);
95 return $converter->process($fields);
96 }
97
98 final public function convertKeysToSnakeCaseFilter($fields)
99 {
100 return $this->convertKeysToSnakeCase($fields);
101 }
102
103 final public function convertKeysToSnakeCaseOrder($fields): array
104 {
105 $result = [];
106
107 $converter = new Converter(Converter::VALUES | Converter::TO_UPPER);
108 $converterForKey = new Converter(Converter::KEYS | Converter::TO_SNAKE | Converter::TO_SNAKE_DIGIT | Converter::TO_UPPER);
109
110 foreach ($converter->process($fields) as $key=>$value)
111 {
112 $result[$converterForKey->process($key)] = $value;
113 }
114
115 return $result;
116 }
117
118 public function convertKeysToSnakeCaseArguments($name, $arguments)
119 {
120 return $arguments;
121 }
122
123 final protected function convertKeysToSnakeCase($data)
124 {
125 $converter = new Converter(Converter::KEYS | Converter::RECURSIVE | Converter::TO_SNAKE | Converter::TO_SNAKE_DIGIT | Converter::TO_UPPER);
126 return $converter->process($data);
127 }
128 //endregion
129
130 //region internalize fields
131 public function internalizeArguments($name, $arguments): array
132 {
133 throw new NotImplementedException('Internalize arguments. The method '.$name.' is not implemented.');
134 }
135
136 public function internalizeFieldsList($arguments, $fieldsInfo=[]): array
137 {
138 $fieldsInfo = empty($fieldsInfo) ? $this->getFields():$fieldsInfo;
139
140 $fieldsInfo = $this->getListFieldInfo($fieldsInfo, ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN]]]);
141
142 $filter = isset($arguments['filter']) ? $this->internalizeFilterFields($arguments['filter'], $fieldsInfo):[];
143 $select = isset($arguments['select']) ? $this->internalizeSelectFields($arguments['select'], $fieldsInfo):[];
144 $order = isset($arguments['order']) ? $this->internalizeOrderFields($arguments['order'], $fieldsInfo):[];
145
146 return [
147 'filter'=>$filter,
148 'select'=>$select,
149 'order'=>$order,
150 ];
151 }
152
153 public function internalizeFieldsAdd($fields, $fieldsInfo=[]): array
154 {
155 $fieldsInfo = empty($fieldsInfo) ? $this->getFields():$fieldsInfo;
156
157 return $this->internalizeFields(
158 $fields,
159 $this->getListFieldInfo(
160 $fieldsInfo,
161 ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN, Attributes::READONLY]]]
162 )
163 );
164 }
165
166 public function internalizeFieldsUpdate($fields, $fieldsInfo=[]): array
167 {
168 $fieldsInfo = empty($fieldsInfo) ? $this->getFields():$fieldsInfo;
169
170 return $this->internalizeFields(
171 $fields,
172 $this->getListFieldInfo(
173 $fieldsInfo,
174 ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN, Attributes::READONLY, Attributes::IMMUTABLE]]]
175 )
176 );
177 }
178
179 final protected function internalizeFields($fields, array $fieldsInfo): array
180 {
181 $result = [];
182
183 foreach ($fields as $name=>$value)
184 {
185 $info = isset($fieldsInfo[$name]) ? $fieldsInfo[$name]:null;
186 if(!$info)
187 {
188 continue;
189 }
190
191 $r = $this->internalizeValue($value, $info);
192
193 if($r->isSuccess() === false)
194 {
195 continue;
196 }
197
198 $result[$this->canonicalizeField($name, $info)] = $r->getData()[0];
199 }
200 return $result;
201 }
202
203 final protected function internalizeValue($value, $info): Result
204 {
205 $r = new Result();
206
207 $type = isset($info['TYPE']) ? $info['TYPE']:'';
208
209 if($type === DataType::TYPE_FLOAT)
210 {
211 $value = floatval($value);
212 }
213 elseif($type === DataType::TYPE_INT)
214 {
215 $value = (int)$value;
216 }
217 elseif($type === DataType::TYPE_DATETIME)
218 {
219 $date = $this->internalizeDateTimeValue($value);
220
221 if($date->isSuccess())
222 {
223 $value = $date->getData()[0];
224 }
225 else
226 {
227 $r->addErrors($date->getErrors());
228 }
229 }
230 elseif($type === DataType::TYPE_DATE)
231 {
232 $date = $this->internalizeDateValue($value);
233
234 if($date->isSuccess())
235 {
236 $value = $date->getData()[0];
237 }
238 else
239 {
240 $r->addErrors($date->getErrors());
241 }
242 }
243 elseif($type === DataType::TYPE_FILE)
244 {
245 $value = $this->internalizeFileValue($value);
246 }
247 else
248 {
249 $r = $this->internalizeExtendedTypeValue($value, $info);
250 if($r->isSuccess())
251 {
252 $value = $r->getData()[0];
253 }
254 }
255
256 if($r->isSuccess())
257 {
258 $r->setData([$value]);
259 }
260
261 return $r;
262 }
263
264 protected function internalizeDateValue($value): Result
265 {
266 $r = new Result();
267
268 $date = $this->internalizeDate($value);
269
270 if($date instanceof Date)
271 {
272 $value = $date;
273 }
274 else
275 {
276 $r->addError(new Error('Wrong type date'));
277 }
278
279 if($r->isSuccess())
280 {
281 $r->setData([$value]);
282 }
283
284 return $r;
285 }
286
287 protected function internalizeDateTimeValue($value): Result
288 {
289 $r = new Result();
290
291 $date = $this->internalizeDateTime($value);
292
293 if($date instanceof DateTime)
294 {
295 $value = $date;
296 }
297 else
298 {
299 $r->addError(new Error('Wrong type datetime'));
300 }
301
302 if($r->isSuccess())
303 {
304 $r->setData([$value]);
305 }
306
307 return $r;
308 }
309
310 final protected function internalizeDate($value)
311 {
312 if($value === '')
313 {
314 $date = '';
315 }
316 else
317 {
318 $time = strtotime($value);
319 $date = ($time) ? \Bitrix\Main\Type\Date::createFromTimestamp($time):'';
320 }
321 return $date;
322 }
323
324 final protected function internalizeDateTime($value)
325 {
326 if($value === '')
327 {
328 $date = '';
329 }
330 else
331 {
332 $time = strtotime($value);
333 $date = ($time) ? \Bitrix\Main\Type\DateTime::createFromTimestamp($time):'';
334 }
335 return $date;
336 }
337
338 final protected function internalizeFileValue($value)
339 {
340 $result = [];
341
342 $remove = isset($value['REMOVE']) && is_string($value['REMOVE']) && mb_strtoupper($value['REMOVE']) === 'Y';
343 $data = isset($value['FILE_DATA']) ? $value['FILE_DATA'] : [];
344
345 $data = $this->parserFileValue($data);
346
347 $content = isset($data['CONTENT']) ? $data['CONTENT']:'';
348 $name = isset($data['NAME']) ? $data['NAME']:'';
349
350 if(is_string($content) && $content !== '')
351 {
352 // Add/replace file
353 $fileInfo = \CRestUtil::saveFile($content, $name);
354 if(is_array($fileInfo))
355 {
356 $result = $fileInfo;
357 }
358 }
359 elseif($remove)
360 {
361 // Remove file
362 $result = ['del'=>'Y'];
363 }
364
365 return $result;
366 }
367
368 protected function internalizeExtendedTypeValue($value, $info): Result
369 {
370 $r = new Result();
371
372 $r->setData([$value]);
373
374 return $r;
375 }
376
377 final protected function parserFileValue(array $data): array
378 {
379 $count = count($data);
380
381 if($count > 1)
382 {
383 $name = $data[0];
384 $content = $data[1];
385 }
386 elseif($count === 1)
387 {
388 $name = '';
389 $content = $data[0];
390 }
391 else
392 {
393 $name = '';
394 $content = '';
395 }
396
397 return ['CONTENT'=>$content, 'NAME'=>$name];
398 }
399
400 final protected function internalizeFilterFields($fields, array $fieldsInfo): array
401 {
402 $result = [];
403
404 $fieldsInfo = empty($fieldsInfo)? $this->getFields():$fieldsInfo;
405
406 if (is_array($fields) && !empty($fields))
407 {
408 $listFieldsInfo = $this->getListFieldInfo($fieldsInfo, ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN]]]);
409
410 foreach ($fields as $rawName=>$value)
411 {
412 $field = \CSqlUtil::GetFilterOperation($rawName);
413
414 $info = isset($listFieldsInfo[$field['FIELD']]) ? $listFieldsInfo[$field['FIELD']]:null;
415 if (!$info)
416 {
417 continue;
418 }
419
420 $r = $this->internalizeValue($value, $info);
421
422 if ($r->isSuccess() === false)
423 {
424 continue;
425 }
426
427 $operation = mb_substr($rawName, 0, mb_strlen($rawName) - mb_strlen($field['FIELD']));
428 if (isset($info['FORBIDDEN_FILTERS'])
429 && is_array($info['FORBIDDEN_FILTERS'])
430 && in_array($operation, $info['FORBIDDEN_FILTERS'], true))
431 {
432 continue;
433 }
434
435 $rawName = $operation.$this->canonicalizeField($field['FIELD'], $info);
436
437 $result[$rawName] = $r->getData()[0];
438 }
439 }
440
441 return $result;
442 }
443
444 final protected function internalizeSelectFields($fields, array $fieldsInfo): array
445 {
446 $result = [];
447
448 $fieldsInfo = empty($fieldsInfo)? $this->getFields():$fieldsInfo;
449
450 $listFieldsInfo = $this->getListFieldInfo($fieldsInfo, ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN]]]);
451
452 if (empty($fields) || in_array('*', $fields, true))
453 {
454 $fields = array_keys($listFieldsInfo);
455 }
456
457 foreach ($fields as $name)
458 {
459 $info = isset($listFieldsInfo[$name]) ? $listFieldsInfo[$name]:null;
460 if (!$info)
461 {
462 continue;
463 }
464
465 $result[] = $this->canonicalizeField($name, $info);
466 }
467
468 return $result;
469 }
470
471 final protected function internalizeOrderFields($fields, array $fieldsInfo): array
472 {
473 $result = [];
474
475 $fieldsInfo = empty($fieldsInfo)? $this->getFields():$fieldsInfo;
476
477 if (is_array($fields) && count($fields)>0)
478 {
479 $listFieldsInfo = $this->getListFieldInfo($fieldsInfo, ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN]]]);
480
481 foreach ($fields as $field => $order)
482 {
483 $info = isset($listFieldsInfo[$field]) ? $listFieldsInfo[$field]:null;
484 if (!$info)
485 {
486 continue;
487 }
488
489 $result[$this->canonicalizeField($field, $info)] = $order;
490 }
491 }
492
493 return $result;
494 }
495
496 final protected function internalizeListFields($list, $fieldsInfo=[]): array
497 {
498 $result = [];
499
500 $fieldsInfo = empty($fieldsInfo) ? $this->getFields():$fieldsInfo;
501
502 $listFieldsInfo = $this->getListFieldInfo($fieldsInfo, ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN]]]);
503
504 if(is_array($list) && count($list)>0)
505 {
506 foreach ($list as $k=>$item)
507 {
508 $result[$k] = $this->internalizeFields($item, $listFieldsInfo);
509 }
510 }
511 return $result;
512 }
513 //endregion
514
515 // region externalize fields
516 final protected function externalizeValue($name, $value, $fields, $fieldsInfo): Result
517 {
518 $r = new Result();
519
520 $type = isset($fieldsInfo[$name]['TYPE']) ? $fieldsInfo[$name]['TYPE']:'';
521
522 if(empty($value))
523 {
524 $value = $this->externalizeEmptyValue($name, $value, $fields, $fieldsInfo);
525 }
526 else
527 {
528 if($type === DataType::TYPE_FLOAT)
529 {
530 $value = floatval($value);
531 }
532 elseif($type === DataType::TYPE_INT)
533 {
534 $value = (int)$value;
535 }
536 elseif($type === DataType::TYPE_DATE)
537 {
538 $date = $this->externalizeDateValue($value);
539
540 if($date->isSuccess())
541 {
542 $value = $date->getData()[0];
543 }
544 else
545 {
546 $r->addErrors($date->getErrors());
547 }
548 }
549 elseif($type === DataType::TYPE_DATETIME)
550 {
551 $date = $this->externalizeDateTimeValue($value);
552
553 if($date->isSuccess())
554 {
555 $value = $date->getData()[0];
556 }
557 else
558 {
559 $r->addErrors($date->getErrors());
560 }
561 }
562 elseif($type === DataType::TYPE_FILE)
563 {
564 $value = $this->externalizeFileValue($name, $value, $fields);
565 }
566 else
567 {
568 $r = $this->externalizeExtendedTypeValue($name, $value, $fields, $fieldsInfo);
569 if($r->isSuccess())
570 {
571 $value = $r->getData()[0];
572 }
573 }
574 }
575
576 if($r->isSuccess())
577 {
578 $r->setData([$value]);
579 }
580
581 return $r;
582 }
583
584 final protected function externalizeFields($fields, $fieldsInfo): array
585 {
586 $result = [];
587
588 if(is_array($fields) && count($fields)>0)
589 {
590 foreach($fields as $name => $value)
591 {
592 $name = $this->aliasesField($name, $fieldsInfo);
593
594 $info = isset($fieldsInfo[$name]) ? $fieldsInfo[$name] : null;
595 if (!$info)
596 {
597 continue;
598 }
599
600 $r = $this->externalizeValue($name, $value, $fields, $fieldsInfo);
601
602 if ($r->isSuccess() === false)
603 {
604 continue;
605 }
606
607 $result[$name] = $r->getData()[0];
608 }
609 }
610 return $result;
611 }
612
613 protected function externalizeEmptyValue($name, $value, $fields, $fieldsInfo)
614 {
615 return null;
616 }
617
618 final protected function externalizeDateValue($value): Result
619 {
620 $r = new Result();
621
622 $time = strtotime($value);
623 $value = ($time) ? \Bitrix\Main\Type\Date::createFromTimestamp($time):'';
624
625 if($r->isSuccess())
626 {
627 $r->setData([$value]);
628 }
629
630 return $r;
631 }
632
633 final protected function externalizeDateTimeValue($value): Result
634 {
635 $r = new Result();
636
637 $time = strtotime($value);
638 $value = ($time) ? \Bitrix\Main\Type\DateTime::createFromTimestamp($time):'';
639
640 if($r->isSuccess())
641 {
642 $r->setData([$value]);
643 }
644
645 return $r;
646 }
647
654 protected function externalizeFileValue($name, $value, $fields): array
655 {
656 throw new NotImplementedException('Externalize file. The method externalizeFile is not implemented.');
657 }
658
666 protected function externalizeExtendedTypeValue($name, $value, $fields, $fieldsInfo): Result
667 {
668 $r = new Result();
669
670 $r->setData([$value]);
671
672 return $r;
673 }
674
675 public function externalizeListFields($list, $fieldsInfo=[]): array
676 {
677 $result = [];
678
679 $fieldsInfo = empty($fieldsInfo) ? $this->getFields():$fieldsInfo;
680
681 $listFieldInfo = $this->getListFieldInfo($fieldsInfo, ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN]]]);
682
683 if(is_array($list) && count($list)>0)
684 {
685 foreach($list as $k=>$fields)
686 $result[$k] = $this->externalizeFields($fields, $listFieldInfo);
687 }
688 return $result;
689 }
690
697 public function externalizeResult($name, $fields): array
698 {
699 throw new NotImplementedException('Externalize result. The method '.$name.' is not implemented.');
700 }
701
702 public function externalizeFieldsGet($fields, $fieldsInfo=[]): array
703 {
704 $fieldsInfo = empty($fieldsInfo) ? $this->getFields():$fieldsInfo;
705
706 return $this->externalizeFields(
707 $fields,
708 $this->getListFieldInfo(
709 $fieldsInfo,
710 ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN]]]
711 )
712 );
713 }
714 // endregion
715
716 //region check fields
717 final public function checkFieldsAdd($fields): Result
718 {
719 $r = new Result();
720
721 $required = $this->checkRequiredFieldsAdd($fields);
722 if(!$required->isSuccess())
723 $r->addError(new Error('Required fields: '.implode(', ', $required->getErrorMessages())));
724
725 return $r;
726 }
727
728 final public function checkFieldsUpdate($fields): Result
729 {
730 $r = new Result();
731
732 $required = $this->checkRequiredFieldsUpdate($fields);
733 if(!$required->isSuccess())
734 $r->addError(new Error('Required fields: '.implode(', ', $required->getErrorMessages())));
735
736 return $r;
737 }
738
739 public function checkFieldsList($arguments): Result
740 {
741 return new Result();
742 }
743
744 public function checkArguments($name, $arguments): Result
745 {
746 return new Result();
747 }
748
749 final protected function checkRequiredFieldsAdd($fields): Result
750 {
751 return $this->checkRequiredFields($fields, $this->getListFieldInfo(
752 $this->getFields(),
753 ['filter'=>['ignoredAttributes'=>[Attributes::HIDDEN, Attributes::READONLY, Attributes::REQUIRED_UPDATE]]]
754 ));
755 }
756
757 final protected function checkRequiredFieldsUpdate($fields): Result
758 {
759 return $this->checkRequiredFields($fields, $this->getListFieldInfo(
760 $this->getFields(),
762 ));
763 }
764
765 final protected function checkRequiredFields($fields, array $fieldsInfo, $params=[]): Result
766 {
767 $r = new Result();
768
769 $addRequiredFields = isset($params['+required']) ? $params['+required']:[];
770 $delRequiredFields = isset($params['-required']) ? $params['-required']:[];
771
772 foreach ($this->prepareFieldInfos($fieldsInfo) as $name=>$info)
773 {
774 if(in_array($name, $delRequiredFields))
775 {
776 continue;
777 }
778 elseif($info['IS_REQUIRED'] == 'Y' || in_array($name, $addRequiredFields))
779 {
780 if(!isset($fields[$name]))
781 $r->addError(new Error(Externalizer::convertKeysToCamelCase($name)));
782 }
783 }
784
785 return $r;
786 }
787 //endregion
788
789 //region canonical
790 final protected function canonicalizeField($name, $info): string
791 {
792 $canonical = $info['CANONICAL_NAME'] ?? null;
793 if ($canonical)
794 {
795 return $canonical;
796 }
797 else
798 {
799 return $name;
800 }
801 }
802 //endregion
803
804 //region aliases
805 final protected function aliasesField($name, $fieldsInfo): string
806 {
807 $alias = $name;
808
809 $item = array_filter($fieldsInfo, function($info) use ($name){
810 $canonical = $info['CANONICAL_NAME'] ?? null;
811 if (!$canonical)
812 {
813 return false;
814 }
815
816 return $canonical === $name;
817 });
818
819 if (is_array($item) && !empty($item))
820 {
821 $alias = array_keys($item)[0];
822 }
823
824 return $alias;
825 }
826 //endregion
827}
static createFromTimestamp($timestamp)
Definition datetime.php:246
externalizeExtendedTypeValue($name, $value, $fields, $fieldsInfo)
Definition base.php:666
aliasesField($name, $fieldsInfo)
Definition base.php:805
canonicalizeField($name, $info)
Definition base.php:790
internalizeFieldsList($arguments, $fieldsInfo=[])
Definition base.php:136
internalizeSelectFields($fields, array $fieldsInfo)
Definition base.php:444
externalizeFields($fields, $fieldsInfo)
Definition base.php:584
internalizeArguments($name, $arguments)
Definition base.php:131
internalizeFieldsAdd($fields, $fieldsInfo=[])
Definition base.php:153
getListFieldInfo(array $fieldsInfo, $params=[])
Definition base.php:53
internalizeFilterFields($fields, array $fieldsInfo)
Definition base.php:400
externalizeValue($name, $value, $fields, $fieldsInfo)
Definition base.php:516
convertKeysToSnakeCaseArguments($name, $arguments)
Definition base.php:118
externalizeFieldsGet($fields, $fieldsInfo=[])
Definition base.php:702
checkArguments($name, $arguments)
Definition base.php:744
internalizeFieldsUpdate($fields, $fieldsInfo=[])
Definition base.php:166
externalizeFileValue($name, $value, $fields)
Definition base.php:654
internalizeOrderFields($fields, array $fieldsInfo)
Definition base.php:471
externalizeListFields($list, $fieldsInfo=[])
Definition base.php:675
externalizeResult($name, $fields)
Definition base.php:697
prepareFieldAttributs($info, $attributs)
Definition base.php:37
internalizeFields($fields, array $fieldsInfo)
Definition base.php:179
internalizeListFields($list, $fieldsInfo=[])
Definition base.php:496
internalizeValue($value, $info)
Definition base.php:203
checkRequiredFields($fields, array $fieldsInfo, $params=[])
Definition base.php:765
externalizeEmptyValue($name, $value, $fields, $fieldsInfo)
Definition base.php:613
internalizeExtendedTypeValue($value, $info)
Definition base.php:368