From 1023ddaffaf383f15e1ba9a06caf42992a867ac3 Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org> Date: Thu, 29 Jun 2017 13:52:17 +0100 Subject: [PATCH] Issue #2854732 by amateescu, jibran, tstoeckler: Use initial values for content translation metadata fields and fix existing data --- .../Sql/SqlContentEntityStorageSchema.php | 2 +- .../content_translation.install | 56 ++++++++++ .../src/ContentTranslationHandler.php | 3 + .../Update/ContentTranslationUpdateTest.php | 100 ++++++++++++++++++ .../Functional/Views/TaxonomyTermViewTest.php | 7 ++ 5 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 core/modules/content_translation/src/Tests/Update/ContentTranslationUpdateTest.php diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php index 0a5e7febf61c..c5751e12db8b 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php @@ -1712,7 +1712,7 @@ protected function getSharedTableFieldSchema(FieldStorageDefinitionInterface $st // Use the initial value of the field storage, if available. if ($initial_value && isset($initial_value[$field_column_name])) { - $schema['fields'][$schema_field_name]['initial'] = $initial_value[$field_column_name]; + $schema['fields'][$schema_field_name]['initial'] = drupal_schema_get_field_value($column_schema, $initial_value[$field_column_name]); } elseif (!empty($initial_value_from_field)) { $schema['fields'][$schema_field_name]['initial_from_field'] = $initial_value_from_field[$field_column_name]; diff --git a/core/modules/content_translation/content_translation.install b/core/modules/content_translation/content_translation.install index dc12d9f3fcf9..67b161c5e259 100644 --- a/core/modules/content_translation/content_translation.install +++ b/core/modules/content_translation/content_translation.install @@ -5,6 +5,8 @@ * Installation functions for Content Translation module. */ +use \Drupal\Core\Entity\Sql\SqlEntityStorageInterface; +use \Drupal\Core\Language\LanguageInterface; use \Drupal\Core\Url; /** @@ -44,3 +46,57 @@ function content_translation_update_8001() { function content_translation_update_8002() { \Drupal::service('plugin.manager.field.field_type')->clearCachedDefinitions(); } + +/** + * Fix the initial values for content translation metadata fields. + */ +function content_translation_update_8400() { + $database = \Drupal::database(); + /** @var \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager */ + $content_translation_manager = \Drupal::service('content_translation.manager'); + /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $last_installed_schema_repository */ + $last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository'); + $entity_type_manager = \Drupal::entityTypeManager(); + $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + + foreach ($content_translation_manager->getSupportedEntityTypes() as $entity_type_id => $entity_type_definition) { + $storage = $entity_type_manager->getStorage($entity_type_id); + if ($storage instanceof SqlEntityStorageInterface) { + $entity_type = $entity_definition_update_manager->getEntityType($entity_type_id); + $storage_definitions = $last_installed_schema_repository->getLastInstalledFieldStorageDefinitions($entity_type_id); + + // Since the entity type is managed by Content Translation, we can assume + // that it is translatable, so we use the data and revision data tables. + $tables_to_update = [$entity_type->getDataTable()]; + if ($entity_type->isRevisionable()) { + $tables_to_update += [$entity_type->getRevisionDataTable()]; + } + + foreach ($tables_to_update as $table_name) { + // Fix the values of the 'content_translation_source' field. + if (isset($storage_definitions['content_translation_source'])) { + $database->update($table_name) + ->fields(['content_translation_source' => LanguageInterface::LANGCODE_NOT_SPECIFIED]) + ->isNull('content_translation_source') + ->execute(); + } + + // Fix the values of the 'content_translation_outdated' field. + if (isset($storage_definitions['content_translation_outdated'])) { + $database->update($table_name) + ->fields(['content_translation_outdated' => 0]) + ->isNull('content_translation_outdated') + ->execute(); + } + + // Fix the values of the 'content_translation_status' field. + if (isset($storage_definitions['content_translation_status'])) { + $database->update($table_name) + ->fields(['content_translation_status' => 1]) + ->isNull('content_translation_status') + ->execute(); + } + } + } + } +} diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php index c1688b9d6477..7e6a7ca3ea6c 100644 --- a/core/modules/content_translation/src/ContentTranslationHandler.php +++ b/core/modules/content_translation/src/ContentTranslationHandler.php @@ -116,6 +116,7 @@ public function getFieldDefinitions() { ->setLabel(t('Translation source')) ->setDescription(t('The source language from which this translation was created.')) ->setDefaultValue(LanguageInterface::LANGCODE_NOT_SPECIFIED) + ->setInitialValue(LanguageInterface::LANGCODE_NOT_SPECIFIED) ->setRevisionable(TRUE) ->setTranslatable(TRUE); @@ -123,6 +124,7 @@ public function getFieldDefinitions() { ->setLabel(t('Translation outdated')) ->setDescription(t('A boolean indicating whether this translation needs to be updated.')) ->setDefaultValue(FALSE) + ->setInitialValue(FALSE) ->setRevisionable(TRUE) ->setTranslatable(TRUE); @@ -142,6 +144,7 @@ public function getFieldDefinitions() { ->setLabel(t('Translation status')) ->setDescription(t('A boolean indicating whether the translation is visible to non-translators.')) ->setDefaultValue(TRUE) + ->setInitialValue(TRUE) ->setRevisionable(TRUE) ->setTranslatable(TRUE); } diff --git a/core/modules/content_translation/src/Tests/Update/ContentTranslationUpdateTest.php b/core/modules/content_translation/src/Tests/Update/ContentTranslationUpdateTest.php new file mode 100644 index 000000000000..85b952c35ba8 --- /dev/null +++ b/core/modules/content_translation/src/Tests/Update/ContentTranslationUpdateTest.php @@ -0,0 +1,100 @@ +<?php + +namespace Drupal\content_translation\Tests\Update; + +use Drupal\Core\Language\LanguageInterface; +use Drupal\system\Tests\Entity\EntityDefinitionTestTrait; +use Drupal\system\Tests\Update\UpdatePathTestBase; + +/** + * Tests the upgrade path for the Content Translation module. + * + * @group Update + */ +class ContentTranslationUpdateTest extends UpdatePathTestBase { + + use EntityDefinitionTestTrait; + + /** + * The database connection used. + * + * @var \Drupal\Core\Database\Connection + */ + protected $database; + + /** + * The entity definition update manager. + * + * @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface + */ + protected $entityDefinitionUpdateManager; + + /** + * The entity manager service. + * + * @var \Drupal\Core\Entity\EntityManagerInterface + */ + protected $entityManager; + + /** + * The state service. + * + * @var \Drupal\Core\State\StateInterface + */ + protected $state; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->database = \Drupal::database(); + $this->entityDefinitionUpdateManager = \Drupal::entityDefinitionUpdateManager(); + $this->entityManager = \Drupal::entityManager(); + $this->state = \Drupal::state(); + } + + /** + * {@inheritdoc} + */ + public function setDatabaseDumpFiles() { + $this->databaseDumpFiles = [ + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.0.0-rc1-filled.standard.entity_test_update_mul.php.gz', + ]; + } + + /** + * Tests that initial values for metadata fields are populated correctly. + */ + public function testContentTranslationUpdate8400() { + $this->updateEntityTypeToTranslatable(); + + // The test database dump contains NULL values for + // 'content_translation_source', 'content_translation_outdated' and + // 'content_translation_status' for the first 50 test entities. + // @see _entity_test_update_create_test_entities() + $first_entity_record = $this->database->select('entity_test_update_data', 'etud') + ->fields('etud') + ->condition('etud.id', 1) + ->execute() + ->fetchAllAssoc('id'); + $this->assertNull($first_entity_record[1]->content_translation_source); + $this->assertNull($first_entity_record[1]->content_translation_outdated); + $this->assertNull($first_entity_record[1]->content_translation_status); + + $this->runUpdates(); + + // After running the updates, all those fields should be populated with + // their default values. + $first_entity_record = $this->database->select('entity_test_update_data', 'etud') + ->fields('etud') + ->condition('etud.id', 1) + ->execute() + ->fetchAllAssoc('id'); + $this->assertEqual(LanguageInterface::LANGCODE_NOT_SPECIFIED, $first_entity_record[1]->content_translation_source); + $this->assertEqual(0, $first_entity_record[1]->content_translation_outdated); + $this->assertEqual(1, $first_entity_record[1]->content_translation_status); + } + +} diff --git a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermViewTest.php b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermViewTest.php index 15f47231ca54..5f70d9042b29 100644 --- a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermViewTest.php +++ b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTermViewTest.php @@ -5,6 +5,7 @@ use Drupal\Component\Utility\Unicode; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\node\Entity\Node; use Drupal\user\Entity\Role; use Drupal\user\RoleInterface; use Drupal\views\Views; @@ -124,6 +125,12 @@ public function testTaxonomyTermView() { // query anymore. // @see \Drupal\views\Plugin\views\filter\LanguageFilter::query() $node->delete(); + + // We also have to remove the nodes created by the parent ::setUp() method + // if we want to be able to uninstall the Content Translation module. + foreach (Node::loadMultiple() as $node) { + $node->delete(); + } \Drupal::service('module_installer')->uninstall(['content_translation', 'language']); $view = Views::getView('taxonomy_term'); -- GitLab