Commit 76fdebab authored by plach's avatar plach

Issue #2960136 by amateescu, tstoeckler, vijaycs85: Add the ability to use a...

Issue #2960136 by amateescu, tstoeckler, vijaycs85: Add the ability to use a prefix for all the tables in a table mapping
parent 543b3f4e
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace Drupal\Core\Entity\Sql; namespace Drupal\Core\Entity\Sql;
use Drupal\Core\Entity\ContentEntityTypeInterface; use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface;
/** /**
...@@ -24,6 +25,13 @@ class DefaultTableMapping implements TableMappingInterface { ...@@ -24,6 +25,13 @@ class DefaultTableMapping implements TableMappingInterface {
*/ */
protected $fieldStorageDefinitions = []; protected $fieldStorageDefinitions = [];
/**
* The prefix to be used by all the tables of this mapping.
*
* @var string
*/
protected $prefix;
/** /**
* The base table of the entity. * The base table of the entity.
* *
...@@ -112,22 +120,26 @@ class DefaultTableMapping implements TableMappingInterface { ...@@ -112,22 +120,26 @@ class DefaultTableMapping implements TableMappingInterface {
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $storage_definitions * @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $storage_definitions
* A list of field storage definitions that should be available for the * A list of field storage definitions that should be available for the
* field columns of this table mapping. * field columns of this table mapping.
* @param string $prefix
* (optional) A prefix to be used by all the tables of this mapping.
* Defaults to an empty string.
*/ */
public function __construct(ContentEntityTypeInterface $entity_type, array $storage_definitions) { public function __construct(ContentEntityTypeInterface $entity_type, array $storage_definitions, $prefix = '') {
$this->entityType = $entity_type; $this->entityType = $entity_type;
$this->fieldStorageDefinitions = $storage_definitions; $this->fieldStorageDefinitions = $storage_definitions;
$this->prefix = $prefix;
// @todo Remove table names from the entity type definition in // @todo Remove table names from the entity type definition in
// https://www.drupal.org/node/2232465. // https://www.drupal.org/node/2232465.
$this->baseTable = $entity_type->getBaseTable() ?: $entity_type->id(); $this->baseTable = $this->prefix . $entity_type->getBaseTable() ?: $entity_type->id();
if ($entity_type->isRevisionable()) { if ($entity_type->isRevisionable()) {
$this->revisionTable = $entity_type->getRevisionTable() ?: $entity_type->id() . '_revision'; $this->revisionTable = $this->prefix . $entity_type->getRevisionTable() ?: $entity_type->id() . '_revision';
} }
if ($entity_type->isTranslatable()) { if ($entity_type->isTranslatable()) {
$this->dataTable = $entity_type->getDataTable() ?: $entity_type->id() . '_field_data'; $this->dataTable = $this->prefix . $entity_type->getDataTable() ?: $entity_type->id() . '_field_data';
} }
if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) { if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) {
$this->revisionDataTable = $entity_type->getRevisionDataTable() ?: $entity_type->id() . '_field_revision'; $this->revisionDataTable = $this->prefix . $entity_type->getRevisionDataTable() ?: $entity_type->id() . '_field_revision';
} }
} }
...@@ -139,13 +151,16 @@ public function __construct(ContentEntityTypeInterface $entity_type, array $stor ...@@ -139,13 +151,16 @@ public function __construct(ContentEntityTypeInterface $entity_type, array $stor
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $storage_definitions * @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $storage_definitions
* A list of field storage definitions that should be available for the * A list of field storage definitions that should be available for the
* field columns of this table mapping. * field columns of this table mapping.
* @param string $prefix
* (optional) A prefix to be used by all the tables of this mapping.
* Defaults to an empty string.
* *
* @return static * @return static
* *
* @internal * @internal
*/ */
public static function create(ContentEntityTypeInterface $entity_type, array $storage_definitions) { public static function create(ContentEntityTypeInterface $entity_type, array $storage_definitions, $prefix = '') {
$table_mapping = new static($entity_type, $storage_definitions); $table_mapping = new static($entity_type, $storage_definitions, $prefix);
$revisionable = $entity_type->isRevisionable(); $revisionable = $entity_type->isRevisionable();
$translatable = $entity_type->isTranslatable(); $translatable = $entity_type->isTranslatable();
...@@ -590,18 +605,30 @@ public function getDedicatedRevisionTableName(FieldStorageDefinitionInterface $s ...@@ -590,18 +605,30 @@ public function getDedicatedRevisionTableName(FieldStorageDefinitionInterface $s
* The final table name. * The final table name.
*/ */
protected function generateFieldTableName(FieldStorageDefinitionInterface $storage_definition, $revision) { protected function generateFieldTableName(FieldStorageDefinitionInterface $storage_definition, $revision) {
// The maximum length of an entity type ID is 32 characters.
$entity_type_id = substr($storage_definition->getTargetEntityTypeId(), 0, EntityTypeInterface::ID_MAX_LENGTH);
$separator = $revision ? '_revision__' : '__'; $separator = $revision ? '_revision__' : '__';
$table_name = $storage_definition->getTargetEntityTypeId() . $separator . $storage_definition->getName();
$table_name = $this->prefix . $entity_type_id . $separator . $storage_definition->getName();
// Limit the string to 48 characters, keeping a 16 characters margin for db // Limit the string to 48 characters, keeping a 16 characters margin for db
// prefixes. // prefixes.
if (strlen($table_name) > 48) { if (strlen($table_name) > 48) {
// Use a shorter separator, a truncated entity_type, and a hash of the // Use a shorter separator and a hash of the field storage unique
// field storage unique identifier. // identifier.
$separator = $revision ? '_r__' : '__'; $separator = $revision ? '_r__' : '__';
// Truncate to the same length for the current and revision tables.
$entity_type = substr($storage_definition->getTargetEntityTypeId(), 0, 34);
$field_hash = substr(hash('sha256', $storage_definition->getUniqueStorageIdentifier()), 0, 10); $field_hash = substr(hash('sha256', $storage_definition->getUniqueStorageIdentifier()), 0, 10);
$table_name = $entity_type . $separator . $field_hash;
$table_name = $this->prefix . $entity_type_id . $separator . $field_hash;
// If the resulting table name is still longer than 48 characters, use the
// following pattern:
// - prefix: max 34 chars;
// - separator: max 4 chars;
// - field_hash: max 10 chars.
if (strlen($table_name) > 48) {
$prefix = substr($this->prefix, 0, 34);
$table_name = $prefix . $separator . $field_hash;
}
} }
return $table_name; return $table_name;
} }
......
...@@ -336,15 +336,18 @@ public function getTableMapping(array $storage_definitions = NULL) { ...@@ -336,15 +336,18 @@ public function getTableMapping(array $storage_definitions = NULL) {
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $storage_definitions * @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $storage_definitions
* An array of field storage definitions to be used to compute the table * An array of field storage definitions to be used to compute the table
* mapping. * mapping.
* @param string $prefix
* (optional) A prefix to be used by all the tables of this mapping.
* Defaults to an empty string.
* *
* @return \Drupal\Core\Entity\Sql\TableMappingInterface * @return \Drupal\Core\Entity\Sql\TableMappingInterface
* A table mapping object for the entity's tables. * A table mapping object for the entity's tables.
* *
* @internal * @internal
*/ */
public function getCustomTableMapping(ContentEntityTypeInterface $entity_type, array $storage_definitions) { public function getCustomTableMapping(ContentEntityTypeInterface $entity_type, array $storage_definitions, $prefix = '') {
$table_mapping_class = $this->temporary ? TemporaryTableMapping::class : DefaultTableMapping::class; $prefix = $prefix ?: ($this->temporary ? 'tmp_' : '');
return $table_mapping_class::create($entity_type, $storage_definitions); return DefaultTableMapping::create($entity_type, $storage_definitions, $prefix);
} }
/** /**
......
...@@ -149,23 +149,19 @@ public function convertToRevisionable(array &$sandbox, array $fields_to_update = ...@@ -149,23 +149,19 @@ public function convertToRevisionable(array &$sandbox, array $fields_to_update =
// Rename the original tables so we can put them back in place in case // Rename the original tables so we can put them back in place in case
// anything goes wrong. // anything goes wrong.
foreach ($sandbox['original_table_mapping']->getTableNames() as $table_name) { $backup_table_names = array_combine($sandbox['original_table_mapping']->getTableNames(), $sandbox['backup_table_mapping']->getTableNames());
$old_table_name = TemporaryTableMapping::getTempTableName($table_name, 'old_'); foreach ($backup_table_names as $original_table_name => $backup_table_name) {
$this->database->schema()->renameTable($table_name, $old_table_name); $this->database->schema()->renameTable($original_table_name, $backup_table_name);
} }
// Put the new tables in place and update the entity type and field // Put the new tables in place and update the entity type and field
// storage definitions. // storage definitions.
try { try {
$storage = $this->entityTypeManager->getStorage($this->entityTypeId); $storage = $this->entityTypeManager->createHandlerInstance($actual_entity_type->getStorageClass(), $actual_entity_type);
$storage->setEntityType($actual_entity_type); $current_table_mapping = $storage->getCustomTableMapping($actual_entity_type, $sandbox['updated_storage_definitions']);
$storage->setTemporary(FALSE);
$actual_table_names = $storage->getTableMapping()->getTableNames(); $table_name_mapping = array_combine($sandbox['temporary_table_mapping']->getTableNames(), $current_table_mapping->getTableNames());
foreach ($table_name_mapping as $temp_table_name => $new_table_name) {
$table_name_mapping = [];
foreach ($actual_table_names as $new_table_name) {
$temp_table_name = TemporaryTableMapping::getTempTableName($new_table_name);
$table_name_mapping[$temp_table_name] = $new_table_name;
$this->database->schema()->renameTable($temp_table_name, $new_table_name); $this->database->schema()->renameTable($temp_table_name, $new_table_name);
} }
...@@ -201,15 +197,14 @@ public function convertToRevisionable(array &$sandbox, array $fields_to_update = ...@@ -201,15 +197,14 @@ public function convertToRevisionable(array &$sandbox, array $fields_to_update =
} }
catch (\Exception $e) { catch (\Exception $e) {
// Something went wrong, bring back the original tables. // Something went wrong, bring back the original tables.
foreach ($sandbox['original_table_mapping']->getTableNames() as $table_name) { foreach ($backup_table_names as $original_table_name => $backup_table_name) {
// We are in the 'original data recovery' phase, so we need to be sure // We are in the 'original data recovery' phase, so we need to be sure
// that the initial tables can be properly restored. // that the initial tables can be properly restored.
if ($this->database->schema()->tableExists($table_name)) { if ($this->database->schema()->tableExists($original_table_name)) {
$this->database->schema()->dropTable($table_name); $this->database->schema()->dropTable($original_table_name);
} }
$old_table_name = TemporaryTableMapping::getTempTableName($table_name, 'old_'); $this->database->schema()->renameTable($backup_table_name, $original_table_name);
$this->database->schema()->renameTable($old_table_name, $table_name);
} }
// Re-throw the original exception. // Re-throw the original exception.
...@@ -219,9 +214,8 @@ public function convertToRevisionable(array &$sandbox, array $fields_to_update = ...@@ -219,9 +214,8 @@ public function convertToRevisionable(array &$sandbox, array $fields_to_update =
// At this point the update process either finished successfully or any // At this point the update process either finished successfully or any
// error has been handled already, so we can drop the backup entity // error has been handled already, so we can drop the backup entity
// tables. // tables.
foreach ($sandbox['original_table_mapping']->getTableNames() as $table_name) { foreach ($backup_table_names as $original_table_name => $backup_table_name) {
$old_table_name = TemporaryTableMapping::getTempTableName($table_name, 'old_'); $this->database->schema()->dropTable($backup_table_name);
$this->database->schema()->dropTable($old_table_name);
} }
} }
} }
...@@ -236,7 +230,7 @@ public function convertToRevisionable(array &$sandbox, array $fields_to_update = ...@@ -236,7 +230,7 @@ public function convertToRevisionable(array &$sandbox, array $fields_to_update =
* Thrown in case of an error during the entity save process. * Thrown in case of an error during the entity save process.
*/ */
protected function copyData(array &$sandbox) { protected function copyData(array &$sandbox) {
/** @var \Drupal\Core\Entity\Sql\TemporaryTableMapping $temporary_table_mapping */ /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $temporary_table_mapping */
$temporary_table_mapping = $sandbox['temporary_table_mapping']; $temporary_table_mapping = $sandbox['temporary_table_mapping'];
$temporary_entity_type = $sandbox['temporary_entity_type']; $temporary_entity_type = $sandbox['temporary_entity_type'];
$original_table_mapping = $sandbox['original_table_mapping']; $original_table_mapping = $sandbox['original_table_mapping'];
...@@ -437,12 +431,13 @@ protected function collectOriginalDefinitions(array &$sandbox) { ...@@ -437,12 +431,13 @@ protected function collectOriginalDefinitions(array &$sandbox) {
/** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $storage */ /** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $storage */
$storage = $this->entityTypeManager->getStorage($this->entityTypeId); $storage = $this->entityTypeManager->getStorage($this->entityTypeId);
$storage->setEntityType($original_entity_type); $original_table_mapping = $storage->getCustomTableMapping($original_entity_type, $original_storage_definitions);
$original_table_mapping = $storage->getTableMapping($original_storage_definitions); $backup_table_mapping = $storage->getCustomTableMapping($original_entity_type, $original_storage_definitions, 'old_');
$sandbox['original_entity_type'] = $original_entity_type; $sandbox['original_entity_type'] = $original_entity_type;
$sandbox['original_storage_definitions'] = $original_storage_definitions; $sandbox['original_storage_definitions'] = $original_storage_definitions;
$sandbox['original_table_mapping'] = $original_table_mapping; $sandbox['original_table_mapping'] = $original_table_mapping;
$sandbox['backup_table_mapping'] = $backup_table_mapping;
$sandbox['original_entity_schema_data'] = $this->installedStorageSchema->get($this->entityTypeId . '.entity_schema_data', []); $sandbox['original_entity_schema_data'] = $this->installedStorageSchema->get($this->entityTypeId . '.entity_schema_data', []);
foreach ($original_storage_definitions as $storage_definition) { foreach ($original_storage_definitions as $storage_definition) {
...@@ -487,20 +482,11 @@ protected function createTemporaryDefinitions(array &$sandbox, array $fields_to_ ...@@ -487,20 +482,11 @@ protected function createTemporaryDefinitions(array &$sandbox, array $fields_to_
$actual_entity_type = $this->entityTypeManager->getDefinition($this->entityTypeId); $actual_entity_type = $this->entityTypeManager->getDefinition($this->entityTypeId);
$temporary_entity_type = clone $actual_entity_type; $temporary_entity_type = clone $actual_entity_type;
$temporary_entity_type->set('base_table', TemporaryTableMapping::getTempTableName($temporary_entity_type->getBaseTable())); $updated_storage_definitions = $this->updateFieldStorageDefinitionsToRevisionable($temporary_entity_type, $sandbox['original_storage_definitions'], $fields_to_update, FALSE);
$temporary_entity_type->set('revision_table', TemporaryTableMapping::getTempTableName($temporary_entity_type->getRevisionTable()));
if ($temporary_entity_type->isTranslatable()) {
$temporary_entity_type->set('data_table', TemporaryTableMapping::getTempTableName($temporary_entity_type->getDataTable()));
$temporary_entity_type->set('revision_data_table', TemporaryTableMapping::getTempTableName($temporary_entity_type->getRevisionDataTable()));
}
/** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $storage */ /** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $storage */
$storage = $this->entityTypeManager->getStorage($this->entityTypeId); $storage = $this->entityTypeManager->getStorage($this->entityTypeId);
$storage->setTemporary(TRUE); $temporary_table_mapping = $storage->getCustomTableMapping($temporary_entity_type, $updated_storage_definitions, 'tmp_');
$storage->setEntityType($temporary_entity_type);
$updated_storage_definitions = $this->updateFieldStorageDefinitionsToRevisionable($temporary_entity_type, $sandbox['original_storage_definitions'], $fields_to_update, FALSE);
$temporary_table_mapping = $storage->getTableMapping($updated_storage_definitions);
$sandbox['temporary_entity_type'] = $temporary_entity_type; $sandbox['temporary_entity_type'] = $temporary_entity_type;
$sandbox['temporary_table_mapping'] = $temporary_table_mapping; $sandbox['temporary_table_mapping'] = $temporary_table_mapping;
......
...@@ -4,8 +4,13 @@ ...@@ -4,8 +4,13 @@
use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface;
@trigger_error(__NAMESPACE__ . '\TemporaryTableMapping is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Use the default table mapping with a prefix instead.', E_USER_DEPRECATED);
/** /**
* Defines a temporary table mapping class. * Defines a temporary table mapping class.
*
* @deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Use the
* default table mapping with a prefix instead.
*/ */
class TemporaryTableMapping extends DefaultTableMapping { class TemporaryTableMapping extends DefaultTableMapping {
......
...@@ -18,7 +18,7 @@ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $res ...@@ -18,7 +18,7 @@ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $res
$schema = parent::getEntitySchema($entity_type, $reset); $schema = parent::getEntitySchema($entity_type, $reset);
if ($entity_type->id() == 'entity_test_update') { if ($entity_type->id() == 'entity_test_update') {
$schema[$entity_type->getBaseTable()]['indexes'] += \Drupal::state()->get('entity_test_update.additional_entity_indexes', []); $schema[$this->storage->getTableMapping()->getBaseTable()]['indexes'] += \Drupal::state()->get('entity_test_update.additional_entity_indexes', []);
} }
return $schema; return $schema;
} }
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
namespace Drupal\Tests\system\Functional\Entity\Update; namespace Drupal\Tests\system\Functional\Entity\Update;
use Drupal\Core\Entity\Sql\TemporaryTableMapping;
use Drupal\FunctionalTests\Update\UpdatePathTestBase; use Drupal\FunctionalTests\Update\UpdatePathTestBase;
use Drupal\Tests\system\Functional\Entity\Traits\EntityDefinitionTestTrait; use Drupal\Tests\system\Functional\Entity\Traits\EntityDefinitionTestTrait;
...@@ -67,10 +66,11 @@ protected function setUp() { ...@@ -67,10 +66,11 @@ protected function setUp() {
public function testMakeRevisionable() { public function testMakeRevisionable() {
// Check that entity type is not revisionable prior to running the update // Check that entity type is not revisionable prior to running the update
// process. // process.
$entity_test_update = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update'); $original_entity_type_definition = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update');
$this->assertFalse($entity_test_update->isRevisionable()); $original_field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update');
$this->assertFalse($original_entity_type_definition->isRevisionable());
$translatable = $entity_test_update->isTranslatable(); $translatable = $original_entity_type_definition->isTranslatable();
// Make the entity type revisionable and run the updates. // Make the entity type revisionable and run the updates.
if ($translatable) { if ($translatable) {
...@@ -156,14 +156,17 @@ public function testMakeRevisionable() { ...@@ -156,14 +156,17 @@ public function testMakeRevisionable() {
// Check that temporary tables have been removed at the end of the process. // Check that temporary tables have been removed at the end of the process.
$schema = \Drupal::database()->schema(); $schema = \Drupal::database()->schema();
foreach ($storage->getTableMapping()->getTableNames() as $table_name) { $temporary_table_names = $storage->getCustomTableMapping($entity_test_update, $field_storage_definitions, 'tmp_')->getTableNames();
$this->assertFalse($schema->tableExists(TemporaryTableMapping::getTempTableName($table_name))); $current_table_names = $storage->getCustomTableMapping($entity_test_update, $field_storage_definitions)->getTableNames();
foreach (array_combine($temporary_table_names, $current_table_names) as $temp_table_name => $table_name) {
$this->assertTrue($schema->tableExists($table_name));
$this->assertFalse($schema->tableExists($temp_table_name));
} }
// Check that backup tables have been removed at the end of the process. // Check that backup tables have been removed at the end of the process.
$schema = \Drupal::database()->schema(); $table_mapping = $storage->getCustomTableMapping($original_entity_type_definition, $original_field_storage_definitions, 'old_');
foreach ($storage->getTableMapping()->getTableNames() as $table_name) { foreach ($table_mapping->getTableNames() as $table_name) {
$this->assertFalse($schema->tableExists(TemporaryTableMapping::getTempTableName($table_name, 'old_'))); $this->assertFalse($schema->tableExists($table_name));
} }
} }
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
namespace Drupal\Tests\system\Functional\Entity\Update; namespace Drupal\Tests\system\Functional\Entity\Update;
use Drupal\Core\Entity\Sql\TemporaryTableMapping;
/** /**
* Tests converting a translatable entity type with data to revisionable. * Tests converting a translatable entity type with data to revisionable.
* *
...@@ -79,8 +77,11 @@ public function testMakeRevisionableErrorHandling() { ...@@ -79,8 +77,11 @@ public function testMakeRevisionableErrorHandling() {
// Check that temporary tables have been removed. // Check that temporary tables have been removed.
$schema = \Drupal::database()->schema(); $schema = \Drupal::database()->schema();
foreach ($storage->getTableMapping()->getTableNames() as $table_name) { $temporary_table_names = $storage->getCustomTableMapping($new_entity_type, $new_storage_definitions, 'tmp_')->getTableNames();
$this->assertFalse($schema->tableExists(TemporaryTableMapping::getTempTableName($table_name))); $current_table_names = $storage->getCustomTableMapping($new_entity_type, $new_storage_definitions)->getTableNames();
foreach (array_combine($temporary_table_names, $current_table_names) as $temp_table_name => $table_name) {
$this->assertTrue($schema->tableExists($table_name));
$this->assertFalse($schema->tableExists($temp_table_name));
} }
// Check that the original tables still exist and their data is intact. // Check that the original tables still exist and their data is intact.
......
...@@ -517,9 +517,9 @@ public function testTableNames() { ...@@ -517,9 +517,9 @@ public function testTableNames() {
'field_name' => $field_name, 'field_name' => $field_name,
'type' => 'test_field', 'type' => 'test_field',
]); ]);
$expected = 'long_entity_type_abcdefghijklmnopq__' . substr(hash('sha256', $field_storage->uuid()), 0, 10); $expected = 'long_entity_type_abcdefghijklmno__' . substr(hash('sha256', $field_storage->uuid()), 0, 10);
$this->assertEqual($this->tableMapping->getDedicatedDataTableName($field_storage), $expected); $this->assertEqual($this->tableMapping->getDedicatedDataTableName($field_storage), $expected);
$expected = 'long_entity_type_abcdefghijklmnopq_r__' . substr(hash('sha256', $field_storage->uuid()), 0, 10); $expected = 'long_entity_type_abcdefghijklmno_r__' . substr(hash('sha256', $field_storage->uuid()), 0, 10);
$this->assertEqual($this->tableMapping->getDedicatedRevisionTableName($field_storage), $expected); $this->assertEqual($this->tableMapping->getDedicatedRevisionTableName($field_storage), $expected);
// Long entity type and field name. // Long entity type and field name.
...@@ -530,9 +530,9 @@ public function testTableNames() { ...@@ -530,9 +530,9 @@ public function testTableNames() {
'field_name' => $field_name, 'field_name' => $field_name,
'type' => 'test_field', 'type' => 'test_field',
]); ]);
$expected = 'long_entity_type_abcdefghijklmnopq__' . substr(hash('sha256', $field_storage->uuid()), 0, 10); $expected = 'long_entity_type_abcdefghijklmno__' . substr(hash('sha256', $field_storage->uuid()), 0, 10);
$this->assertEqual($this->tableMapping->getDedicatedDataTableName($field_storage), $expected); $this->assertEqual($this->tableMapping->getDedicatedDataTableName($field_storage), $expected);
$expected = 'long_entity_type_abcdefghijklmnopq_r__' . substr(hash('sha256', $field_storage->uuid()), 0, 10); $expected = 'long_entity_type_abcdefghijklmno_r__' . substr(hash('sha256', $field_storage->uuid()), 0, 10);
$this->assertEqual($this->tableMapping->getDedicatedRevisionTableName($field_storage), $expected); $this->assertEqual($this->tableMapping->getDedicatedRevisionTableName($field_storage), $expected);
// Try creating a second field and check there are no clashes. // Try creating a second field and check there are no clashes.
$field_storage2 = FieldStorageConfig::create([ $field_storage2 = FieldStorageConfig::create([
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
use Drupal\Core\Entity\Sql\DefaultTableMapping; use Drupal\Core\Entity\Sql\DefaultTableMapping;
use Drupal\Core\Entity\Sql\SqlContentEntityStorageException; use Drupal\Core\Entity\Sql\SqlContentEntityStorageException;
use Drupal\Core\Entity\Sql\TemporaryTableMapping;
use Drupal\Tests\UnitTestCase; use Drupal\Tests\UnitTestCase;
/** /**
...@@ -444,6 +445,142 @@ public function testGetFieldTableNameInvalid() { ...@@ -444,6 +445,142 @@ public function testGetFieldTableNameInvalid() {
$table_mapping->getFieldTableName('invalid_field_name'); $table_mapping->getFieldTableName('invalid_field_name');
} }
/**
* @covers ::getDedicatedDataTableName
* @covers ::getDedicatedRevisionTableName
*
* @dataProvider providerTestGetDedicatedTableName
*/
public function testGetDedicatedTableName($info, $expected_data_table, $expected_revision_table) {
$entity_type_id = $info['entity_type_id'];
$field_name = $info['field_name'];
$definition = $this->setUpDefinition($field_name, []);
$definition->expects($this->any())
->method('getTargetEntityTypeId')
->will($this->returnValue($entity_type_id));
$definition->expects($this->any())
->method('getUniqueStorageIdentifier')
->will($this->returnValue($entity_type_id . '-' . $field_name));
$this->entityType
->expects($this->any())
->method('getBaseTable')
->willReturn($info['entity_type_id']);
$this->entityType
->expects($this->any())
->method('isTranslatable')
->willReturn(FALSE);
$this->entityType
->expects($this->any())
->method('isRevisionable')
->willReturn(FALSE);
$table_mapping = new DefaultTableMapping($this->entityType, [], $info['prefix']);
$this->assertSame($expected_data_table, $table_mapping->getDedicatedDataTableName($definition));
$this->assertSame($expected_revision_table, $table_mapping->getDedicatedRevisionTableName($definition));
}
/**
* Provides test data for testGetDedicatedTableName().
*
* @return array[]
* A nested array where each inner array has the following values: an array
* consisting of the entity type ID, field name and a table prefix, followed
* by the expected data table name and the revision table name.
*/
public function providerTestGetDedicatedTableName() {
$data = [];
$data['short entity type; short field name; no prefix'] = [
[
'entity_type_id' => 'short_entity_type',
'field_name' => 'short_field_name',
'prefix' => '',
],
'short_entity_type__short_field_name',
'short_entity_type_revision__short_field_name',
];
$data['short entity type; long field name; no prefix'] = [
[
'entity_type_id' => 'short_entity_type',
'field_name' => 'long_field_name_abcdefghijklmnopqrstuvwxyz',
'prefix' => '',
],
'short_entity_type__28a01c7777',
'short_entity_type_r__28a01c7777',
];
$data['long entity type; short field name; no prefix'] = [
[
'entity_type_id' => 'long_entity_type_abcdefghijklmnopqrstuvwxyz',
'field_name' => 'short_field_name',
'prefix' => '',
],
'long_entity_type_abcdefghijklmno__a526e4e042',
'long_entity_type_abcdefghijklmno_r__a526e4e042',
];
$data['long entity type; long field name; no prefix'] = [
[
'entity_type_id' => 'long_entity_type_abcdefghijklmnopqrstuvwxyz',
'field_name' => 'long_field_name_abcdefghijklmnopqrstuvwxyz',
'prefix' => '',
],
'long_entity_type_abcdefghijklmno__7705d52d75',
'long_entity_type_abcdefghijklmno_r__7705d52d75',
];
$data['short entity type; short field name; with prefix'] = [
[
'entity_type_id' => 'short_entity_type',
'field_name' => 'short_field_name',
'prefix' => 'prefix_',
],
'prefix_short_entity_type__short_field_name',
'prefix_short_entity_type_r__a133cc765a',
];
$data['short entity type; long field name; with prefix'] = [
[
'entity_type_id' => 'short_entity_type',
'field_name' => 'long_field_name_abcdefghijklmnopqrstuvwxyz',
'prefix' => 'prefix_',
],
'prefix_short_entity_type__28a01c7777',
'prefix_short_entity_type_r__28a01c7777',
];
$data['long entity type; short field name; with prefix'] = [
[
'entity_type_id' => 'long_entity_type_abcdefghijklmnopqrstuvwxyz',
'field_name' => 'short_field_name',
'prefix' => 'prefix_',
],
'prefix___a526e4e042',
'prefix__r__a526e4e042',
];
$data['long entity type; long field name; with prefix'] = [
[
'entity_type_id' => 'long_entity_type_abcdefghijklmnopqrstuvwxyz',
'field_name' => 'long_field_name_abcdefghijklmnopqrstuvwxyz',
'prefix' => 'prefix_',
],
'prefix___7705d52d75',
'prefix__r__7705d52d75',
];
return $data;
}
/**
* @coversDefaultClass \Drupal\Core\Entity\Sql\TemporaryTableMapping
*
* @expectedDeprecation Drupal\Core\Entity\Sql\TemporaryTableMapping is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Use the default table mapping with a prefix instead.
* @group legacy
*/
public function testTemporaryTableMapping() {
$table_mapping = new TemporaryTableMapping($this->entityType, [], '');
$this->assertTrue($table_mapping instanceof DefaultTableMapping);
}
/** /**
* Sets up a field storage definition for the test. * Sets up a field storage definition for the test.
* *
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment