diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php index 353aab0..11666f3 100644 --- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php @@ -869,8 +869,8 @@ protected function doLoadFieldItems($entities, $age) { foreach ($results as $row) { // Ensure that records for non-translatable fields having invalid // languages are skipped. - // @todo Remove BC support for 'und' untransltable fields as soon as can - // write a migration for them. + // @todo Remove BC support for 'und' untranslatable fields as soon as + // can write a migration for them. if ($translatable || $row->langcode == Language::LANGCODE_NOT_SPECIFIED || $row->langcode == $entities[$row->entity_id]->getUntranslated()->language()->id) { if (!isset($delta_count[$row->entity_id][$row->langcode])) { $delta_count[$row->entity_id][$row->langcode] = 0; diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php index 1f82ea9..28fa615 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php @@ -7,9 +7,12 @@ namespace Drupal\system\Tests\Entity; +use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\FieldableDatabaseStorageController; use Drupal\Core\Language\Language; use Drupal\Core\TypedData\TranslatableInterface; use Drupal\entity_test\Entity\EntityTestMulRev; +use Drupal\field\Field as FieldService; /** * Tests entity translation. @@ -18,6 +21,20 @@ class EntityTranslationTest extends EntityUnitTestBase { protected $langcodes; + /** + * The test field name. + * + * @var string + */ + protected $field_name; + + /** + * The untranslatable test field name. + * + * @var string + */ + protected $untranslatable_field_name; + public static $modules = array('language', 'entity_test'); public static function getInfo() { @@ -534,4 +551,128 @@ function testFieldDefinitions() { } } + /** + * Tests field SQL storage. + */ + function testFieldSqlStorage() { + $entity_type = 'entity_test_mul'; + $this->untranslatable_field_name = drupal_strtolower($this->randomName() . '_field_name'); + + entity_create('field_entity', array( + 'name' => $this->untranslatable_field_name, + 'entity_type' => $entity_type, + 'type' => 'text', + 'cardinality' => 4, + 'translatable' => FALSE, + ))->save(); + entity_create('field_instance', array( + 'field_name' => $this->untranslatable_field_name, + 'entity_type' => $entity_type, + 'bundle' => $entity_type, + ))->save(); + + $controller = $this->entityManager->getStorageController($entity_type); + $values = array( + $this->field_name => $this->randomName(), + $this->untranslatable_field_name => $this->randomName(), + ); + $entity = $controller->create($values); + $entity->save(); + + // Tests that when changing language field language codes are still correct. + $langcode = $this->langcodes[0]; + $entity->langcode->value = $langcode; + $entity->save(); + $this->assertFieldStorageLangcode($entity, 'Field language successfully changed from language neutral.'); + $langcode = $this->langcodes[1]; + $entity->langcode->value = $langcode; + $entity->save(); + $this->assertFieldStorageLangcode($entity, 'Field language successfully changed.'); + $langcode = Language::LANGCODE_NOT_SPECIFIED; + $entity->langcode->value = $langcode; + $entity->save(); + $this->assertFieldStorageLangcode($entity, 'Field language successfully changed to language neutral.'); + + // Test that after switching field translatability things keep working as + // before. + $this->toggleFieldTranslatability($entity_type); + $entity = $this->reloadEntity($entity); + foreach (array($this->field_name, $this->untranslatable_field_name) as $field_name) { + $this->assertEqual($entity->get($field_name)->value, $values[$field_name], 'Field language works as expected after switching translatability.'); + } + + // Test that after disabling field translatability translated values are not + // loaded. + $this->toggleFieldTranslatability($entity_type); + $entity = $this->reloadEntity($entity); + $entity->langcode->value = $this->langcodes[0]; + $translation = $entity->addTranslation($this->langcodes[1]); + $translated_value = $this->randomName(); + $translation->get($this->field_name)->value = $translated_value; + $translation->save(); + $this->toggleFieldTranslatability($entity_type); + $entity = $this->reloadEntity($entity); + $this->assertEqual($entity->getTranslation($this->langcodes[1])->get($this->field_name)->value, $values[$this->field_name]); + } + + /** + * Checks whether field languages are correctly stored for the given entity. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The entity fields are attached to. + * @param string $message + * (optional) A message to display with the assertion. + */ + protected function assertFieldStorageLangcode(ContentEntityInterface $entity, $message = '') { + $status = TRUE; + $entity_type = $entity->entityType(); + $id = $entity->id(); + $langcode = $entity->getUntranslated()->language()->id; + $fields = array($this->field_name, $this->untranslatable_field_name); + + foreach ($fields as $field_name) { + $field = FieldService::fieldInfo()->getField($entity_type, $field_name); + $tables = array( + FieldableDatabaseStorageController::_fieldTableName($field), + FieldableDatabaseStorageController::_fieldRevisionTableName($field), + ); + + foreach ($tables as $table) { + $record = \Drupal::database() + ->select($table, 'f') + ->fields('f') + ->condition('f.entity_id', $id) + ->condition('f.revision_id', $id) + ->execute() + ->fetchObject(); + + if ($record->langcode != $langcode) { + $status = FALSE; + break; + } + } + } + + return $this->assertTrue($status, $message); + } + + /** + * Toggles field translatability. + * + * @param string $entity_type + * The type of the entity fields are attached to. + */ + protected function toggleFieldTranslatability($entity_type) { + $fields = array($this->field_name, $this->untranslatable_field_name); + foreach ($fields as $field_name) { + $field = FieldService::fieldInfo()->getField($entity_type, $field_name); + $translatable = !$field->isFieldTranslatable(); + $field->set('translatable', $translatable); + $field->save(); + FieldService::fieldInfo()->flush(); + $field = FieldService::fieldInfo()->getField($entity_type, $field_name); + $this->assertEqual($field->isFieldTranslatable(), $translatable, 'Field translatability changed.'); + } + \Drupal::cache('field')->deleteAll(); + } }