1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
IBlockElementToUpdate.php
См. документацию.
1<?php
2
3namespace Bitrix\Lists\Api\Data\IBlockService;
4
5use Bitrix\Lists\Api\Data\Data;
6use Bitrix\Lists\Api\Request\IBlockService\UpdateIBlockElementRequest;
7use Bitrix\Lists\Api\Response\IBlockService\IBlockElementToUpdateValues;
8use Bitrix\Main\ArgumentOutOfRangeException;
9use Bitrix\Main\Error;
10use Bitrix\Main\IO\Path;
11use Bitrix\Main\Localization\Loc;
12use Bitrix\Main\Result;
13
15{
16 protected bool $isLocalizationLoaded = false;
17 protected int $modifiedBy;
18 protected int $elementId;
19 protected int $iBlockId;
20 protected int $sectionId;
21 protected array $values;
22 private array $elementOldFields;
23 private array $elementOldProps;
24 private array $propsMap = [];
25 private array $select = [];
26
27 protected function __construct(
28 int $modifiedBy,
29 int $elementId,
30 int $iBlockId,
31 int $sectionId,
33 )
34 {
35 $this->elementId = $elementId;
36 $this->iBlockId = $iBlockId;
37 $this->sectionId = $sectionId;
38 $this->modifiedBy = $modifiedBy;
39 $this->values = $values;
40
41 $this->init();
42 }
43
44 protected function init(): void
45 {
46 $this->elementOldFields = $this->getElementFieldsData();
47 $this->elementOldProps = $this->getElementPropsData();
48 }
49
55 public static function createFromRequest($request): self
56 {
58 if ($elementId === null || $elementId === 0)
59 {
60 throw new ArgumentOutOfRangeException('elementId', 1, null);
61 }
62
64 if ($iBlockId === null || $iBlockId === 0)
65 {
66 throw new ArgumentOutOfRangeException('iBlockId', 1, null);
67 }
68
70 if ($sectionId === null)
71 {
72 throw new ArgumentOutOfRangeException('sectionId', 0, null);
73 }
74
75 $modifiedBy = self::validateId($request->modifiedByUserId);
76 if ($modifiedBy === null || $modifiedBy === 0)
77 {
78 throw new ArgumentOutOfRangeException('modifiedBy', 1, null);
79 }
80
82
84 }
85
86 protected static function validateValues(array $values, int $iBlockId, int $sectionId): array
87 {
88 unset($values['ID']);
89 $values['IBLOCK_ID'] = $iBlockId;
90 $values['IBLOCK_SECTION_ID'] = $sectionId;
91
92 return $values;
93 }
94
95 public function getElementId(): int
96 {
97 return $this->elementId;
98 }
99
100 public function getSectionId(): int
101 {
102 return $this->sectionId;
103 }
104
105 public function getIBlockId(): int
106 {
107 return $this->iBlockId;
108 }
109
110 public function getOriginalValues(): array
111 {
112 return $this->values;
113 }
114
115 public function getFieldValueById(string $fieldsId)
116 {
117 return $this->values[$fieldsId] ?? null;
118 }
119
120 public function getModifiedBy(): int
121 {
122 return $this->modifiedBy;
123 }
124
126 {
128 $result
129 ->setHasChangedFields(false)
130 ->setHasChangedProps(false)
131 ;
132
133 $element = [
134 'IBLOCK_ID' => $this->getIBlockId(),
135 'IBLOCK_SECTION_ID' => $this->getSectionId(),
136 'MODIFIED_BY' => $this->getModifiedBy(),
137 ];
138
139 unset($fields['TIMESTAMP_X']);
140 $preparedFields = $this->prepareFields($fields, $result);
141 $element = array_merge($element, $preparedFields);
142
143 $preparedProps = $this->prepareProps($props, $result);
144 if ($preparedProps)
145 {
146 $element['PROPERTY_VALUES'] = $preparedProps;
147 }
148
149 return $result->setElementData($element);
150 }
151
153 {
154 $hasChangedFields = false;
155
156 $prepared = [];
157 foreach ($fields as $fieldId => $property)
158 {
159 if ($fieldId === 'NAME' && empty($property['SETTINGS']))
160 {
161 $property['SETTINGS'] = ['SHOW_EDIT_FORM' => 'Y'];
162 }
163
164 $showEditForm = isset($property['SETTINGS']['SHOW_EDIT_FORM']) && $property['SETTINGS']['SHOW_EDIT_FORM'] === 'Y';
165 $isEditReadOnlyField = in_array($fieldId, ['DATE_CREATE', 'TIMESTAMP_X', 'CREATED_BY', 'MODIFIED_BY']);
166 if (isset($property['SETTINGS']['EDIT_READ_ONLY_FIELD']))
167 {
168 $isEditReadOnlyField = $property['SETTINGS']['EDIT_READ_ONLY_FIELD'] === 'Y';
169 }
170
171 // to prevent stripping SEARCHABLE_CONTENT
172 if (!$showEditForm || $isEditReadOnlyField)
173 {
174 if (array_key_exists($fieldId, $this->elementOldFields))
175 {
176 $prepared[$fieldId] = $this->elementOldFields[$fieldId];
177 }
178
179 continue;
180 }
181
182 if (in_array($fieldId, ['PREVIEW_TEXT', 'DETAIL_TEXT'], true))
183 {
184 $useEditor = isset($property['SETTINGS']['USE_EDITOR']) && $property['SETTINGS']['USE_EDITOR'] === 'Y';
185 $prepared[$fieldId . '_TYPE'] = $useEditor ? 'html' : 'text';
186 }
187
188 $value = $this->getFieldValueById($fieldId);
189 $prepared[$fieldId] = $value;
190
191 if ($hasChangedFields === false && array_key_exists($fieldId, $this->elementOldFields))
192 {
193 $oldValue = $this->elementOldFields[$fieldId];
194 if (!$this->isEqualAsStrings($oldValue, $value))
195 {
196 $hasChangedFields = true;
197 }
198 }
199 }
200
201 $result->setHasChangedFields($hasChangedFields);
202
203 return $prepared;
204 }
205
207 {
208 $hasChangedProps = false;
209 $prepared = [];
210 foreach ($props as $key => $property)
211 {
212 $propertyId = $property['ID'];
213
214 $showEditForm = ($property['SETTINGS']['SHOW_EDIT_FORM'] ?? 'Y') === 'Y';
215 $isEditReadOnlyField = ($property['SETTINGS']['EDIT_READ_ONLY_FIELD'] ?? 'N') === 'Y';
216
217 // to prevent reset props
218 if (!$showEditForm || $isEditReadOnlyField)
219 {
220 if (array_key_exists($key, $this->elementOldProps))
221 {
222 $prepared[$propertyId] = $this->elementOldProps[$key];
223 }
224
225 continue;
226 }
227
228 $requestValues = $this->getFieldValueById($key);
229 if (is_array($requestValues))
230 {
231 $prepared[$propertyId] = $this->preparePropValue($requestValues, $property, $result);
232
233 if ($hasChangedProps === false && array_key_exists($key, $this->elementOldProps))
234 {
235 $oldValue = $this->elementOldProps[$key];
236
237 $newValue = array_filter($requestValues);
238 if ($property['TYPE'] === 'S:HTML')
239 {
240 $newValue = array_map(static fn($text) => ['TYPE' => 'HTML', 'TEXT' => $text], $newValue);
241 if (!$this->isEqualAsMultiArrays($newValue, $oldValue))
242 {
243 $hasChangedProps = true;
244 }
245 }
246 elseif (!$this->isEqualAsArrays($newValue, $oldValue))
247 {
248 $hasChangedProps = true;
249 }
250 }
251 }
252 }
253
254 $result->setHasChangedProps($hasChangedProps);
255
256 return $prepared;
257 }
258
259 protected function preparePropValue(array $requestValues, array $property, Result $result)
260 {
261 $baseType = $property['TYPE'];
262 $type = $property['PROPERTY_TYPE'];
263 $isMultiple = $property['MULTIPLE'] === 'Y';
264
265 $values = [];
266 foreach ($requestValues as $key => $value)
267 {
268 if (in_array($type, ['L', 'E', 'G'], true))
269 {
270 if ($value === '0')
271 {
272 $value = '';
273 }
274
275 if ($isMultiple)
276 {
277 $values[$key] = $value;
278
279 continue;
280 }
281
282 $values = $value;
283
284 break;
285 }
286
287 if ($type === 'N' && !empty($value))
288 {
289 if (is_string($value))
290 {
291 $value = str_replace([',', ' '], ['.', ''], $value);
292 }
293
294 if (is_numeric($value))
295 {
296 $value = (double)$value;
297 }
298 else
299 {
300 $this->loadLocalization();
301 $result->addError(
302 new Error(
303 Loc::getMessage(
304 'LISTS_LIB_API_DATA_IBLOCK_SERVICE_VALIDATE_FIELD_ERROR',
305 ['#FIELD_NAME#' => $property['NAME']]
306 ),
307 )
308 );
309
310 return [];
311 }
312 }
313
314 if ($type === 'S' && $baseType === 'S:HTML')
315 {
316 if (!is_array($value) || !isset($value['TYPE'], $value['TEXT']))
317 {
318 $value = ['TYPE' => 'html', 'TEXT' => is_scalar($value) ? (string)$value : ''];
319 }
320 }
321
322 $values[$key] = ['VALUE' => $value];
323
324 if (!$isMultiple)
325 {
326 break;
327 }
328 }
329
330 return $values;
331 }
332
333 private function getElementFieldsData(): array
334 {
335 if (empty($this->select))
336 {
337 $this->select = ['ID', 'IBLOCK_SECTION_ID'];
338
339 $list = new \CList($this->iBlockId);
340 foreach ($list->GetFields() as $fieldId => $property)
341 {
342 if ($list->is_field($fieldId))
343 {
344 $this->select[] = $fieldId;
345 }
346
347 if ($fieldId === 'CREATED_BY')
348 {
349 $this->select[] = 'CREATED_USER_NAME';
350 }
351
352 if ($fieldId === 'MODIFIED_BY')
353 {
354 $this->select[] = 'USER_NAME';
355 }
356 }
357 }
358
359 $filter = [
360 '=IBLOCK_ID' => $this->iBlockId,
361 '=ID' => $this->elementId,
362 'CHECK_PERMISSIONS' => false,
363 ];
364 $iterator = \CIBlockElement::GetList([], $filter, false, [], $this->select);
365 $element = $iterator->Fetch();
366
367 return is_array($element) ? $element : [];
368 }
369
370 private function getElementPropsData(): array
371 {
372 $elementProperties = \CIBlockElement::GetProperty(
373 $this->iBlockId, $this->elementId, 'sort', 'asc', ['ACTIVE' => 'Y']
374 );
375
376 $properties = [];
377 while ($property = $elementProperties->Fetch())
378 {
379 $propertyId = $property['ID'];
380 $propertyValueId = $property['PROPERTY_VALUE_ID'] ?? null;
381 $propertyValue = $property['VALUE'] ?? null;
382
383 $key = 'PROPERTY_' . $propertyId;
384 if (!array_key_exists($key, $properties))
385 {
386 $properties[$key] = [];
387 }
388
389 if (isset($propertyValueId, $propertyValue))
390 {
391 $properties[$key][$propertyValueId] = $propertyValue;
392 }
393
394 $this->propsMap[$key] = $property['CODE'] ?? $property['ID'];
395 }
396
397 return $properties;
398 }
399
401 {
402 $oldData = array_merge($this->elementOldFields, $this->elementOldProps);
403 $newData = array_merge($this->getElementFieldsData(), $this->getElementPropsData());
404
405 $valuesToChange = $this->getOriginalValues();
406 unset($valuesToChange['ID'], $valuesToChange['IBLOCK_ID'], $valuesToChange['DATE_CREATE'], $valuesToChange['CREATED_BY']);
407
408 $changed = [];
409 foreach (array_keys($valuesToChange) as $key)
410 {
411 if (!array_key_exists($key, $oldData) || !array_key_exists($key, $newData))
412 {
413 continue;
414 }
415
416 $oldValue = $oldData[$key];
417 $newValue = $newData[$key];
418 if (empty($oldValue) && empty($newValue))
419 {
420 continue;
421 }
422
423 $modifiedKey = array_key_exists($key, $this->propsMap) ? 'PROPERTY_' . $this->propsMap[$key] : $key;
424
425 $isArrayOldValue = is_array($oldValue);
426 $isArrayNewValue = is_array($newValue);
427
428 if (!$isArrayOldValue && !$isArrayNewValue)
429 {
430 if (!$this->isEqualAsStrings($oldValue, $newValue))
431 {
432 $changed[] = $modifiedKey;
433 }
434
435 continue;
436 }
437
438 $oldValue = $isArrayOldValue ? $oldValue : [$oldValue];
439 $newValue = $isArrayNewValue ? $newValue : [$newValue];
440
441 if (is_array(current($newValue)) || is_array(current($oldValue)))
442 {
443 if (!$this->isEqualAsMultiArrays($newValue, $oldValue))
444 {
445 $changed[] = $modifiedKey;
446 }
447 }
448 elseif (!$this->isEqualAsArrays($newValue, $oldValue))
449 {
450 $changed[] = $modifiedKey;
451 }
452 }
453
454 return $changed;
455 }
456
457 private function isEqualAsStrings($string1, $string2): bool
458 {
459 if (!is_string($string1))
460 {
461 $string1 =
462 (is_scalar($string1) || (is_object($string1) && method_exists($string1, '__toString')))
463 ? (string)$string1
464 : ''
465 ;
466 }
467
468 if (!is_string($string2))
469 {
470 $string2 =
471 (is_scalar($string2) || (is_object($string2) && method_exists($string2, '__toString')))
472 ? (string)$string2
473 : ''
474 ;
475 }
476
477 return strcmp($string1, $string2) === 0;
478 }
479
480 private function isEqualAsMultiArrays(array $value1, array $value2): bool
481 {
482 $oldFieldValues = [];
483 $newFieldValues = [];
484
485 foreach ($value1 as $singleValue)
486 {
487 if (is_array($singleValue))
488 {
489 if (isset($singleValue['TEXT']))
490 {
491 $oldFieldValues[] = $singleValue['TEXT'];
492 }
493
494 continue;
495 }
496
497 $oldFieldValues[] = $singleValue;
498 }
499 foreach ($value2 as $singleValue)
500 {
501 if (is_array($singleValue))
502 {
503 if (isset($singleValue['TEXT']))
504 {
505 $newFieldValues[] = $singleValue['TEXT'];
506 }
507
508 continue;
509 }
510
511 $newFieldValues[] = $singleValue;
512 }
513
514 return $this->isEqualAsArrays($newFieldValues, $oldFieldValues);
515 }
516
517 private function isEqualAsArrays(array $value1, array $value2): bool
518 {
519 $differences = array_diff($value1, $value2);
520 if (!empty($differences))
521 {
522 return false;
523 }
524
525 $differences = array_diff($value2, $value1);
526
527 return empty($differences);
528 }
529
530 protected function loadLocalization(): void
531 {
532 if (!$this->isLocalizationLoaded)
533 {
534 Loc::loadLanguageFile(
535 \Bitrix\Main\Application::getDocumentRoot()
536 . Path::normalize('/bitrix/modules/lists/lib/Api/Data/IBlockService/IBlockElementToUpdate')
537 );
538
539 $this->isLocalizationLoaded = true;
540 }
541 }
542}
return select
Определения access_edit.php:440
$type
Определения options.php:106
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
Определения catalog_reindex.php:36
static validateId(int $id)
Определения Data.php:9
prepareProps(array $props, IBlockElementToUpdateValues $result)
Определения IBlockElementToUpdate.php:206
static validateValues(array $values, int $iBlockId, int $sectionId)
Определения IBlockElementToUpdate.php:86
__construct(int $modifiedBy, int $elementId, int $iBlockId, int $sectionId, array $values,)
Определения IBlockElementToUpdate.php:27
preparePropValue(array $requestValues, array $property, Result $result)
Определения IBlockElementToUpdate.php:259
prepareFields(array $fields, IBlockElementToUpdateValues $result)
Определения IBlockElementToUpdate.php:152
Определения error.php:15
addError(Error $error)
Определения result.php:50
</td ></tr ></table ></td ></tr ><?endif?><? $propertyIndex=0;foreach( $arGlobalProperties as $propertyCode=> $propertyValue
Определения file_new.php:729
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$filter
Определения iblock_catalog_list.php:54
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if(empty($signedUserToken)) $key
Определения quickway.php:257
$text
Определения template_pdf.php:79
$props
Определения template.php:269
$iterator
Определения yandex_run.php:610
$fields
Определения yandex_run.php:501