1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
userfieldhelper.php
См. документацию.
1<?php
2
3namespace Bitrix\Main\UserField\Internal;
4
5use Bitrix\Main\Application;
6use Bitrix\Main\DB\SqlExpression;
7use Bitrix\Main\DB\SqlQueryException;
8use Bitrix\Main\Event;
9use Bitrix\Main\EventResult;
10use Bitrix\Main\InvalidOperationException;
11use Bitrix\Main\ORM\Entity;
12use Bitrix\Main\Localization\Loc;
13
14final class UserFieldHelper
15{
16 public const ERROR_CODE_USER_FIELD_CREATION = 'ERROR_CODE_USER_FIELD_CREATION';
17
19 private static $instance;
20
21 private function __construct()
22 {
23 }
24
25 private function __clone()
26 {
27 }
28
33 public static function getInstance(): UserFieldHelper
34 {
35 if (!isset(self::$instance))
36 {
37 self::$instance = new UserFieldHelper;
38 }
39
40 return self::$instance;
41 }
42
46 public function getManager(): ?\CUserTypeManager
47 {
49
51 }
52
56 public function getApplication(): ?\CMain
57 {
58 global $APPLICATION;
59
60 return $APPLICATION;
61 }
62
67 public function parseUserFieldEntityId(string $entityId): ?array
68 {
69 if(preg_match('/^([A-Z]+)_([0-9A-Z_]+)$/', $entityId, $matches))
70 {
72 $factory = Registry::getInstance()->getFactoryByCode($typeCode);
73 if($factory)
74 {
75 $typeId = $factory->prepareIdentifier($matches[2]);
76 if ($typeId > 0)
77 {
78 return [$factory, $typeId];
79 }
80 }
81 }
82
83 return null;
84 }
85
90 public static function OnBeforeUserTypeAdd($field)
91 {
92 if (static::getInstance()->parseUserFieldEntityId($field['ENTITY_ID']))
93 {
94 if (str_ends_with($field['FIELD_NAME'], '_REF'))
95 {
100 global $APPLICATION;
101
102 Loc::loadLanguageFile(__DIR__.'/highloadblock.php');
103 $APPLICATION->ThrowException(
104 Loc::getMessage('HIGHLOADBLOCK_HIGHLOAD_BLOCK_ENTITY_FIELD_NAME_REF_RESERVED'),
105 );
106
107 return false;
108 }
109
110 return [
111 'PROVIDE_STORAGE' => false,
112 ];
113 }
114
115 return true;
116 }
117
122 public static function onAfterUserTypeAdd($field)
123 {
124 $userFieldHelper = static::getInstance();
125 $parseResult = $userFieldHelper->parseUserFieldEntityId($field['ENTITY_ID']);
126 if($parseResult)
127 {
128 [$factory, $typeId] = $parseResult;
129 $userFieldManager = $userFieldHelper->getManager();
130 $application = $userFieldHelper->getApplication();
133 $dataClass = $factory->getTypeDataClass();
134
135 $field['USER_TYPE'] = $userFieldManager->getUserType($field['USER_TYPE_ID']);
136
137 $typeData = $dataClass::getById($typeId)->fetch();
138
139 if (empty($typeData))
140 {
141 $application->throwException(sprintf(
142 'Entity "%s" wasn\'t found.', $factory->getUserFieldEntityId($typeId),
143 ));
144
145 return false;
146 }
147
148 // get usertype info
149 $sql_column_type = $userFieldManager->getUtsDBColumnType($field);
150
151 // create field in db
153 $sqlHelper = $connection->getSqlHelper();
154
155 try
156 {
157 $connection->query(sprintf(
158 'ALTER TABLE %s ADD %s %s',
159 $sqlHelper->quote($typeData['TABLE_NAME']), $sqlHelper->quote($field['FIELD_NAME']), $sql_column_type,
160 ));
161
162 if ($field['MULTIPLE'] == 'Y')
163 {
164 // create table for this relation
165 $typeEntity = $dataClass::compileEntity($typeData);
166 $utmEntity = Entity::getInstance($dataClass::getUtmEntityClassName($typeEntity, $field));
167
168 $utmEntity->createDbTable();
169
170 // add indexes
171 $connection->query(sprintf(
172 'CREATE INDEX %s ON %s (%s)',
173 $sqlHelper->quote('IX_UTM_HL'.$typeId.'_'.$field['ID'].'_ID'),
174 $sqlHelper->quote($utmEntity->getDBTableName()),
175 $sqlHelper->quote('ID'),
176 ));
177
178 $connection->query(sprintf(
179 'CREATE INDEX %s ON %s (%s)',
180 $sqlHelper->quote('IX_UTM_HL'.$typeId.'_'.$field['ID'].'_VALUE'),
181 $sqlHelper->quote($utmEntity->getDBTableName()),
182 $sqlHelper->quote('VALUE'),
183 ));
184 }
185 }
186 catch (SqlQueryException $sqlQueryException)
187 {
188 $userTypeEntity = new \CUserTypeEntity;
189 $userTypeEntity->Delete($field['ID']);
190
191 throw new InvalidOperationException(
192 'Could not create new user field ' . $field['FIELD_NAME'],
193 $sqlQueryException,
194 );
195 }
196
197 return [
198 'PROVIDE_STORAGE' => false,
199 ];
200 }
201
202 return true;
203 }
204
209 public static function OnBeforeUserTypeDelete($field)
210 {
211 $userFieldHelper = static::getInstance();
212 $parseResult = $userFieldHelper->parseUserFieldEntityId($field['ENTITY_ID']);
213 if (!$parseResult)
214 {
215 return true;
216 }
217
218 return [
219 'PROVIDE_STORAGE' => false,
220 ];
221 }
222
223 public static function OnAfterUserTypeDelete($field): void
224 {
225 $userFieldHelper = static::getInstance();
226 $parseResult = $userFieldHelper->parseUserFieldEntityId($field['ENTITY_ID']);
227 if (!$parseResult)
228 {
229 return;
230 }
231
234 [$factory, $typeId] = $parseResult;
236 $dataClass = $factory->getTypeDataClass();
237 $typeData = $dataClass::getById($typeId)->fetch();
238
239 if (empty($typeData))
240 {
241 // non-existent or zombie. let it go
242 return;
243 }
244
245 $fieldType = $userFieldHelper->getManager()->GetUserType($field['USER_TYPE_ID']);
246 if ($fieldType && $fieldType['BASE_TYPE'] === 'file')
247 {
248 self::deleteAllFilesFromUserField($typeData['TABLE_NAME'], $field['FIELD_NAME']);
249 }
250
252
253 try
254 {
255 $connection->dropColumn($typeData['TABLE_NAME'], $field['FIELD_NAME']);
256 }
257 catch (SqlQueryException)
258 {
259 // no column is ok
260 }
261
262 if ($field['MULTIPLE'] === 'Y')
263 {
264 $utmTableName = $dataClass::getMultipleValueTableName($typeData, $field);
265 if ($connection->isTableExists($utmTableName))
266 {
267 $connection->dropTable($utmTableName);
268 }
269 }
270 }
271
272 private static function deleteAllFilesFromUserField(string $tableName, string $fieldName): void
273 {
274 // cant use ORM here, the field is already deleted
275 $query = new SqlExpression(
276 'SELECT ?# FROM ?#',
277 $fieldName,
278 $tableName,
279 );
280
281 try
282 {
283 $queryResult = Application::getConnection()->query($query->compile());
284 }
285 catch (SqlQueryException)
286 {
287 // no column is ok
288 return;
289 }
290
291 while ($oldData = $queryResult->fetch())
292 {
293 $value = $oldData[$fieldName];
294
295 if (empty($value))
296 {
297 continue;
298 }
299
300 if (is_numeric($value))
301 {
302 // single file
303 \CFile::Delete($value);
304 continue;
305 }
306
307 if (is_string($value))
308 {
309 // multiple files
310
311 try
312 {
313 $valueUnserialized = unserialize($value, ['allowed_classes' => false, 'max_depth' => 1]);
314 }
315 catch (\Throwable)
316 {
317 continue;
318 }
319
320 if (!is_array($valueUnserialized))
321 {
322 continue;
323 }
324
325 foreach ($valueUnserialized as $singleValue)
326 {
327 if (!empty($singleValue) && is_numeric($singleValue))
328 {
329 \CFile::Delete($singleValue);
330 }
331 }
332 }
333 }
334 }
335
336 public static function onGetUserFieldValues(Event $event): EventResult
337 {
338 $result = new EventResult(EventResult::SUCCESS);
339
340 $entityId = $event->getParameter('entityId');
341 $userFieldHelper = static::getInstance();
342 $parseResult = $userFieldHelper->parseUserFieldEntityId($entityId);
343 if($parseResult)
344 {
345 $userFields = $event->getParameter('userFields');
346 $value = $event->getParameter('value');
347
349 [$factory, $typeId] = $parseResult;
350 $dataClass = $factory->getTypeDataClass();
351 $typeData = $dataClass::getById($typeId)->fetch();
352 if(!$typeData)
353 {
354 return $result;
355 }
356 $itemDataClass = $factory->getItemDataClass($typeData);
357 $values = $itemDataClass::getUserFieldValues($value, $userFields);
358
359 if(!$values)
360 {
361 $values = [];
362 }
363
364 $result = new EventResult(EventResult::SUCCESS, [
365 'values' => $values,
366 ]);
367 }
368
369 return $result;
370 }
371
372 public static function onUpdateUserFieldValues(Event $event): EventResult
373 {
374 $result = new EventResult(EventResult::UNDEFINED);
375
376 $entityId = $event->getParameter('entityId');
377 $userFieldHelper = static::getInstance();
378 $parseResult = $userFieldHelper->parseUserFieldEntityId($entityId);
379 if($parseResult)
380 {
381 $fields = $event->getParameter('fields');
382 $id = $event->getParameter('id');
383
385 [$factory, $typeId] = $parseResult;
386 $dataClass = $factory->getTypeDataClass();
387 $typeData = $dataClass::getById($typeId)->fetch();
388 if(!$typeData)
389 {
390 return $result;
391 }
392 $itemDataClass = $factory->getItemDataClass($typeData);
393 $updateResult = $itemDataClass::updateUserFieldValues($id, $fields);
394 if($updateResult->isSuccess())
395 {
396 $result = new EventResult(EventResult::SUCCESS);
397 }
398 else
399 {
400 $result = new EventResult(EventResult::ERROR);
401 }
402 }
403
404 return $result;
405 }
406
407 public static function onDeleteUserFieldValues(Event $event): EventResult
408 {
409 $result = new EventResult(EventResult::UNDEFINED);
410
411 $entityId = $event->getParameter('entityId');
412 $userFieldHelper = static::getInstance();
413 $parseResult = $userFieldHelper->parseUserFieldEntityId($entityId);
414 if($parseResult)
415 {
416 $id = $event->getParameter('id');
417
419 [$factory, $typeId] = $parseResult;
420 $dataClass = $factory->getTypeDataClass();
421 $typeData = $dataClass::getById($typeId)->fetch();
422 if(!$typeData)
423 {
424 return $result;
425 }
426 $itemDataClass = $factory->getItemDataClass($typeData);
427 $updateResult = $itemDataClass::deleteUserFieldValues($id);
428 if($updateResult->isSuccess())
429 {
430 $result = new EventResult(EventResult::SUCCESS);
431 }
432 else
433 {
434 $result = new EventResult(EventResult::ERROR);
435 }
436 }
437
438 return $result;
439 }
440}
$connection
Определения actionsdefinitions.php:38
global $APPLICATION
Определения include.php:80
static getConnection($name="")
Определения application.php:638
static getCodeByPrefix(string $prefix)
Определения typefactory.php:66
parseUserFieldEntityId(string $entityId)
Определения userfieldhelper.php:67
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
global $USER_FIELD_MANAGER
Определения attempt.php:6
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$application
Определения bitrix.php:23
$value
Определения Param.php:39
$entityId
Определения payment.php:4
$event
Определения prolog_after.php:141
$matches
Определения index.php:22
$fields
Определения yandex_run.php:501