ContentEntityStorageBase.php 6.04 KB
Newer Older
1 2 3 4
<?php

/**
 * @file
5
 * Contains \Drupal\Core\Entity\ContentEntityStorageBase.
6 7 8 9
 */

namespace Drupal\Core\Entity;

10
use Drupal\Component\Utility\String;
11 12
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
13
use Symfony\Component\DependencyInjection\ContainerInterface;
14

15
abstract class ContentEntityStorageBase extends EntityStorageBase implements FieldableEntityStorageInterface {
16

17 18 19 20 21 22 23 24
  /**
   * The entity bundle key.
   *
   * @var string|bool
   */
  protected $bundleKey = FALSE;

  /**
25
   * Constructs a ContentEntityStorageBase object.
26
   *
27 28
   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
   *   The entity type definition.
29
   */
30 31
  public function __construct(EntityTypeInterface $entity_type) {
    parent::__construct($entity_type);
32

33
    $this->bundleKey = $this->entityType->getKey('bundle');
34 35 36 37 38
  }

  /**
   * {@inheritdoc}
   */
39
  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
40
    return new static(
41
      $entity_type
42 43 44 45 46 47
    );
  }

  /**
   * {@inheritdoc}
   */
48
  protected function doCreate(array $values) {
49 50 51 52
    // We have to determine the bundle first.
    $bundle = FALSE;
    if ($this->bundleKey) {
      if (!isset($values[$this->bundleKey])) {
53
        throw new EntityStorageException(String::format('Missing bundle for entity type @type', array('@type' => $this->entityTypeId)));
54 55 56
      }
      $bundle = $values[$this->bundleKey];
    }
57
    $entity = new $this->entityClass(array(), $this->entityTypeId, $bundle);
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

    foreach ($entity as $name => $field) {
      if (isset($values[$name])) {
        $entity->$name = $values[$name];
      }
      elseif (!array_key_exists($name, $values)) {
        $entity->get($name)->applyDefaultValue();
      }
      unset($values[$name]);
    }

    // Set any passed values for non-defined fields also.
    foreach ($values as $name => $value) {
      $entity->$name = $value;
    }
    return $entity;
  }

76 77 78
  /**
   * {@inheritdoc}
   */
79
  public function onFieldStorageDefinitionCreate(FieldStorageDefinitionInterface $storage_definition) { }
80 81 82 83

  /**
   * {@inheritdoc}
   */
84
  public function onFieldStorageDefinitionUpdate(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original) { }
85 86 87 88

  /**
   * {@inheritdoc}
   */
89
  public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $storage_definition) { }
90 91 92 93

  /**
   * {@inheritdoc}
   */
94
  public function onFieldDefinitionCreate(FieldDefinitionInterface $field_definition) { }
95 96 97 98

  /**
   * {@inheritdoc}
   */
99
  public function onFieldDefinitionUpdate(FieldDefinitionInterface $field_definition, FieldDefinitionInterface $original) { }
100 101 102 103

  /**
   * {@inheritdoc}
   */
104
  public function onFieldDefinitionDelete(FieldDefinitionInterface $field_definition) { }
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123

  /**
   * {@inheritdoc}
   */
  public function onBundleCreate($bundle) { }

  /**
   * {@inheritdoc}
   */
  public function onBundleRename($bundle, $bundle_new) { }

  /**
   * {@inheritdoc}
   */
  public function onBundleDelete($bundle) { }

  /**
   * {@inheritdoc}
   */
124 125 126 127
  public function purgeFieldData(FieldDefinitionInterface $field_definition, $batch_size) {
    $items_by_entity = $this->readFieldItemsToPurge($field_definition, $batch_size);

    foreach ($items_by_entity as $items) {
128
      $items->delete();
129
      $this->purgeFieldItems($items->getEntity(), $field_definition);
130
    }
131
    return count($items_by_entity);
132 133 134
  }

  /**
135
   * Reads values to be purged for a single field.
136 137
   *
   * This method is called during field data purge, on fields for which
138
   * onFieldDelete() or onFieldDelete() has previously run.
139
   *
140 141 142 143
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
   *   The field definition.
   * @param $batch_size
   *   The maximum number of field data records to purge before returning.
144
   *
145 146
   * @return \Drupal\Core\Field\FieldItemListInterface[]
   *   An array of field item lists, keyed by entity revision id.
147
   */
148
  abstract protected function readFieldItemsToPurge(FieldDefinitionInterface $field_definition, $batch_size);
149 150

  /**
151
   * Removes field items from storage per entity during purge.
152
   *
153 154 155
   * @param ContentEntityInterface $entity
   *   The entity revision, whose values are being purged.
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
156 157
   *   The field whose values are bing purged.
   */
158
  abstract protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefinitionInterface $field_definition);
159 160 161 162

  /**
   * {@inheritdoc}
   */
163
  public function finalizePurge(FieldStorageDefinitionInterface $storage_definition) { }
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
  /**
   * Checks translation statuses and invoke the related hooks if needed.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity being saved.
   */
  protected function invokeTranslationHooks(ContentEntityInterface $entity) {
    $translations = $entity->getTranslationLanguages(FALSE);
    $original_translations = $entity->original->getTranslationLanguages(FALSE);
    $all_translations = array_keys($translations + $original_translations);

    // Notify modules of translation insertion/deletion.
    foreach ($all_translations as $langcode) {
      if (isset($translations[$langcode]) && !isset($original_translations[$langcode])) {
        $this->invokeHook('translation_insert', $entity->getTranslation($langcode));
      }
      elseif (!isset($translations[$langcode]) && isset($original_translations[$langcode])) {
        $this->invokeHook('translation_delete', $entity->getTranslation($langcode));
      }
    }
  }

  /**
   * Invokes a method on the Field objects within an entity.
   *
   * @param string $method
   *   The method name.
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity object.
   */
  protected function invokeFieldMethod($method, ContentEntityInterface $entity) {
    foreach (array_keys($entity->getTranslationLanguages()) as $langcode) {
      $translation = $entity->getTranslation($langcode);
198
      foreach ($translation->getProperties(TRUE) as $field) {
199 200 201 202 203
        $field->$method();
      }
    }
  }

204
}