EntityDatabaseStorage.php 5.03 KB
Newer Older
1 2 3 4
<?php

/**
 * @file
5
 * Contains \Drupal\Core\Entity\EntityDatabaseStorage.
6 7
 */

8
namespace Drupal\Core\Entity;
9

10
use Drupal\Component\Uuid\UuidInterface;
11
use Drupal\Core\Database\Connection;
12
use Symfony\Component\DependencyInjection\ContainerInterface;
13 14

/**
15
 * Defines a base entity storage class.
16
 *
17
 * This class only supports bare, non-content entities.
18
 */
19
class EntityDatabaseStorage extends EntityStorageBase {
20

21 22 23 24 25 26 27
  /**
   * The UUID service.
   *
   * @var \Drupal\Component\Uuid\UuidInterface
   */
  protected $uuidService;

28 29 30 31 32 33 34
  /**
   * Whether this entity type should use the static cache.
   *
   * @var boolean
   */
  protected $cache;

35 36 37 38 39 40 41 42 43 44
  /**
   * Active database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * {@inheritdoc}
   */
45
  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
46
    return new static(
47
      $entity_type,
48
      $container->get('database'),
49
      $container->get('uuid')
50 51
    );
  }
52

53
  /**
54
   * Constructs a EntityDatabaseStorage object.
55
   *
56 57
   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
   *   The entity type definition.
58 59
   * @param \Drupal\Core\Database\Connection $database
   *   The database connection to be used.
60 61
   * @param \Drupal\Component\Uuid\UuidInterface $uuid_service
   *   The UUID service.
62
   */
63 64
  public function __construct(EntityTypeInterface $entity_type, Connection $database, UuidInterface $uuid_service) {
    parent::__construct($entity_type);
65

66
    $this->database = $database;
67
    $this->uuidService = $uuid_service;
68

69
    // Check if the entity type supports UUIDs.
70
    $this->uuidKey = $this->entityType->getKey('uuid');
71 72 73
  }

  /**
74
   * {@inheritdoc}
75
   */
76 77 78 79 80 81
  protected function doLoadMultiple(array $ids = NULL) {
    // Build and execute the query.
    $records = $this
      ->buildQuery($ids)
      ->execute()
      ->fetchAllAssoc($this->idKey, \PDO::FETCH_ASSOC);
82

83
    return $this->mapFromStorageRecords($records);
84 85
  }

86
  /**
87
   * {@inheritdoc}
88 89
   */
  public function loadRevision($revision_id) {
90
    throw new \Exception('Database storage does not support revisions.');
91 92
  }

93
  /**
94
   * {@inheritdoc}
95 96
   */
  public function deleteRevision($revision_id) {
97
    throw new \Exception('Database storage does not support revisions.');
98 99
  }

100 101 102
  /**
   * Builds the query to load the entity.
   *
103 104
   * @param array|null $ids
   *   An array of entity IDs, or NULL to load all entities.
105
   *
106
   * @return \Drupal\Core\Database\Query\Select
107 108
   *   A SelectQuery object for loading the entity.
   */
109
  protected function buildQuery($ids) {
110
    $query = $this->database->select($this->entityType->getBaseTable(), 'base');
111

112
    $query->addTag($this->entityTypeId . '_load_multiple');
113 114

    // Add fields from the {entity} table.
115
    $entity_fields = drupal_schema_fields_sql($this->entityType->getBaseTable());
116 117 118 119 120
    $query->fields('base', $entity_fields);

    if ($ids) {
      $query->condition("base.{$this->idKey}", $ids, 'IN');
    }
121

122 123 124
    return $query;
  }

125
  /**
126
   * {@inheritdoc}
127
   */
128
  public function delete(array $entities) {
129 130 131 132
    if (!$entities) {
      // If no IDs or invalid IDs were passed, do nothing.
      return;
    }
133
    $transaction = $this->database->startTransaction();
134 135

    try {
136 137
      parent::delete($entities);

138 139
      // Ignore replica server temporarily.
      db_ignore_replica();
140
    }
141
    catch (\Exception $e) {
142
      $transaction->rollback();
143
      watchdog_exception($this->entityTypeId, $e);
144
      throw new EntityStorageException($e->getMessage(), $e->getCode(), $e);
145 146 147
    }
  }

148 149 150 151 152 153 154 155 156 157 158 159 160 161
  /**
   * {@inheritdoc}
   */
  protected function doDelete($entities) {
    $ids = array_keys($entities);

    $this->database->delete($this->entityType->getBaseTable())
      ->condition($this->idKey, $ids, 'IN')
      ->execute();

    // Reset the cache as soon as the changes have been applied.
    $this->resetCache($ids);
  }

162
  /**
163
   * {@inheritdoc}
164
   */
165
  public function save(EntityInterface $entity) {
166
    $transaction = $this->database->startTransaction();
167
    try {
168
      $return = parent::save($entity);
169

170 171
      // Ignore replica server temporarily.
      db_ignore_replica();
172 173
      return $return;
    }
174
    catch (\Exception $e) {
175
      $transaction->rollback();
176
      watchdog_exception($this->entityTypeId, $e);
177 178 179 180
      throw new EntityStorageException($e->getMessage(), $e->getCode(), $e);
    }
  }

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
  /**
   * {@inheritdoc}
   */
  protected function doSave($id, EntityInterface $entity) {
    if (!$entity->isNew()) {
      $return = drupal_write_record($this->entityType->getBaseTable(), $entity, $this->idKey);
      $this->resetCache(array($entity->id()));
    }
    else {
      $return = drupal_write_record($this->entityType->getBaseTable(), $entity);
      // Reset general caches, but keep caches specific to certain entities.
      $this->resetCache(array());
    }

    return $return;
  }

  /**
   * {@inheritdoc}
   */
  protected function has($id, EntityInterface $entity) {
    return !$entity->isNew();
  }

205
  /**
206 207 208 209 210 211
   * {@inheritdoc}
   */
  public function getQueryServiceName() {
    return 'entity.query.sql';
  }

212
}