f20f3a503be99ede6eb78293f4774c4820b1c38d
[yaffs-website] / web / core / lib / Drupal / Core / Field / Entity / BaseFieldOverride.php
1 <?php
2
3 namespace Drupal\Core\Field\Entity;
4
5 use Drupal\Core\Entity\EntityStorageInterface;
6 use Drupal\Core\Field\BaseFieldDefinition;
7 use Drupal\Core\Field\FieldConfigBase;
8 use Drupal\Core\Field\FieldException;
9
10 /**
11  * Defines the base field override entity.
12  *
13  * Allows base fields to be overridden on the bundle level.
14  *
15  * @ConfigEntityType(
16  *   id = "base_field_override",
17  *   label = @Translation("Base field override"),
18  *   handlers = {
19  *     "storage" = "Drupal\Core\Field\BaseFieldOverrideStorage",
20  *     "access" = "Drupal\Core\Field\BaseFieldOverrideAccessControlHandler",
21  *   },
22  *   config_prefix = "base_field_override",
23  *   entity_keys = {
24  *     "id" = "id",
25  *     "label" = "label"
26  *   },
27  *   config_export = {
28  *     "id",
29  *     "field_name",
30  *     "entity_type",
31  *     "bundle",
32  *     "label",
33  *     "description",
34  *     "required",
35  *     "translatable",
36  *     "default_value",
37  *     "default_value_callback",
38  *     "settings",
39  *     "field_type",
40  *   }
41  * )
42  */
43 class BaseFieldOverride extends FieldConfigBase {
44
45   /**
46    * The base field definition.
47    *
48    * @var \Drupal\Core\Field\BaseFieldDefinition
49    */
50   protected $baseFieldDefinition;
51
52   /**
53    * Creates a base field override object.
54    *
55    * @param \Drupal\Core\Field\BaseFieldDefinition $base_field_definition
56    *   The base field definition to override.
57    * @param string $bundle
58    *   The bundle to which the override applies.
59    *
60    * @return \Drupal\Core\Field\Entity\BaseFieldOverride
61    *   A new base field override object.
62    */
63   public static function createFromBaseFieldDefinition(BaseFieldDefinition $base_field_definition, $bundle) {
64     $values = $base_field_definition->toArray();
65     $values['bundle'] = $bundle;
66     $values['baseFieldDefinition'] = $base_field_definition;
67     return \Drupal::entityManager()->getStorage('base_field_override')->create($values);
68   }
69
70   /**
71    * Constructs a BaseFieldOverride object.
72    *
73    * In most cases, base field override entities are created via
74    * BaseFieldOverride::createFromBaseFieldDefinition($definition, 'bundle')
75    *
76    * @param array $values
77    *   An array of base field bundle override properties, keyed by property
78    *   name. The field to override is specified by referring to an existing
79    *   field with:
80    *   - field_name: The field name.
81    *   - entity_type: The entity type.
82    *   Additionally, a 'bundle' property is required to indicate the entity
83    *   bundle to which the bundle field override is attached to. Other array
84    *   elements will be used to set the corresponding properties on the class;
85    *   see the class property documentation for details.
86    * @param string $entity_type
87    *   (optional) The type of the entity to create. Defaults to
88    *   'base_field_override'.
89    *
90    * @see entity_create()
91    *
92    * @throws \Drupal\Core\Field\FieldException
93    *   Exception thrown if $values does not contain a field_name, entity_type or
94    *   bundle value.
95    */
96   public function __construct(array $values, $entity_type = 'base_field_override') {
97     if (empty($values['field_name'])) {
98       throw new FieldException('Attempt to create a base field bundle override of a field without a field_name');
99     }
100     if (empty($values['entity_type'])) {
101       throw new FieldException("Attempt to create a base field bundle override of field {$values['field_name']} without an entity_type");
102     }
103     if (empty($values['bundle'])) {
104       throw new FieldException("Attempt to create a base field bundle override of field {$values['field_name']} without a bundle");
105     }
106
107     parent::__construct($values, $entity_type);
108   }
109
110   /**
111    * {@inheritdoc}
112    */
113   public function getFieldStorageDefinition() {
114     return $this->getBaseFieldDefinition()->getFieldStorageDefinition();
115   }
116
117   /**
118    * {@inheritdoc}
119    */
120   public function isDisplayConfigurable($context) {
121     return $this->getBaseFieldDefinition()->isDisplayConfigurable($context);
122   }
123
124   /**
125    * {@inheritdoc}
126    */
127   public function getDisplayOptions($display_context) {
128     return $this->getBaseFieldDefinition()->getDisplayOptions($display_context);
129   }
130
131   /**
132    * {@inheritdoc}
133    */
134   public function isReadOnly() {
135     return $this->getBaseFieldDefinition()->isReadOnly();
136   }
137
138   /**
139    * {@inheritdoc}
140    */
141   public function isComputed() {
142     return $this->getBaseFieldDefinition()->isComputed();
143   }
144
145   /**
146    * Gets the base field definition.
147    *
148    * @return \Drupal\Core\Field\BaseFieldDefinition
149    */
150   protected function getBaseFieldDefinition() {
151     if (!isset($this->baseFieldDefinition)) {
152       $fields = $this->entityManager()->getBaseFieldDefinitions($this->entity_type);
153       $this->baseFieldDefinition = $fields[$this->getName()];
154     }
155     return $this->baseFieldDefinition;
156   }
157
158   /**
159    * {@inheritdoc}
160    *
161    * @throws \Drupal\Core\Field\FieldException
162    *   If the bundle is being changed.
163    */
164   public function preSave(EntityStorageInterface $storage) {
165     // Filter out unknown settings and make sure all settings are present, so
166     // that a complete field definition is passed to the various hooks and
167     // written to config.
168     $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
169     $default_settings = $field_type_manager->getDefaultFieldSettings($this->getType());
170     $this->settings = array_intersect_key($this->settings, $default_settings) + $default_settings;
171
172     // Call the parent's presave method to perform validate and calculate
173     // dependencies.
174     parent::preSave($storage);
175
176     if ($this->isNew()) {
177       // @todo This assumes that the previous definition isn't some
178       //   non-config-based override, but that might not be the case:
179       //   https://www.drupal.org/node/2321071.
180       $previous_definition = $this->getBaseFieldDefinition();
181     }
182     else {
183       // Some updates are always disallowed.
184       if ($this->entity_type != $this->original->entity_type) {
185         throw new FieldException("Cannot change the entity_type of an existing base field bundle override (entity type:{$this->entity_type}, bundle:{$this->original->bundle}, field name: {$this->field_name})");
186       }
187       if ($this->bundle != $this->original->bundle) {
188         throw new FieldException("Cannot change the bundle of an existing base field bundle override (entity type:{$this->entity_type}, bundle:{$this->original->bundle}, field name: {$this->field_name})");
189       }
190       $previous_definition = $this->original;
191     }
192     // Notify the entity storage.
193     $this->entityManager()->getStorage($this->getTargetEntityTypeId())->onFieldDefinitionUpdate($this, $previous_definition);
194   }
195
196   /**
197    * {@inheritdoc}
198    */
199   public static function postDelete(EntityStorageInterface $storage, array $field_overrides) {
200     $entity_manager = \Drupal::entityManager();
201     // Clear the cache upfront, to refresh the results of getBundles().
202     $entity_manager->clearCachedFieldDefinitions();
203     /** @var \Drupal\Core\Field\Entity\BaseFieldOverride $field_override */
204     foreach ($field_overrides as $field_override) {
205       // Inform the system that the field definition is being updated back to
206       // its non-overridden state.
207       // @todo This assumes that there isn't a non-config-based override that
208       //   we're returning to, but that might not be the case:
209       //   https://www.drupal.org/node/2321071.
210       $entity_manager->getStorage($field_override->getTargetEntityTypeId())->onFieldDefinitionUpdate($field_override->getBaseFieldDefinition(), $field_override);
211     }
212   }
213
214   /**
215    * Loads a base field bundle override config entity.
216    *
217    * @param string $entity_type_id
218    *   ID of the entity type.
219    * @param string $bundle
220    *   Bundle name.
221    * @param string $field_name
222    *   Name of the field.
223    *
224    * @return static
225    *   The base field bundle override config entity if one exists for the
226    *   provided field name, otherwise NULL.
227    */
228   public static function loadByName($entity_type_id, $bundle, $field_name) {
229     return \Drupal::entityManager()->getStorage('base_field_override')->load($entity_type_id . '.' . $bundle . '.' . $field_name);
230   }
231
232   /**
233    * Implements the magic __sleep() method.
234    */
235   public function __sleep() {
236     // Only serialize necessary properties, excluding those that can be
237     // recalculated.
238     unset($this->baseFieldDefinition);
239     return parent::__sleep();
240   }
241
242 }