Commit 5289c3e3 authored by webchick's avatar webchick

Issue #2326949 by plach, effulgentsia: Move entity-type-specific schema...

Issue #2326949 by plach, effulgentsia: Move entity-type-specific schema information from the storage class to a schema handler.
parent 72450c6a
......@@ -13,13 +13,11 @@
use Drupal\Core\Database\Database;
use Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Entity\Schema\ContentEntitySchemaHandler;
use Drupal\Core\Entity\Sql\DefaultTableMapping;
use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -28,7 +26,7 @@
* This class can be used as-is by most content entity types. Entity types
* requiring special handling can extend the class.
*
* The class uses \Drupal\Core\Entity\Schema\ContentEntitySchemaHandler
* The class uses \Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema
* internally in order to automatically generate the database schema based on
* the defined base fields. Entity types can override
* ContentEntityDatabaseStorage::getSchema() to customize the generated
......@@ -229,12 +227,13 @@ public function getSchema() {
/**
* Gets the schema handler for this entity storage.
*
* @return \Drupal\Core\Entity\Schema\ContentEntitySchemaHandler
* @return \Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema
* The schema handler.
*/
protected function schemaHandler() {
if (!isset($this->schemaHandler)) {
$this->schemaHandler = new ContentEntitySchemaHandler($this->entityManager, $this->entityType, $this);
$schema_handler_class = $this->entityType->getHandlerClass('storage_schema') ?: 'Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema';
$this->schemaHandler = new $schema_handler_class($this->entityManager, $this->entityType, $this);
}
return $this->schemaHandler;
}
......@@ -1024,8 +1023,8 @@ protected function mapToStorageRecord(ContentEntityInterface $entity, $table_nam
* @return bool
* TRUE if the the column is serial, FALSE otherwise.
*
* @see \Drupal\Core\Entity\Schema\ContentEntitySchemaHandler::processBaseTable()
* @see \Drupal\Core\Entity\Schema\ContentEntitySchemaHandler::processRevisionTable()
* @see \Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema::processBaseTable()
* @see \Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema::processRevisionTable()
*/
protected function isColumnSerial($table_name, $schema_name) {
$result = FALSE;
......
......@@ -2,7 +2,7 @@
/**
* @file
* Contains \Drupal\Core\Entity\Schema\ContentEntitySchemaHandler.
* Contains \Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema.
*/
namespace Drupal\Core\Entity\Schema;
......@@ -14,7 +14,7 @@
/**
* Defines a schema handler that supports revisionable, translatable entities.
*/
class ContentEntitySchemaHandler implements EntitySchemaHandlerInterface {
class SqlContentEntityStorageSchema implements EntitySchemaHandlerInterface {
/**
* The entity type this schema builder is responsible for.
......@@ -45,7 +45,7 @@ class ContentEntitySchemaHandler implements EntitySchemaHandlerInterface {
protected $schema;
/**
* Constructs a ContentEntitySchemaHandler.
* Constructs a SqlContentEntityStorageSchema.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
......@@ -64,11 +64,28 @@ public function __construct(EntityManagerInterface $entity_manager, ContentEntit
* {@inheritdoc}
*/
public function getSchema() {
// Prepare basic information about the entity type.
$tables = $this->getTables();
return $this->getEntitySchema($this->entityType);
}
/**
* Returns the entity schema for the specified entity type.
*
* @param \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type
* The entity type definition.
* @param bool $reset
* (optional) If set to TRUE static cache will be ignored and a new schema
* array generation will be performed. Defaults to FALSE.
*
* @return array
* A Schema API array describing the entity schema, excluding dedicated
* field tables.
*/
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$entity_type_id = $entity_type->id();
if (!isset($this->schema[$this->entityType->id()])) {
if (!isset($this->schema[$entity_type_id]) || $reset) {
// Initialize the table schema.
$tables = $this->getTables();
$schema[$tables['base_table']] = $this->initializeBaseTable();
if (isset($tables['revision_table'])) {
$schema[$tables['revision_table']] = $this->initializeRevisionTable();
......@@ -108,10 +125,10 @@ public function getSchema() {
$this->processRevisionDataTable($schema[$tables['revision_data_table']]);
}
$this->schema[$this->entityType->id()] = $schema;
$this->schema[$entity_type_id] = $schema;
}
return $this->schema[$this->entityType->id()];
return $this->schema[$entity_type_id];
}
/**
......
......@@ -22,6 +22,7 @@
* label = @Translation("Aggregator feed"),
* handlers = {
* "storage" = "Drupal\aggregator\FeedStorage",
* "storage_schema" = "Drupal\aggregator\FeedStorageSchema",
* "view_builder" = "Drupal\aggregator\FeedViewBuilder",
* "access" = "Drupal\aggregator\FeedAccessControlHandler",
* "views_data" = "Drupal\aggregator\AggregatorFeedViewsData",
......
......@@ -23,6 +23,7 @@
* label = @Translation("Aggregator feed item"),
* handlers = {
* "storage" = "Drupal\aggregator\ItemStorage",
* "storage_schema" = "Drupal\aggregator\ItemStorageSchema",
* "view_builder" = "Drupal\aggregator\ItemViewBuilder",
* "access" = "Drupal\aggregator\FeedAccessControlHandler",
* "views_data" = "Drupal\aggregator\AggregatorItemViewsData"
......
......@@ -7,7 +7,6 @@
namespace Drupal\aggregator;
use Drupal\aggregator\FeedInterface;
use Drupal\Core\Entity\ContentEntityDatabaseStorage;
/**
......@@ -18,29 +17,6 @@
*/
class FeedStorage extends ContentEntityDatabaseStorage implements FeedStorageInterface {
/**
* {@inheritdoc}
*/
public function getSchema() {
$schema = parent::getSchema();
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['aggregator_feed']['fields']['url']['not null'] = TRUE;
$schema['aggregator_feed']['fields']['queued']['not null'] = TRUE;
$schema['aggregator_feed']['fields']['title']['not null'] = TRUE;
$schema['aggregator_feed']['indexes'] += array(
'aggregator_feed__url' => array(array('url', 255)),
'aggregator_feed__queued' => array('queued'),
);
$schema['aggregator_feed']['unique keys'] += array(
'aggregator_feed__title' => array('title'),
);
return $schema;
}
/**
* {@inheritdoc}
*/
......
<?php
/**
* @file
* Contains \Drupal\aggregator\FeedStorageSchema.
*/
namespace Drupal\aggregator;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema;
/**
* Defines the feed schema handler.
*/
class FeedStorageSchema extends SqlContentEntityStorageSchema {
/**
* {@inheritdoc}
*/
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset);
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['aggregator_feed']['fields']['url']['not null'] = TRUE;
$schema['aggregator_feed']['fields']['queued']['not null'] = TRUE;
$schema['aggregator_feed']['fields']['title']['not null'] = TRUE;
$schema['aggregator_feed']['indexes'] += array(
'aggregator_feed__url' => array(array('url', 255)),
'aggregator_feed__queued' => array('queued'),
);
$schema['aggregator_feed']['unique keys'] += array(
'aggregator_feed__title' => array('title'),
);
return $schema;
}
}
......@@ -7,9 +7,8 @@
namespace Drupal\aggregator;
use Drupal\aggregator\Entity\Item;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Entity\ContentEntityDatabaseStorage;
use Drupal\Core\Entity\Query\QueryInterface;
/**
* Controller class for aggregators items.
......@@ -19,29 +18,6 @@
*/
class ItemStorage extends ContentEntityDatabaseStorage implements ItemStorageInterface {
/**
* {@inheritdoc}
*/
public function getSchema() {
$schema = parent::getSchema();
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['aggregator_item']['fields']['timestamp']['not null'] = TRUE;
$schema['aggregator_item']['indexes'] += array(
'aggregator_item__timestamp' => array('timestamp'),
);
$schema['aggregator_item']['foreign keys'] += array(
'aggregator_item__aggregator_feed' => array(
'table' => 'aggregator_feed',
'columns' => array('fid' => 'fid'),
),
);
return $schema;
}
/**
* {@inheritdoc}
*/
......
<?php
/**
* @file
* Contains \Drupal\aggregator\ItemStorageSchema.
*/
namespace Drupal\aggregator;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema;
/**
* Defines the item schema handler.
*/
class ItemStorageSchema extends SqlContentEntityStorageSchema {
/**
* {@inheritdoc}
*/
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset);
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['aggregator_item']['fields']['timestamp']['not null'] = TRUE;
$schema['aggregator_item']['indexes'] += array(
'aggregator_item__timestamp' => array('timestamp'),
);
$schema['aggregator_item']['foreign keys'] += array(
'aggregator_item__aggregator_feed' => array(
'table' => 'aggregator_feed',
'columns' => array('fid' => 'fid'),
),
);
return $schema;
}
}
......@@ -2,23 +2,24 @@
/**
* @file
* Contains \Drupal\block_content\BlockContentStorage.
* Contains \Drupal\block_content\BlockContentStorageSchema.
*/
namespace Drupal\block_content;
use Drupal\Core\Entity\ContentEntityDatabaseStorage;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema;
/**
* Provides storage for the 'block_content' entity type.
* Defines the block content schema handler.
*/
class BlockContentStorage extends ContentEntityDatabaseStorage {
class BlockContentStorageSchema extends SqlContentEntityStorageSchema {
/**
* {@inheritdoc}
*/
public function getSchema() {
$schema = parent::getSchema();
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset);
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
......
......@@ -21,7 +21,8 @@
* label = @Translation("Custom Block"),
* bundle_label = @Translation("Custom Block type"),
* handlers = {
* "storage" = "Drupal\block_content\BlockContentStorage",
* "storage" = "Drupal\Core\Entity\ContentEntityDatabaseStorage",
* "storage_schema" = "Drupal\block_content\BlockContentStorageSchema",
* "access" = "Drupal\block_content\BlockContentAccessControlHandler",
* "list_builder" = "Drupal\block_content\BlockContentListBuilder",
* "view_builder" = "Drupal\block_content\BlockContentViewBuilder",
......
......@@ -9,11 +9,11 @@
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\ContentEntityDatabaseStorage;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\ContentEntityDatabaseStorage;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -318,48 +318,6 @@ public function loadThread(EntityInterface $entity, $field_name, $mode, $comment
return $comments;
}
/**
* {@inheritdoc}
*/
public function getSchema() {
$schema = parent::getSchema();
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['comment_field_data']['fields']['created']['not null'] = TRUE;
$schema['comment_field_data']['fields']['thread']['not null'] = TRUE;
unset($schema['comment_field_data']['indexes']['comment_field__pid__target_id']);
unset($schema['comment_field_data']['indexes']['comment_field__entity_id__target_id']);
$schema['comment_field_data']['indexes'] += array(
'comment__status_pid' => array('pid', 'status'),
'comment__num_new' => array(
'entity_id',
'entity_type',
'comment_type',
'status',
'created',
'cid',
'thread',
),
'comment__entity_langcode' => array(
'entity_id',
'entity_type',
'comment_type',
'default_langcode',
),
'comment__created' => array('created'),
);
$schema['comment_field_data']['foreign keys'] += array(
'comment__author' => array(
'table' => 'users',
'columns' => array('uid' => 'uid'),
),
);
return $schema;
}
/**
* {@inheritdoc}
*/
......
<?php
/**
* @file
* Contains \Drupal\comment\CommentStorageSchema.
*/
namespace Drupal\comment;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema;
/**
* Defines the comment schema handler.
*/
class CommentStorageSchema extends SqlContentEntityStorageSchema {
/**
* {@inheritdoc}
*/
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset);
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['comment_field_data']['fields']['created']['not null'] = TRUE;
$schema['comment_field_data']['fields']['thread']['not null'] = TRUE;
unset($schema['comment_field_data']['indexes']['comment_field__pid__target_id']);
unset($schema['comment_field_data']['indexes']['comment_field__entity_id__target_id']);
$schema['comment_field_data']['indexes'] += array(
'comment__status_pid' => array('pid', 'status'),
'comment__num_new' => array(
'entity_id',
'entity_type',
'comment_type',
'status',
'created',
'cid',
'thread',
),
'comment__entity_langcode' => array(
'entity_id',
'entity_type',
'comment_type',
'default_langcode',
),
'comment__created' => array('created'),
);
$schema['comment_field_data']['foreign keys'] += array(
'comment__author' => array(
'table' => 'users',
'columns' => array('uid' => 'uid'),
),
);
return $schema;
}
}
......@@ -25,6 +25,7 @@
* bundle_label = @Translation("Content type"),
* handlers = {
* "storage" = "Drupal\comment\CommentStorage",
* "storage_schema" = "Drupal\comment\CommentStorageSchema",
* "access" = "Drupal\comment\CommentAccessControlHandler",
* "view_builder" = "Drupal\comment\CommentViewBuilder",
* "views_data" = "Drupal\comment\CommentViewsData",
......
......@@ -23,6 +23,7 @@
* label = @Translation("File"),
* handlers = {
* "storage" = "Drupal\file\FileStorage",
* "storage_schema" = "Drupal\file\FileStorageSchema",
* "access" = "Drupal\file\FileAccessControlHandler",
* "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
* "views_data" = "Drupal\file\FileViewsData",
......
......@@ -27,29 +27,4 @@ public function spaceUsed($uid = NULL, $status = FILE_STATUS_PERMANENT) {
return $query->execute()->fetchField();
}
/**
* {@inheritdoc}
*/
public function getSchema() {
$schema = parent::getSchema();
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['file_managed']['fields']['status']['not null'] = TRUE;
$schema['file_managed']['fields']['changed']['not null'] = TRUE;
$schema['file_managed']['fields']['uri']['not null'] = TRUE;
// @todo There should be a 'binary' field type or setting.
$schema['file_managed']['fields']['uri']['binary'] = TRUE;
$schema['file_managed']['indexes'] += array(
'file__status' => array('status'),
'file__changed' => array('changed'),
);
$schema['file_managed']['unique keys'] += array(
'file__uri' => array('uri'),
);
return $schema;
}
}
<?php
/**
* @file
* Contains \Drupal\file\FileStorageSchema.
*/
namespace Drupal\file;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema;
/**
* Defines the file schema handler.
*/
class FileStorageSchema extends SqlContentEntityStorageSchema {
/**
* {@inheritdoc}
*/
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset);
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['file_managed']['fields']['status']['not null'] = TRUE;
$schema['file_managed']['fields']['changed']['not null'] = TRUE;
$schema['file_managed']['fields']['uri']['not null'] = TRUE;
// @todo There should be a 'binary' field type or setting.
$schema['file_managed']['fields']['uri']['binary'] = TRUE;
$schema['file_managed']['indexes'] += array(
'file__status' => array('status'),
'file__changed' => array('changed'),
);
$schema['file_managed']['unique keys'] += array(
'file__uri' => array('uri'),
);
return $schema;
}
}
......@@ -25,6 +25,7 @@
* bundle_label = @Translation("Content type"),
* handlers = {
* "storage" = "Drupal\node\NodeStorage",
* "storage_schema" = "Drupal\node\NodeStorageSchema",
* "view_builder" = "Drupal\node\NodeViewBuilder",
* "access" = "Drupal\node\NodeAccessControlHandler",
* "views_data" = "Drupal\node\NodeViewsData",
......
......@@ -59,50 +59,4 @@ public function clearRevisionsLanguage($language) {
->execute();
}
/**
* {@inheritdoc}
*/
public function getSchema() {
$schema = parent::getSchema();
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['node_field_data']['fields']['changed']['not null'] = TRUE;
$schema['node_field_data']['fields']['created']['not null'] = TRUE;
$schema['node_field_data']['fields']['default_langcode']['not null'] = TRUE;
$schema['node_field_data']['fields']['promote']['not null'] = TRUE;
$schema['node_field_data']['fields']['status']['not null'] = TRUE;
$schema['node_field_data']['fields']['sticky']['not null'] = TRUE;
$schema['node_field_data']['fields']['title']['not null'] = TRUE;
$schema['node_field_revision']['fields']['default_langcode']['not null'] = TRUE;
// @todo Revisit index definitions in https://drupal.org/node/2015277.
$schema['node_revision']['indexes'] += array(
'node__langcode' => array('langcode'),
);
$schema['node_revision']['foreign keys'] += array(
'node__revision_author' => array(
'table' => 'users',
'columns' => array('revision_uid' => 'uid'),
),
);
$schema['node_field_data']['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)),
);
$schema['node_field_revision']['indexes'] += array(
'node__default_langcode' => array('default_langcode'),
'node__langcode' => array('langcode'),
);
return $schema;
}
}
<?php
/**
* @file
* Contains \Drupal\node\NodeStorageSchema.
*/
namespace Drupal\node;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema;
/**
* Defines the node schema handler.
*/
class NodeStorageSchema extends SqlContentEntityStorageSchema {
/**
* {@inheritdoc}
*/
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset);
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['node_field_data']['fields']['changed']['not null'] = TRUE;
$schema['node_field_data']['fields']['created']['not null'] = TRUE;
$schema['node_field_data']['fields']['default_langcode']['not null'] = TRUE;
$schema['node_field_data']['fields']['promote']['not null'] = TRUE;
$schema['node_field_data']['fields']['status']['not null'] = TRUE;
$schema['node_field_data']['fields']['sticky']['not null'] = TRUE;
$schema['node_field_data']['fields']['title']['not null'] = TRUE;
$schema['node_field_revision']['fields']['default_langcode']['not null'] = TRUE;
// @todo Revisit index definitions in https://drupal.org/node/2015277.
$schema['node_revision']['indexes'] += array(
'node__langcode' => array('langcode'),
);
$schema['node_revision']['foreign keys'] += array(
'node__revision_author' => array(
'table' => 'users',
'columns' => array('revision_uid' => 'uid'),
),
);
$schema['node_field_data']['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)),
);
$schema['node_field_revision']['indexes'] += array(
'node__default_langcode' => array('default_langcode'),
'node__langcode' => array('langcode'),
);
return $schema;
}
}
......@@ -22,6 +22,7 @@
* bundle_label = @Translation("Vocabulary"),
* handlers = {
* "storage" = "Drupal\taxonomy\TermStorage",
* "storage_schema" = "Drupal\taxonomy\TermStorageSchema",
* "view_builder" = "Drupal\taxonomy\TermViewBuilder",
* "access" = "Drupal\taxonomy\TermAccessControlHandler",
* "views_data" = "Drupal\taxonomy\TermViewsData",
......
......@@ -154,105 +154,6 @@ public function resetWeights($vid) {
->execute();
}
/**
* {@inheritdoc}
*/
public function getSchema() {
$schema = parent::getSchema();
// Marking the respective fields as NOT NULL makes the indexes more
// performant.
$schema['taxonomy_term_field_data']['fields']['weight']['not null'] = TRUE;
$schema['taxonomy_term_field_data']['fields']['name']['not null'] = TRUE;
unset($schema['taxonomy_term_field_data']['indexes']['taxonomy_term_field__vid__target_id']);
unset($schema['taxonomy_term_field_data']['indexes']['taxonomy_term_field__description__format']);
$schema['taxonomy_term_field_data']['indexes'] += array(
'taxonomy_term__tree' => array('vid', 'weight', 'name'),
'taxonomy_term__vid_name' => array('vid', 'name'),
'taxonomy_term__name' => array('name'),