diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index d335e65..4222066 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -968,7 +968,7 @@ function install_base_system(&$install_state) {
// Enable the user module so that sessions can be recorded during the
// upcoming bootstrap step.
- \Drupal::moduleHandler()->install(array('user'), FALSE);
+ \Drupal::moduleHandler()->install(array('user'));
// Save the list of other modules to install for the upcoming tasks.
// State can be set to the database now that system.module is installed.
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
index 6b7de03..709a807 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
@@ -8,7 +8,11 @@
namespace Drupal\Core\Entity;
use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Database;
use Drupal\Core\Entity\Query\QueryInterface;
+use Drupal\Core\Entity\Schema\ContentEntitySchemaHandler;
+use Drupal\Core\Entity\Schema\ContentEntitySchemaHandlerInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Language\Language;
use Drupal\field\FieldInfo;
use Drupal\field\FieldConfigUpdateForbiddenException;
@@ -25,7 +29,58 @@
* This class can be used as-is by most simple entity types. Entity types
* requiring special handling can extend the class.
*/
-class ContentEntityDatabaseStorage extends ContentEntityStorageBase {
+class ContentEntityDatabaseStorage extends ContentEntityStorageBase implements ContentEntitySchemaHandlerInterface, SqlStorageInterface {
+
+ /**
+ * The base table layout: no revision or multilingual support for base fields.
+ *
+ * @var int
+ */
+ const LAYOUT_BASE = 0;
+
+ /**
+ * The revision table layout: provides revision support for base fields.
+ *
+ * @var int
+ */
+ const LAYOUT_REVISION = 1;
+
+ /**
+ * The multilingual table layout: provides multilingual support for base
+ * fields.
+ *
+ * @var int
+ */
+ const LAYOUT_MULTILINGUAL = 2;
+
+ /**
+ * The multilingual revision table layout: provides revision and multilingual
+ * support for base fields.
+ *
+ * @var int
+ */
+ const LAYOUT_MULTILINGUAL_REVISION = 3;
+
+ /**
+ * The base field definitions for this entity type.
+ *
+ * @var \Drupal\Core\Field\FieldDefinitionInterface[]
+ */
+ protected $fieldDefinitions;
+
+ /**
+ * The table layout associated to the entity type.
+ *
+ * @var int
+ */
+ protected $layoutType;
+
+ /**
+ * A mapping of schema fields that will be stored per entity table.
+ *
+ * @var array
+ */
+ protected $tableMapping;
/**
* Name of entity's revision database table field, if it supports revisions.
@@ -37,6 +92,22 @@ class ContentEntityDatabaseStorage extends ContentEntityStorageBase {
protected $revisionKey = FALSE;
/**
+ * Name of entity's default_langcode database table field.
+ *
+ * Has the value FALSE if this entity does not support multilingual storage.
+ *
+ * @var string|bool
+ */
+ protected $defaultLangcodeKey = FALSE;
+
+ /**
+ * The base table of the entity, if the entity has storage.
+ *
+ * @var string
+ */
+ protected $baseTable;
+
+ /**
* The table that stores revisions, if the entity supports revisions.
*
* @var string
@@ -79,12 +150,27 @@ class ContentEntityDatabaseStorage extends ContentEntityStorageBase {
protected $fieldInfo;
/**
+ * The entity manager.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface
+ */
+ protected $entityManager;
+
+ /**
+ * The entity schema builder.
+ *
+ * @var \Drupal\Core\Entity\Schema\ContentEntitySchemaHandlerInterface
+ */
+ protected $schemaHandler;
+
+ /**
* {@inheritdoc}
*/
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static(
$entity_type,
$container->get('database'),
+ $container->get('entity.manager'),
$container->get('field.info')
);
}
@@ -96,38 +182,257 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
* The entity type definition.
* @param \Drupal\Core\Database\Connection $database
* The database connection to be used.
+ * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+ * The entity manager.
* @param \Drupal\field\FieldInfo $field_info
- * The field info service.
+ * (optional) The field info service. Defaults to NULL as storage can be
+ * instantiated before Field module is installed.
*/
- public function __construct(EntityTypeInterface $entity_type, Connection $database, FieldInfo $field_info) {
+ public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, FieldInfo $field_info = NULL) {
parent::__construct($entity_type);
$this->database = $database;
$this->fieldInfo = $field_info;
+ $this->entityManager = $entity_manager;
+ $this->fieldDefinitions = $entity_manager->getBaseFieldDefinitions($entity_type->id());
+
+ $this->initTableLayout();
+ }
- // Check if the entity type supports IDs.
- if ($this->entityType->hasKey('id')) {
- $this->idKey = $this->entityType->getKey('id');
+ /**
+ * Initializes table and key names based on the current layout type.
+ */
+ protected function initTableLayout() {
+ $this->idKey = $this->entityType->getKey('id') ?: 'id';
+ $this->uuidKey = $this->entityType->getKey('uuid') ?: 'uuid';
+
+ // The bundle key is optional.
+ $this->bundleKey = $this->entityType->getKey('bundle');
+
+ // @todo Table names do not belong to the entity type definition, they are
+ // storage implementation details. Rip them out.
+ $this->baseTable = $this->entityType->getBaseTable() ?: $this->entityTypeId;
+
+ // Retrieve the current table layout type based on the entity type
+ // definition.
+ $layout_type = $this->getLayoutType();
+
+ if ($layout_type & static::LAYOUT_REVISION) {
+ $this->revisionKey = $this->entityType->getKey('revision') ?: 'revision_id';
+ $this->revisionTable = $this->entityType->getRevisionTable() ?: $this->entityTypeId . '_revision';
}
- // Check if the entity type supports UUIDs.
- $this->uuidKey = $this->entityType->getKey('uuid');
+ if ($layout_type & static::LAYOUT_MULTILINGUAL) {
+ $this->dataTable = $this->entityType->getDataTable() ?: $this->entityTypeId . '_field_data';
+ $this->langcodeKey = $this->entityType->getKey('langcode') ?: 'langcode';
+ $this->defaultLangcodeKey = $this->entityType->getKey('default_langcode') ?: 'default_langcode';
+ }
- // Check if the entity type supports revisions.
- if ($this->entityType->hasKey('revision')) {
- $this->revisionKey = $this->entityType->getKey('revision');
- $this->revisionTable = $this->entityType->getRevisionTable();
+ if ($layout_type == static::LAYOUT_MULTILINGUAL_REVISION) {
+ $this->revisionDataTable = $this->entityType->getRevisionDataTable() ?: $this->entityTypeId . '_field_revision';
}
+ }
- // Check if the entity type has a dedicated table for fields.
- if ($data_table = $this->entityType->getDataTable()) {
- $this->dataTable = $data_table;
- // Entity types having both revision and translation support should always
- // define a revision data table.
- if ($this->revisionTable && $revision_data_table = $this->entityType->getRevisionDataTable()) {
- $this->revisionDataTable = $revision_data_table;
+ /**
+ * Returns the current layout type.
+ *
+ * @return int
+ * An integer value identifiying the current layour type.
+ *
+ * @see static::LAYOUT_BASE
+ * @see static::LAYOUT_REVISION
+ * @see static::LAYOUT_MULTILINGUAL
+ * @see static::LAYOUT_MULTILINGUAL_REVISION
+ */
+ public function getLayoutType() {
+ if (!isset($this->layoutType)) {
+ $this->layoutType = static::LAYOUT_BASE;
+ if ($this->entityType->hasKey('revision')) {
+ $this->layoutType |= static::LAYOUT_REVISION;
+ }
+ // @todo Remove the data table check once all entity types are using
+ // entity query and we have a views data controller. See:
+ // - https://drupal.org/node/2068325
+ // - https://drupal.org/node/1740492
+ $data_table = $this->entityType->getDataTable();
+ if ($data_table && $this->entityType->isTranslatable()) {
+ $this->layoutType |= static::LAYOUT_MULTILINGUAL;
}
}
+ return $this->layoutType;
+ }
+
+ /**
+ * Returns the base table name.
+ *
+ * @return string
+ * The table name.
+ */
+ public function getBaseTable() {
+ return $this->baseTable;
+ }
+
+ /**
+ * Returns the revision table name.
+ *
+ * @return string|bool
+ * The table name or FALSE if it is not available.
+ */
+ public function getRevisionTable() {
+ return $this->revisionTable;
+ }
+
+ /**
+ * Returns the data table name.
+ *
+ * @return string|bool
+ * The table name or FALSE if it is not available.
+ */
+ public function getDataTable() {
+ return $this->dataTable;
+ }
+
+ /**
+ * Returns the revision data table name.
+ *
+ * @return string|bool
+ * The table name or FALSE if it is not available.
+ */
+ public function getRevisionDataTable() {
+ return $this->revisionDataTable;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSchema() {
+ return $this->schemaHandler()->getSchema();
+ }
+
+ /**
+ * Gets the schema builder for this storage controller.
+ */
+ protected function schemaHandler() {
+ if (!isset($this->schemaHandler)) {
+ $this->schemaHandler = new ContentEntitySchemaHandler($this->entityManager, $this->entityType, $this);
+ }
+ return $this->schemaHandler;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTableMapping() {
+ if (!isset($this->tableMapping)) {
+ $table_mapping = array();
+
+ // @todo Remove this. This is currently needed because some entity types
+ // declare a schema that does not match their field definitions.
+ // Therefore we use the legacy schema if it's still declared. This
+ // allows to iteratively enable the automatic schema generation for all
+ // entity types.
+ if (drupal_get_schema($this->baseTable)) {
+ $tables = array_filter(array($this->baseTable, $this->revisionTable, $this->dataTable, $this->revisionDataTable));
+ foreach ($tables as $table) {
+ foreach (array_keys(drupal_get_schema($table)['fields']) as $column_name) {
+ $field_name = strstr($column_name, '__', TRUE) ?: $column_name;
+ $table_mapping[$table][$field_name][] = $column_name;
+ }
+ }
+ }
+ else {
+ $key_fields = array_filter(array($this->idKey, $this->revisionKey, $this->bundleKey, $this->uuidKey, $this->langcodeKey));
+
+ $storable_definitions = array_filter($this->fieldDefinitions, function (FieldDefinitionInterface $field_definition) {
+ return !$field_definition->isComputed() && !$field_definition->hasCustomStorage();
+ });
+ $storable_fields = array_keys($storable_definitions);
+
+ // @todo Provide automatic definitions for revision metadata fields.
+ // Rename 'log' to 'revision_log'.
+ $revision_metadata_fields = array_intersect(array('revision_timestamp', 'revision_uid', 'log'), $storable_fields);
+ $revisionable_filter_callback = function (FieldDefinitionInterface $definition) { return $definition->isRevisionable(); };
+
+ switch ($this->getLayoutType()) {
+ // The base layout stores all the base field values in the base table.
+ case static::LAYOUT_BASE:
+ $table_mapping[$this->baseTable] = $this->processFields(array_merge($key_fields, array_diff($storable_fields, $key_fields)));
+ break;
+
+ // The base layout stores all the base field values in the base table.
+ // Revisionable fields are also stored in the revision table.
+ case static::LAYOUT_REVISION:
+ $table_mapping[$this->baseTable] = $this->processFields(array_merge($key_fields, array_diff($storable_fields, $key_fields, $revision_metadata_fields)));
+ $revision_key_fields = array($this->idKey, $this->revisionKey);
+ $revisionable_fields = array_keys(array_filter($storable_definitions, $revisionable_filter_callback));
+ $table_mapping[$this->revisionTable] = $this->processFields(array_merge($revision_key_fields, $revisionable_fields));
+ break;
+
+ // Multilingual layouts store key field values in the base table. The
+ // other base field values are stored in the data table, no matter
+ // whether they are translatable or not. The data table holds also a
+ // denormalized copy of the bundle field value to allow for more
+ // performant queries.
+ case static::LAYOUT_MULTILINGUAL:
+ $table_mapping[$this->baseTable] = $this->processFields($key_fields);
+ $data_key_fields = array_diff($key_fields, array($this->uuidKey));
+ $data_fields = array_diff($storable_fields, $key_fields);
+ $table_mapping[$this->dataTable] = $this->processFields(array_merge($data_key_fields, $data_fields));
+ break;
+
+ // The revisionable multilingual layout stores key field values in the
+ // base table, except for language, which is stored in the revision
+ // table along with revision metadata. The revision data table holds
+ // data field values for all the available revisions without
+ // denormalizations.
+ case static::LAYOUT_MULTILINGUAL_REVISION:
+ $table_mapping[$this->baseTable] = $this->processFields(array_diff($key_fields, array($this->langcodeKey)));
+ $data_key_fields = array_diff($key_fields, array($this->uuidKey));
+ $data_fields = array_diff($storable_fields, $key_fields, $revision_metadata_fields);
+ $table_mapping[$this->dataTable] = $this->processFields(array_merge($data_key_fields, $data_fields));
+ $table_mapping[$this->revisionTable] = $this->processFields(array_merge(array($this->idKey, $this->revisionKey, $this->langcodeKey), $revision_metadata_fields));
+ $revision_data_key_fields = array_diff($key_fields, array($this->bundleKey, $this->uuidKey));
+ $revisionable_fields = array_keys(array_filter($storable_definitions, $revisionable_filter_callback));
+ $revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields, $revision_data_key_fields);
+ $table_mapping[$this->revisionDataTable] = $this->processFields(array_merge($revision_data_key_fields, $revision_data_fields));
+ break;
+ }
+ }
+
+ $this->tableMapping = $table_mapping;
+ }
+
+ return $this->tableMapping;
+ }
+
+ /**
+ * Returns a mapping between field and column names.
+ *
+ * @param array $field_names
+ * An array of names of fields to map.
+ *
+ * @return array
+ * An associative array of arrays of column names keyed by field name.
+ */
+ protected function processFields($field_names) {
+ $mapping = array();
+ foreach ($field_names as $field_name) {
+ $columns = isset($this->fieldDefinitions[$field_name]) ? array_keys($this->fieldDefinitions[$field_name]->getColumns()) : array();
+ // @todo Remove the entity reference check once we can handle schema
+ // changes or the Entity reference module stops messing with field
+ // schema. See:
+ // - https://drupal.org/node/1498720
+ // - https://drupal.org/node/2209981
+ if (count($columns) > 1 && $this->fieldDefinitions[$field_name]->getType() != 'entity_reference') {
+ foreach ($columns as $column) {
+ $mapping[$field_name][] = $field_name . '__' . $column;
+ }
+ }
+ else {
+ $mapping[$field_name] = array($field_name);
+ }
+ }
+ return $mapping;
}
/**
@@ -265,15 +570,18 @@ protected function attachPropertyData(array &$entities) {
}
$data = $query->execute();
- $field_definitions = \Drupal::entityManager()->getBaseFieldDefinitions($this->entityTypeId);
+ $field_definitions = $this->entityManager->getBaseFieldDefinitions($this->entityTypeId);
+
+ $table_mapping = $this->getTableMapping();
$translations = array();
if ($this->revisionDataTable) {
- $data_column_names = array_flip(array_diff(drupal_schema_fields_sql($this->entityType->getRevisionDataTable()), drupal_schema_fields_sql($this->entityType->getBaseTable())));
+ $data_column_names = call_user_func_array('array_merge', array_diff_key($table_mapping[$this->revisionDataTable], $table_mapping[$this->baseTable]));
}
else {
- $data_column_names = array_flip(drupal_schema_fields_sql($this->entityType->getDataTable()));
+ $data_column_names = call_user_func_array('array_merge', $table_mapping[$this->dataTable]);
}
+ $data_column_names = array_combine($data_column_names, $data_column_names);
foreach ($data as $values) {
$id = $values[$this->idKey];
@@ -403,11 +711,12 @@ protected function buildQuery($ids, $revision_id = FALSE) {
}
// Add fields from the {entity} table.
- $entity_fields = drupal_schema_fields_sql($this->entityType->getBaseTable());
+ $table_mapping = $this->getTableMapping();
+ $entity_fields = call_user_func_array('array_merge', $table_mapping[$this->baseTable]);
if ($this->revisionTable) {
// Add all fields from the {entity_revision} table.
- $entity_revision_fields = drupal_schema_fields_sql($this->entityType->getRevisionTable());
+ $entity_revision_fields = call_user_func_array('array_merge', $table_mapping[$this->revisionTable]);
$entity_revision_fields = array_combine($entity_revision_fields, $entity_revision_fields);
// The ID field is provided by entity, so remove it.
unset($entity_revision_fields[$this->idKey]);
@@ -552,7 +861,12 @@ public function save(EntityInterface $entity) {
if (!$entity->isNew()) {
if ($entity->isDefaultRevision()) {
- $return = drupal_write_record($this->entityType->getBaseTable(), $record, $this->idKey);
+ $this->database
+ ->update($this->baseTable)
+ ->fields((array) $record)
+ ->condition($this->idKey, $record->{$this->idKey})
+ ->execute();
+ $return = SAVED_UPDATED;
}
else {
// @todo, should a different value be returned when saving an entity
@@ -560,13 +874,13 @@ public function save(EntityInterface $entity) {
$return = FALSE;
}
if ($this->revisionTable) {
- $record->{$this->revisionKey} = $this->saveRevision($entity);
+ $entity->{$this->revisionKey}->value = $this->saveRevision($entity);
}
if ($this->dataTable) {
$this->savePropertyData($entity);
}
if ($this->revisionDataTable) {
- $this->savePropertyData($entity, 'revision_data_table');
+ $this->savePropertyData($entity, $this->revisionDataTable);
}
$entity->setNewRevision(FALSE);
$this->invokeFieldMethod('update', $entity);
@@ -582,7 +896,17 @@ public function save(EntityInterface $entity) {
// Ensure the entity is still seen as new after assigning it an id,
// while storing its data.
$entity->enforceIsNew();
- $return = drupal_write_record($this->entityType->getBaseTable(), $record);
+ $insert_id = $this->database
+ ->insert($this->baseTable, array('return' => Database::RETURN_INSERT_ID))
+ ->fields((array) $record)
+ ->execute();
+ // Even if this is a new entity, the ID key might have been set in which
+ // case we should not override the provided ID. An empty value for the
+ // id is interpreted as NULL and thus overriden.
+ if (empty($record->{$this->idKey})) {
+ $record->{$this->idKey} = $insert_id;
+ }
+ $return = SAVED_NEW;
$entity->{$this->idKey}->value = (string) $record->{$this->idKey};
if ($this->revisionTable) {
$entity->setNewRevision();
@@ -592,10 +916,9 @@ public function save(EntityInterface $entity) {
$this->savePropertyData($entity);
}
if ($this->revisionDataTable) {
- $this->savePropertyData($entity, 'revision_data_table');
+ $this->savePropertyData($entity, $this->revisionDataTable);
}
-
$entity->enforceIsNew(FALSE);
$this->invokeFieldMethod('insert', $entity);
$this->saveFieldItems($entity, FALSE);
@@ -623,13 +946,14 @@ public function save(EntityInterface $entity) {
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity object.
- * @param string $table_key
- * (optional) The entity key identifying the target table. Defaults to
- * 'data_table'.
+ * @param string $table_name
+ * (optional) The table name to save to. Defaults to the data table.
*/
- protected function savePropertyData(EntityInterface $entity, $table_key = 'data_table') {
- $table_name = $this->entityType->get($table_key);
- $revision = $table_key != 'data_table';
+ protected function savePropertyData(EntityInterface $entity, $table_name = NULL) {
+ if (!isset($table_name)) {
+ $table_name = $this->dataTable;
+ }
+ $revision = $table_name != $this->dataTable;
if (!$revision || !$entity->isNewRevision()) {
$key = $revision ? $this->revisionKey : $this->idKey;
@@ -644,7 +968,7 @@ protected function savePropertyData(EntityInterface $entity, $table_key = 'data_
foreach ($entity->getTranslationLanguages() as $langcode => $language) {
$translation = $entity->getTranslation($langcode);
- $record = $this->mapToDataStorageRecord($translation, $table_key);
+ $record = $this->mapToDataStorageRecord($translation, $table_name);
$values = (array) $record;
$query
->fields(array_keys($values))
@@ -657,53 +981,58 @@ protected function savePropertyData(EntityInterface $entity, $table_key = 'data_
/**
* Maps from an entity object to the storage record.
*
- * @param \Drupal\Core\Entity\EntityInterface $entity
+ * @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity object.
- * @param string $table_key
- * (optional) The entity key identifying the target table. Defaults to
- * 'base_table'.
+ * @param string $table_name
+ * (optional) The table name to map records to. Defaults to the base table.
*
* @return \stdClass
* The record to store.
*/
- protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'base_table') {
+ protected function mapToStorageRecord(ContentEntityInterface $entity, $table_name = NULL) {
+ if (!isset($table_name)) {
+ $table_name = $this->baseTable;
+ }
+
$record = new \stdClass();
- $values = array();
- $definitions = $entity->getFieldDefinitions();
- $schema = drupal_get_schema($this->entityType->get($table_key));
$is_new = $entity->isNew();
+ $table_mapping = $this->getTableMapping();
+
+ // @todo We still need to retrieve the schema as long as we have the BC
+ // layer in place.
+ $schema = drupal_get_schema($table_name);
+
+ foreach ($table_mapping[$table_name] as $name => $storage_columns) {
+ if (!empty($this->fieldDefinitions[$name])) {
+ $definition = $this->fieldDefinitions[$name];
+ foreach ($definition->getColumns() as $column => $column_info) {
+ $value = isset($entity->$name->$column) ? $entity->$name->$column : NULL;
+
+ // We allow for storage controllers to have schema fields which are
+ // not entity fields, which can be useful for normalization purposes.
+ // The 'default_langcode' field, for example, is simply a
+ // denormalization of checking the language code in the data table
+ // against the language code in the base table and similarly the
+ // 'isDefaultRevision' field (which we add as a query expression in
+ // self::buildQuery()) is denormalization of checking the revision ID
+ // in the revision table against the revision ID in the base table.
+ if (!empty($column_info['serialize'])) {
+ $value = serialize($value);
+ }
- $multi_column_fields = array();
- foreach (drupal_schema_fields_sql($this->entityType->get($table_key)) as $name) {
- // Check for fields which store data in multiple columns and process them
- // separately.
- if ($field = strstr($name, '__', TRUE)) {
- $multi_column_fields[$field] = TRUE;
- continue;
- }
- $values[$name] = isset($definitions[$name]) && isset($entity->$name->value) ? $entity->$name->value : NULL;
- }
-
- // Handle fields that store multiple properties and match each property name
- // to its schema column name.
- foreach (array_keys($multi_column_fields) as $field_name) {
- $field_items = $entity->get($field_name);
- $field_value = $field_items->getValue();
- foreach (array_keys($field_items->getFieldDefinition()->getColumns()) as $field_schema_column) {
- if (isset($schema['fields'][$field_name . '__' . $field_schema_column])) {
- $values[$field_name . '__' . $field_schema_column] = isset($field_value[0][$field_schema_column]) ? $field_value[0][$field_schema_column] : NULL;
+ // If we are creating a new entity, we must not populate the record
+ // with NULL values otherwise defaults would not be applied.
+ if (isset($value) || !$is_new) {
+ $info = isset($schema['fields'][$name]) ? $schema['fields'][$name] : $definition->getSchema()['columns'][$column];
+ list(, $storage_column) = each($storage_columns);
+ if (!empty($storage_column)) {
+ $record->$storage_column = drupal_schema_get_field_value($info, $value);
+ }
+ }
}
}
}
- foreach ($values as $field_name => $value) {
- // If we are creating a new entity, we must not populate the record with
- // NULL values otherwise defaults would not be applied.
- if (isset($value) || !$is_new) {
- $record->$field_name = drupal_schema_get_field_value($schema['fields'][$field_name], $value);
- }
- }
-
return $record;
}
@@ -712,15 +1041,17 @@ protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'bas
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity object.
- * @param string $table_key
- * (optional) The entity key identifying the target table. Defaults to
- * 'data_table'.
+ * @param string $table_name
+ * (optional) The table name to map records to. Defaults to the data table.
*
* @return \stdClass
* The record to store.
*/
- protected function mapToDataStorageRecord(EntityInterface $entity, $table_key = 'data_table') {
- $record = $this->mapToStorageRecord($entity, $table_key);
+ protected function mapToDataStorageRecord(EntityInterface $entity, $table_name = NULL) {
+ if (!isset($table_name)) {
+ $table_name = $this->dataTable;
+ }
+ $record = $this->mapToStorageRecord($entity, $table_name);
$record->langcode = $entity->language()->id;
$record->default_langcode = intval($record->langcode == $entity->getUntranslated()->language()->id);
return $record;
@@ -736,7 +1067,7 @@ protected function mapToDataStorageRecord(EntityInterface $entity, $table_key =
* The revision id.
*/
protected function saveRevision(EntityInterface $entity) {
- $record = $this->mapToStorageRecord($entity, 'revision_table');
+ $record = $this->mapToStorageRecord($entity, $this->revisionTable);
// When saving a new revision, set any existing revision ID to NULL so as to
// ensure that a new revision will actually be created.
@@ -747,7 +1078,15 @@ protected function saveRevision(EntityInterface $entity) {
$entity->preSaveRevision($this, $record);
if ($entity->isNewRevision()) {
- drupal_write_record($this->revisionTable, $record);
+ $insert_id = $this->database
+ ->insert($this->revisionTable, array('return' => Database::RETURN_INSERT_ID))
+ ->fields((array) $record)
+ ->execute();
+ // Even if this is a new revsision, the revision ID key might have been
+ // set in which case we should not override the provided revision ID.
+ if (!isset($record->{$this->revisionKey})) {
+ $record->{$this->revisionKey} = $insert_id;
+ }
if ($entity->isDefaultRevision()) {
$this->database->update($this->entityType->getBaseTable())
->fields(array($this->revisionKey => $record->{$this->revisionKey}))
@@ -756,7 +1095,11 @@ protected function saveRevision(EntityInterface $entity) {
}
}
else {
- drupal_write_record($this->revisionTable, $record, $this->revisionKey);
+ $this->database
+ ->update($this->revisionTable)
+ ->fields((array) $record)
+ ->condition($this->revisionKey, $record->{$this->revisionKey})
+ ->execute();
}
// Make sure to update the new revision key for the entity.
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index 0c2bfe4..469047c 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -23,6 +23,13 @@
protected $bundleKey = FALSE;
/**
+ * The entity langcode key
+ *
+ * @var string|bool
+ */
+ protected $langcodeKey = FALSE;
+
+ /**
* Name of the entity class.
*
* @var string
diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
index ee2bebc..5276c26 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
@@ -12,6 +12,7 @@
use Drupal\Core\Entity\ContentEntityDatabaseStorage;
use Drupal\Core\Entity\Plugin\DataType\EntityReference;
use Drupal\Core\Entity\Query\QueryException;
+use Drupal\Core\Entity\SqlStorageInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Field as FieldInfo;
@@ -35,7 +36,6 @@ class Tables implements TablesInterface {
*/
protected $entityTables = array();
-
/**
* Field table array, key is table name, value is alias.
*
@@ -46,10 +46,18 @@ class Tables implements TablesInterface {
protected $fieldTables = array();
/**
+ * The entity manager.
+ *
+ * @var \Drupal\Core\Entity\EntityManager
+ */
+ protected $entityManager;
+
+ /**
* @param \Drupal\Core\Database\Query\SelectInterface $sql_query
*/
public function __construct(SelectInterface $sql_query) {
$this->sqlQuery = $sql_query;
+ $this->entityManager = \Drupal::entityManager();
}
/**
@@ -57,7 +65,6 @@ public function __construct(SelectInterface $sql_query) {
*/
public function addField($field, $type, $langcode) {
$entity_type_id = $this->sqlQuery->getMetaData('entity_type');
- $entity_manager = \Drupal::entityManager();
$field_info = FieldInfo::fieldInfo();
$age = $this->sqlQuery->getMetaData('age');
// This variable ensures grouping works correctly. For example:
@@ -74,7 +81,7 @@ public function addField($field, $type, $langcode) {
// This will contain the definitions of the last specifier seen by the
// system.
$propertyDefinitions = array();
- $entity_type = $entity_manager->getDefinition($entity_type_id);
+ $entity_type = $this->entityManager->getDefinition($entity_type_id);
// Use the lightweight and fast field map for checking whether a specifier
// is a field or not. While calling field_info_field() on every specifier
// delivers the same information, if no specifiers are using the field API
@@ -141,7 +148,7 @@ public function addField($field, $type, $langcode) {
if ($bundle_key = $entity_type->getKey('bundle')) {
$values[$bundle_key] = reset($field_map[$entity_type_id][$field_name]['bundles']);
}
- $entity = $entity_manager
+ $entity = $this->entityManager
->getStorage($entity_type_id)
->create($values);
$propertyDefinitions = $entity->$field_name->getFieldDefinition()->getPropertyDefinitions();
@@ -174,10 +181,10 @@ public function addField($field, $type, $langcode) {
$entity_tables = array();
if ($data_table = $entity_type->getDataTable()) {
$this->sqlQuery->addMetaData('simple_query', FALSE);
- $entity_tables[$data_table] = drupal_get_schema($data_table);
+ $entity_tables[$data_table] = $this->getTableSchema($data_table);
}
$entity_base_table = $entity_type->getBaseTable();
- $entity_tables[$entity_base_table] = drupal_get_schema($entity_base_table);
+ $entity_tables[$entity_base_table] = $this->getTableSchema($entity_base_table);
$sql_column = $specifier;
$table = $this->ensureEntityTable($index_prefix, $specifier, $type, $langcode, $base_table, $entity_id_field, $entity_tables);
}
@@ -195,7 +202,7 @@ public function addField($field, $type, $langcode) {
$bundles = entity_get_bundles($entity_type_id);
$values[$bundle_key] = key($bundles);
}
- $entity = $entity_manager
+ $entity = $this->entityManager
->getStorage($entity_type_id)
->create($values);
$propertyDefinitions = $entity->$specifier->getFieldDefinition()->getPropertyDefinitions();
@@ -206,7 +213,7 @@ public function addField($field, $type, $langcode) {
if (isset($propertyDefinitions[$relationship_specifier]) && $entity->get($specifier)->first()->get('entity') instanceof EntityReference) {
// If it is, use the entity type.
$entity_type_id = $propertyDefinitions[$relationship_specifier]->getTargetDefinition()->getEntityTypeId();
- $entity_type = $entity_manager->getDefinition($entity_type_id);
+ $entity_type = $this->entityManager->getDefinition($entity_type_id);
// Add the new entity base table using the table and sql column.
$join_condition= '%alias.' . $entity_type->getKey('id') . " = $table.$sql_column";
$base_table = $this->sqlQuery->leftJoin($entity_type->getBaseTable(), NULL, $join_condition);
@@ -272,4 +279,26 @@ protected function addJoin($type, $table, $join_condition, $langcode) {
return $this->sqlQuery->addJoin($type, $table, NULL, $join_condition, $arguments);
}
+ /**
+ * Returns the schema for the given table.
+ *
+ * @param string $table
+ * The table name.
+ *
+ * @return array|bool
+ * The schema for the given table or FALSE if not available.
+ */
+ protected function getTableSchema($table) {
+ $entity_type_id = $this->sqlQuery->getMetaData('entity_type');
+ $storage = $this->entityManager->getStorage($entity_type_id);
+ // @todo Stop calling drupal_get_schema() once menu links are converted
+ // to the Entity Field API. See https://drupal.org/node/1842858.
+ $schema = drupal_get_schema($table);
+ if (!$schema && $storage instanceof SqlStorageInterface) {
+ $storage_schema = $storage->getSchema();
+ $schema = isset($storage_schema[$table]) ? $storage_schema[$table] : FALSE;
+ }
+ return $schema;
+ }
+
}
diff --git a/core/lib/Drupal/Core/Entity/Schema/ContentEntitySchemaHandler.php b/core/lib/Drupal/Core/Entity/Schema/ContentEntitySchemaHandler.php
new file mode 100644
index 0000000..0ce7242
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/Schema/ContentEntitySchemaHandler.php
@@ -0,0 +1,465 @@
+entityType = $entity_type;
+ $this->fieldDefinitions = $entity_manager->getBaseFieldDefinitions($entity_type->id());
+ $this->storage = $storage;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSchema() {
+ // Prepare basic information about the entity type.
+ $tables = $this->getTables();
+ // If this entity type does not support storage, no schema information can
+ // be collected.
+ if (empty($tables)) {
+ $this->schema[$this->entityType->id()] = NULL;
+ }
+
+ if (!isset($this->schema[$this->entityType->id()])) {
+ // @todo Remove this. This is currently needed because some entity types
+ // declare a schema that does not match their field definitions.
+ // Therefore we use the legacy schema if it's still declared. This
+ // allows to iteratively enable the automatic schema generation for all
+ // entity types.
+ if ($base_schema = drupal_get_schema($tables['base_table'])) {
+ $schema[$tables['base_table']] = $base_schema;
+ unset($tables['base_table']);
+ foreach ($tables as $table) {
+ $schema[$table] = drupal_get_schema($table);
+ }
+ }
+ else {
+ // Initialize the table schema.
+ $schema[$tables['base_table']] = $this->initializeBaseTable();
+ if (isset($tables['revision_table'])) {
+ $schema[$tables['revision_table']] = $this->initializeRevisionTable();
+ }
+ if (isset($tables['data_table'])) {
+ $schema[$tables['data_table']] = $this->initializeDataTable();
+ }
+ if (isset($tables['revision_data_table'])) {
+ $schema[$tables['revision_data_table']] = $this->initializeRevisionDataTable();
+ }
+
+ // Add the schema from field definitions.
+ foreach ($this->storage->getTableMapping() as $table => $field_names) {
+ foreach ($field_names as $field_name => $column_names) {
+ $this->addFieldSchema($schema[$table], $field_name);
+ }
+ }
+
+ // Process tables after having gathered field information.
+ $this->processBaseTable($schema[$tables['base_table']]);
+ if (isset($tables['revision_table'])) {
+ $this->processRevisionTable($schema[$tables['revision_table']]);
+ }
+ if (isset($tables['data_table'])) {
+ $this->processDataTable($schema[$tables['data_table']]);
+ }
+ if (isset($tables['revision_data_table'])) {
+ $this->processRevisionDataTable($schema[$tables['revision_data_table']]);
+ }
+ }
+
+ // TODO Document this.
+ // We do not allow field schema to be changed.
+// $alterable_schema = array_diff_key($schema, array('fields' => TRUE));
+ $alterable_schema = $schema;
+ $context = array('entity_type_id' => $this->entityType->id());
+ \Drupal::moduleHandler()->alter('entity_schema', $alterable_schema, $context);
+
+ $this->schema[$this->entityType->id()] = $alterable_schema + $schema;
+ }
+
+ return $this->schema[$this->entityType->id()];
+ }
+
+ /**
+ * Gets a list of entity type tables.
+ *
+ * @return array
+ * A list of entity type tables, keyed by table key.
+ */
+ protected function getTables() {
+ return array_filter(array(
+ 'base_table' => $this->storage->getBaseTable(),
+ 'revision_table' => $this->storage->getRevisionTable(),
+ 'data_table' => $this->storage->getDataTable(),
+ 'revision_data_table' => $this->storage->getRevisionDataTable(),
+ ));
+ }
+
+ /**
+ * Returns the schema for a single field definition.
+ *
+ * @param array $schema
+ * The table schema to add the field schema to, passed by reference.
+ * @param string $field_name
+ * The name of the field.
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $definition
+ * The field definition to return the schema for.
+ */
+ protected function addFieldSchema(array &$schema, $field_name) {
+ $definition = $this->fieldDefinitions[$field_name];
+ $field_schema = $definition->getSchema();
+
+ foreach ($field_schema['columns'] as $column_name => $column_schema) {
+ $schema_field_name = $this->getFieldColumnName($definition, $column_name);
+ $schema['fields'][$schema_field_name] = $column_schema;
+ $schema['fields'][$schema_field_name]['description'] = $definition->getDescription();
+ // Only entity keys are required.
+ $schema['fields'][$schema_field_name]['not null'] = (bool) $this->entityType->getKey($field_name);
+
+ if (!empty($field_schema['indexes'])) {
+ $indexes = $this->getFieldSchemaData($definition, 'indexes');
+ $schema['indexes'] = !empty($schema['indexes']) ? array_merge($schema['indexes'], $indexes) : $indexes;
+ }
+
+ if (!empty($field_schema['unique keys'])) {
+ $unique_keys = $this->getFieldSchemaData($definition, 'unique keys');
+ $schema['unique keys'] = !empty($schema['unique keys']) ? array_merge($schema['unique keys'], $unique_keys) : $unique_keys;
+ }
+
+ if (!empty($field_schema['foreign keys'])) {
+ $foreign_keys = $this->getFieldForeignKeys($definition);
+ $schema['foreign keys'] = !empty($schema['foreign keys']) ? array_merge($schema['foreign keys'], $foreign_keys) : $foreign_keys;
+ }
+ }
+ }
+
+ /**
+ * Returns field schema data for the given key.
+ *
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $definition
+ * The field definition.
+ * @param string $key
+ * The schema key, e.g. 'indexes'.
+ *
+ * @return array
+ * The schema definition for the specified key.
+ */
+ protected function getFieldSchemaData(FieldDefinitionInterface $definition, $key) {
+ $data = array();
+ $schema = $definition->getSchema();
+
+ foreach ($schema[$key] as $key => $columns) {
+ $real_name = 'field__' . $this->getFieldColumnName($definition, $key);
+ foreach ($columns as $column) {
+ // Indexes can be specified as either a column name or an array with
+ // column name and length. Allow for either case.
+ $data[$real_name][] = is_array($column) ?
+ array($this->getFieldColumnName($definition, $column[0]), $column[1]) :
+ $this->getFieldColumnName($definition, $column);
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Returns field foreign keys.
+ *
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $definition
+ * The field definition.
+ *
+ * @return array
+ * The schema definition for the foreign keys.
+ */
+ protected function getFieldForeignKeys(FieldDefinitionInterface $definition) {
+ $foreign_keys = array();
+ $schema = $definition->getSchema();
+
+ foreach ($schema['foreign keys'] as $specifier => $specification) {
+ $real_name = $this->getFieldIndexName($definition, $specifier);
+ $foreign_keys[$real_name]['table'] = $specification['table'];
+ foreach ($specification['columns'] as $column => $referenced) {
+ $sql_storage_column = $this->getFieldColumnName($definition, $column);
+ $foreign_keys[$real_name]['columns'][$sql_storage_column] = $referenced;
+ }
+ }
+
+ return $foreign_keys;
+ }
+
+ /**
+ * Returns the name to be used for the given field column.
+ *
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $definition
+ * The field definition.
+ *
+ * @return string
+ * The column name.
+ */
+ protected function getFieldColumnName(FieldDefinitionInterface $definition, $column) {
+ $name = $definition->getName();
+ return count($definition->getSchema()['columns']) == 1 ? $name : $name . '__' . $column;
+ }
+
+ /**
+ * Returns the schema for the 'default_langcode' metadata field.
+ *
+ * @return array
+ * A schema field array for the 'default_langcode' metadata field.
+ */
+ protected function getDefaultLangcodeSchema() {
+ return array(
+ 'description' => 'Boolean indicating whether field values are in the default entity language.',
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 1,
+ );
+ }
+
+ /**
+ * Initializes common information for a base table.
+ *
+ * @return array
+ * A partial schema array for the base table.
+ */
+ protected function initializeBaseTable() {
+ $key = $this->entityType->getKey('uuid') ?: 'uuid';
+ $schema = array(
+ 'description' => "The base table for {$this->entityType->id()} entities.",
+ 'primary key' => array($this->entityType->getKey('id')),
+ 'unique keys' => array(
+ $this->getEntityIndexName($key) => array($key),
+ ),
+ );
+
+ if ($this->storage->getLayoutType() & ContentEntityDatabaseStorage::LAYOUT_REVISION) {
+ $key = $this->entityType->getKey('revision');
+ $schema['unique keys'][$this->getEntityIndexName($key)] = array($key);
+ }
+
+ return $schema;
+ }
+
+ /**
+ * Initializes common information for a revision table.
+ *
+ * @return array
+ * A partial schema array for the revision table.
+ */
+ protected function initializeRevisionTable() {
+ $id_key = $this->entityType->getKey('id');
+ $schema = array(
+ 'description' => "The revision table for {$this->entityType->id()} entities.",
+ 'primary key' => array($this->entityType->getKey('revision')),
+ 'foreign keys' => array(
+ $id_key => array(
+ 'table' => $this->entityType->getBaseTable(),
+ 'columns' => array($id_key => $id_key),
+ ),
+ ),
+ );
+
+ $key = $this->entityType->getKey('id');
+ $schema['indexes'][$this->getEntityIndexName($key)] = array($key);
+
+ $key = $this->entityType->getKey('revision');
+ $schema['indexes'][$this->getEntityIndexName($key)] = array($key);
+
+ if (isset($this->fieldDefinitions['revision_uid'])) {
+ $key = 'revision_uid';
+ $schema['indexes'][$this->getEntityIndexName($key)] = array($key);
+ }
+
+ return $schema;
+ }
+
+ /**
+ * Initializes common information for a data table.
+ *
+ * @return array
+ * A partial schema array for the data table.
+ */
+ protected function initializeDataTable() {
+ $id_key = $this->entityType->getKey('id');
+ $schema = array(
+ 'description' => "The data table for {$this->entityType->id()} entities.",
+ // @todo Use the language entity key when https://drupal.org/node/2143729
+ // is in.
+ 'primary key' => array($id_key, 'langcode'),
+ 'foreign keys' => array(
+ $id_key => array(
+ 'table' => $this->entityType->getBaseTable(),
+ 'columns' => array($id_key => $id_key),
+ ),
+ ),
+ );
+
+ if ($this->storage->getLayoutType() & ContentEntityDatabaseStorage::LAYOUT_REVISION) {
+ $key = $this->entityType->getKey('revision');
+ $schema['indexes'][$this->getEntityIndexName($key)] = array($key);
+ }
+
+ return $schema;
+ }
+
+ /**
+ * Initializes common information for a revision data table.
+ *
+ * @return array
+ * A partial schema array for the revision data table.
+ */
+ protected function initializeRevisionDataTable() {
+ $id_key = $this->entityType->getKey('id');
+ $revision_key = $this->entityType->getKey('revision');
+ $schema = array(
+ 'description' => "The revision data table for {$this->entityType->id()} entities.",
+ // @todo Use the language entity key when https://drupal.org/node/2143729
+ // is in.
+ 'primary key' => array($revision_key, 'langcode'),
+ 'foreign keys' => array(
+ $id_key => array(
+ 'table' => $this->entityType->getBaseTable(),
+ 'columns' => array($id_key => $id_key),
+ ),
+ $revision_key => array(
+ 'table' => $this->entityType->getRevisionTable(),
+ 'columns' => array($revision_key => $revision_key),
+ )
+ ),
+ );
+
+ $key = $this->entityType->getKey('id');
+ $schema['indexes'][$this->getEntityIndexName($key)] = array($key);
+
+ return $schema;
+ }
+
+ /**
+ * Processes the gathered schema for a base table.
+ *
+ * @param array $schema
+ * The table schema, passed by reference.
+ *
+ * @return array
+ * A partial schema array for the base table.
+ */
+ protected function processBaseTable(array &$schema) {
+ $this->processIdentifierSchema($schema, $this->entityType->getKey('id'));
+ }
+
+ /**
+ * Processes the gathered schema for a base table.
+ *
+ * @param array $schema
+ * The table schema, passed by reference.
+ *
+ * @return array
+ * A partial schema array for the base table.
+ */
+ protected function processRevisionTable(array &$schema) {
+ $this->processIdentifierSchema($schema, $this->entityType->getKey('revision'));
+ }
+
+ /**
+ * Processes the gathered schema for a base table.
+ *
+ * @param array $schema
+ * The table schema, passed by reference.
+ *
+ * @return array
+ * A partial schema array for the base table.
+ */
+ protected function processDataTable(array &$schema) {
+ $schema['fields']['default_langcode'] = $this->getDefaultLangcodeSchema();
+ }
+
+ /**
+ * Processes the gathered schema for a base table.
+ *
+ * @param array $schema
+ * The table schema, passed by reference.
+ *
+ * @return array
+ * A partial schema array for the base table.
+ */
+ protected function processRevisionDataTable(array &$schema) {
+ $schema['fields']['default_langcode'] = $this->getDefaultLangcodeSchema();
+ }
+
+ /**
+ * Processes the specified entity key.
+ *
+ * @param string $key
+ * The entity key name.
+ */
+ protected function processIdentifierSchema(&$schema, $key) {
+ if ($schema['fields'][$key]['type'] == 'int') {
+ $schema['fields'][$key]['type'] = 'serial';
+ }
+ unset($schema['fields'][$key]['default']);
+ }
+
+ /**
+ * Returns the name to be used for the given entity index.
+ *
+ * @param string $index
+ * The index column name.
+ *
+ * @return string
+ * The index name.
+ */
+ protected function getEntityIndexName($index) {
+ return $this->entityType->id() . '__' . $index;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Entity/Schema/ContentEntitySchemaHandlerInterface.php b/core/lib/Drupal/Core/Entity/Schema/ContentEntitySchemaHandlerInterface.php
new file mode 100644
index 0000000..5b958d8
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/Schema/ContentEntitySchemaHandlerInterface.php
@@ -0,0 +1,21 @@
+ 'Stores contents of custom-made blocks.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'serial',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => "The block's {custom_block}.id.",
- ),
- 'uuid' => array(
- 'description' => 'Unique Key: Universally unique identifier for this entity.',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => FALSE,
- ),
- 'info' => array(
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => 'Block description.',
- ),
- // Defaults to NULL in order to avoid a brief period of potential
- // deadlocks on the index.
- 'revision_id' => array(
- 'description' => 'The current {block_custom_revision}.revision_id version identifier.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- 'default' => NULL,
- ),
- 'type' => array(
- 'description' => 'The type of this custom block.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'changed' => array(
- 'description' => 'The Unix timestamp when the custom block was most recently saved.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this node.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- ),
- 'primary key' => array('id'),
- 'indexes' => array(
- 'block_custom_type' => array(array('type', 4)),
- ),
- 'unique keys' => array(
- 'revision_id' => array('revision_id'),
- 'uuid' => array('uuid'),
- 'info' => array('info'),
- ),
- 'foreign keys' => array(
- 'custom_block_revision' => array(
- 'table' => 'custom_block_revision',
- 'columns' => array('revision_id' => 'revision_id'),
- ),
- ),
- );
-
- $schema['custom_block_revision'] = array(
- 'description' => 'Stores contents of custom-made blocks.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- 'description' => "The block's {custom_block}.id.",
- ),
- // Defaults to NULL in order to avoid a brief period of potential
- // deadlocks on the index.
- 'revision_id' => array(
- 'description' => 'The current version identifier.',
- 'type' => 'serial',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'log' => array(
- 'description' => 'The log entry explaining the changes in this version.',
- 'type' => 'text',
- 'not null' => TRUE,
- 'size' => 'big',
- ),
- 'info' => array(
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => 'Block description.',
- ),
- 'changed' => array(
- 'description' => 'The Unix timestamp when the version was most recently saved.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- ),
- 'primary key' => array('revision_id'),
- );
- return $schema;
-}
-
-/**
* Implements hook_schema_0().
*/
function custom_block_schema_0() {
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorage.php b/core/modules/comment/lib/Drupal/comment/CommentStorage.php
index d05b2c3..b0958d4 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStorage.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStorage.php
@@ -9,6 +9,7 @@
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\ContentEntityDatabaseStorage;
use Drupal\field\FieldInfo;
@@ -36,13 +37,15 @@ class CommentStorage extends ContentEntityDatabaseStorage implements CommentStor
* An array of entity info for the entity type.
* @param \Drupal\Core\Database\Connection $database
* The database connection to be used.
- * @param \Drupal\field\FieldInfo $field_info
- * The field info service.
+ * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+ * The entity manager.
* @param \Drupal\comment\CommentStatisticsInterface $comment_statistics
* The comment statistics service.
+ * @param \Drupal\field\FieldInfo $field_info
+ * The field info service.
*/
- public function __construct(EntityTypeInterface $entity_info, Connection $database, FieldInfo $field_info, CommentStatisticsInterface $comment_statistics) {
- parent::__construct($entity_info, $database, $field_info);
+ public function __construct(EntityTypeInterface $entity_info, Connection $database, EntityManagerInterface $entity_manager, CommentStatisticsInterface $comment_statistics, FieldInfo $field_info) {
+ parent::__construct($entity_info, $database, $entity_manager, $field_info);
$this->statistics = $comment_statistics;
}
@@ -53,8 +56,9 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
return new static(
$entity_info,
$container->get('database'),
- $container->get('field.info'),
- $container->get('comment.statistics')
+ $container->get('entity.manager'),
+ $container->get('comment.statistics'),
+ $container->get('field.info')
);
}
diff --git a/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php
index 753745f..0ae29c8 100644
--- a/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php
+++ b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php
@@ -27,7 +27,7 @@ class EditTestBase extends DrupalUnitTestBase {
protected function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array('entity_test', 'entity_test_rev'));
+ $this->installEntitySchema('entity_test');
$this->installConfig(array('field', 'filter'));
}
diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module
index 1fa3852..c14ff66 100644
--- a/core/modules/entity/entity.module
+++ b/core/modules/entity/entity.module
@@ -9,6 +9,7 @@
*/
use Drupal\Core\Config\Entity\ConfigEntityStorage;
+use Drupal\Core\Entity\Schema\ContentEntitySchemaHandlerInterface;
/**
* Implements hook_help().
@@ -99,6 +100,38 @@ function entity_entity_bundle_delete($entity_type_id, $bundle) {
}
/**
+ * Implements hook_modules_installed().
+ */
+function entity_modules_installed($modules) {
+ // Install entity type tables.
+ $entity_manager = \Drupal::entityManager();
+ $schema = \Drupal::database()->schema();
+ $definitions = $entity_manager->getDefinitions();
+ $installed = array();
+
+ foreach ($modules as $module) {
+ foreach ($definitions as $entity_type_id => $entity_type) {
+ if ($entity_type->getProvider() == $module) {
+ $storage = $entity_manager->getStorage($entity_type_id);
+ if ($storage instanceof ContentEntitySchemaHandlerInterface) {
+ foreach ($storage->getSchema() as $table_name => $table_schema) {
+ // @todo Remove the drupal_get_schema() call once all entity types
+ // have been converted to an automatic schema.
+ if (!drupal_get_schema($table_name) && !$schema->tableExists($table_name)) {
+ $schema->createTable($table_name, $table_schema);
+ $installed[$module] = $entity_type_id;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // TODO Document this.
+ \Drupal::moduleHandler()->invokeAll('entity_schema_installed', array($installed));
+}
+
+/**
* Implements hook_module_preuninstall().
*/
function entity_module_preuninstall($module) {
@@ -112,3 +145,30 @@ function entity_module_preuninstall($module) {
}
}
}
+
+/**
+ * Implements hook_modules_uninstalled().
+ */
+function entity_modules_uninstalled($modules) {
+ $entity_manager = \Drupal::entityManager();
+ $schema = \Drupal::database()->schema();
+ $definitions = $entity_manager->getDefinitions();
+
+ foreach ($modules as $module) {
+ foreach ($definitions as $entity_type_id => $entity_type) {
+ if ($entity_type->getProvider() == $module) {
+ // Remove entity tables.
+ $storage = $entity_manager->getStorage($entity_type->id());
+ if ($storage instanceof ContentEntitySchemaHandlerInterface) {
+ foreach ($storage->getSchema() as $table_name => $table_schema) {
+ // @todo Remove the drupal_get_schema() call once all entity types
+ // have been converted to an automatic schema.
+ if (!drupal_get_schema($table_name) && $schema->tableExists($table_name)) {
+ $schema->dropTable($table_name, $table_schema);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFieldTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFieldTest.php
index f035f37..f032080 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFieldTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFieldTest.php
@@ -75,7 +75,7 @@ public static function getInfo() {
public function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array('entity_test_rev', 'entity_test_rev_revision'));
+ $this->installEntitySchema('entity_test_rev');
// Setup a field and instance.
entity_reference_create_instance(
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
index 4b0e85e..eed2791 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
@@ -36,7 +36,7 @@ public static function getInfo() {
public function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array('entity_test_rev', 'entity_test_rev_revision'));
+ $this->installEntitySchema('entity_test_rev');
}
/**
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
index cf43966..8f9d07c 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
@@ -35,7 +35,7 @@
*/
function setUp() {
parent::setUp();
- $this->installSchema('entity_test', 'entity_test');
+ $this->installEntitySchema('entity_test', 'entity_test');
$this->installSchema('system', array('sequences', 'config_snapshot'));
$this->installSchema('user', array('users', 'users_roles'));
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
index d8d9f9c..85ea0dc 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
@@ -33,7 +33,7 @@ class TranslationWebTest extends FieldTestBase {
*
* @var string
*/
- protected $entity_type = 'entity_test_rev';
+ protected $entity_type = 'entity_test_mulrev';
/**
* The field to use in this test.
@@ -78,7 +78,7 @@ function setUp() {
'bundle' => $this->entity_type,
);
entity_create('field_instance_config', $instance)->save();
- $this->instance = entity_load('field_instance_config', 'entity_test.' . $instance['bundle'] . '.' . $this->field_name);
+ $this->instance = entity_load('field_instance_config', $this->entity_type . '.' . $instance['bundle'] . '.' . $this->field_name);
entity_get_form_display($this->entity_type, $this->entity_type, 'default')
->setComponent($this->field_name)
diff --git a/core/modules/file/file.install b/core/modules/file/file.install
index fb5a4eb..17722b4 100644
--- a/core/modules/file/file.install
+++ b/core/modules/file/file.install
@@ -9,104 +9,6 @@
* Implements hook_schema().
*/
function file_schema() {
- $schema['file_managed'] = array(
- 'description' => 'Stores information for uploaded files.',
- 'fields' => array(
- 'fid' => array(
- 'description' => 'File ID.',
- 'type' => 'serial',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'uuid' => array(
- 'description' => 'Unique Key: Universally unique identifier for this entity.',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => FALSE,
- ),
- 'uid' => array(
- 'description' => 'The {users}.uid of the user who is associated with the file.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'filename' => array(
- 'description' => 'Name of the file with no path components. This may differ from the basename of the URI if the file is renamed to avoid overwriting an existing file.',
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'uri' => array(
- 'description' => 'The URI to access the file (either local or remote).',
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => '',
- 'binary' => TRUE,
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this file.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'filemime' => array(
- 'description' => "The file's MIME type.",
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'filesize' => array(
- 'description' => 'The size of the file in bytes.',
- 'type' => 'int',
- 'size' => 'big',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'status' => array(
- 'description' => 'A field indicating the status of the file. Two status are defined in core: temporary (0) and permanent (1). Temporary files older than DRUPAL_MAXIMUM_TEMP_FILE_AGE will be removed during a cron run.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- 'size' => 'tiny',
- ),
- 'created' => array(
- 'description' => 'UNIX timestamp for when the file added.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'changed' => array(
- 'description' => 'UNIX timestamp for when the file was last changed.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- ),
- 'indexes' => array(
- 'uid' => array('uid'),
- 'status' => array('status'),
- 'changed' => array('changed'),
- ),
- 'unique keys' => array(
- 'uuid' => array('uuid'),
- 'uri' => array('uri'),
- ),
- 'primary key' => array('fid'),
- 'foreign keys' => array(
- 'file_owner' => array(
- 'table' => 'users',
- 'columns' => array('uid' => 'uid'),
- ),
- ),
- );
$schema['file_usage'] = array(
'description' => 'Track where a file is used.',
diff --git a/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php b/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php
index 7f859a1..e3c09f6 100644
--- a/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php
+++ b/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php
@@ -63,7 +63,7 @@ function setUp() {
parent::setUp();
$this->installSchema('system', array('url_alias', 'router'));
$this->installSchema('user', array('users'));
- $this->installSchema('entity_test', array('entity_test'));
+ $this->installEntitySchema('entity_test');
$this->installConfig(array('field', 'language'));
// Add English as a language.
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index a6af612..2634bb2 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -39,310 +39,6 @@ function node_requirements($phase) {
* Implements hook_schema().
*/
function node_schema() {
- $schema['node'] = array(
- 'description' => 'The base table for nodes.',
- 'fields' => array(
- 'nid' => array(
- 'description' => 'The primary identifier for a node.',
- 'type' => 'serial',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'uuid' => array(
- 'description' => 'Unique Key: Universally unique identifier for this entity.',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => FALSE,
- ),
- // Defaults to NULL in order to avoid a brief period of potential
- // deadlocks on the index.
- 'vid' => array(
- 'description' => 'The current {node_field_revision}.vid version identifier.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- 'default' => NULL,
- ),
- 'type' => array(
- 'description' => 'The type of this node.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- ),
- 'indexes' => array(
- 'node_type' => array(array('type', 4)),
- ),
- 'unique keys' => array(
- 'vid' => array('vid'),
- 'uuid' => array('uuid'),
- ),
- 'foreign keys' => array(
- 'node_revision' => array(
- 'table' => 'node_revision',
- 'columns' => array('vid' => 'vid'),
- ),
- ),
- 'primary key' => array('nid'),
- );
-
- $schema['node_revision'] = array(
- 'description' => 'Stores information about each saved version of a {node}.',
- 'fields' => array(
- 'nid' => array(
- 'description' => 'The {node} this version belongs to.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'vid' => array(
- 'description' => 'The primary identifier for this version.',
- 'type' => 'serial',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'revision_uid' => array(
- 'description' => 'The {users}.uid that created this version.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'log' => array(
- 'description' => 'The log entry explaining the changes in this version.',
- 'type' => 'text',
- 'not null' => FALSE,
- 'size' => 'big',
- ),
- 'revision_timestamp' => array(
- 'description' => 'The Unix timestamp when the version was created.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this version.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- ),
- 'indexes' => array(
- 'nid' => array('nid'),
- 'revision_uid' => array('revision_uid'),
- 'node_langcode' => array('langcode'),
- ),
- 'foreign keys' => array(
- 'versioned_node' => array(
- 'table' => 'node',
- 'columns' => array('nid' => 'nid'),
- ),
- 'version_author' => array(
- 'table' => 'users',
- 'columns' => array('revision_uid' => 'uid'),
- ),
- ),
- 'primary key' => array('vid'),
- );
-
- // Node field storage.
- $schema['node_field_data'] = array(
- 'description' => 'Data table for node base fields.',
- 'fields' => array(
- 'nid' => array(
- 'description' => 'The primary identifier for a node.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'vid' => array(
- 'description' => 'The current {node_field_revision}.vid version identifier.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'type' => array(
- 'description' => 'The {node_type}.type of this node.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of these node property values.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'default_langcode' => array(
- 'description' => 'Boolean indicating whether the property values are in the {language}.langcode of this node.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 1,
- ),
- 'title' => array(
- 'description' => 'The title of this node, always treated as non-markup plain text.',
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'uid' => array(
- 'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'status' => array(
- 'description' => 'Boolean indicating whether the node translation is published (visible to non-administrators).',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 1,
- ),
- 'created' => array(
- 'description' => 'The Unix timestamp when the node translation was created.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'changed' => array(
- 'description' => 'The Unix timestamp when the node translation was most recently saved.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'promote' => array(
- 'description' => 'Boolean indicating whether the node translation should be displayed on the front page.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'sticky' => array(
- 'description' => 'Boolean indicating whether the node translation should be displayed at the top of lists in which it appears.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- ),
- 'indexes' => array(
- 'node_changed' => array('changed'),
- 'node_created' => array('created'),
- 'node_default_langcode' => array('default_langcode'),
- 'node_langcode' => array('langcode'),
- 'node_frontpage' => array('promote', 'status', 'sticky', 'created'),
- 'node_status_type' => array('status', 'type', 'nid'),
- 'node_title_type' => array('title', array('type', 4)),
- 'node_type' => array(array('type', 4)),
- 'vid' => array('vid'),
- 'uid' => array('uid'),
- ),
- 'foreign keys' => array(
- 'node_base' => array(
- 'table' => 'node',
- 'columns' => array('nid' => 'nid'),
- ),
- 'node_author' => array(
- 'table' => 'users',
- 'columns' => array('uid' => 'uid'),
- ),
- ),
- 'primary key' => array('nid', 'langcode'),
- );
-
- $schema['node_field_revision'] = array(
- 'description' => 'Revision table for node base fields.',
- 'fields' => array(
- 'nid' => array(
- 'description' => 'The {node} this version belongs to.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'vid' => array(
- 'description' => 'The primary identifier for this version.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this version.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'default_langcode' => array(
- 'description' => 'Boolean indicating whether the property values of this version are in the {language}.langcode of this node.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 1,
- ),
- 'title' => array(
- 'description' => 'The title of this version, always treated as non-markup plain text.',
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'uid' => array(
- 'description' => 'The {users}.uid that created this node.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'status' => array(
- 'description' => 'Boolean indicating whether the node (at the time of this revision) is published (visible to non-administrators).',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 1,
- ),
- 'created' => array(
- 'description' => 'The Unix timestamp when the node was created.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'changed' => array(
- 'description' => 'The Unix timestamp when the version was most recently saved.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'promote' => array(
- 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed on the front page.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'sticky' => array(
- 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- ),
- 'indexes' => array(
- 'uid' => array('uid'),
- 'node_default_langcode' => array('default_langcode'),
- 'node_langcode' => array('langcode'),
- ),
- 'foreign keys' => array(
- 'versioned_node' => array(
- 'table' => 'node',
- 'columns' => array('nid' => 'nid'),
- ),
- 'node_author' => array(
- 'table' => 'users',
- 'columns' => array('uid' => 'uid'),
- ),
- ),
- 'primary key' => array('vid', 'langcode'),
- );
$schema['node_access'] = array(
'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.',
diff --git a/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php b/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php
index adff21d..78a8629 100644
--- a/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php
+++ b/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php
@@ -58,7 +58,6 @@ public function testPatchUpdate() {
$patch_entity = entity_create($entity_type, $patch_values);
// We don't want to overwrite the UUID.
unset($patch_entity->uuid);
- $patch_entity->save();
$serialized = $serializer->serialize($patch_entity, $this->defaultFormat);
// Update the entity over the REST API.
diff --git a/core/modules/serialization/lib/Drupal/serialization/Tests/EntitySerializationTest.php b/core/modules/serialization/lib/Drupal/serialization/Tests/EntitySerializationTest.php
index 865704d..1ad843a 100644
--- a/core/modules/serialization/lib/Drupal/serialization/Tests/EntitySerializationTest.php
+++ b/core/modules/serialization/lib/Drupal/serialization/Tests/EntitySerializationTest.php
@@ -80,18 +80,12 @@ public function testNormalize() {
'id' => array(
array('value' => 1),
),
- 'revision_id' => array(
- array('value' => 1),
- ),
'uuid' => array(
array('value' => $this->entity->uuid()),
),
'langcode' => array(
array('value' => Language::LANGCODE_NOT_SPECIFIED),
),
- 'default_langcode' => array(
- array('value' => NULL),
- ),
'name' => array(
array('value' => $this->values['name']),
),
@@ -101,6 +95,9 @@ public function testNormalize() {
'user_id' => array(
array('target_id' => $this->values['user_id']),
),
+ 'revision_id' => array(
+ array('value' => 1),
+ ),
'field_test_text' => array(
array(
'value' => $this->values['field_test_text']['value'],
@@ -141,13 +138,12 @@ public function testSerialize() {
// order.
$expected = array(
'id' => '' . $this->entity->id() . '',
- 'revision_id' => '' . $this->entity->getRevisionId() . '',
'uuid' => '' . $this->entity->uuid() . '',
'langcode' => '' . Language::LANGCODE_NOT_SPECIFIED . '',
- 'default_langcode' => '',
'name' => '' . $this->values['name'] . '',
'type' => 'entity_test_mulrev',
'user_id' => '' . $this->values['user_id'] . '',
+ 'revision_id' => '' . $this->entity->getRevisionId() . '',
'field_test_text' => '' . $this->values['field_test_text']['value'] . '' . $this->values['field_test_text']['format'] . '',
);
// Sort it in the same order as normalised.
diff --git a/core/modules/serialization/lib/Drupal/serialization/Tests/NormalizerTestBase.php b/core/modules/serialization/lib/Drupal/serialization/Tests/NormalizerTestBase.php
index 3b0cfd6..c4eb1ca 100644
--- a/core/modules/serialization/lib/Drupal/serialization/Tests/NormalizerTestBase.php
+++ b/core/modules/serialization/lib/Drupal/serialization/Tests/NormalizerTestBase.php
@@ -21,7 +21,7 @@
protected function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array('entity_test_mulrev', 'entity_test_mulrev_revision', 'entity_test_mulrev_property_revision', 'entity_test_mulrev_property_data'));
+ $this->installEntitySchema('entity_test_mulrev');
$this->installSchema('user', array('users', 'users_roles'));
$this->installSchema('system', array('url_alias'));
$this->installConfig(array('field'));
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Entity/Shortcut.php b/core/modules/shortcut/lib/Drupal/shortcut/Entity/Shortcut.php
index eaf7079..255200a 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/Entity/Shortcut.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Entity/Shortcut.php
@@ -170,10 +170,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setLabel(t('Language code'))
->setDescription(t('The language code of the shortcut.'));
- $fields['default_langcode'] = FieldDefinition::create('boolean')
- ->setLabel(t('Default language'))
- ->setDescription(t('Flag to indicate whether this is the default language.'));
-
$fields['path'] = FieldDefinition::create('string')
->setLabel(t('Path'))
->setDescription(t('The computed shortcut path.'))
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
index 7737cc8..5d89844 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
@@ -7,8 +7,10 @@
namespace Drupal\simpletest;
+use Drupal\Component\Utility\String;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DrupalKernel;
+use Drupal\Core\Entity\Schema\ContentEntitySchemaHandlerInterface;
use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
use Drupal\Core\Language\Language;
use Symfony\Component\DependencyInjection\Reference;
@@ -332,6 +334,36 @@ protected function installSchema($module, $tables) {
}
/**
+ * Installs the tables for a specific entity type.
+ *
+ * @param string $entity_type_id
+ * The ID of the entity type.
+ */
+ protected function installEntitySchema($entity_type_id) {
+ /** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */
+ $entity_manager = $this->container->get('entity.manager');
+ /** @var \Drupal\Core\Database\Schema $schema_handler */
+ $schema_handler = $this->container->get('database')->schema();
+
+ $storage = $entity_manager->getStorage($entity_type_id);
+ if ($storage instanceof ContentEntitySchemaHandlerInterface) {
+ $schema = $storage->getSchema();
+ foreach ($schema as $table_name => $table_schema) {
+ $schema_handler->createTable($table_name, $table_schema);
+ }
+ $this->pass(String::format('Installed entity type tables for the %entity_type entity type: %tables', array(
+ '%entity_type' => $entity_type_id,
+ '%tables' => '{' . implode('}, {', array_keys($schema)) . '}',
+ )));
+ }
+ else {
+ throw new \RuntimeException(String::format('Entity type %entity_type does not support automatic schema installation.', array(
+ '%entity-type' => $entity_type_id,
+ )));
+ }
+ }
+
+ /**
* Enables modules for this test.
*
* @param array $modules
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
index 2acf138..6cd8d39 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
@@ -19,7 +19,7 @@ class DrupalUnitTestBaseTest extends DrupalUnitTestBase {
*
* @var array
*/
- public static $modules = array('entity', 'entity_test');
+ public static $modules = array('entity', 'entity_test', 'field', 'simpletest_test');
public static function getInfo() {
return array(
@@ -33,17 +33,18 @@ public static function getInfo() {
* Tests expected behavior of setUp().
*/
function testSetUp() {
- $modules = array('entity', 'entity_test');
- $table = 'entity_test';
+ $tables = array('entity_test', 'simpletest_test');
// Verify that specified $modules have been loaded.
$this->assertTrue(function_exists('entity_test_permission'), 'entity_test.module was loaded.');
// Verify that there is a fixed module list.
- $this->assertIdentical(array_keys(\Drupal::moduleHandler()->getModuleList()), $modules);
- $this->assertIdentical(\Drupal::moduleHandler()->getImplementations('permission'), $modules);
+ $this->assertIdentical(array_keys(\Drupal::moduleHandler()->getModuleList()), static::$modules);
+ $this->assertIdentical(\Drupal::moduleHandler()->getImplementations('permission'), array('entity', 'entity_test'));
// Verify that no modules have been installed.
- $this->assertFalse(db_table_exists($table), "'$table' database table not found.");
+ foreach($tables as $table){
+ $this->assertFalse(db_table_exists($table), "'$table' database table not found.");
+ }
}
/**
@@ -124,8 +125,8 @@ function testEnableModulesInstallContainer() {
* Tests expected behavior of installSchema().
*/
function testInstallSchema() {
- $module = 'entity_test';
- $table = 'entity_test';
+ $module = 'simpletest_test';
+ $table = 'simpletest_test';
// Verify that we can install a table from the module schema.
$this->installSchema($module, $table);
$this->assertTrue(db_table_exists($table), "'$table' database table found.");
diff --git a/core/modules/simpletest/tests/modules/simpletest_test/simpletest_test.info.yml b/core/modules/simpletest/tests/modules/simpletest_test/simpletest_test.info.yml
new file mode 100644
index 0000000..6c98069
--- /dev/null
+++ b/core/modules/simpletest/tests/modules/simpletest_test/simpletest_test.info.yml
@@ -0,0 +1,7 @@
+name: Simpletest Test
+type: module
+description: 'Provides dummy hook implementations for use by SimpleTest tests.'
+package: Testing
+version: VERSION
+core: 8.x
+hidden: TRUE
diff --git a/core/modules/simpletest/tests/modules/simpletest_test/simpletest_test.install b/core/modules/simpletest/tests/modules/simpletest_test/simpletest_test.install
new file mode 100644
index 0000000..f9b16a0
--- /dev/null
+++ b/core/modules/simpletest/tests/modules/simpletest_test/simpletest_test.install
@@ -0,0 +1,50 @@
+ 'Stores simpltest_test data.',
+ 'fields' => array(
+ 'sid' => array(
+ 'type' => 'serial',
+ 'not null' => TRUE,
+ 'description' => 'Primary Key: Unique ID.',
+ ),
+ 'uuid' => array(
+ 'description' => 'Unique Key: Universally unique identifier for this entity.',
+ 'type' => 'varchar',
+ 'length' => 128,
+ 'not null' => FALSE,
+ ),
+ 'dummy_textfield' => array(
+ 'type' => 'varchar',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'A Dummy text field.',
+ ),
+ 'dummy_integer' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'A dummy integer field.',
+ ),
+ ),
+ 'indexes' => array(
+ 'simpltest_test_index' => array('sid', 'dummy_integer'),
+ ),
+ 'primary key' => array('sid'),
+ 'unique keys' => array(
+ 'uuid' => array('uuid'),
+ ),
+ );
+
+ return $schema;
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php
index a9f0105..5d2364c 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php
@@ -25,16 +25,10 @@ public static function getInfo() {
public function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array(
- 'entity_test_mul',
- 'entity_test_mul_property_data',
- 'entity_test_rev',
- 'entity_test_rev_revision',
- 'entity_test_mulrev',
- 'entity_test_mulrev_revision',
- 'entity_test_mulrev_property_data',
- 'entity_test_mulrev_property_revision'
- ));
+
+ $this->installEntitySchema('entity_test_rev');
+ $this->installEntitySchema('entity_test_mul');
+ $this->installEntitySchema('entity_test_mulrev');
}
/**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
index 61c8c87..7435100 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
@@ -42,16 +42,10 @@ public function setUp() {
parent::setUp();
$this->installSchema('user', array('users_data'));
$this->installSchema('node', array('node', 'node_revision', 'node_field_data', 'node_field_revision', 'node_access'));
- $this->installSchema('entity_test', array(
- 'entity_test_mul',
- 'entity_test_mul_property_data',
- 'entity_test_rev',
- 'entity_test_rev_revision',
- 'entity_test_mulrev',
- 'entity_test_mulrev_revision',
- 'entity_test_mulrev_property_data',
- 'entity_test_mulrev_property_revision'
- ));
+
+ $this->installEntitySchema('entity_test_rev');
+ $this->installEntitySchema('entity_test_mul');
+ $this->installEntitySchema('entity_test_mulrev');
// Create the test field.
entity_test_install();
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLanguageTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLanguageTestBase.php
index bd2ceb9..db45c92 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLanguageTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLanguageTestBase.php
@@ -50,16 +50,10 @@ function setUp() {
$this->languageManager = $this->container->get('language_manager');
- $this->installSchema('entity_test', array(
- 'entity_test_mul',
- 'entity_test_mul_property_data',
- 'entity_test_rev',
- 'entity_test_rev_revision',
- 'entity_test_mulrev',
- 'entity_test_mulrev_revision',
- 'entity_test_mulrev_property_data',
- 'entity_test_mulrev_property_revision',
- ));
+ $this->installEntitySchema('entity_test_rev');
+ $this->installEntitySchema('entity_test_mul');
+ $this->installEntitySchema('entity_test_mulrev');
+
$this->installConfig(array('language'));
// Create the test field.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php
index 70f180e..4c2220f 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php
@@ -57,7 +57,9 @@ public static function getInfo() {
function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array('entity_test_mulrev', 'entity_test_mulrev_revision', 'entity_test_mulrev_property_data', 'entity_test_mulrev_property_revision'));
+
+ $this->installEntitySchema('entity_test_mulrev');
+
$this->installConfig(array('language'));
$figures = drupal_strtolower($this->randomName());
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUUIDTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUUIDTest.php
index ec7134c..a0ec726 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUUIDTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUUIDTest.php
@@ -23,16 +23,9 @@ public static function getInfo() {
public function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array(
- 'entity_test_mul',
- 'entity_test_mul_property_data',
- 'entity_test_rev',
- 'entity_test_rev_revision',
- 'entity_test_mulrev',
- 'entity_test_mulrev_revision',
- 'entity_test_mulrev_property_data',
- 'entity_test_mulrev_property_revision',
- ));
+ $this->installEntitySchema('entity_test_rev');
+ $this->installEntitySchema('entity_test_mul');
+ $this->installEntitySchema('entity_test_mulrev');
}
/**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
index 99fe76a..ffeb3c8 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
@@ -44,7 +44,9 @@ public function setUp() {
$this->installSchema('user', array('users', 'users_roles'));
$this->installSchema('system', 'sequences');
- $this->installSchema('entity_test', 'entity_test');
+
+ $this->installEntitySchema('entity_test');
+
$this->installConfig(array('field'));
}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php
index 118abe9..169ab3d 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php
@@ -38,16 +38,10 @@ public static function getInfo() {
public function setUp() {
parent::setUp();
$this->installSchema('user', array('users_data'));
- $this->installSchema('entity_test', array(
- 'entity_test_mul',
- 'entity_test_mul_property_data',
- 'entity_test_rev',
- 'entity_test_rev_revision',
- 'entity_test_mulrev',
- 'entity_test_mulrev_revision',
- 'entity_test_mulrev_property_data',
- 'entity_test_mulrev_property_revision'
- ));
+
+ $this->installEntitySchema('entity_test_rev');
+ $this->installEntitySchema('entity_test_mul');
+ $this->installEntitySchema('entity_test_mulrev');
// Create the test field.
entity_test_install();
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/FieldSqlStorageTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/FieldSqlStorageTest.php
index 82e63b2..de4aa63 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/FieldSqlStorageTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/FieldSqlStorageTest.php
@@ -66,7 +66,8 @@ public static function getInfo() {
function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array('entity_test_rev', 'entity_test_rev_revision'));
+
+ $this->installEntitySchema('entity_test_rev');
$entity_type = 'entity_test_rev';
$this->field_name = strtolower($this->randomName());
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.install b/core/modules/system/tests/modules/entity_test/entity_test.install
index 9e48029..f2db594 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.install
+++ b/core/modules/system/tests/modules/entity_test/entity_test.install
@@ -36,406 +36,3 @@ function entity_test_install() {
->save();
}
}
-
-/**
- * Implements hook_schema().
- */
-function entity_test_schema() {
- // Schema for simple entity.
- $schema['entity_test'] = array(
- 'description' => 'Stores entity_test items.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'serial',
- 'not null' => TRUE,
- 'description' => 'Primary Key: Unique entity-test item ID.',
- ),
- 'uuid' => array(
- 'description' => 'Unique Key: Universally unique identifier for this entity.',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => FALSE,
- ),
- 'type' => array(
- 'description' => 'The bundle of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of the original variant of this test entity.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'name' => array(
- 'description' => 'The name of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'user_id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- 'default' => NULL,
- 'description' => 'The {users}.uid of the associated user.',
- ),
- ),
- 'primary key' => array('id'),
- 'unique keys' => array(
- 'uuid' => array('uuid'),
- ),
- );
-
- // Schema for entity with revisions.
- $schema['entity_test_rev'] = array(
- 'description' => 'Stores entity_test_rev items.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'serial',
- 'not null' => TRUE,
- 'description' => 'Primary Key: Unique entity-test item ID.',
- ),
- 'revision_id' => array(
- 'description' => 'The current {entity_test_rev_property_revision}.revision_id version identifier.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'uuid' => array(
- 'description' => 'Unique Key: Universally unique identifier for this entity.',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => FALSE,
- ),
- 'type' => array(
- 'description' => 'The bundle of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'name' => array(
- 'description' => 'The name of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'user_id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- 'default' => NULL,
- 'description' => 'The {users}.uid of the associated user.',
- ),
- ),
- 'primary key' => array('id'),
- 'unique keys' => array(
- 'uuid' => array('uuid'),
- ),
- );
- $schema['entity_test_rev_revision'] = array(
- 'description' => 'Stores entity_test_rev item property revisions.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'The {entity_test_rev}.id of the test entity.',
- ),
- 'revision_id' => array(
- 'type' => 'serial',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'The primary identifier for this version.',
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this variant of this test entity.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'name' => array(
- 'description' => 'The name of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'user_id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- 'default' => NULL,
- 'description' => 'The {users}.uid of the associated user.',
- ),
- ),
- 'indexes' => array(
- 'user_id' => array('user_id'),
- ),
- 'foreign keys' => array(
- 'user_id' => array('users' => 'uid'),
- 'id' => array('entity_test_rev' => 'id'),
- ),
- 'primary key' => array('revision_id'),
- );
-
- // Schema for entity with data table.
- $schema['entity_test_mul'] = array(
- 'description' => 'Stores entity_test_mul items.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'serial',
- 'not null' => TRUE,
- 'description' => 'Primary Key: Unique entity-test item ID.',
- ),
- 'uuid' => array(
- 'description' => 'Unique Key: Universally unique identifier for this entity.',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => FALSE,
- ),
- 'type' => array(
- 'description' => 'The bundle of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of the original variant of this test entity.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- ),
- 'primary key' => array('id'),
- 'unique keys' => array(
- 'uuid' => array('uuid'),
- ),
- );
- $schema['entity_test_mul_property_data'] = array(
- 'description' => 'Stores entity_test_mul item properties.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'The {entity_test_mul}.id of the test entity.',
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this variant of this test entity.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'default_langcode' => array(
- 'description' => 'Boolean indicating whether the current variant is in the original entity language.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 1,
- ),
- 'name' => array(
- 'description' => 'The name of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => FALSE,
- ),
- 'user_id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- 'default' => NULL,
- 'description' => 'The {users}.uid of the associated user.',
- ),
- ),
- 'indexes' => array(
- 'user_id' => array('user_id'),
- ),
- 'foreign keys' => array(
- 'user_id' => array('users' => 'uid'),
- 'id' => array('entity_test_mul' => 'id'),
- ),
- 'primary key' => array('id', 'langcode'),
- );
-
- // Schema for entity with data table and revisions.
- $schema['entity_test_mulrev'] = array(
- 'description' => 'Stores entity_test_mulrev items.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'serial',
- 'not null' => TRUE,
- 'description' => 'Primary Key: Unique entity-test item ID.',
- ),
- 'revision_id' => array(
- 'description' => 'The current {entity_test_mulrev_property_revision}.revision_id version identifier.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'uuid' => array(
- 'description' => 'Unique Key: Universally unique identifier for this entity.',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => FALSE,
- ),
- 'type' => array(
- 'description' => 'The bundle of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- ),
- 'primary key' => array('id'),
- 'unique keys' => array(
- 'uuid' => array('uuid'),
- ),
- );
- $schema['entity_test_mulrev_revision'] = array(
- 'description' => 'Stores entity_test_rev item property revisions.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'The {entity_test_rev}.id of the test entity.',
- ),
- 'revision_id' => array(
- 'type' => 'serial',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'The primary identifier for this version.',
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this variant of this test entity.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- ),
- 'foreign keys' => array(
- 'id' => array('entity_test_rev' => 'id'),
- ),
- 'primary key' => array('revision_id'),
- );
- $schema['entity_test_mulrev_property_data'] = array(
- 'description' => 'Stores entity_test_mulrev item properties.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'The {entity_test_mulrev}.id of the test entity.',
- ),
- 'revision_id' => array(
- 'description' => 'The current {entity_test_mulrev_property_revision}.revision_id version identifier.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this variant of this test entity.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'default_langcode' => array(
- 'description' => 'Boolean indicating whether the current variant is in the original entity language.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 1,
- ),
- 'name' => array(
- 'description' => 'The name of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'user_id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- 'default' => NULL,
- 'description' => 'The {users}.uid of the associated user.',
- ),
- ),
- 'indexes' => array(
- 'user_id' => array('user_id'),
- ),
- 'foreign keys' => array(
- 'user_id' => array('users' => 'uid'),
- 'id' => array('entity_test_mulrev' => 'id'),
- ),
- 'primary key' => array('id', 'langcode'),
- );
- $schema['entity_test_mulrev_property_revision'] = array(
- 'description' => 'Stores entity_test_mulrev item property revisions.',
- 'fields' => array(
- 'id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'The {entity_test_mulrev}.id of the test entity.',
- ),
- 'revision_id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'The primary identifier for this version.',
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this variant of this test entity.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'default_langcode' => array(
- 'description' => 'Boolean indicating whether the current variant is in the original entity language.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 1,
- ),
- 'name' => array(
- 'description' => 'The name of the test entity.',
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'user_id' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => FALSE,
- 'default' => NULL,
- 'description' => 'The {users}.uid of the associated user.',
- ),
- ),
- 'indexes' => array(
- 'user_id' => array('user_id'),
- ),
- 'foreign keys' => array(
- 'user_id' => array('users' => 'uid'),
- 'id' => array('entity_test_mulrev' => 'id'),
- ),
- 'primary key' => array('revision_id', 'langcode'),
- );
-
- return $schema;
-}
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestBaseFieldDisplay.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestBaseFieldDisplay.php
index c76cff7..6b7100a 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestBaseFieldDisplay.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestBaseFieldDisplay.php
@@ -28,7 +28,6 @@
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid",
- * "revision" = "revision_id",
* "bundle" = "type"
* },
* links = {
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php
index 481711f..e881b9a 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php
@@ -15,7 +15,6 @@
* label = @Translation("Entity test label callback"),
* field_cache = FALSE,
* base_table = "entity_test",
- * revision_table = "entity_test_revision",
* label_callback = "entity_test_label_callback",
* fieldable = TRUE,
* entity_keys = {
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
index 49f7d5f..bec368c 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
@@ -44,17 +44,4 @@
*/
class EntityTestMul extends EntityTest {
- /**
- * {@inheritdoc}
- */
- public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
- $fields = parent::baseFieldDefinitions($entity_type);
-
- $fields['default_langcode'] = FieldDefinition::create('boolean')
- ->setLabel(t('Default language'))
- ->setDescription(t('Flag to indicate whether this is the default language.'));
-
- return $fields;
- }
-
}
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php
index 870af93..d1ea8da 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php
@@ -44,22 +44,4 @@
*/
class EntityTestMulRev extends EntityTestRev {
- /**
- * {@inheritdoc}
- */
- public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
- $fields = parent::baseFieldDefinitions($entity_type);
-
- $fields['revision_id'] = FieldDefinition::create('integer')
- ->setLabel(t('Revision ID'))
- ->setDescription(t('The version id of the test entity.'))
- ->setReadOnly(TRUE);
-
- $fields['default_langcode'] = FieldDefinition::create('boolean')
- ->setLabel(t('Default language'))
- ->setDescription(t('Flag to indicate whether this is the default language.'));
-
- return $fields;
- }
-
}
diff --git a/core/modules/taxonomy/taxonomy.install b/core/modules/taxonomy/taxonomy.install
index f76d350..fdf7fa1 100644
--- a/core/modules/taxonomy/taxonomy.install
+++ b/core/modules/taxonomy/taxonomy.install
@@ -9,77 +9,6 @@
* Implements hook_schema().
*/
function taxonomy_schema() {
- $schema['taxonomy_term_data'] = array(
- 'description' => 'Stores term information.',
- 'fields' => array(
- 'tid' => array(
- 'type' => 'serial',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'Primary Key: Unique term ID.',
- ),
- 'uuid' => array(
- 'description' => 'Unique Key: Universally unique identifier for this entity.',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => FALSE,
- ),
- 'vid' => array(
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => 'The ID of the vocabulary to which the term is assigned.',
- ),
- 'langcode' => array(
- 'description' => 'The {language}.langcode of this term.',
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- ),
- 'name' => array(
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => 'The term name.',
- ),
- 'description__value' => array(
- 'type' => 'text',
- 'not null' => FALSE,
- 'size' => 'big',
- 'description' => 'A description of the term.',
- ),
- 'description__format' => array(
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => FALSE,
- 'description' => 'The filter format ID of the description.',
- ),
- 'weight' => array(
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- 'description' => 'The weight of this term in relation to other terms.',
- ),
- 'changed' => array(
- 'description' => 'The Unix timestamp when the term was most recently saved.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- ),
- 'primary key' => array('tid'),
- 'unique keys' => array(
- 'uuid' => array('uuid'),
- ),
- 'indexes' => array(
- 'taxonomy_tree' => array(array('vid', 64), 'weight', 'name'),
- 'vid_name' => array(array('vid', 64), 'name'),
- 'name' => array('name'),
- ),
- );
$schema['taxonomy_term_hierarchy'] = array(
'description' => 'Stores the hierarchical relationship between terms.',
diff --git a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
index 8e37920..633ee0b 100644
--- a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
@@ -48,7 +48,7 @@ function setUp() {
// Configure the theme system.
$this->installConfig(array('system', 'field'));
- $this->installSchema('entity_test', 'entity_test');
+ $this->installEntitySchema('entity_test');
// @todo Add helper methods for all of the following.
diff --git a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
index 9b93095..30af0bf 100644
--- a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
@@ -50,7 +50,7 @@ public static function getInfo() {
public function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array('entity_test_rev', 'entity_test_rev_revision'));
+ $this->installEntitySchema('entity_test_rev');
// Create the necessary formats.
$this->installConfig(array('filter'));
diff --git a/core/modules/user/lib/Drupal/user/UserStorage.php b/core/modules/user/lib/Drupal/user/UserStorage.php
index d3f4990..6c74e91 100644
--- a/core/modules/user/lib/Drupal/user/UserStorage.php
+++ b/core/modules/user/lib/Drupal/user/UserStorage.php
@@ -9,7 +9,9 @@
use Drupal\Component\Uuid\UuidInterface;
use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\Schema\ContentEntitySchemaHandlerInterface;
use Drupal\Core\Password\PasswordInterface;
use Drupal\Core\Database\Connection;
use Drupal\field\FieldInfo;
@@ -46,17 +48,20 @@ class UserStorage extends ContentEntityDatabaseStorage implements UserStorageInt
* The entity type definition.
* @param \Drupal\Core\Database\Connection $database
* The database connection to be used.
- * @param \Drupal\field\FieldInfo $field_info
- * The field info service.
- * @param \Drupal\Component\Uuid\UuidInterface $uuid_service
- * The UUID Service.
+ * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+ * The entity manager.
+ * @param \Drupal\Core\Entity\Schema\ContentEntitySchemaHandlerInterface $schema_builder
+ * The entity schema builder.
* @param \Drupal\Core\Password\PasswordInterface $password
* The password hashing service.
* @param \Drupal\user\UserDataInterface $user_data
* The user data service.
+ * @param \Drupal\field\FieldInfo $field_info
+ * (optional) The field info service. Defaults to NULL as user storage can
+ * be instantiated before Field module is installed.
*/
- public function __construct(EntityTypeInterface $entity_type, Connection $database, FieldInfo $field_info, UuidInterface $uuid_service, PasswordInterface $password, UserDataInterface $user_data) {
- parent::__construct($entity_type, $database, $field_info, $uuid_service);
+ public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, PasswordInterface $password, UserDataInterface $user_data, FieldInfo $field_info = NULL) {
+ parent::__construct($entity_type, $database, $entity_manager, $field_info);
$this->password = $password;
$this->userData = $user_data;
@@ -69,10 +74,10 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
return new static(
$entity_type,
$container->get('database'),
- $container->get('field.info'),
- $container->get('uuid'),
+ $container->get('entity.manager'),
$container->get('password'),
- $container->get('user.data')
+ $container->get('user.data'),
+ $container->has('field.info') ? $container->get('field.info') : NULL
);
}
diff --git a/core/modules/user/user.info.yml b/core/modules/user/user.info.yml
index 45a421a..dbdb520 100644
--- a/core/modules/user/user.info.yml
+++ b/core/modules/user/user.info.yml
@@ -6,3 +6,5 @@ version: VERSION
core: 8.x
required: true
configure: user.admin_index
+dependencies:
+ - entity
diff --git a/core/modules/user/user.install b/core/modules/user/user.install
index c21e295..fda74db 100644
--- a/core/modules/user/user.install
+++ b/core/modules/user/user.install
@@ -12,129 +12,6 @@
* Implements hook_schema().
*/
function user_schema() {
- // The table name here is plural, despite Drupal table naming standards,
- // because "user" is a reserved word in many databases.
- $schema['users'] = array(
- 'description' => 'Stores user data.',
- 'fields' => array(
- 'uid' => array(
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'description' => 'Primary Key: Unique user ID.',
- 'default' => 0,
- ),
- 'uuid' => array(
- 'description' => 'Unique Key: Universally unique identifier for this entity.',
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => FALSE,
- ),
- 'name' => array(
- 'type' => 'varchar',
- 'length' => 60,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => 'Unique user name.',
- ),
- 'langcode' => array(
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => "The {language}.langcode of the user's profile.",
- ),
- 'pass' => array(
- 'type' => 'varchar',
- 'length' => 128,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => "User's password (hashed).",
- ),
- 'mail' => array(
- 'type' => 'varchar',
- 'length' => 254,
- 'not null' => FALSE,
- 'default' => '',
- 'description' => "User's e-mail address.",
- ),
- 'signature' => array(
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => "User's signature.",
- ),
- 'signature_format' => array(
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => FALSE,
- 'description' => 'The filter format ID of the signature.',
- ),
- 'created' => array(
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- 'description' => 'Timestamp for when user was created.',
- ),
- 'access' => array(
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- 'description' => 'Timestamp for previous time user accessed the site.',
- ),
- 'login' => array(
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- 'description' => "Timestamp for user's last login.",
- ),
- 'status' => array(
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- 'size' => 'tiny',
- 'description' => 'Whether the user is active(1) or blocked(0).',
- ),
- 'timezone' => array(
- 'type' => 'varchar',
- 'length' => 32,
- 'not null' => FALSE,
- 'description' => "User's time zone.",
- ),
- 'preferred_langcode' => array(
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => 'The {language}.langcode that the user prefers for receiving emails and viewing the site.',
- ),
- 'preferred_admin_langcode' => array(
- 'type' => 'varchar',
- 'length' => 12,
- 'not null' => TRUE,
- 'default' => '',
- 'description' => 'The {language}.langcode that the user prefers for viewing administration pages.',
- ),
- 'init' => array(
- 'type' => 'varchar',
- 'length' => 254,
- 'not null' => FALSE,
- 'default' => '',
- 'description' => 'E-mail address used for initial account creation.',
- ),
- ),
- 'indexes' => array(
- 'access' => array('access'),
- 'created' => array('created'),
- 'mail' => array('mail'),
- ),
- 'unique keys' => array(
- 'uuid' => array('uuid'),
- 'name' => array('name'),
- ),
- 'primary key' => array('uid'),
- );
$schema['users_data'] = array(
'description' => 'Stores module data as key/value pairs per user.',
@@ -217,31 +94,33 @@ function user_schema() {
}
/**
- * Implements hook_install().
+ * Implements hook_entity_schema_installed().
*/
-function user_install() {
- // Insert a row for the anonymous user.
- db_insert('users')
- ->fields(array(
- 'uid' => 0,
- 'uuid' => \Drupal::service('uuid')->generate(),
- 'name' => '',
- 'mail' => '',
- 'langcode' => language_default()->id,
- ))
- ->execute();
+function user_entity_schema_installed($installed) {
+ if (isset($installed['user'])) {
+ // Insert a row for the anonymous user.
+ db_insert('users')
+ ->fields(array(
+ 'uid' => 0,
+ 'uuid' => \Drupal::service('uuid')->generate(),
+ 'name' => '',
+ 'mail' => '',
+ 'langcode' => language_default()->id,
+ ))
+ ->execute();
- // We need some placeholders here as name and mail are uniques.
- // This will be changed by the settings form in the installer.
- db_insert('users')
- ->fields(array(
- 'uid' => 1,
- 'uuid' => \Drupal::service('uuid')->generate(),
- 'name' => 'placeholder-for-uid-1',
- 'mail' => 'placeholder-for-uid-1',
- 'created' => REQUEST_TIME,
- 'status' => 1,
- 'langcode' => language_default()->id,
- ))
- ->execute();
+ // We need some placeholders here as name and mail are uniques.
+ // This will be changed by the settings form in the installer.
+ db_insert('users')
+ ->fields(array(
+ 'uid' => 1,
+ 'uuid' => \Drupal::service('uuid')->generate(),
+ 'name' => 'placeholder-for-uid-1',
+ 'mail' => 'placeholder-for-uid-1',
+ 'created' => REQUEST_TIME,
+ 'status' => 1,
+ 'langcode' => language_default()->id,
+ ))
+ ->execute();
+ }
}
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 0ed9aa1..5de7394 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -146,6 +146,15 @@ function user_js_alter(&$javascript) {
}
/**
+ * Implements hook_entity_schema_alter().
+ */
+function user_entity_schema_alter(&$schema, $context) {
+ if ($context['entity_type_id'] == 'user') {
+ $schema['users']['fields']['uid']['type'] = 'int';
+ }
+}
+
+/**
* Implements hook_entity_bundle_info().
*/
function user_entity_bundle_info() {
diff --git a/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php b/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php
index 7b7d0b7..ff0c225 100644
--- a/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php
@@ -49,7 +49,7 @@ public static function getInfo() {
protected function setUp() {
parent::setUp();
- $this->installSchema('entity_test', array('entity_test'));
+ $this->installEntitySchema('entity_test');
$this->storage = $this->container->get('entity.manager')->getStorage('entity_test');
}