Bitrix-D7  20.5.0
main/lib/orm/fields/field.php
См. документацию.
1 <?php
2 /**
3  * Bitrix Framework
4  * @package bitrix
5  * @subpackage main
6  * @copyright 2001-2012 Bitrix
7  */
8 
9 namespace Bitrix\Main\ORM\Fields;
18 
19 /**
20  * Base entity field class
21  * @package bitrix
22  * @subpackage main
23  */
24 abstract class Field
25 {
26  /** @var string */
27  protected $name;
28 
29  /** @var string */
30  protected $dataType;
31 
32  /** @var array */
33  protected $initialParameters;
34 
35  /** @var string */
36  protected $title;
37 
38  /** @var null|callback */
39  protected $validation = null;
40 
41  /** @var null|callback[]|Validators\Validator[] */
42  protected $validators = null;
43 
44  /** @var array|callback[]|Validators\Validator[] */
45  protected $additionalValidators = array();
46 
47  /** @var null|callback */
48  protected $fetchDataModification = null;
49 
50  /** @var null|callback[] */
52 
53  /** @var null|callback[] */
54  protected $additionalFetchDataModifiers = array();
55 
56  /** @var null|callback */
57  protected $saveDataModification = null;
58 
59  /** @var null|callback[] */
60  protected $saveDataModifiers;
61 
62  /** @var null|callback[] */
63  protected $additionalSaveDataModifiers = array();
64 
65  /**
66  * @deprecated
67  * @see ArrayField
68  * @var bool
69  */
70  protected $isSerialized = false;
71 
72  /** @var Field */
73  protected $parentField;
74 
75  /** @var Entity */
76  protected $entity;
77 
78  /**
79  * @deprecated
80  * @var array
81  */
82  protected static $oldDataTypes = array(
83  'float' => 'Bitrix\Main\ORM\Fields\FloatField',
84  'string' => 'Bitrix\Main\ORM\Fields\StringField',
85  'text' => 'Bitrix\Main\ORM\Fields\TextField',
86  'datetime' => 'Bitrix\Main\ORM\Fields\DatetimeField',
87  'date' => 'Bitrix\Main\ORM\Fields\DateField',
88  'integer' => 'Bitrix\Main\ORM\Fields\IntegerField',
89  'enum' => 'Bitrix\Main\ORM\Fields\EnumField',
90  'boolean' => 'Bitrix\Main\ORM\Fields\BooleanField'
91  );
92 
93  /**
94  * @param string $name
95  * @param array $parameters deprecated, use configure* and add* methods instead
96  *
97  * @throws SystemException
98  */
99  public function __construct($name, $parameters = array())
100  {
101  if ($name == '')
102  {
103  throw new SystemException('Field name required');
104  }
105 
106  $this->name = $name;
107  $this->dataType = null;
108  $this->initialParameters = $parameters;
109 
110  if (isset($parameters['title']))
111  {
112  $this->title = $parameters['title'];
113  }
114 
115  // validation
116  if (isset($parameters['validation']))
117  {
118  $this->validation = $parameters['validation'];
119  }
120 
121  // fetch data modifiers
122  if (isset($parameters['fetch_data_modification']))
123  {
124  $this->fetchDataModification = $parameters['fetch_data_modification'];
125  }
126 
127  // save data modifiers
128  if (isset($parameters['save_data_modification']))
129  {
130  $this->saveDataModification = $parameters['save_data_modification'];
131  }
132 
133  if (!empty($parameters['serialized']))
134  {
135  $this->setSerialized();
136  }
137  }
138 
139  /**
140  * @param Entity $entity
141  *
142  * @throws SystemException
143  */
144  public function setEntity(Entity $entity)
145  {
146  if ($this->entity !== null)
147  {
148  throw new SystemException(sprintf('Field "%s" already has entity', $this->name));
149  }
150 
151  $this->entity = $entity;
152  }
153 
154  public function resetEntity()
155  {
156  $this->entity = null;
157  }
158 
159  abstract public function getTypeMask();
160 
161  /**
162  * @param $value
163  * @param $primary
164  * @param $row
165  * @param Result $result
166  *
167  * @return Result
168  * @throws SystemException
169  */
170  public function validateValue($value, $primary, $row, Result $result)
171  {
172  if ($value instanceof SqlExpression)
173  {
174  return $result;
175  }
176 
177  $validators = $this->getValidators();
178 
179  foreach ($validators as $validator)
180  {
181  if ($validator instanceof IValidator)
182  {
183  $vResult = $validator->validate($value, $primary, $row, $this);
184  }
185  else
186  {
187  $vResult = call_user_func_array($validator, array($value, $primary, $row, $this));
188  }
189 
190  if ($vResult !== true)
191  {
192  if ($vResult instanceof EntityError)
193  {
194  $result->addError($vResult);
195  }
196  else
197  {
198  $result->addError(new FieldError($this, $vResult, FieldError::INVALID_VALUE));
199  }
200  }
201  }
202 
203  return $result;
204  }
205 
206  /**
207  * @param $value
208  * @param $data
209  *
210  * @return mixed
211  * @throws SystemException
212  */
213  public function modifyValueBeforeSave($value, $data)
214  {
215  $modifiers = $this->getSaveDataModifiers();
216 
217  foreach ($modifiers as $modifier)
218  {
219  $value = call_user_func_array($modifier, array($value, $data));
220  }
221 
222  return $value;
223  }
224 
225  /**
226  * @return callback[]|Validators\Validator[]
227  * @throws SystemException
228  */
229  public function getValidators()
230  {
231  if ($this->validators === null)
232  {
233  $this->validators = array();
234 
235  if ($this->validation !== null)
236  {
237  $validators = call_user_func($this->validation);
238 
239  if (!is_array($validators))
240  {
241  throw new SystemException(sprintf(
242  'Validation for %s field of %s entity should return array of validators',
243  $this->name, $this->entity->getDataClass()
244  ));
245  }
246 
247  foreach ($validators as $validator)
248  {
249  $this->appendValidator($validator);
250  }
251  }
252 
253  foreach ($this->additionalValidators as $validator)
254  {
255  $this->appendValidator($validator);
256  }
257  }
258 
259  return $this->validators;
260  }
261 
262  /**
263  * @param Validators\Validator|callable $validator
264  *
265  * @return $this
266  * @throws SystemException
267  */
268  public function addValidator($validator)
269  {
270  // append only when not null. and when is null - delay it
271  if ($this->validators === null)
272  {
273  $this->additionalValidators[] = $validator;
274  }
275  else
276  {
277  $this->appendValidator($validator);
278  }
279 
280  return $this;
281  }
282 
283  /**
284  * @param Validators\Validator|callable $validator
285  *
286  * @throws SystemException
287  */
288  protected function appendValidator($validator)
289  {
290  if (!($validator instanceof Validators\Validator) && !is_callable($validator))
291  {
292  throw new SystemException(sprintf(
293  'Validators of "%s" field of "%s" entity should be a Validator\Base or callback',
294  $this->name, $this->entity->getDataClass()
295  ));
296  }
297 
298  $this->validators[] = $validator;
299  }
300 
301  /**
302  * @return array|callback[]|null
303  * @throws SystemException
304  */
305  public function getFetchDataModifiers()
306  {
307  if ($this->fetchDataModifiers === null)
308  {
309  $this->fetchDataModifiers = array();
310 
311  if ($this->fetchDataModification !== null)
312  {
313  $modifiers = call_user_func($this->fetchDataModification);
314 
315  if (!is_array($modifiers))
316  {
317  throw new SystemException(sprintf(
318  'Fetch Data Modification for %s field of %s entity should return array of modifiers (callbacks)',
319  $this->name, $this->entity->getDataClass()
320  ));
321  }
322 
323  foreach ($modifiers as $modifier)
324  {
325  $this->appendFetchDataModifier($modifier);
326  }
327  }
328 
329  foreach ($this->additionalFetchDataModifiers as $modifier)
330  {
331  $this->appendFetchDataModifier($modifier);
332  }
333  }
334 
336  }
337 
338  /**
339  * @param \callable $modifier
340  *
341  * @return $this
342  * @throws SystemException
343  */
344  public function addFetchDataModifier($modifier)
345  {
346  // append only when not null. and when is null - delay it
347  if ($this->fetchDataModifiers === null)
348  {
349  $this->additionalFetchDataModifiers[] = $modifier;
350  }
351  else
352  {
353  $this->appendFetchDataModifier($modifier);
354  }
355 
356  return $this;
357  }
358 
359  /**
360  * @param \callable $modifier
361  *
362  * @throws SystemException
363  */
364  protected function appendFetchDataModifier($modifier)
365  {
366  if (!is_callable($modifier))
367  {
368  throw new SystemException(sprintf(
369  'Modifier of "%s" field of "%s" entity should be a callback',
370  $this->name, $this->entity->getDataClass()
371  ));
372  }
373 
374  $this->fetchDataModifiers[] = $modifier;
375  }
376 
377  /**
378  * @return array|callback[]|null
379  * @throws SystemException
380  */
381  public function getSaveDataModifiers()
382  {
383  if ($this->saveDataModifiers === null)
384  {
385  $this->saveDataModifiers = array();
386 
387  if ($this->saveDataModification !== null)
388  {
389  $modifiers = call_user_func($this->saveDataModification);
390 
391  if (!is_array($modifiers))
392  {
393  throw new SystemException(sprintf(
394  'Save Data Modification for %s field of %s entity should return array of modifiers (callbacks)',
395  $this->name, $this->entity->getDataClass()
396  ));
397  }
398 
399  foreach ($modifiers as $modifier)
400  {
401  $this->appendSaveDataModifier($modifier);
402  }
403  }
404 
405  foreach ($this->additionalSaveDataModifiers as $modifier)
406  {
407  $this->appendSaveDataModifier($modifier);
408  }
409  }
410 
412  }
413 
414  /**
415  * @param \callable $modifier
416  *
417  * @return $this
418  * @throws SystemException
419  */
420  public function addSaveDataModifier($modifier)
421  {
422  // append only when not null. and when is null - delay it
423  if ($this->saveDataModifiers === null)
424  {
425  $this->additionalSaveDataModifiers[] = $modifier;
426  }
427  else
428  {
429  $this->appendSaveDataModifier($modifier);
430  }
431 
432  return $this;
433  }
434 
435  /**
436  * @param \callable $modifier
437  *
438  * @throws SystemException
439  */
440  protected function appendSaveDataModifier($modifier)
441  {
442  if (!is_callable($modifier))
443  {
444  throw new SystemException(sprintf(
445  'Save modifier of "%s" field of "%s" entity should be a callback',
446  $this->name, $this->entity->getDataClass()
447  ));
448  }
449 
450  $this->saveDataModifiers[] = $modifier;
451  }
452 
453  /**
454  * @return boolean
455  */
456  public function isSerialized()
457  {
458  return !empty($this->isSerialized);
459  }
460 
461  /**
462  * @throws SystemException
463  */
464  public function setSerialized()
465  {
466  if (!$this->isSerialized)
467  {
468  $this->isSerialized = true;
469 
470  // add save- and fetch modifiers
471  $this->addSaveDataModifier(array($this, 'serialize'));
472  $this->addFetchDataModifier(array($this, 'unserialize'));
473  }
474  }
475 
476  /**
477  * @deprecated
478  * @return $this
479  * @throws SystemException
480  */
481  public function configureSerialized()
482  {
483  $this->setSerialized();
484  return $this;
485  }
486 
487  public function getName()
488  {
489  return $this->name;
490  }
491 
492  public function setName($name)
493  {
494  $this->name = $name;
495  }
496 
497  /**
498  * Lang phrase
499  *
500  * @param $title
501  *
502  * @return $this
503  */
504  public function configureTitle($title)
505  {
506  $this->title = $title;
507  return $this;
508  }
509 
510  public function getTitle()
511  {
512  if($this->title !== null)
513  {
514  return $this->title;
515  }
516 
517  if(($title = Loc::getMessage($this->getLangCode())) <> '')
518  {
519  return $this->title = $title;
520  }
521 
522  return $this->title = $this->name;
523  }
524 
525  public function setParameter($name, $value)
526  {
527  $this->initialParameters[$name] = $value;
528 
529  return $this;
530  }
531 
532  public function getParameter($name)
533  {
534  return $this->initialParameters[$name];
535  }
536 
537  public function hasParameter($name)
538  {
539  return array_key_exists($name, $this->initialParameters);
540  }
541 
542  /**
543  * @param Field $parentField
544  */
546  {
547  $this->parentField = $parentField;
548  }
549 
550  /**
551  * @return Field
552  */
553  public function getParentField()
554  {
555  return $this->parentField;
556  }
557 
558  /**
559  * @deprecated
560  * @return null|string
561  */
562  public function getDataType()
563  {
564  if (empty($this->dataType))
565  {
566  return static::getOldDataTypeByField($this);
567  }
568 
569  return $this->dataType;
570  }
571 
572  /**
573  * @deprecated
574  * @param $class
575  *
576  * @return bool
577  */
578  public static function getOldDataTypeByClass($class)
579  {
580  $map = array_flip(static::$oldDataTypes);
581 
582  return isset($map[$class]) ? $map[$class] : 'string';
583  }
584 
585  /**
586  * @deprecated
587  * @param Field $field
588  *
589  * @return bool
590  */
591  public static function getOldDataTypeByField(Field $field)
592  {
593  return static::getOldDataTypeByClass(get_class($field));
594  }
595 
596  /**
597  * @deprecated
598  * @param $dateType
599  *
600  * @return bool
601  */
602  public static function getClassByOldDataType($dateType)
603  {
604  return isset(static::$oldDataTypes[$dateType]) ? '\\'.static::$oldDataTypes[$dateType] : false;
605  }
606 
607  public function getEntity()
608  {
609  return $this->entity;
610  }
611 
612  public function getLangCode()
613  {
614  $entity = $this->getEntity();
615  if($entity !== null)
616  {
617  return $entity->getLangCode().'_'.$this->getName().'_FIELD';
618  }
619  return null;
620  }
621 
622  /**
623  * @return \Bitrix\Main\DB\Connection
624  * @throws SystemException
625  */
626  public function getConnection()
627  {
628  if ($this->entity)
629  {
630  return $this->entity->getConnection();
631  }
632 
634  }
635 
636  public function serialize($value)
637  {
638  return serialize($value);
639  }
640 
641  public function unserialize($value)
642  {
643  return unserialize($value);
644  }
645 
646  /**
647  * Called after being initialized by Entity
648  * @return null
649  */
650  public function postInitialize()
651  {
652  return null;
653  }
654 }
Base class for any application.
static getConnection($name="")
Static method returns database connection for the specified name.
static getMessage($code, $replace=null, $language=null)
Returns translation by message code.
Definition: loc.php:29
postInitialize()
Called after being initialized by Entity.
__construct($name, $parameters=array())
validateValue($value, $primary, $row, Result $result)
addError(Error $error)
Adds the error.
Base class for fatal exceptions.