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 @@ ...@@ -13,13 +13,11 @@
use Drupal\Core\Database\Database; use Drupal\Core\Database\Database;
use Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException; use Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException;
use Drupal\Core\Entity\Query\QueryInterface; use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Entity\Schema\ContentEntitySchemaHandler;
use Drupal\Core\Entity\Sql\DefaultTableMapping; use Drupal\Core\Entity\Sql\DefaultTableMapping;
use Drupal\Core\Entity\Sql\SqlEntityStorageInterface; use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
...@@ -28,7 +26,7 @@ ...@@ -28,7 +26,7 @@
* This class can be used as-is by most content entity types. Entity types * This class can be used as-is by most content entity types. Entity types
* requiring special handling can extend the class. * 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 * internally in order to automatically generate the database schema based on
* the defined base fields. Entity types can override * the defined base fields. Entity types can override
* ContentEntityDatabaseStorage::getSchema() to customize the generated * ContentEntityDatabaseStorage::getSchema() to customize the generated
...@@ -229,12 +227,13 @@ public function getSchema() { ...@@ -229,12 +227,13 @@ public function getSchema() {
/** /**
* Gets the schema handler for this entity storage. * Gets the schema handler for this entity storage.
* *
* @return \Drupal\Core\Entity\Schema\ContentEntitySchemaHandler * @return \Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema
* The schema handler. * The schema handler.
*/ */
protected function schemaHandler() { protected function schemaHandler() {
if (!isset($this->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; return $this->schemaHandler;
} }
...@@ -1024,8 +1023,8 @@ protected function mapToStorageRecord(ContentEntityInterface $entity, $table_nam ...@@ -1024,8 +1023,8 @@ protected function mapToStorageRecord(ContentEntityInterface $entity, $table_nam
* @return bool * @return bool
* TRUE if the the column is serial, FALSE otherwise. * TRUE if the the column is serial, FALSE otherwise.
* *
* @see \Drupal\Core\Entity\Schema\ContentEntitySchemaHandler::processBaseTable() * @see \Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema::processBaseTable()
* @see \Drupal\Core\Entity\Schema\ContentEntitySchemaHandler::processRevisionTable() * @see \Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema::processRevisionTable()
*/ */
protected function isColumnSerial($table_name, $schema_name) { protected function isColumnSerial($table_name, $schema_name) {
$result = FALSE; $result = FALSE;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/** /**
* @file * @file
* Contains \Drupal\Core\Entity\Schema\ContentEntitySchemaHandler. * Contains \Drupal\Core\Entity\Schema\SqlContentEntityStorageSchema.
*/ */
namespace Drupal\Core\Entity\Schema; namespace Drupal\Core\Entity\Schema;
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
/** /**
* Defines a schema handler that supports revisionable, translatable entities. * 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. * The entity type this schema builder is responsible for.
...@@ -45,7 +45,7 @@ class ContentEntitySchemaHandler implements EntitySchemaHandlerInterface { ...@@ -45,7 +45,7 @@ class ContentEntitySchemaHandler implements EntitySchemaHandlerInterface {
protected $schema; protected $schema;
/** /**
* Constructs a ContentEntitySchemaHandler. * Constructs a SqlContentEntityStorageSchema.
* *
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager. * The entity manager.
...@@ -64,11 +64,28 @@ public function __construct(EntityManagerInterface $entity_manager, ContentEntit ...@@ -64,11 +64,28 @@ public function __construct(EntityManagerInterface $entity_manager, ContentEntit
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getSchema() { public function getSchema() {
// Prepare basic information about the entity type. return $this->getEntitySchema($this->entityType);
$tables = $this->getTables(); }
/**
* 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. // Initialize the table schema.
$tables = $this->getTables();
$schema[$tables['base_table']] = $this->initializeBaseTable(); $schema[$tables['base_table']] = $this->initializeBaseTable();
if (isset($tables['revision_table'])) { if (isset($tables['revision_table'])) {
$schema[$tables['revision_table']] = $this->initializeRevisionTable(); $schema[$tables['revision_table']] = $this->initializeRevisionTable();
...@@ -108,10 +125,10 @@ public function getSchema() { ...@@ -108,10 +125,10 @@ public function getSchema() {
$this->processRevisionDataTable($schema[$tables['revision_data_table']]); $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 @@ ...@@ -22,6 +22,7 @@
* label = @Translation("Aggregator feed"), * label = @Translation("Aggregator feed"),
* handlers = { * handlers = {
* "storage" = "Drupal\aggregator\FeedStorage", * "storage" = "Drupal\aggregator\FeedStorage",
* "storage_schema" = "Drupal\aggregator\FeedStorageSchema",
* "view_builder" = "Drupal\aggregator\FeedViewBuilder", * "view_builder" = "Drupal\aggregator\FeedViewBuilder",
* "access" = "Drupal\aggregator\FeedAccessControlHandler", * "access" = "Drupal\aggregator\FeedAccessControlHandler",
* "views_data" = "Drupal\aggregator\AggregatorFeedViewsData", * "views_data" = "Drupal\aggregator\AggregatorFeedViewsData",
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
* label = @Translation("Aggregator feed item"), * label = @Translation("Aggregator feed item"),
* handlers = { * handlers = {
* "storage" = "Drupal\aggregator\ItemStorage", * "storage" = "Drupal\aggregator\ItemStorage",
* "storage_schema" = "Drupal\aggregator\ItemStorageSchema",
* "view_builder" = "Drupal\aggregator\ItemViewBuilder", * "view_builder" = "Drupal\aggregator\ItemViewBuilder",
* "access" = "Drupal\aggregator\FeedAccessControlHandler", * "access" = "Drupal\aggregator\FeedAccessControlHandler",
* "views_data" = "Drupal\aggregator\AggregatorItemViewsData" * "views_data" = "Drupal\aggregator\AggregatorItemViewsData"
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
namespace Drupal\aggregator; namespace Drupal\aggregator;
use Drupal\aggregator\FeedInterface;
use Drupal\Core\Entity\ContentEntityDatabaseStorage; use Drupal\Core\Entity\ContentEntityDatabaseStorage;
/** /**
...@@ -18,29 +17,6 @@ ...@@ -18,29 +17,6 @@
*/ */
class FeedStorage extends ContentEntityDatabaseStorage implements FeedStorageInterface { 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} * {@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 @@ ...@@ -7,9 +7,8 @@
namespace Drupal\aggregator; namespace Drupal\aggregator;
use Drupal\aggregator\Entity\Item;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Entity\ContentEntityDatabaseStorage; use Drupal\Core\Entity\ContentEntityDatabaseStorage;
use Drupal\Core\Entity\Query\QueryInterface;
/** /**
* Controller class for aggregators items. * Controller class for aggregators items.
...@@ -19,29 +18,6 @@ ...@@ -19,29 +18,6 @@
*/ */
class ItemStorage extends ContentEntityDatabaseStorage implements ItemStorageInterface { 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} * {@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 @@ ...@@ -2,23 +2,24 @@
/** /**
* @file * @file
* Contains \Drupal\block_content\BlockContentStorage. * Contains \Drupal\block_content\BlockContentStorageSchema.
*/ */
namespace Drupal\block_content; 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} * {@inheritdoc}
*/ */
public function getSchema() { protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getSchema(); $schema = parent::getEntitySchema($entity_type, $reset);
// Marking the respective fields as NOT NULL makes the indexes more // Marking the respective fields as NOT NULL makes the indexes more
// performant. // performant.
......
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
* label = @Translation("Custom Block"), * label = @Translation("Custom Block"),
* bundle_label = @Translation("Custom Block type"), * bundle_label = @Translation("Custom Block type"),
* handlers = { * handlers = {
* "storage" = "Drupal\block_content\BlockContentStorage", * "storage" = "Drupal\Core\Entity\ContentEntityDatabaseStorage",
* "storage_schema" = "Drupal\block_content\BlockContentStorageSchema",
* "access" = "Drupal\block_content\BlockContentAccessControlHandler", * "access" = "Drupal\block_content\BlockContentAccessControlHandler",
* "list_builder" = "Drupal\block_content\BlockContentListBuilder", * "list_builder" = "Drupal\block_content\BlockContentListBuilder",
* "view_builder" = "Drupal\block_content\BlockContentViewBuilder", * "view_builder" = "Drupal\block_content\BlockContentViewBuilder",
......
...@@ -9,11 +9,11 @@ ...@@ -9,11 +9,11 @@
use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Database\Connection; use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\ContentEntityDatabaseStorage;
use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\ContentEntityDatabaseStorage;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
...@@ -318,48 +318,6 @@ public function loadThread(EntityInterface $entity, $field_name, $mode, $comment ...@@ -318,48 +318,6 @@ public function loadThread(EntityInterface $entity, $field_name, $mode, $comment
return $comments; 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} * {@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 @@ ...@@ -25,6 +25,7 @@
* bundle_label = @Translation("Content type"), * bundle_label = @Translation("Content type"),
* handlers = { * handlers = {
* "storage" = "Drupal\comment\CommentStorage", * "storage" = "Drupal\comment\CommentStorage",
* "storage_schema" = "Drupal\comment\CommentStorageSchema",
* "access" = "Drupal\comment\CommentAccessControlHandler", * "access" = "Drupal\comment\CommentAccessControlHandler",
* "view_builder" = "Drupal\comment\CommentViewBuilder", * "view_builder" = "Drupal\comment\CommentViewBuilder",
* "views_data" = "Drupal\comment\CommentViewsData", * "views_data" = "Drupal\comment\CommentViewsData",
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
* label = @Translation("File"), * label = @Translation("File"),
* handlers = { * handlers = {
* "storage" = "Drupal\file\FileStorage", * "storage" = "Drupal\file\FileStorage",
* "storage_schema" = "Drupal\file\FileStorageSchema",
* "access" = "Drupal\file\FileAccessControlHandler", * "access" = "Drupal\file\FileAccessControlHandler",
* "view_builder" = "Drupal\Core\Entity\EntityViewBuilder", * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
* "views_data" = "Drupal\file\FileViewsData", * "views_data" = "Drupal\file\FileViewsData",
......
...@@ -27,29 +27,4 @@ public function spaceUsed($uid = NULL, $status = FILE_STATUS_PERMANENT) { ...@@ -27,29 +27,4 @@ public function spaceUsed($uid = NULL, $status = FILE_STATUS_PERMANENT) {
return $query->execute()->fetchField(); 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'),