Mercurial > hg > isophonics-drupal-site
comparison core/lib/Drupal/Core/Field/FieldConfigBase.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Core\Field; | |
4 | |
5 use Drupal\Core\Config\Entity\ConfigEntityBase; | |
6 use Drupal\Core\Entity\EntityStorageInterface; | |
7 use Drupal\Core\Entity\FieldableEntityInterface; | |
8 use Drupal\Core\Field\TypedData\FieldItemDataDefinition; | |
9 | |
10 /** | |
11 * Base class for configurable field definitions. | |
12 */ | |
13 abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigInterface { | |
14 | |
15 /** | |
16 * The field ID. | |
17 * | |
18 * The ID consists of 3 parts: the entity type, bundle and the field name. | |
19 * | |
20 * Example: node.article.body, user.user.field_main_image. | |
21 * | |
22 * @var string | |
23 */ | |
24 protected $id; | |
25 | |
26 /** | |
27 * The field name. | |
28 * | |
29 * @var string | |
30 */ | |
31 protected $field_name; | |
32 | |
33 /** | |
34 * The field type. | |
35 * | |
36 * This property is denormalized from the field storage for optimization of | |
37 * the "entity and render cache hits" critical paths. If not present in the | |
38 * $values passed to create(), it is populated from the field storage in | |
39 * postCreate(), and saved in config records so that it is present on | |
40 * subsequent loads. | |
41 * | |
42 * @var string | |
43 */ | |
44 protected $field_type; | |
45 | |
46 /** | |
47 * The name of the entity type the field is attached to. | |
48 * | |
49 * @var string | |
50 */ | |
51 protected $entity_type; | |
52 | |
53 /** | |
54 * The name of the bundle the field is attached to. | |
55 * | |
56 * @var string | |
57 */ | |
58 protected $bundle; | |
59 | |
60 /** | |
61 * The human-readable label for the field. | |
62 * | |
63 * This will be used as the title of Form API elements for the field in entity | |
64 * edit forms, or as the label for the field values in displayed entities. | |
65 * | |
66 * If not specified, this defaults to the field_name (mostly useful for fields | |
67 * created in tests). | |
68 * | |
69 * @var string | |
70 */ | |
71 protected $label; | |
72 | |
73 /** | |
74 * The field description. | |
75 * | |
76 * A human-readable description for the field when used with this bundle. | |
77 * For example, the description will be the help text of Form API elements for | |
78 * this field in entity edit forms. | |
79 * | |
80 * @var string | |
81 */ | |
82 protected $description = ''; | |
83 | |
84 /** | |
85 * Field-type specific settings. | |
86 * | |
87 * An array of key/value pairs. The keys and default values are defined by the | |
88 * field type. | |
89 * | |
90 * @var array | |
91 */ | |
92 protected $settings = []; | |
93 | |
94 /** | |
95 * Flag indicating whether the field is required. | |
96 * | |
97 * TRUE if a value for this field is required when used with this bundle, | |
98 * FALSE otherwise. Currently, required-ness is only enforced at the Form API | |
99 * level in entity edit forms, not during direct API saves. | |
100 * | |
101 * @var bool | |
102 */ | |
103 protected $required = FALSE; | |
104 | |
105 /** | |
106 * Flag indicating whether the field is translatable. | |
107 * | |
108 * Defaults to TRUE. | |
109 * | |
110 * @var bool | |
111 */ | |
112 protected $translatable = TRUE; | |
113 | |
114 /** | |
115 * Default field value. | |
116 * | |
117 * The default value is used when an entity is created, either: | |
118 * - through an entity creation form; the form elements for the field are | |
119 * prepopulated with the default value. | |
120 * - through direct API calls (i.e. $entity->save()); the default value is | |
121 * added if the $entity object provides no explicit entry (actual values or | |
122 * "the field is empty") for the field. | |
123 * | |
124 * The default value is expressed as a numerically indexed array of items, | |
125 * each item being an array of key/value pairs matching the set of 'columns' | |
126 * defined by the "field schema" for the field type, as exposed in | |
127 * hook_field_schema(). If the number of items exceeds the cardinality of the | |
128 * field, extraneous items will be ignored. | |
129 * | |
130 * This property is overlooked if the $default_value_callback is non-empty. | |
131 * | |
132 * Example for a integer field: | |
133 * @code | |
134 * array( | |
135 * array('value' => 1), | |
136 * array('value' => 2), | |
137 * ) | |
138 * @endcode | |
139 * | |
140 * @var array | |
141 */ | |
142 protected $default_value = []; | |
143 | |
144 /** | |
145 * The name of a callback function that returns default values. | |
146 * | |
147 * The function will be called with the following arguments: | |
148 * - \Drupal\Core\Entity\FieldableEntityInterface $entity | |
149 * The entity being created. | |
150 * - \Drupal\Core\Field\FieldDefinitionInterface $definition | |
151 * The field definition. | |
152 * It should return an array of default values, in the same format as the | |
153 * $default_value property. | |
154 * | |
155 * This property takes precedence on the list of fixed values specified in the | |
156 * $default_value property. | |
157 * | |
158 * @var string | |
159 */ | |
160 protected $default_value_callback = ''; | |
161 | |
162 /** | |
163 * The field storage object. | |
164 * | |
165 * @var \Drupal\Core\Field\FieldStorageDefinitionInterface | |
166 */ | |
167 protected $fieldStorage; | |
168 | |
169 /** | |
170 * The data definition of a field item. | |
171 * | |
172 * @var \Drupal\Core\Field\TypedData\FieldItemDataDefinition | |
173 */ | |
174 protected $itemDefinition; | |
175 | |
176 /** | |
177 * Array of constraint options keyed by constraint plugin ID. | |
178 * | |
179 * @var array | |
180 */ | |
181 protected $constraints = []; | |
182 | |
183 /** | |
184 * Array of property constraint options keyed by property ID. The values are | |
185 * associative array of constraint options keyed by constraint plugin ID. | |
186 * | |
187 * @var array[] | |
188 */ | |
189 protected $propertyConstraints = []; | |
190 | |
191 /** | |
192 * {@inheritdoc} | |
193 */ | |
194 public function id() { | |
195 return $this->entity_type . '.' . $this->bundle . '.' . $this->field_name; | |
196 } | |
197 | |
198 /** | |
199 * {@inheritdoc} | |
200 */ | |
201 public function getName() { | |
202 return $this->field_name; | |
203 } | |
204 | |
205 /** | |
206 * {@inheritdoc} | |
207 */ | |
208 public function getType() { | |
209 return $this->field_type; | |
210 } | |
211 | |
212 /** | |
213 * {@inheritdoc} | |
214 */ | |
215 public function getTargetEntityTypeId() { | |
216 return $this->entity_type; | |
217 } | |
218 | |
219 /** | |
220 * {@inheritdoc} | |
221 */ | |
222 public function getTargetBundle() { | |
223 return $this->bundle; | |
224 } | |
225 | |
226 /** | |
227 * {@inheritdoc} | |
228 */ | |
229 public function calculateDependencies() { | |
230 parent::calculateDependencies(); | |
231 // Add dependencies from the field type plugin. We can not use | |
232 // self::calculatePluginDependencies() because instantiation of a field item | |
233 // plugin requires a parent entity. | |
234 /** @var $field_type_manager \Drupal\Core\Field\FieldTypePluginManagerInterface */ | |
235 $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); | |
236 $definition = $field_type_manager->getDefinition($this->getType()); | |
237 $this->addDependency('module', $definition['provider']); | |
238 // Plugins can declare additional dependencies in their definition. | |
239 if (isset($definition['config_dependencies'])) { | |
240 $this->addDependencies($definition['config_dependencies']); | |
241 } | |
242 // Let the field type plugin specify its own dependencies. | |
243 // @see \Drupal\Core\Field\FieldItemInterface::calculateDependencies() | |
244 $this->addDependencies($definition['class']::calculateDependencies($this)); | |
245 | |
246 // Create dependency on the bundle. | |
247 $bundle_config_dependency = $this->entityManager()->getDefinition($this->entity_type)->getBundleConfigDependency($this->bundle); | |
248 $this->addDependency($bundle_config_dependency['type'], $bundle_config_dependency['name']); | |
249 | |
250 return $this; | |
251 } | |
252 | |
253 /** | |
254 * {@inheritdoc} | |
255 */ | |
256 public function onDependencyRemoval(array $dependencies) { | |
257 $changed = parent::onDependencyRemoval($dependencies); | |
258 $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); | |
259 $definition = $field_type_manager->getDefinition($this->getType()); | |
260 if ($definition['class']::onDependencyRemoval($this, $dependencies)) { | |
261 $changed = TRUE; | |
262 } | |
263 return $changed; | |
264 } | |
265 | |
266 | |
267 /** | |
268 * {@inheritdoc} | |
269 */ | |
270 public function postCreate(EntityStorageInterface $storage) { | |
271 parent::postCreate($storage); | |
272 // If it was not present in the $values passed to create(), (e.g. for | |
273 // programmatic creation), populate the denormalized field_type property | |
274 // from the field storage, so that it gets saved in the config record. | |
275 if (empty($this->field_type)) { | |
276 $this->field_type = $this->getFieldStorageDefinition()->getType(); | |
277 } | |
278 } | |
279 | |
280 /** | |
281 * {@inheritdoc} | |
282 */ | |
283 public function postSave(EntityStorageInterface $storage, $update = TRUE) { | |
284 // Clear the cache. | |
285 $this->entityManager()->clearCachedFieldDefinitions(); | |
286 | |
287 // Invalidate the render cache for all affected entities. | |
288 $entity_type = $this->getFieldStorageDefinition()->getTargetEntityTypeId(); | |
289 if ($this->entityManager()->hasHandler($entity_type, 'view_builder')) { | |
290 $this->entityManager()->getViewBuilder($entity_type)->resetCache(); | |
291 } | |
292 } | |
293 | |
294 /** | |
295 * {@inheritdoc} | |
296 */ | |
297 public function getLabel() { | |
298 return $this->label(); | |
299 } | |
300 | |
301 /** | |
302 * {@inheritdoc} | |
303 */ | |
304 public function setLabel($label) { | |
305 $this->label = $label; | |
306 return $this; | |
307 } | |
308 | |
309 /** | |
310 * {@inheritdoc} | |
311 */ | |
312 public function getDescription() { | |
313 return $this->description; | |
314 } | |
315 | |
316 /** | |
317 * {@inheritdoc} | |
318 */ | |
319 public function setDescription($description) { | |
320 $this->description = $description; | |
321 return $this; | |
322 } | |
323 | |
324 /** | |
325 * {@inheritdoc} | |
326 */ | |
327 public function isTranslatable() { | |
328 // A field can be enabled for translation only if translation is supported. | |
329 return $this->translatable && $this->getFieldStorageDefinition()->isTranslatable(); | |
330 } | |
331 | |
332 /** | |
333 * {@inheritdoc} | |
334 */ | |
335 public function setTranslatable($translatable) { | |
336 $this->translatable = $translatable; | |
337 return $this; | |
338 } | |
339 | |
340 /** | |
341 * {@inheritdoc} | |
342 */ | |
343 public function getSettings() { | |
344 return $this->settings + $this->getFieldStorageDefinition()->getSettings(); | |
345 } | |
346 | |
347 /** | |
348 * {@inheritdoc} | |
349 */ | |
350 public function setSettings(array $settings) { | |
351 $this->settings = $settings + $this->settings; | |
352 return $this; | |
353 } | |
354 | |
355 /** | |
356 * {@inheritdoc} | |
357 */ | |
358 public function getSetting($setting_name) { | |
359 if (array_key_exists($setting_name, $this->settings)) { | |
360 return $this->settings[$setting_name]; | |
361 } | |
362 else { | |
363 return $this->getFieldStorageDefinition()->getSetting($setting_name); | |
364 } | |
365 } | |
366 | |
367 /** | |
368 * {@inheritdoc} | |
369 */ | |
370 public function setSetting($setting_name, $value) { | |
371 $this->settings[$setting_name] = $value; | |
372 return $this; | |
373 } | |
374 | |
375 /** | |
376 * {@inheritdoc} | |
377 */ | |
378 public function isRequired() { | |
379 return $this->required; | |
380 } | |
381 | |
382 /** | |
383 * [@inheritdoc} | |
384 */ | |
385 public function setRequired($required) { | |
386 $this->required = $required; | |
387 return $this; | |
388 } | |
389 | |
390 /** | |
391 * {@inheritdoc} | |
392 */ | |
393 public function getDefaultValue(FieldableEntityInterface $entity) { | |
394 // Allow custom default values function. | |
395 if ($callback = $this->getDefaultValueCallback()) { | |
396 $value = call_user_func($callback, $entity, $this); | |
397 } | |
398 else { | |
399 $value = $this->getDefaultValueLiteral(); | |
400 } | |
401 // Allow the field type to process default values. | |
402 $field_item_list_class = $this->getClass(); | |
403 return $field_item_list_class::processDefaultValue($value, $entity, $this); | |
404 } | |
405 | |
406 /** | |
407 * {@inheritdoc} | |
408 */ | |
409 public function getDefaultValueLiteral() { | |
410 return $this->default_value; | |
411 } | |
412 | |
413 /** | |
414 * {@inheritdoc} | |
415 */ | |
416 public function setDefaultValue($value) { | |
417 if (!is_array($value)) { | |
418 if ($value === NULL) { | |
419 $value = []; | |
420 } | |
421 $key = $this->getFieldStorageDefinition()->getPropertyNames()[0]; | |
422 // Convert to the multi value format to support fields with a cardinality | |
423 // greater than 1. | |
424 $value = [ | |
425 [$key => $value], | |
426 ]; | |
427 } | |
428 $this->default_value = $value; | |
429 return $this; | |
430 } | |
431 | |
432 /** | |
433 * {@inheritdoc} | |
434 */ | |
435 public function getDefaultValueCallback() { | |
436 return $this->default_value_callback; | |
437 } | |
438 | |
439 /** | |
440 * {@inheritdoc} | |
441 */ | |
442 public function setDefaultValueCallback($callback) { | |
443 $this->default_value_callback = $callback; | |
444 return $this; | |
445 } | |
446 | |
447 /** | |
448 * Implements the magic __sleep() method. | |
449 * | |
450 * Using the Serialize interface and serialize() / unserialize() methods | |
451 * breaks entity forms in PHP 5.4. | |
452 * @todo Investigate in https://www.drupal.org/node/2074253. | |
453 */ | |
454 public function __sleep() { | |
455 // Only serialize necessary properties, excluding those that can be | |
456 // recalculated. | |
457 $properties = get_object_vars($this); | |
458 unset($properties['fieldStorage'], $properties['itemDefinition'], $properties['original']); | |
459 return array_keys($properties); | |
460 } | |
461 | |
462 /** | |
463 * {@inheritdoc} | |
464 */ | |
465 public static function createFromItemType($item_type) { | |
466 // Forward to the field definition class for creating new data definitions | |
467 // via the typed manager. | |
468 return BaseFieldDefinition::createFromItemType($item_type); | |
469 } | |
470 | |
471 /** | |
472 * {@inheritdoc} | |
473 */ | |
474 public static function createFromDataType($type) { | |
475 // Forward to the field definition class for creating new data definitions | |
476 // via the typed manager. | |
477 return BaseFieldDefinition::createFromDataType($type); | |
478 } | |
479 | |
480 /** | |
481 * {@inheritdoc} | |
482 */ | |
483 public function getDataType() { | |
484 return 'list'; | |
485 } | |
486 | |
487 /** | |
488 * {@inheritdoc} | |
489 */ | |
490 public function isList() { | |
491 return TRUE; | |
492 } | |
493 | |
494 /** | |
495 * {@inheritdoc} | |
496 */ | |
497 public function getClass() { | |
498 // Derive list class from the field type. | |
499 $type_definition = \Drupal::service('plugin.manager.field.field_type') | |
500 ->getDefinition($this->getType()); | |
501 return $type_definition['list_class']; | |
502 } | |
503 | |
504 /** | |
505 * {@inheritdoc} | |
506 */ | |
507 public function getConstraints() { | |
508 return \Drupal::typedDataManager()->getDefaultConstraints($this) + $this->constraints; | |
509 } | |
510 | |
511 /** | |
512 * {@inheritdoc} | |
513 */ | |
514 public function getConstraint($constraint_name) { | |
515 $constraints = $this->getConstraints(); | |
516 return isset($constraints[$constraint_name]) ? $constraints[$constraint_name] : NULL; | |
517 } | |
518 | |
519 /** | |
520 * {@inheritdoc} | |
521 */ | |
522 public function getItemDefinition() { | |
523 if (!isset($this->itemDefinition)) { | |
524 $this->itemDefinition = FieldItemDataDefinition::create($this) | |
525 ->setSettings($this->getSettings()); | |
526 | |
527 // Add any custom property constraints, overwriting as required. | |
528 $item_constraints = $this->itemDefinition->getConstraint('ComplexData') ?: []; | |
529 foreach ($this->propertyConstraints as $name => $constraints) { | |
530 if (isset($item_constraints[$name])) { | |
531 $item_constraints[$name] = $constraints + $item_constraints[$name]; | |
532 } | |
533 else { | |
534 $item_constraints[$name] = $constraints; | |
535 } | |
536 $this->itemDefinition->addConstraint('ComplexData', $item_constraints); | |
537 } | |
538 } | |
539 | |
540 return $this->itemDefinition; | |
541 } | |
542 | |
543 /** | |
544 * {@inheritdoc} | |
545 */ | |
546 public function getConfig($bundle) { | |
547 return $this; | |
548 } | |
549 | |
550 /** | |
551 * {@inheritdoc} | |
552 */ | |
553 public function setConstraints(array $constraints) { | |
554 $this->constraints = $constraints; | |
555 return $this; | |
556 } | |
557 | |
558 /** | |
559 * {@inheritdoc} | |
560 */ | |
561 public function addConstraint($constraint_name, $options = NULL) { | |
562 $this->constraints[$constraint_name] = $options; | |
563 return $this; | |
564 } | |
565 | |
566 /** | |
567 * {@inheritdoc} | |
568 */ | |
569 public function setPropertyConstraints($name, array $constraints) { | |
570 $this->propertyConstraints[$name] = $constraints; | |
571 | |
572 // Reset the field item definition so the next time it is instantiated it | |
573 // will receive the new constraints. | |
574 $this->itemDefinition = NULL; | |
575 | |
576 return $this; | |
577 } | |
578 | |
579 /** | |
580 * {@inheritdoc} | |
581 */ | |
582 public function addPropertyConstraints($name, array $constraints) { | |
583 foreach ($constraints as $constraint_name => $options) { | |
584 $this->propertyConstraints[$name][$constraint_name] = $options; | |
585 } | |
586 | |
587 // Reset the field item definition so the next time it is instantiated it | |
588 // will receive the new constraints. | |
589 $this->itemDefinition = NULL; | |
590 | |
591 return $this; | |
592 } | |
593 | |
594 } |