Mercurial > hg > isophonics-drupal-site
comparison core/modules/field/src/Entity/FieldStorageConfig.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\field\Entity; | |
4 | |
5 use Drupal\Component\Utility\Unicode; | |
6 use Drupal\Core\Config\Entity\ConfigEntityBase; | |
7 use Drupal\Core\Entity\EntityStorageInterface; | |
8 use Drupal\Core\Entity\FieldableEntityInterface; | |
9 use Drupal\Core\Entity\FieldableEntityStorageInterface; | |
10 use Drupal\Core\Field\FieldException; | |
11 use Drupal\Core\Field\FieldStorageDefinitionInterface; | |
12 use Drupal\Core\TypedData\OptionsProviderInterface; | |
13 use Drupal\field\FieldStorageConfigInterface; | |
14 | |
15 /** | |
16 * Defines the Field storage configuration entity. | |
17 * | |
18 * @ConfigEntityType( | |
19 * id = "field_storage_config", | |
20 * label = @Translation("Field storage"), | |
21 * handlers = { | |
22 * "access" = "Drupal\field\FieldStorageConfigAccessControlHandler", | |
23 * "storage" = "Drupal\field\FieldStorageConfigStorage" | |
24 * }, | |
25 * config_prefix = "storage", | |
26 * entity_keys = { | |
27 * "id" = "id", | |
28 * "label" = "id" | |
29 * }, | |
30 * config_export = { | |
31 * "id", | |
32 * "field_name", | |
33 * "entity_type", | |
34 * "type", | |
35 * "settings", | |
36 * "module", | |
37 * "locked", | |
38 * "cardinality", | |
39 * "translatable", | |
40 * "indexes", | |
41 * "persist_with_no_fields", | |
42 * "custom_storage", | |
43 * } | |
44 * ) | |
45 */ | |
46 class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigInterface { | |
47 | |
48 /** | |
49 * The maximum length of the field name, in characters. | |
50 * | |
51 * For fields created through Field UI, this includes the 'field_' prefix. | |
52 */ | |
53 const NAME_MAX_LENGTH = 32; | |
54 | |
55 /** | |
56 * The field ID. | |
57 * | |
58 * The ID consists of 2 parts: the entity type and the field name. | |
59 * | |
60 * Example: node.body, user.field_main_image. | |
61 * | |
62 * @var string | |
63 */ | |
64 protected $id; | |
65 | |
66 /** | |
67 * The field name. | |
68 * | |
69 * This is the name of the property under which the field values are placed in | |
70 * an entity: $entity->{$field_name}. The maximum length is | |
71 * Field:NAME_MAX_LENGTH. | |
72 * | |
73 * Example: body, field_main_image. | |
74 * | |
75 * @var string | |
76 */ | |
77 protected $field_name; | |
78 | |
79 /** | |
80 * The name of the entity type the field can be attached to. | |
81 * | |
82 * @var string | |
83 */ | |
84 protected $entity_type; | |
85 | |
86 /** | |
87 * The field type. | |
88 * | |
89 * Example: text, integer. | |
90 * | |
91 * @var string | |
92 */ | |
93 protected $type; | |
94 | |
95 /** | |
96 * The name of the module that provides the field type. | |
97 * | |
98 * @var string | |
99 */ | |
100 protected $module; | |
101 | |
102 /** | |
103 * Field-type specific settings. | |
104 * | |
105 * An array of key/value pairs, The keys and default values are defined by the | |
106 * field type. | |
107 * | |
108 * @var array | |
109 */ | |
110 protected $settings = []; | |
111 | |
112 /** | |
113 * The field cardinality. | |
114 * | |
115 * The maximum number of values the field can hold. Possible values are | |
116 * positive integers or | |
117 * FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED. Defaults to 1. | |
118 * | |
119 * @var int | |
120 */ | |
121 protected $cardinality = 1; | |
122 | |
123 /** | |
124 * Flag indicating whether the field is translatable. | |
125 * | |
126 * Defaults to TRUE. | |
127 * | |
128 * @var bool | |
129 */ | |
130 protected $translatable = TRUE; | |
131 | |
132 /** | |
133 * Flag indicating whether the field is available for editing. | |
134 * | |
135 * If TRUE, some actions not available though the UI (but are still possible | |
136 * through direct API manipulation): | |
137 * - field settings cannot be changed, | |
138 * - new fields cannot be created | |
139 * - existing fields cannot be deleted. | |
140 * Defaults to FALSE. | |
141 * | |
142 * @var bool | |
143 */ | |
144 protected $locked = FALSE; | |
145 | |
146 /** | |
147 * Flag indicating whether the field storage should be deleted when orphaned. | |
148 * | |
149 * By default field storages for configurable fields are removed when there | |
150 * are no remaining fields using them. If multiple modules provide bundles | |
151 * which need to use the same field storage then setting this to TRUE will | |
152 * preserve the field storage regardless of what happens to the bundles. The | |
153 * classic use case for this is node body field storage since Book, Forum, the | |
154 * Standard profile and bundle (node type) creation through the UI all use | |
155 * same field storage. | |
156 * | |
157 * @var bool | |
158 */ | |
159 protected $persist_with_no_fields = FALSE; | |
160 | |
161 /** | |
162 * A boolean indicating whether or not the field item uses custom storage. | |
163 * | |
164 * @var bool | |
165 */ | |
166 public $custom_storage = FALSE; | |
167 | |
168 /** | |
169 * The custom storage indexes for the field data storage. | |
170 * | |
171 * This set of indexes is merged with the "default" indexes specified by the | |
172 * field type in hook_field_schema() to determine the actual set of indexes | |
173 * that get created. | |
174 * | |
175 * The indexes are defined using the same definition format as Schema API | |
176 * index specifications. Only columns that are part of the field schema, as | |
177 * defined by the field type in hook_field_schema(), are allowed. | |
178 * | |
179 * Some storage backends might not support indexes, and discard that | |
180 * information. | |
181 * | |
182 * @var array | |
183 */ | |
184 protected $indexes = []; | |
185 | |
186 /** | |
187 * Flag indicating whether the field is deleted. | |
188 * | |
189 * The delete() method marks the field as "deleted" and removes the | |
190 * corresponding entry from the config storage, but keeps its definition in | |
191 * the state storage while field data is purged by a separate | |
192 * garbage-collection process. | |
193 * | |
194 * Deleted fields stay out of the regular entity lifecycle (notably, their | |
195 * values are not populated in loaded entities, and are not saved back). | |
196 * | |
197 * @var bool | |
198 */ | |
199 protected $deleted = FALSE; | |
200 | |
201 /** | |
202 * The field schema. | |
203 * | |
204 * @var array | |
205 */ | |
206 protected $schema; | |
207 | |
208 /** | |
209 * An array of field property definitions. | |
210 * | |
211 * @var \Drupal\Core\TypedData\DataDefinitionInterface[] | |
212 * | |
213 * @see \Drupal\Core\TypedData\ComplexDataDefinitionInterface::getPropertyDefinitions() | |
214 */ | |
215 protected $propertyDefinitions; | |
216 | |
217 /** | |
218 * Static flag set to prevent recursion during field deletes. | |
219 * | |
220 * @var bool | |
221 */ | |
222 protected static $inDeletion = FALSE; | |
223 | |
224 /** | |
225 * Constructs a FieldStorageConfig object. | |
226 * | |
227 * In most cases, Field entities are created via | |
228 * FieldStorageConfig::create($values)), where $values is the same parameter | |
229 * as in this constructor. | |
230 * | |
231 * @param array $values | |
232 * An array of field properties, keyed by property name. Most array | |
233 * elements will be used to set the corresponding properties on the class; | |
234 * see the class property documentation for details. Some array elements | |
235 * have special meanings and a few are required. Special elements are: | |
236 * - name: required. As a temporary Backwards Compatibility layer right now, | |
237 * a 'field_name' property can be accepted in place of 'id'. | |
238 * - entity_type: required. | |
239 * - type: required. | |
240 * | |
241 * @see entity_create() | |
242 */ | |
243 public function __construct(array $values, $entity_type = 'field_storage_config') { | |
244 // Check required properties. | |
245 if (empty($values['field_name'])) { | |
246 throw new FieldException('Attempt to create a field storage without a field name.'); | |
247 } | |
248 if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $values['field_name'])) { | |
249 throw new FieldException("Attempt to create a field storage {$values['field_name']} with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character"); | |
250 } | |
251 if (empty($values['type'])) { | |
252 throw new FieldException("Attempt to create a field storage {$values['field_name']} with no type."); | |
253 } | |
254 if (empty($values['entity_type'])) { | |
255 throw new FieldException("Attempt to create a field storage {$values['field_name']} with no entity_type."); | |
256 } | |
257 | |
258 parent::__construct($values, $entity_type); | |
259 } | |
260 | |
261 /** | |
262 * {@inheritdoc} | |
263 */ | |
264 public function id() { | |
265 return $this->getTargetEntityTypeId() . '.' . $this->getName(); | |
266 } | |
267 | |
268 /** | |
269 * Overrides \Drupal\Core\Entity\Entity::preSave(). | |
270 * | |
271 * @throws \Drupal\Core\Field\FieldException | |
272 * If the field definition is invalid. | |
273 * @throws \Drupal\Core\Entity\EntityStorageException | |
274 * In case of failures at the configuration storage level. | |
275 */ | |
276 public function preSave(EntityStorageInterface $storage) { | |
277 // Clear the derived data about the field. | |
278 unset($this->schema); | |
279 | |
280 // Filter out unknown settings and make sure all settings are present, so | |
281 // that a complete field definition is passed to the various hooks and | |
282 // written to config. | |
283 $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); | |
284 $default_settings = $field_type_manager->getDefaultStorageSettings($this->type); | |
285 $this->settings = array_intersect_key($this->settings, $default_settings) + $default_settings; | |
286 | |
287 if ($this->isNew()) { | |
288 $this->preSaveNew($storage); | |
289 } | |
290 else { | |
291 $this->preSaveUpdated($storage); | |
292 } | |
293 | |
294 parent::preSave($storage); | |
295 } | |
296 | |
297 /** | |
298 * Prepares saving a new field definition. | |
299 * | |
300 * @param \Drupal\Core\Entity\EntityStorageInterface $storage | |
301 * The entity storage. | |
302 * | |
303 * @throws \Drupal\Core\Field\FieldException | |
304 * If the field definition is invalid. | |
305 */ | |
306 protected function preSaveNew(EntityStorageInterface $storage) { | |
307 $entity_manager = \Drupal::entityManager(); | |
308 $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); | |
309 | |
310 // Assign the ID. | |
311 $this->id = $this->id(); | |
312 | |
313 // Field name cannot be longer than FieldStorageConfig::NAME_MAX_LENGTH characters. | |
314 // We use Unicode::strlen() because the DB layer assumes that column widths | |
315 // are given in characters rather than bytes. | |
316 if (Unicode::strlen($this->getName()) > static::NAME_MAX_LENGTH) { | |
317 throw new FieldException('Attempt to create a field storage with an name longer than ' . static::NAME_MAX_LENGTH . ' characters: ' . $this->getName()); | |
318 } | |
319 | |
320 // Disallow reserved field names. | |
321 $disallowed_field_names = array_keys($entity_manager->getBaseFieldDefinitions($this->getTargetEntityTypeId())); | |
322 if (in_array($this->getName(), $disallowed_field_names)) { | |
323 throw new FieldException("Attempt to create field storage {$this->getName()} which is reserved by entity type {$this->getTargetEntityTypeId()}."); | |
324 } | |
325 | |
326 // Check that the field type is known. | |
327 $field_type = $field_type_manager->getDefinition($this->getType(), FALSE); | |
328 if (!$field_type) { | |
329 throw new FieldException("Attempt to create a field storage of unknown type {$this->getType()}."); | |
330 } | |
331 $this->module = $field_type['provider']; | |
332 | |
333 // Notify the entity manager. | |
334 $entity_manager->onFieldStorageDefinitionCreate($this); | |
335 } | |
336 | |
337 /** | |
338 * {@inheritdoc} | |
339 */ | |
340 public function calculateDependencies() { | |
341 parent::calculateDependencies(); | |
342 // Ensure the field is dependent on the providing module. | |
343 $this->addDependency('module', $this->getTypeProvider()); | |
344 // Ask the field type for any additional storage dependencies. | |
345 // @see \Drupal\Core\Field\FieldItemInterface::calculateStorageDependencies() | |
346 $definition = \Drupal::service('plugin.manager.field.field_type')->getDefinition($this->getType(), FALSE); | |
347 $this->addDependencies($definition['class']::calculateStorageDependencies($this)); | |
348 | |
349 // Ensure the field is dependent on the provider of the entity type. | |
350 $entity_type = \Drupal::entityManager()->getDefinition($this->entity_type); | |
351 $this->addDependency('module', $entity_type->getProvider()); | |
352 return $this; | |
353 } | |
354 | |
355 /** | |
356 * Prepares saving an updated field definition. | |
357 * | |
358 * @param \Drupal\Core\Entity\EntityStorageInterface $storage | |
359 * The entity storage. | |
360 */ | |
361 protected function preSaveUpdated(EntityStorageInterface $storage) { | |
362 $module_handler = \Drupal::moduleHandler(); | |
363 $entity_manager = \Drupal::entityManager(); | |
364 | |
365 // Some updates are always disallowed. | |
366 if ($this->getType() != $this->original->getType()) { | |
367 throw new FieldException("Cannot change the field type for an existing field storage."); | |
368 } | |
369 if ($this->getTargetEntityTypeId() != $this->original->getTargetEntityTypeId()) { | |
370 throw new FieldException("Cannot change the entity type for an existing field storage."); | |
371 } | |
372 | |
373 // See if any module forbids the update by throwing an exception. This | |
374 // invokes hook_field_storage_config_update_forbid(). | |
375 $module_handler->invokeAll('field_storage_config_update_forbid', [$this, $this->original]); | |
376 | |
377 // Notify the entity manager. A listener can reject the definition | |
378 // update as invalid by raising an exception, which stops execution before | |
379 // the definition is written to config. | |
380 $entity_manager->onFieldStorageDefinitionUpdate($this, $this->original); | |
381 } | |
382 | |
383 /** | |
384 * {@inheritdoc} | |
385 */ | |
386 public function postSave(EntityStorageInterface $storage, $update = TRUE) { | |
387 if ($update) { | |
388 // Invalidate the render cache for all affected entities. | |
389 $entity_manager = \Drupal::entityManager(); | |
390 $entity_type = $this->getTargetEntityTypeId(); | |
391 if ($entity_manager->hasHandler($entity_type, 'view_builder')) { | |
392 $entity_manager->getViewBuilder($entity_type)->resetCache(); | |
393 } | |
394 } | |
395 } | |
396 | |
397 /** | |
398 * {@inheritdoc} | |
399 */ | |
400 public static function preDelete(EntityStorageInterface $storage, array $field_storages) { | |
401 $state = \Drupal::state(); | |
402 | |
403 // Set the static flag so that we don't delete field storages whilst | |
404 // deleting fields. | |
405 static::$inDeletion = TRUE; | |
406 | |
407 // Delete or fix any configuration that is dependent, for example, fields. | |
408 parent::preDelete($storage, $field_storages); | |
409 | |
410 // Keep the field definitions in the state storage so we can use them later | |
411 // during field_purge_batch(). | |
412 $deleted_storages = $state->get('field.storage.deleted') ?: []; | |
413 /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ | |
414 foreach ($field_storages as $field_storage) { | |
415 // Only mark a field for purging if there is data. Otherwise, just remove | |
416 // it. | |
417 $target_entity_storage = \Drupal::entityTypeManager()->getStorage($field_storage->getTargetEntityTypeId()); | |
418 if (!$field_storage->deleted && $target_entity_storage instanceof FieldableEntityStorageInterface && $target_entity_storage->countFieldData($field_storage, TRUE)) { | |
419 $config = $field_storage->toArray(); | |
420 $config['deleted'] = TRUE; | |
421 $config['bundles'] = $field_storage->getBundles(); | |
422 $deleted_storages[$field_storage->uuid()] = $config; | |
423 } | |
424 } | |
425 | |
426 $state->set('field.storage.deleted', $deleted_storages); | |
427 } | |
428 | |
429 /** | |
430 * {@inheritdoc} | |
431 */ | |
432 public static function postDelete(EntityStorageInterface $storage, array $fields) { | |
433 // Notify the storage. | |
434 foreach ($fields as $field) { | |
435 if (!$field->deleted) { | |
436 \Drupal::entityManager()->onFieldStorageDefinitionDelete($field); | |
437 $field->deleted = TRUE; | |
438 } | |
439 } | |
440 // Unset static flag. | |
441 static::$inDeletion = FALSE; | |
442 } | |
443 | |
444 /** | |
445 * {@inheritdoc} | |
446 */ | |
447 public function getSchema() { | |
448 if (!isset($this->schema)) { | |
449 // Get the schema from the field item class. | |
450 $class = $this->getFieldItemClass(); | |
451 $schema = $class::schema($this); | |
452 // Fill in default values for optional entries. | |
453 $schema += [ | |
454 'columns' => [], | |
455 'unique keys' => [], | |
456 'indexes' => [], | |
457 'foreign keys' => [], | |
458 ]; | |
459 | |
460 // Merge custom indexes with those specified by the field type. Custom | |
461 // indexes prevail. | |
462 $schema['indexes'] = $this->indexes + $schema['indexes']; | |
463 | |
464 $this->schema = $schema; | |
465 } | |
466 | |
467 return $this->schema; | |
468 } | |
469 | |
470 /** | |
471 * {@inheritdoc} | |
472 */ | |
473 public function hasCustomStorage() { | |
474 return $this->custom_storage; | |
475 } | |
476 | |
477 /** | |
478 * {@inheritdoc} | |
479 */ | |
480 public function isBaseField() { | |
481 return FALSE; | |
482 } | |
483 | |
484 /** | |
485 * {@inheritdoc} | |
486 */ | |
487 public function getColumns() { | |
488 $schema = $this->getSchema(); | |
489 // A typical use case for the method is to iterate on the columns, while | |
490 // some other use cases rely on identifying the first column with the key() | |
491 // function. Since the schema is persisted in the Field object, we take care | |
492 // of resetting the array pointer so that the former does not interfere with | |
493 // the latter. | |
494 reset($schema['columns']); | |
495 return $schema['columns']; | |
496 } | |
497 | |
498 /** | |
499 * {@inheritdoc} | |
500 */ | |
501 public function getBundles() { | |
502 if (!$this->isDeleted()) { | |
503 $map = \Drupal::entityManager()->getFieldMap(); | |
504 if (isset($map[$this->getTargetEntityTypeId()][$this->getName()]['bundles'])) { | |
505 return $map[$this->getTargetEntityTypeId()][$this->getName()]['bundles']; | |
506 } | |
507 } | |
508 return []; | |
509 } | |
510 | |
511 /** | |
512 * {@inheritdoc} | |
513 */ | |
514 public function getName() { | |
515 return $this->field_name; | |
516 } | |
517 | |
518 /** | |
519 * {@inheritdoc} | |
520 */ | |
521 public function isDeleted() { | |
522 return $this->deleted; | |
523 } | |
524 | |
525 /** | |
526 * {@inheritdoc} | |
527 */ | |
528 public function getTypeProvider() { | |
529 return $this->module; | |
530 } | |
531 | |
532 /** | |
533 * {@inheritdoc} | |
534 */ | |
535 public function getType() { | |
536 return $this->type; | |
537 } | |
538 | |
539 /** | |
540 * {@inheritdoc} | |
541 */ | |
542 public function getSettings() { | |
543 // @todo FieldTypePluginManager maintains its own static cache. However, do | |
544 // some CPU and memory profiling to see if it's worth statically caching | |
545 // $field_type_info, or the default field storage and field settings, | |
546 // within $this. | |
547 $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); | |
548 | |
549 $settings = $field_type_manager->getDefaultStorageSettings($this->getType()); | |
550 return $this->settings + $settings; | |
551 } | |
552 | |
553 /** | |
554 * {@inheritdoc} | |
555 */ | |
556 public function getSetting($setting_name) { | |
557 // @todo See getSettings() about potentially statically caching this. | |
558 // We assume here that one call to array_key_exists() is more efficient | |
559 // than calling getSettings() when all we need is a single setting. | |
560 if (array_key_exists($setting_name, $this->settings)) { | |
561 return $this->settings[$setting_name]; | |
562 } | |
563 $settings = $this->getSettings(); | |
564 if (array_key_exists($setting_name, $settings)) { | |
565 return $settings[$setting_name]; | |
566 } | |
567 else { | |
568 return NULL; | |
569 } | |
570 } | |
571 | |
572 /** | |
573 * {@inheritdoc} | |
574 */ | |
575 public function setSetting($setting_name, $value) { | |
576 $this->settings[$setting_name] = $value; | |
577 return $this; | |
578 } | |
579 | |
580 /** | |
581 * {@inheritdoc} | |
582 */ | |
583 public function setSettings(array $settings) { | |
584 $this->settings = $settings + $this->settings; | |
585 return $this; | |
586 } | |
587 | |
588 /** | |
589 * {@inheritdoc} | |
590 */ | |
591 public function isTranslatable() { | |
592 return $this->translatable; | |
593 } | |
594 | |
595 /** | |
596 * {@inheritdoc} | |
597 */ | |
598 public function isRevisionable() { | |
599 // All configurable fields are revisionable. | |
600 return TRUE; | |
601 } | |
602 | |
603 /** | |
604 * {@inheritdoc} | |
605 */ | |
606 public function setTranslatable($translatable) { | |
607 $this->translatable = $translatable; | |
608 return $this; | |
609 } | |
610 | |
611 /** | |
612 * {@inheritdoc} | |
613 */ | |
614 public function getProvider() { | |
615 return 'field'; | |
616 } | |
617 | |
618 /** | |
619 * {@inheritdoc} | |
620 */ | |
621 public function getLabel() { | |
622 return $this->label(); | |
623 } | |
624 | |
625 /** | |
626 * {@inheritdoc} | |
627 */ | |
628 public function getDescription() { | |
629 return NULL; | |
630 } | |
631 | |
632 /** | |
633 * {@inheritdoc} | |
634 */ | |
635 public function getCardinality() { | |
636 /** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */ | |
637 $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); | |
638 $definition = $field_type_manager->getDefinition($this->getType()); | |
639 $enforced_cardinality = isset($definition['cardinality']) ? $definition['cardinality'] : NULL; | |
640 | |
641 // Enforced cardinality is a positive integer or -1. | |
642 if ($enforced_cardinality !== NULL && $enforced_cardinality < 1 && $enforced_cardinality !== FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) { | |
643 throw new FieldException("Invalid enforced cardinality '$enforced_cardinality'. Allowed values: a positive integer or -1."); | |
644 } | |
645 | |
646 return $enforced_cardinality ?: $this->cardinality; | |
647 } | |
648 | |
649 /** | |
650 * {@inheritdoc} | |
651 */ | |
652 public function setCardinality($cardinality) { | |
653 $this->cardinality = $cardinality; | |
654 return $this; | |
655 } | |
656 | |
657 /** | |
658 * {@inheritdoc} | |
659 */ | |
660 public function getOptionsProvider($property_name, FieldableEntityInterface $entity) { | |
661 // If the field item class implements the interface, create an orphaned | |
662 // runtime item object, so that it can be used as the options provider | |
663 // without modifying the entity being worked on. | |
664 if (is_subclass_of($this->getFieldItemClass(), OptionsProviderInterface::class)) { | |
665 $items = $entity->get($this->getName()); | |
666 return \Drupal::service('plugin.manager.field.field_type')->createFieldItem($items, 0); | |
667 } | |
668 // @todo: Allow setting custom options provider, see | |
669 // https://www.drupal.org/node/2002138. | |
670 } | |
671 | |
672 /** | |
673 * {@inheritdoc} | |
674 */ | |
675 public function isMultiple() { | |
676 $cardinality = $this->getCardinality(); | |
677 return ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) || ($cardinality > 1); | |
678 } | |
679 | |
680 /** | |
681 * {@inheritdoc} | |
682 */ | |
683 public function isLocked() { | |
684 return $this->locked; | |
685 } | |
686 | |
687 /** | |
688 * {@inheritdoc} | |
689 */ | |
690 public function setLocked($locked) { | |
691 $this->locked = $locked; | |
692 return $this; | |
693 } | |
694 | |
695 /** | |
696 * {@inheritdoc} | |
697 */ | |
698 public function getTargetEntityTypeId() { | |
699 return $this->entity_type; | |
700 } | |
701 | |
702 /** | |
703 * {@inheritdoc} | |
704 */ | |
705 public function isQueryable() { | |
706 return TRUE; | |
707 } | |
708 | |
709 /** | |
710 * Determines whether a field has any data. | |
711 * | |
712 * @return bool | |
713 * TRUE if the field has data for any entity; FALSE otherwise. | |
714 */ | |
715 public function hasData() { | |
716 return \Drupal::entityManager()->getStorage($this->entity_type)->countFieldData($this, TRUE); | |
717 } | |
718 | |
719 /** | |
720 * Implements the magic __sleep() method. | |
721 * | |
722 * Using the Serialize interface and serialize() / unserialize() methods | |
723 * breaks entity forms in PHP 5.4. | |
724 * @todo Investigate in https://www.drupal.org/node/2074253. | |
725 */ | |
726 public function __sleep() { | |
727 // Only serialize necessary properties, excluding those that can be | |
728 // recalculated. | |
729 $properties = get_object_vars($this); | |
730 unset($properties['schema'], $properties['propertyDefinitions'], $properties['original']); | |
731 return array_keys($properties); | |
732 } | |
733 | |
734 /** | |
735 * {@inheritdoc} | |
736 */ | |
737 public function getConstraints() { | |
738 return []; | |
739 } | |
740 | |
741 /** | |
742 * {@inheritdoc} | |
743 */ | |
744 public function getConstraint($constraint_name) { | |
745 return NULL; | |
746 } | |
747 | |
748 /** | |
749 * {@inheritdoc} | |
750 */ | |
751 public function getPropertyDefinition($name) { | |
752 if (!isset($this->propertyDefinitions)) { | |
753 $this->getPropertyDefinitions(); | |
754 } | |
755 if (isset($this->propertyDefinitions[$name])) { | |
756 return $this->propertyDefinitions[$name]; | |
757 } | |
758 } | |
759 | |
760 /** | |
761 * {@inheritdoc} | |
762 */ | |
763 public function getPropertyDefinitions() { | |
764 if (!isset($this->propertyDefinitions)) { | |
765 $class = $this->getFieldItemClass(); | |
766 $this->propertyDefinitions = $class::propertyDefinitions($this); | |
767 } | |
768 return $this->propertyDefinitions; | |
769 } | |
770 | |
771 /** | |
772 * {@inheritdoc} | |
773 */ | |
774 public function getPropertyNames() { | |
775 return array_keys($this->getPropertyDefinitions()); | |
776 } | |
777 | |
778 /** | |
779 * {@inheritdoc} | |
780 */ | |
781 public function getMainPropertyName() { | |
782 $class = $this->getFieldItemClass(); | |
783 return $class::mainPropertyName(); | |
784 } | |
785 | |
786 /** | |
787 * {@inheritdoc} | |
788 */ | |
789 public function getUniqueStorageIdentifier() { | |
790 return $this->uuid(); | |
791 } | |
792 | |
793 /** | |
794 * Helper to retrieve the field item class. | |
795 */ | |
796 protected function getFieldItemClass() { | |
797 $type_definition = \Drupal::typedDataManager() | |
798 ->getDefinition('field_item:' . $this->getType()); | |
799 return $type_definition['class']; | |
800 } | |
801 | |
802 /** | |
803 * Loads a field config entity based on the entity type and field name. | |
804 * | |
805 * @param string $entity_type_id | |
806 * ID of the entity type. | |
807 * @param string $field_name | |
808 * Name of the field. | |
809 * | |
810 * @return static | |
811 * The field config entity if one exists for the provided field name, | |
812 * otherwise NULL. | |
813 */ | |
814 public static function loadByName($entity_type_id, $field_name) { | |
815 return \Drupal::entityManager()->getStorage('field_storage_config')->load($entity_type_id . '.' . $field_name); | |
816 } | |
817 | |
818 /** | |
819 * {@inheritdoc} | |
820 */ | |
821 public function isDeletable() { | |
822 // The field storage is not deleted, is configured to be removed when there | |
823 // are no fields, the field storage has no bundles, and field storages are | |
824 // not in the process of being deleted. | |
825 return !$this->deleted && !$this->persist_with_no_fields && count($this->getBundles()) == 0 && !static::$inDeletion; | |
826 } | |
827 | |
828 /** | |
829 * {@inheritdoc} | |
830 */ | |
831 public function getIndexes() { | |
832 return $this->indexes; | |
833 } | |
834 | |
835 /** | |
836 * {@inheritdoc} | |
837 */ | |
838 public function setIndexes(array $indexes) { | |
839 $this->indexes = $indexes; | |
840 return $this; | |
841 } | |
842 | |
843 } |