b31833a728b3202df81697f0cca2ecd809b2c6ff
[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    * {@inheritdoc}
147    */
148   public function getClass() {
149     return $this->getBaseFieldDefinition()->getClass();
150   }
151
152   /**
153    * Gets the base field definition.
154    *
155    * @return \Drupal\Core\Field\BaseFieldDefinition
156    */
157   protected function getBaseFieldDefinition() {
158     if (!isset($this->baseFieldDefinition)) {
159       $fields = $this->entityManager()->getBaseFieldDefinitions($this->entity_type);
160       $this->baseFieldDefinition = $fields[$this->getName()];
161     }
162     return $this->baseFieldDefinition;
163   }
164
165   /**
166    * {@inheritdoc}
167    *
168    * @throws \Drupal\Core\Field\FieldException
169    *   If the bundle is being changed.
170    */
171   public function preSave(EntityStorageInterface $storage) {
172     // Filter out unknown settings and make sure all settings are present, so
173     // that a complete field definition is passed to the various hooks and
174     // written to config.
175     $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
176     $default_settings = $field_type_manager->getDefaultFieldSettings($this->getType());
177     $this->settings = array_intersect_key($this->settings, $default_settings) + $default_settings;
178
179     // Call the parent's presave method to perform validate and calculate
180     // dependencies.
181     parent::preSave($storage);
182
183     if ($this->isNew()) {
184       // @todo This assumes that the previous definition isn't some
185       //   non-config-based override, but that might not be the case:
186       //   https://www.drupal.org/node/2321071.
187       $previous_definition = $this->getBaseFieldDefinition();
188     }
189     else {
190       // Some updates are always disallowed.
191       if ($this->entity_type != $this->original->entity_type) {
192         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})");
193       }
194       if ($this->bundle != $this->original->bundle) {
195         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})");
196       }
197       $previous_definition = $this->original;
198     }
199     // Notify the entity storage.
200     $this->entityManager()->getStorage($this->getTargetEntityTypeId())->onFieldDefinitionUpdate($this, $previous_definition);
201   }
202
203   /**
204    * {@inheritdoc}
205    */
206   public static function postDelete(EntityStorageInterface $storage, array $field_overrides) {
207     $entity_manager = \Drupal::entityManager();
208     // Clear the cache upfront, to refresh the results of getBundles().
209     $entity_manager->clearCachedFieldDefinitions();
210     /** @var \Drupal\Core\Field\Entity\BaseFieldOverride $field_override */
211     foreach ($field_overrides as $field_override) {
212       // Inform the system that the field definition is being updated back to
213       // its non-overridden state.
214       // @todo This assumes that there isn't a non-config-based override that
215       //   we're returning to, but that might not be the case:
216       //   https://www.drupal.org/node/2321071.
217       $entity_manager->getStorage($field_override->getTargetEntityTypeId())->onFieldDefinitionUpdate($field_override->getBaseFieldDefinition(), $field_override);
218     }
219   }
220
221   /**
222    * Loads a base field bundle override config entity.
223    *
224    * @param string $entity_type_id
225    *   ID of the entity type.
226    * @param string $bundle
227    *   Bundle name.
228    * @param string $field_name
229    *   Name of the field.
230    *
231    * @return static
232    *   The base field bundle override config entity if one exists for the
233    *   provided field name, otherwise NULL.
234    */
235   public static function loadByName($entity_type_id, $bundle, $field_name) {
236     return \Drupal::entityManager()->getStorage('base_field_override')->load($entity_type_id . '.' . $bundle . '.' . $field_name);
237   }
238
239   /**
240    * Implements the magic __sleep() method.
241    */
242   public function __sleep() {
243     // Only serialize necessary properties, excluding those that can be
244     // recalculated.
245     unset($this->baseFieldDefinition);
246     return parent::__sleep();
247   }
248
249 }