Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
datamanager.php
1<?php
10
11use Bitrix\Main;
18
19abstract class DataManager extends Entity\DataManager
20{
25 public static function getHighloadBlock()
26 {
27 return null;
28 }
29
30 public static function checkFields(Entity\Result $result, $primary, array $data)
31 {
32 // check for unknown fields
33 foreach ($data as $k => $v)
34 {
35 if (!(static::getEntity()->hasField($k) && static::getEntity()->getField($k) instanceof Entity\ScalarField))
36 {
37 throw new Main\SystemException(sprintf(
38 'Field `%s` not found in entity when trying to query %s row.',
39 $k, static::getEntity()->getName()
40 ));
41 }
42 }
43 }
44
53 public static function add(array $data)
54 {
55 global $USER_FIELD_MANAGER, $APPLICATION;
56
57 // prepare entity object for compatibility with new code
58 $object = static::convertArrayToObject($data, true);
59
60 $result = new Entity\AddResult;
61 $hlblock = static::getHighloadBlock();
62 $entity = static::getEntity();
63
64 try
65 {
66 static::callOnBeforeAddEvent($object, $data, $result);
67
68 // actualize old-style fields array from object
69 $data = $object->collectValues(Values::CURRENT, FieldTypeMask::SCALAR);
70
71 // check data by uf manager
72 if (!$USER_FIELD_MANAGER->checkFields('HLBLOCK_'.$hlblock['ID'], null, $data))
73 {
74 if(is_object($APPLICATION) && $APPLICATION->getException())
75 {
76 $e = $APPLICATION->getException();
77 $result->addError(new Entity\EntityError($e->getString()));
78 $APPLICATION->resetException();
79 }
80 else
81 {
82 $result->addError(new Entity\EntityError("Unknown error while checking userfields"));
83 }
84 }
85
86 // return if any error
87 if (!$result->isSuccess(true))
88 {
89 return $result;
90 }
91
92 //event on adding
93 self::callOnAddEvent($object, $data, []);
94
95 // insert base row
96 $connection = Main\Application::getConnection();
97
98 $tableName = $entity->getDBTableName();
99 $identity = $entity->getAutoIncrement();
100
101 $id = $connection->add($tableName, [$identity => new Main\DB\SqlExpression('DEFAULT')], $identity);
102
103 // format data before save
104 $fields = $USER_FIELD_MANAGER->getUserFields('HLBLOCK_'.$hlblock['ID']);
105
106 foreach ($fields as $k => $field)
107 {
108 $fields[$k]['VALUE_ID'] = $id;
109 }
110
111 list($data, $multiValues) = static::convertValuesBeforeSave($data, $fields);
112
113 // data could be changed by uf manager
114 foreach ($data as $k => $v)
115 {
116 $object->set($k, $v);
117 }
118
119 // use save modifiers
120 foreach ($data as $fieldName => $value)
121 {
122 $field = static::getEntity()->getField($fieldName);
123 $data[$fieldName] = $field->modifyValueBeforeSave($value, $data);
124 }
125
126 if (!empty($data))
127 {
128 // save data
129 $helper = $connection->getSqlHelper();
130 $update = $helper->prepareUpdate($tableName, $data);
131
132 $sql = "UPDATE ".$helper->quote($tableName)." SET ".$update[0]." WHERE ".$helper->quote($identity)." = ".((int) $id);
133 $connection->queryExecute($sql, $update[1]);
134 }
135
136 // save multi values
137 if (!empty($multiValues))
138 {
139 foreach ($multiValues as $userfieldName => $values)
140 {
141 $utmTableName = HighloadBlockTable::getMultipleValueTableName($hlblock, $fields[$userfieldName]);
142
143 foreach ($values as $value)
144 {
145 $connection->add($utmTableName, array('ID' => $id, 'VALUE' => $value));
146 }
147 }
148 }
149
150 // build standard primary
151 $primary = null;
152
153 if (!empty($id))
154 {
155 $primary = array($entity->getAutoIncrement() => $id);
156 static::normalizePrimary($primary);
157 }
158 else
159 {
160 static::normalizePrimary($primary, $data);
161 }
162
163 // fill result
164 $result->setPrimary($primary);
165 $result->setData($data);
166 $result->setObject($object);
167
168 foreach ($primary as $primaryName => $primaryValue)
169 {
170 $object->sysSetActual($primaryName, $primaryValue);
171 }
172
173 $entity->cleanCache();
174
175 static::callOnAfterAddEvent($object, $data, $id);
176 }
177 catch (\Exception $e)
178 {
179 // check result to avoid warning
180 $result->isSuccess();
181
182 throw $e;
183 }
184
185 return $result;
186 }
187
197 public static function update($primary, array $data)
198 {
199 global $USER_FIELD_MANAGER, $APPLICATION;
200
201 // check primary
202 static::normalizePrimary(
203 $primary, isset($data["fields"]) && is_array($data["fields"]) ? $data["fields"] : $data
204 );
205 static::validatePrimary($primary);
206
208 $object = static::convertArrayToObject($data, false, $primary);
209
210 //$oldData = static::getByPrimary($primary)->fetch();
211 $object->fill(FieldTypeMask::SCALAR);
212 $oldData = $object->collectValues(Values::ACTUAL, FieldTypeMask::SCALAR);
213
214 $hlblock = static::getHighloadBlock();
215 $entity = static::getEntity();
216 $result = new UpdateResult();
217
218 try
219 {
220 static::callOnBeforeUpdateEvent($object, $data, $result);
221
222 // actualize old-style fields array from object
223 $data = $object->collectValues(Values::CURRENT, FieldTypeMask::SCALAR);
224
225 // check data by uf manager CheckFieldsWithOldData
226 if (!$USER_FIELD_MANAGER->checkFieldsWithOldData('HLBLOCK_'.$hlblock['ID'], $oldData, $data))
227 {
228 if(is_object($APPLICATION) && $APPLICATION->getException())
229 {
230 $e = $APPLICATION->getException();
231 $result->addError(new Entity\EntityError($e->getString()));
232 $APPLICATION->resetException();
233 }
234 else
235 {
236 $result->addError(new Entity\EntityError("Unknown error while checking userfields"));
237 }
238 }
239
240 // return if any error
241 if (!$result->isSuccess(true))
242 {
243 return $result;
244 }
245
246 static::callOnUpdateEvent($object, $data, []);
247
248 // format data before save
249 $fields = $USER_FIELD_MANAGER->getUserFieldsWithReadyData('HLBLOCK_'.$hlblock['ID'], $oldData, LANGUAGE_ID, false, 'ID');
250 list($data, $multiValues) = static::convertValuesBeforeSave($data, $fields);
251
252 // data could be changed by uf manager
253 foreach ($data as $k => $v)
254 {
255 $object->set($k, $v);
256 }
257
258 // use save modifiers
259 foreach ($data as $fieldName => $value)
260 {
261 $field = static::getEntity()->getField($fieldName);
262 $data[$fieldName] = $field->modifyValueBeforeSave($value, $data);
263 }
264
265 $connection = Main\Application::getConnection();
266
267 if (!empty($data))
268 {
269 // save data
270 $helper = $connection->getSqlHelper();
271 $tableName = $entity->getDBTableName();
272
273 $update = $helper->prepareUpdate($tableName, $data);
274
275 $id = array();
276 foreach ($primary as $k => $v)
277 {
278 $id[] = $helper->prepareAssignment($tableName, $k, $v);
279 }
280 $where = implode(' AND ', $id);
281
282 $sql = "UPDATE ".$helper->quote($tableName)." SET ".$update[0]." WHERE ".$where;
283 $connection->queryExecute($sql, $update[1]);
284 }
285
286 $result->setAffectedRowsCount($connection);
287 $result->setData($data);
288 $result->setPrimary($primary);
289 $result->setObject($object);
290
291 // save multi values
292 if (!empty($multiValues))
293 {
294 foreach ($multiValues as $userfieldName => $values)
295 {
296 $utmTableName = HighloadBlockTable::getMultipleValueTableName($hlblock, $fields[$userfieldName]);
297
298 // first, delete old values
299 $connection->query(sprintf(
300 'DELETE FROM %s WHERE %s = %d',
301 $helper->quote($utmTableName), $helper->quote('ID'), $primary['ID']
302 ));
303
304 // insert new values
305 foreach ($values as $value)
306 {
307 $connection->add($utmTableName, array('ID' => $primary['ID'], 'VALUE' => $value));
308 }
309 }
310 }
311
312 $entity->cleanCache();
313
314 // event after update
315 static::callOnAfterUpdateEvent($object, $data);
316 }
317 catch (\Exception $e)
318 {
319 // check result to avoid warning
320 $result->isSuccess();
321
322 throw $e;
323 }
324
325 return $result;
326 }
327
336 public static function delete($primary)
337 {
338 global $USER_FIELD_MANAGER;
339
340 // check primary
341 static::normalizePrimary($primary);
342 static::validatePrimary($primary);
343
344 $entity = static::getEntity();
345 $result = new Entity\DeleteResult();
346 $hlblock = static::getHighloadBlock();
347
348 // get old data
349 $oldData = static::getByPrimary($primary)->fetch();
350
351 try
352 {
353 //event before delete
354 static::callOnBeforeDeleteEvent($primary, $entity, $result, $oldData);
355
356 // return if any error
357 if (!$result->isSuccess(true))
358 {
359 return $result;
360 }
361
362 //event on delete
363 static::callOnDeleteEvent($primary, $entity, $oldData);
364
365 // remove row
366 $connection = Main\Application::getConnection();
367 $helper = $connection->getSqlHelper();
368
369 $tableName = $entity->getDBTableName();
370
371 $id = array();
372 foreach ($primary as $k => $v)
373 {
374 $id[] = $k." = '".$helper->forSql($v)."'";
375 }
376 $where = implode(' AND ', $id);
377
378 $sql = "DELETE FROM ".$helper->quote($tableName)." WHERE ".$where;
379 $connection->queryExecute($sql);
380
381 $fields = $USER_FIELD_MANAGER->getUserFields('HLBLOCK_'.$hlblock['ID']);
382
383 foreach ($oldData as $k => $v)
384 {
385 $userfield = $fields[$k];
386
387 // remove multi values
388 if ($userfield['MULTIPLE'] == 'Y')
389 {
390 $utmTableName = HighloadBlockTable::getMultipleValueTableName($hlblock, $userfield);
391
392 $connection->query(sprintf(
393 'DELETE FROM %s WHERE %s = %d',
394 $helper->quote($utmTableName), $helper->quote('ID'), $primary['ID']
395 ));
396 }
397
398 // remove files
399 if ($userfield["USER_TYPE"]["BASE_TYPE"]=="file")
400 {
401 if(is_array($oldData[$k]))
402 {
403 foreach($oldData[$k] as $value)
404 {
405 \CFile::delete($value);
406 }
407 }
408 else
409 {
410 \CFile::delete($oldData[$k]);
411 }
412 }
413 }
414
415 $entity->cleanCache();
416
417 //event after delete
418 static::callOnAfterDeleteEvent($primary, $entity, $oldData);
419 }
420 catch (\Exception $e)
421 {
422 // check result to avoid warning
423 $result->isSuccess();
424
425 throw $e;
426 }
427
428 return $result;
429 }
430
431 protected static function callOnBeforeUpdateEvent($object, $fields, $result)
432 {
433 //event before update
434 $event = new Entity\Event($object->entity, self::EVENT_ON_BEFORE_UPDATE, [
435 "id" => $object->primary,
436 "fields" => $fields,
437 'object' => $object
438 ]);
439
440 $event->send();
441 $event->getErrors($result);
442 $event->mergeObjectFields($object);
443
444 $oldData = $object->collectValues(Values::ACTUAL, FieldTypeMask::SCALAR);
445
446 //event before update (modern with namespace)
447 $event = new Entity\Event($object->entity, self::EVENT_ON_BEFORE_UPDATE, [
448 "id" => $object->primary,
449 "primary" => $object->primary,
450 "fields" => $fields,
451 'object' => $object,
452 "oldFields" => $oldData
453 ], true);
454
455 $event->send();
456 $event->getErrors($result);
457 $event->mergeObjectFields($object);
458 }
459
460 protected static function callOnUpdateEvent($object, $fields, $ufdata)
461 {
462 //event on update
463 $event = new Event($object->entity, self::EVENT_ON_UPDATE, [
464 "id" => $object->primary,
465 "fields" => $fields,
466 'object' => clone $object
467 ]);
468 $event->send();
469
470 $oldData = $object->collectValues(Values::ACTUAL, FieldTypeMask::SCALAR);
471
472 //event on update (modern with namespace)
473 $event = new Event($object->entity, self::EVENT_ON_UPDATE, [
474 "id" => $object->primary,
475 "primary" => $object->primary,
476 "fields" => $fields,
477 'object' => clone $object,
478 "oldFields" => $oldData
479 ], true);
480 $event->send();
481 }
482
483 protected static function callOnAfterUpdateEvent($object, $fields)
484 {
485 //event after update
486 $event = new Entity\Event($object->entity, self::EVENT_ON_AFTER_UPDATE, [
487 "id"=> $object->primary,
488 "fields" => $fields,
489 'object' => clone $object
490 ]);
491 $event->send();
492
493 $oldData = $object->collectValues(Values::ACTUAL, FieldTypeMask::SCALAR);
494
495 //event after update (modern with namespace)
496 $event = new Entity\Event($object->entity, self::EVENT_ON_AFTER_UPDATE, [
497 "id" => $object->primary,
498 "primary" => $object->primary,
499 "fields" => $fields,
500 'object' => clone $object,
501 "oldFields" => $oldData
502 ], true);
503 $event->send();
504 }
505
506 protected static function callOnBeforeDeleteEvent($primary, $entity, $result, $oldData = null)
507 {
508 //event before delete
509 $event = new Entity\Event($entity, self::EVENT_ON_BEFORE_DELETE, array("id"=>$primary));
510 $event->send();
511 $event->getErrors($result);
512
513 //event before delete (modern with namespace)
514 $event = new Entity\Event($entity, self::EVENT_ON_BEFORE_DELETE, array(
515 "id"=>$primary, "primary"=>$primary, "oldFields" => $oldData
516 ), true);
517 $event->send();
518 $event->getErrors($result);
519 }
520
521 protected static function callOnDeleteEvent($primary, $entity, $oldData = null)
522 {
523 //event on delete
524 $event = new Entity\Event($entity, self::EVENT_ON_DELETE, array("id"=>$primary));
525 $event->send();
526
527 //event on delete (modern with namespace)
528 $event = new Entity\Event($entity, self::EVENT_ON_DELETE, array(
529 "id"=>$primary, "primary"=>$primary, "oldFields" => $oldData
530 ), true);
531 $event->send();
532 }
533
534 protected static function callOnAfterDeleteEvent($primary, $entity, $oldData = null)
535 {
536 //event after delete
537 $event = new Entity\Event($entity, self::EVENT_ON_AFTER_DELETE, array("id"=>$primary));
538 $event->send();
539
540 //event after delete (modern with namespace)
541 $event = new Entity\Event($entity, self::EVENT_ON_AFTER_DELETE, array(
542 "id"=>$primary, "primary" => $primary, "oldFields" => $oldData
543 ), true);
544 $event->send();
545 }
546
547 protected static function convertValuesBeforeSave($data, $userfields)
548 {
549 $multiValues = array();
550
551 foreach ($data as $k => $v)
552 {
553 if ($k == 'ID')
554 {
555 continue;
556 }
557
558 $userfield = $userfields[$k];
559
560 if ($userfield['MULTIPLE'] == 'N')
561 {
562 $inputValue = array($v);
563 }
564 else
565 {
566 $inputValue = $v;
567 }
568
569 $tmpValue = array();
570
571 foreach ($inputValue as $singleValue)
572 {
573 $tmpValue[] = static::convertSingleValueBeforeSave($singleValue, $userfield);
574 }
575
576 // write value back
577 if ($userfield['MULTIPLE'] == 'N')
578 {
579 $data[$k] = $tmpValue[0];
580 }
581 else
582 {
583 // remove empty (false) values
584 $tmpValue = array_filter($tmpValue, array('static', 'isNotNull'));
585
586 $data[$k] = $tmpValue;
587 $multiValues[$k] = $tmpValue;
588 }
589 }
590
591 return array($data, $multiValues);
592 }
593
600 protected static function convertSingleValueBeforeSave($value, $userfield)
601 {
602 if (!isset($userfield['USER_TYPE']) || !is_array($userfield['USER_TYPE']))
603 {
604 $userfield['USER_TYPE'] = array();
605 }
606
607 if (
608 isset($userfield['USER_TYPE']['CLASS_NAME']) &&
609 is_callable(array($userfield['USER_TYPE']['CLASS_NAME'], 'onbeforesave'))
610 )
611 {
612 $value = call_user_func_array(
613 array($userfield['USER_TYPE']['CLASS_NAME'], 'onbeforesave'), array($userfield, $value)
614 );
615 }
616
617 if (static::isNotNull($value))
618 {
619 return $value;
620 }
621 elseif (
622 isset($userfield['USER_TYPE']['BASE_TYPE']) &&
623 (
624 $userfield['USER_TYPE']['BASE_TYPE'] == 'int' ||
625 $userfield['USER_TYPE']['BASE_TYPE'] == 'double'
626 )
627 )
628 {
629 return null;
630 }
631 else
632 {
633 return false;
634 }
635 }
636
637 protected static function isNotNull($value)
638 {
639 return !($value === null || $value === false || $value === '');
640 }
641}
static callOnBeforeUpdateEvent($object, $fields, $result)
static callOnAfterUpdateEvent($object, $fields)
static callOnAfterDeleteEvent($primary, $entity, $oldData=null)
static convertValuesBeforeSave($data, $userfields)
static callOnBeforeDeleteEvent($primary, $entity, $result, $oldData=null)
static callOnUpdateEvent($object, $fields, $ufdata)
static checkFields(Entity\Result $result, $primary, array $data)
static convertSingleValueBeforeSave($value, $userfield)
static callOnDeleteEvent($primary, $entity, $oldData=null)
static getMultipleValueTableName($hlblock, $userfield)