Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
elementfilterfields.php
1<?php
2
4
9use CIBlockSection;
10
12{
13 private const PROPERTY_PREFIX = 'PROPERTY_';
14 private const PROPERTY_MASK = '/^' . self::PROPERTY_PREFIX . '([0-9]+)$/';
15
16 private int $iblockId;
17 private bool $isShowXmlId;
18 private bool $isShowSections;
19 private array $propertyList = [];
20 private array $userTypeList;
21
22 public function __construct(int $iblockId, bool $isShowXmlId, bool $isShowSections)
23 {
24 $this->iblockId = $iblockId;
25 $this->isShowXmlId = $isShowXmlId;
26 $this->isShowSections = $isShowSections;
27 }
28
29 public static function createFromElementSettings(ElementSettings $settings): self
30 {
31 return new static(
32 $settings->getIblockId(),
33 $settings->isShowXmlId(),
34 $settings->isShowSections()
35 );
36 }
37
38 public function getElementFieldsParams(): array
39 {
40 $fields = [];
41
42 $fields['NAME'] = [
43 'type' => 'string',
44 'default' => true,
45 ];
46 $fields['ID'] = [
47 'type' => 'number',
48 'default' => true,
49 ];
50
51 if ($this->isShowSections)
52 {
53 $fields['SECTION_ID'] = [
54 'type' => 'list',
55 'default' => true,
56 'partial' => true,
57 ];
58 $fields['INCLUDE_SUBSECTIONS'] = [
59 'type' => 'checkbox',
60 'default' => true,
61 ];
62 }
63
64 $fields['ACTIVE'] = [
65 'type' => 'checkbox',
66 'default' => false,
67 ];
68
69 if ($this->isShowXmlId)
70 {
71 $fields['XML_ID'] = [
72 'type' => 'string',
73 'default' => false,
74 ];
75 }
76 $fields['CODE'] = [
77 'type' => 'string',
78 'default' => false,
79 ];
80 $fields['TIMESTAMP_X'] = [
81 'type' => 'date',
82 'default' => false,
83 ];
84 $fields['MODIFIED_BY'] = [
85 'type' => 'entity_selector',
86 'partial' => true,
87 ];
88 $fields['DATE_CREATE'] = [
89 'type' => 'date',
90 'default' => false,
91 ];
92 $fields['CREATED_BY'] = [
93 'type' => 'entity_selector',
94 'partial' => true,
95 ];
96 $fields['ACTIVE_FROM'] = [
97 'type' => 'date',
98 'default' => false,
99 ];
100 $fields['ACTIVE_TO'] = [
101 'type' => 'date',
102 'default' => false,
103 ];
104
105 return $fields;
106 }
107
108 public function getElementPropertiesParams(): array
109 {
110 $properties = [];
111
112 $typesMap = [
113 PropertyTable::TYPE_STRING => 'string',
114 PropertyTable::TYPE_NUMBER => 'number',
115 PropertyTable::TYPE_LIST => 'list',
119 ];
120
121 $iterator = PropertyTable::getList([
122 'select' => [
123 'ID',
124 'IBLOCK_ID',
125 'NAME',
126 'SORT',
127 'PROPERTY_TYPE',
128 'LIST_TYPE',
129 'MULTIPLE',
130 'LINK_IBLOCK_ID',
131 'USER_TYPE',
132 'USER_TYPE_SETTINGS_LIST',
133 ],
134 'filter' => [
135 '=IBLOCK_ID' => $this->iblockId,
136 '=ACTIVE' => 'Y',
137 '=FILTRABLE' => 'Y',
138 ],
139 'order' => [
140 'SORT' => 'ASC',
141 'ID' => 'ASC',
142 ],
143 'cache' => [
144 'ttl' => 84600,
145 ],
146 ]);
147 while ($row = $iterator->fetch())
148 {
149 $row = $this->validateProperty($row);
150 if ($row === null)
151 {
152 continue;
153 }
154
155 $fullType =
156 empty($row['USER_TYPE'])
157 ? $row['PROPERTY_TYPE']
158 : $row['PROPERTY_TYPE'] . ':' . $row['USER_TYPE']
159 ;
160
161 $fieldType = $typesMap[$fullType] ?? null;
162 if (!$fieldType)
163 {
164 continue;
165 }
166
167 $id = $this->getPropertyId($row['ID']);
168 $field = [
169 'type' => $fieldType,
170 'name' => $row['NAME'],
171 ];
172
173 if ($fullType === PropertyTable::TYPE_LIST)
174 {
175 $field['partial'] = true;
176 }
177 elseif (
178 $row['USER_TYPE'] !== ''
179 )
180 {
181 $userType = $this->userTypeList[$row['USER_TYPE']];
182 if (isset($userType['GetUIFilterProperty']) && is_callable($userType['GetUIFilterProperty']))
183 {
184 call_user_func_array(
185 $userType['GetUIFilterProperty'],
186 [
187 $row,
188 [],
189 &$field
190 ]
191 );
192 if (empty($field) || !is_array($field))
193 {
194 continue;
195 }
196 $field['partial'] = true;
197 }
198 }
199
200 $properties[$id] = $field;
201
202 $this->propertyList[$id] = $row;
203 }
204 unset($row, $iterator);
205
206 return $properties;
207 }
208
209 public function prepareFilterValue(array $rawFilterValue): array
210 {
211 $result = [];
212 foreach ($rawFilterValue as $fieldId => $values)
213 {
214 $field = \CIBlock::MkOperationFilter($fieldId);
215 $id = $field['FIELD'];
216 if (!$this->isPropertyId($id))
217 {
218 $result[$fieldId] = $values;
219 }
220 elseif (isset($this->propertyList[$id]))
221 {
222 $prepareResult = $this->preparePropertyValues($id, $values);
223 if ($prepareResult)
224 {
225 $result[$fieldId] = $prepareResult;
226 }
227 unset($prepareResult);
228 }
229 }
230
231 return $result;
232 }
233
234 private function preparePropertyValues(string $propertyId, $values): mixed
235 {
236 $result = null;
237 $row = $this->propertyList[$propertyId];
238 if ($row['USER_TYPE'] === '')
239 {
240 $result = $values;
241 }
242 else
243 {
244 $userType = $this->userTypeList[$row['USER_TYPE']] ?? null;
245 if ($userType)
246 {
247 if (isset($userType['ConvertToDB']) && is_callable($userType['ConvertToDB']))
248 {
249 if (is_array($values))
250 {
251 $prepareValues = [];
252 foreach ($values as $item)
253 {
254 $prepareItem = $this->convertPropertyValueToDb(
255 $userType['ConvertToDB'],
256 $row,
257 $item
258 );
259 if ($prepareItem)
260 {
261 $prepareValues[] = $prepareItem;
262 }
263 unset($prepareItem);
264 }
265 if (!empty($prepareValues))
266 {
267 $result = $prepareValues;
268 }
269 unset($prepareValues);
270 }
271 else
272 {
273 $prepareValue = $this->convertPropertyValueToDb(
274 $userType['ConvertToDB'],
275 $row,
276 $values
277 );
278 if ($prepareValue)
279 {
280 $result = $prepareValue;
281 }
282 unset($prepareValue);
283 }
284 }
285 else
286 {
287 $result = $values;
288 }
289 }
290 unset($userType);
291 }
292 unset($row);
293
294 return $result;
295 }
296
297 private function convertPropertyValueToDb(callable $function, array $property, $value): mixed
298 {
299 $result = call_user_func_array(
300 $function,
301 [
302 $property,
303 [
304 'VALUE' => $value,
305 ],
306 ]
307 );
308
309 if (
310 is_array($result) && isset($result['VALUE']) && (string)$result['VALUE'] !== ''
311 )
312 {
313 return $result['VALUE'];
314 }
315
316 return null;
317 }
318
319 public function getSectionListItems(): array
320 {
321 $result = [];
322
323 $result[''] = null;
324 $result[0] = Loc::getMessage('IBLOCK_FILTER_DATAPROVIDER_ELEMENT_FIELDS_SECTION_TOP_LEVEL');
325
326 $iterator = CIBlockSection::GetList(
327 [
328 'LEFT_MARGIN' => 'ASC',
329 ],
330 [
331 'IBLOCK_ID' => $this->iblockId,
332 'CHECK_PERMISSIONS' => 'Y',
333 'MIN_PERMISSION' => 'R',
334 ],
335 false,
336 [
337 'ID',
338 'NAME',
339 'IBLOCK_ID',
340 'DEPTH_LEVEL',
341 'LEFT_MARGIN',
342 ]
343 );
344 while ($row = $iterator->Fetch())
345 {
346 $margin = max((int)$row['DEPTH_LEVEL'], 1) - 1;
347 $result[$row['ID']] = str_repeat('.', $margin) . $row['NAME'];
348 }
349 unset($row, $iterator);
350
351 return $result;
352 }
353
354 public function isPropertyEnumField(string $fieldId): bool
355 {
356 if (!$this->isPropertyId($fieldId))
357 {
358 return false;
359 }
360 if (!isset($this->propertyList[$fieldId]))
361 {
362 return false;
363 }
364 $row = $this->propertyList[$fieldId];
365
366 return
367 $row['PROPERTY_TYPE'] === PropertyTable::TYPE_LIST
368 && $row['USER_TYPE'] === ''
369 ;
370 }
371
372 /*
373 * @deprecated
374 */
375 public function getPropertyEnumFieldListItems(string $fieldId): array
376 {
377 $propertyId = $this->propertyList[$fieldId]['ID'] ?? null;
378 if ($propertyId)
379 {
380 return $this->getPropertyEnumValueListItems($propertyId);
381 }
382
383 return [];
384 }
385
386 private function getPropertyEnumValueListItems(int $propertyId): array
387 {
388 $result = [];
389 $iterator = PropertyEnumerationTable::getList([
390 'select' => [
391 'ID',
392 'VALUE',
393 'SORT',
394 ],
395 'filter' => [
396 '=PROPERTY_ID' => $propertyId,
397 ],
398 'order' => [
399 'SORT' => 'ASC',
400 'VALUE' => 'ASC',
401 'ID' => 'ASC',
402 ],
403 'cache' => [
404 'ttl' => 86400,
405 ],
406 ]);
407 while ($row = $iterator->fetch())
408 {
409 $result[$row['ID']] = $row['VALUE'];
410 }
411 unset($row, $iterator);
412
413 return $result;
414 }
415
416 private function getPropertyId(string|int $id): string
417 {
418 return self::PROPERTY_PREFIX . $id;
419 }
420
421 public function isPropertyId(string $id): bool
422 {
423 return (preg_match(self::PROPERTY_MASK, $id) === 1);
424 }
425
426 public function getPropertyDescription(string $id): ?array
427 {
428 if (!isset($this->propertyList[$id]))
429 {
430 return null;
431 }
432
433 $row = $this->propertyList[$id];
434
435 $description = null;
436 if ($row['USER_TYPE'] === '')
437 {
438 switch ($row['PROPERTY_TYPE'])
439 {
441 $description = [
442 'items' => $this->getPropertyEnumValueListItems($row['ID']),
443 ];
444 if (count($description['items']) > 1)
445 {
446 $description['params'] = [
447 'multiple' => true,
448 ];
449 }
450 break;
451 }
452 }
453 else
454 {
455 $userType = $this->userTypeList[$row['USER_TYPE']];
456 if (isset($userType['GetUIFilterProperty']) && is_callable($userType['GetUIFilterProperty']))
457 {
458 $description = [];
459 call_user_func_array(
460 $userType['GetUIFilterProperty'],
461 [
462 $row,
463 [],
464 &$description
465 ]
466 );
467 if (empty($description) || !is_array($description))
468 {
469 $description = null;
470 }
471 }
472 }
473
474 return $description;
475 }
476
477 private function validateProperty(array $row): ?array
478 {
479 $row['ID'] = (int)$row['ID'];
480 $row['USER_TYPE'] = (string)$row['USER_TYPE'];
481 $row['USER_TYPE_SETTINGS'] = $row['USER_TYPE_SETTINGS_LIST'];
482 unset($row['USER_TYPE_SETTINGS_LIST']);
483 $row['FULL_PROPERTY_TYPE'] = $this->getFullPropertyType($row);
484 if ($row['USER_TYPE'] === '')
485 {
486 return $row;
487 }
488
489 if (!isset($this->userTypeList))
490 {
491 $this->userTypeList = \CIBlockProperty::GetUserType();
492 }
493 $userTypeId = $row['USER_TYPE'];
494 if (!isset($this->userTypeList[$userTypeId]))
495 {
496 return null;
497 }
498
499 return $row;
500 }
501
502 private function getFullPropertyType(array $row): string
503 {
504 return
505 $row['USER_TYPE'] === ''
506 ? $row['PROPERTY_TYPE']
507 : $row['PROPERTY_TYPE'] . ':' . $row['USER_TYPE']
508 ;
509 }
510}
__construct(int $iblockId, bool $isShowXmlId, bool $isShowSections)
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static getList(array $parameters=array())