BaseFieldOverride.php 8.08 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
<?php

/**
 * @file
 * Contains \Drupal\Core\Field\Entity\BaseFieldOverride.
 */

namespace Drupal\Core\Field\Entity;

use Drupal\Component\Utility\String;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\BaseFieldDefinition;
13 14
use Drupal\Core\Field\FieldConfigBase;
use Drupal\Core\Field\FieldException;
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82

/**
 * Defines the base field override entity.
 *
 * Allows base fields to be overridden on the bundle level.
 *
 * @ConfigEntityType(
 *   id = "base_field_override",
 *   label = @Translation("Base field override"),
 *   controllers = {
 *     "storage" = "Drupal\Core\Field\BaseFieldOverrideStorage"
 *   },
 *   config_prefix = "base_field_override",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label"
 *   }
 * )
 */
class BaseFieldOverride extends FieldConfigBase {

  /**
   * The base field definition.
   *
   * @var \Drupal\Core\Field\BaseFieldDefinition
   */
  protected $baseFieldDefinition;

  /**
   * Creates a base field override object.
   *
   * @param \Drupal\Core\Field\BaseFieldDefinition $base_field_definition
   *   The base field definition to override.
   * @param string $bundle
   *   The bundle to which the override applies.
   *
   * @return \Drupal\Core\Field\Entity\BaseFieldOverride
   *   A new base field override object.
   */
  public static function createFromBaseFieldDefinition(BaseFieldDefinition $base_field_definition, $bundle) {
    $values = $base_field_definition->toArray();
    $values['bundle'] = $bundle;
    $values['baseFieldDefinition'] = $base_field_definition;
    return \Drupal::entityManager()->getStorage('base_field_override')->create($values);
  }

  /**
   * Constructs a BaseFieldOverride object.
   *
   * In most cases, base field override entities are created via
   * BaseFieldOverride::createFromBaseFieldDefinition($definition, 'bundle')
   *
   * @param array $values
   *   An array of base field bundle override properties, keyed by property
   *   name. The field to override is specified by referring to an existing
   *   field with:
   *   - field_name: The field name.
   *   - entity_type: The entity type.
   *   Additionally, a 'bundle' property is required to indicate the entity
   *   bundle to which the bundle field override is attached to. Other array
   *   elements will be used to set the corresponding properties on the class;
   *   see the class property documentation for details.
   * @param string $entity_type
   *   (optional) The type of the entity to create. Defaults to
   *   'base_field_override'.
   *
   * @see entity_create()
   *
83
   * @throws \Drupal\Core\Field\FieldException
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
   *   Exception thrown if $values does not contain a field_name, entity_type or
   *   bundle value.
   */
  public function __construct(array $values, $entity_type = 'base_field_override') {
    if (empty($values['field_name'])) {
      throw new FieldException('Attempt to create a base field bundle override of a field without a field_name');
    }
    if (empty($values['entity_type'])) {
      throw new FieldException(String::format('Attempt to create a base field bundle override of field @field_name without an entity_type', array('@field_name' => $values['field_name'])));
    }
    if (empty($values['bundle'])) {
      throw new FieldException(String::format('Attempt to create a base field bundle override of field @field_name without a bundle', array('@field_name' => $values['field_name'])));
    }

    parent::__construct($values, $entity_type);
  }

  /**
   * {@inheritdoc}
   */
  public function getFieldStorageDefinition() {
    return $this->getBaseFieldDefinition()->getFieldStorageDefinition();
  }

  /**
   * {@inheritdoc}
   */
  public function isDisplayConfigurable($context) {
    return $this->getBaseFieldDefinition()->isDisplayConfigurable($context);
  }

  /**
   * {@inheritdoc}
   */
  public function getDisplayOptions($display_context) {
    return $this->getBaseFieldDefinition()->getDisplayOptions($display_context);
  }

  /**
   * {@inheritdoc}
   */
  public function isReadOnly() {
    return $this->getBaseFieldDefinition()->isReadOnly();
  }

  /**
   * {@inheritdoc}
   */
  public function isComputed() {
    return $this->getBaseFieldDefinition()->isComputed();
  }

  /**
   * Gets the base field definition.
   *
   * @return \Drupal\Core\Field\BaseFieldDefinition
   */
  protected function getBaseFieldDefinition() {
    if (!isset($this->baseFieldDefinition)) {
      $fields = $this->entityManager()->getBaseFieldDefinitions($this->entity_type);
      $this->baseFieldDefinition = $fields[$this->getName()];
    }
    return $this->baseFieldDefinition;
  }

  /**
   * {@inheritdoc}
   *
152
   * @throws \Drupal\Core\Field\FieldException
153 154 155 156 157
   *   If the bundle is being changed and
   *   BaseFieldOverride::allowBundleRename() has not been called.
   */
  public function preSave(EntityStorageInterface $storage) {
    // Set the default instance settings.
158
    $this->settings += \Drupal::service('plugin.manager.field.field_type')->getDefaultFieldSettings($this->getType());
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230

    // Call the parent's presave method to perform validate and calculate
    // dependencies.
    parent::preSave($storage);

    if ($this->isNew()) {
      // @todo This assumes that the previous definition isn't some
      //   non-config-based override, but that might not be the case:
      //   https://www.drupal.org/node/2321071.
      $previous_definition = $this->getBaseFieldDefinition();
    }
    else {
      // Some updates are always disallowed.
      if ($this->entity_type != $this->original->entity_type) {
        throw new FieldException(String::format('Cannot change the entity_type of an existing base field bundle override (entity type:@entity_type, bundle:@bundle, field name: @field_name)', array('@field_name' => $this->field_name, '@entity_type' => $this->entity_type, '@bundle' => $this->original->bundle)));
      }
      if ($this->bundle != $this->original->bundle && empty($this->bundleRenameAllowed)) {
        throw new FieldException(String::format('Cannot change the bundle of an existing base field bundle override (entity type:@entity_type, bundle:@bundle, field name: @field_name)', array('@field_name' => $this->field_name, '@entity_type' => $this->entity_type, '@bundle' => $this->original->bundle)));
      }
      $previous_definition = $this->original;
    }
    // Notify the entity storage.
    $this->entityManager()->getStorage($this->getTargetEntityTypeId())->onFieldDefinitionUpdate($this, $previous_definition);
  }

  /**
   * {@inheritdoc}
   */
  public static function postDelete(EntityStorageInterface $storage, array $field_overrides) {
    $entity_manager = \Drupal::entityManager();
    // Clear the cache upfront, to refresh the results of getBundles().
    $entity_manager->clearCachedFieldDefinitions();
    /** @var \Drupal\Core\Field\Entity\BaseFieldOverride $field_override */
    foreach ($field_overrides as $field_override) {
      // Inform the system that the field definition is being updated back to
      // its non-overridden state.
      // @todo This assumes that there isn't a non-config-based override that
      //   we're returning to, but that might not be the case:
      //   https://www.drupal.org/node/2321071.
      $entity_manager->getStorage($field_override->getTargetEntityTypeId())->onFieldDefinitionUpdate($field_override->getBaseFieldDefinition(), $field_override);
    }
  }

  /**
   * Loads a base field bundle override config entity.
   *
   * @param string $entity_type_id
   *   ID of the entity type.
   * @param string $bundle
   *   Bundle name.
   * @param string $field_name
   *   Name of the field.
   *
   * @return static
   *   The base field bundle override config entity if one exists for the
   *   provided field name, otherwise NULL.
   */
  public static function loadByName($entity_type_id, $bundle, $field_name) {
    return \Drupal::entityManager()->getStorage('base_field_override')->load($entity_type_id . '.' . $bundle . '.' . $field_name);
  }

  /**
   * Implements the magic __sleep() method.
   */
  public function __sleep() {
    // Only serialize necessary properties, excluding those that can be
    // recalculated.
    unset($this->baseFieldDefinition);
    return parent::__sleep();
  }

}