Commit 34dec4b7 authored by catch's avatar catch
Browse files

Issue #2078625 by yched: Field/FieldItem value objects should carry their language.

parent 5b578a55
......@@ -315,7 +315,9 @@ protected function getTranslatedField($property_name, $langcode) {
$value = $this->values[$property_name][$default_langcode];
}
}
$this->fields[$property_name][$langcode] = \Drupal::typedData()->getPropertyInstance($this, $property_name, $value);
$field = \Drupal::typedData()->getPropertyInstance($this, $property_name, $value);
$field->setLangcode($langcode);
$this->fields[$property_name][$langcode] = $field;
}
}
return $this->fields[$property_name][$langcode];
......
......@@ -11,6 +11,7 @@
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\Core\TypedData\ItemList;
use Drupal\Core\Language\Language;
/**
* Represents an entity field; that is, a list of field item objects.
......@@ -36,6 +37,13 @@ class Field extends ItemList implements FieldInterface {
*/
protected $list = array();
/**
* The langcode of the field values held in the object.
*
* @var string
*/
protected $langcode = Language::LANGCODE_DEFAULT;
/**
* Overrides TypedData::__construct().
*/
......@@ -48,6 +56,20 @@ public function __construct(array $definition, $name = NULL, TypedDataInterface
$this->list[0] = $this->createItem(0);
}
/**
* {@inheritdoc}
*/
public function setLangcode($langcode) {
$this->langcode = $langcode;
}
/**
* {@inheritdoc}
*/
public function getLangcode() {
return $this->langcode;
}
/**
* {@inheritdoc}
*/
......
......@@ -27,6 +27,22 @@
*/
interface FieldInterface extends ListInterface, AccessibleInterface {
/**
* Sets the langcode of the field values held in the object.
*
* @param string $langcode
* The langcode.
*/
public function setLangcode($langcode);
/**
* Gets the langcode of the field values held in the object.
*
* @return $langcode
* The langcode.
*/
public function getLangcode();
/**
* Gets the field definition.
*
......
......@@ -36,6 +36,13 @@ public function __construct(array $definition, $name = NULL, TypedDataInterface
}
}
/**
* {@inheritdoc}
*/
public function getLangcode() {
return $this->parent->getLangcode();
}
/**
* {@inheritdoc}
*/
......
......@@ -23,6 +23,14 @@
*/
interface FieldItemInterface extends ComplexDataInterface {
/**
* Gets the langcode of the field values held in the object.
*
* @return $langcode
* The langcode.
*/
public function getLangcode();
/**
* Gets the field definition.
*
......
......@@ -94,7 +94,7 @@ function setUp() {
public function testEntityLanguageMethods() {
// All entity variations have to have the same results.
foreach (entity_test_entity_types() as $entity_type) {
$this->assertEntityLanguageMethods($entity_type);
$this->_testEntityLanguageMethods($entity_type);
}
}
......@@ -104,7 +104,7 @@ public function testEntityLanguageMethods() {
* @param string $entity_type
* The entity type to run the tests with.
*/
protected function assertEntityLanguageMethods($entity_type) {
protected function _testEntityLanguageMethods($entity_type) {
$entity = entity_create($entity_type, array(
'name' => 'test',
'user_id' => $GLOBALS['user']->id(),
......@@ -115,7 +115,9 @@ protected function assertEntityLanguageMethods($entity_type) {
// Set the value in default language.
$entity->set($this->field_name, array(0 => array('value' => 'default value')));
// Get the value.
$this->assertEqual($entity->getTranslation(Language::LANGCODE_DEFAULT)->get($this->field_name)->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation(Language::LANGCODE_DEFAULT)->get($this->field_name);
$this->assertEqual($field->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
$this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Set the value in a certain language. As the entity is not
// language-specific it should use the default language and so ignore the
......@@ -126,7 +128,9 @@ protected function assertEntityLanguageMethods($entity_type) {
// Test getting a field value using a specific language for a not
// language-specific entity.
$this->assertEqual($entity->getTranslation($this->langcodes[1])->get($this->field_name)->value, 'default value2', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation($this->langcodes[1])->get($this->field_name);
$this->assertEqual($field->value, 'default value2', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
$this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Now, make the entity language-specific by assigning a language and test
// translating it.
......@@ -138,14 +142,20 @@ protected function assertEntityLanguageMethods($entity_type) {
// Set the value in default language.
$entity->set($this->field_name, array(0 => array('value' => 'default value')));
// Get the value.
$this->assertEqual($entity->get($this->field_name)->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
$field = $entity->get($this->field_name);
$this->assertEqual($field->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
$this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Set a translation.
$entity->getTranslation($this->langcodes[1])->set($this->field_name, array(0 => array('value' => 'translation 1')));
$this->assertEqual($entity->getTranslation($this->langcodes[1])->{$this->field_name}->value, 'translation 1', format_string('%entity_type: Translated value set.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation($this->langcodes[1])->{$this->field_name};
$this->assertEqual($field->value, 'translation 1', format_string('%entity_type: Translated value set.', array('%entity_type' => $entity_type)));
$this->assertEqual($field->getLangcode(), $this->langcodes[1], format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Make sure the untranslated value stays.
$this->assertEqual($entity->get($this->field_name)->value, 'default value', 'Untranslated value stays.');
$field = $entity->get($this->field_name);
$this->assertEqual($field->value, 'default value', 'Untranslated value stays.');
$this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, 'Untranslated value has the expected langcode.');
$translations[$this->langcodes[1]] = language_load($this->langcodes[1]);
$this->assertEqual($entity->getTranslationLanguages(FALSE), $translations, 'Translations retrieved.');
......@@ -175,7 +185,9 @@ protected function assertEntityLanguageMethods($entity_type) {
$field_name = 'field_test_text';
$entity->getTranslation($this->langcodes[1])->set($field_name, array(0 => array('value' => 'default value2')));
// Get the value.
$this->assertEqual($entity->get($field_name)->value, 'default value2', format_string('%entity_type: Untranslated value set into a translation in non-strict mode.', array('%entity_type' => $entity_type)));
$field = $entity->get($field_name);
$this->assertEqual($field->value, 'default value2', format_string('%entity_type: Untranslated value set into a translation in non-strict mode.', array('%entity_type' => $entity_type)));
$this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
}
/**
......@@ -184,7 +196,7 @@ protected function assertEntityLanguageMethods($entity_type) {
public function testMultilingualProperties() {
// Test all entity variations with data table support.
foreach (entity_test_entity_types(ENTITY_TEST_TYPES_MULTILINGUAL) as $entity_type) {
$this->assertMultilingualProperties($entity_type);
$this->_testMultilingualProperties($entity_type);
}
}
......@@ -194,7 +206,7 @@ public function testMultilingualProperties() {
* @param string $entity_type
* The entity type to run the tests with.
*/
protected function assertMultilingualProperties($entity_type) {
protected function _testMultilingualProperties($entity_type) {
$name = $this->randomName();
$uid = mt_rand(0, 127);
$langcode = $this->langcodes[0];
......@@ -205,13 +217,19 @@ protected function assertMultilingualProperties($entity_type) {
$entity->save();
$entity = entity_load($entity_type, $entity->id());
$this->assertEqual($entity->language()->id, Language::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Entity created as language neutral.', array('%entity_type' => $entity_type)));
$this->assertEqual($name, $entity->getTranslation(Language::LANGCODE_DEFAULT)->get('name')->value, format_string('%entity_type: The entity name has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation(Language::LANGCODE_DEFAULT)->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
$this->assertEqual(Language::LANGCODE_DEFAULT, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation(Language::LANGCODE_DEFAULT)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
// As fields, translatable properties should ignore the given langcode and
// use neutral language if the entity is not translatable.
$this->assertEqual($name, $entity->getTranslation($langcode)->get('name')->value, format_string('%entity_type: The entity name defaults to neutral language.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation($langcode)->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to neutral language.', array('%entity_type' => $entity_type)));
$this->assertEqual(Language::LANGCODE_DEFAULT, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to neutral language.', array('%entity_type' => $entity_type)));
$this->assertEqual($name, $entity->get('name')->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
$field = $entity->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
$this->assertEqual(Language::LANGCODE_DEFAULT, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->get('user_id')->target_id, format_string('%entity_type: The entity author can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
// Create a language-aware entity and check that properties are stored
......@@ -220,13 +238,19 @@ protected function assertMultilingualProperties($entity_type) {
$entity->save();
$entity = entity_load($entity_type, $entity->id());
$this->assertEqual($entity->language()->id, $langcode, format_string('%entity_type: Entity created as language specific.', array('%entity_type' => $entity_type)));
$this->assertEqual($name, $entity->getTranslation($langcode)->get('name')->value, format_string('%entity_type: The entity name has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation($langcode)->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
$this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
// Translatable properties on a translatable entity should use default
// language if Language::LANGCODE_NOT_SPECIFIED is passed.
$this->assertEqual($name, $entity->getTranslation(Language::LANGCODE_NOT_SPECIFIED)->get('name')->value, format_string('%entity_type: The entity name defaults to the default language.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation(Language::LANGCODE_NOT_SPECIFIED)->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to the default language.', array('%entity_type' => $entity_type)));
$this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation(Language::LANGCODE_NOT_SPECIFIED)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to the default language.', array('%entity_type' => $entity_type)));
$this->assertEqual($name, $entity->get('name')->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
$field = $entity->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
$this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->get('user_id')->target_id, format_string('%entity_type: The entity author can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
// Create property translations.
......@@ -256,7 +280,11 @@ protected function assertMultilingualProperties($entity_type) {
'%entity_type' => $entity_type,
'%langcode' => $langcode,
);
$this->assertEqual($properties[$langcode]['name'][0], $entity->getTranslation($langcode)->get('name')->value, format_string('%entity_type: The entity name has been correctly stored for language %langcode.', $args));
$field = $entity->getTranslation($langcode)->get('name');
$this->assertEqual($properties[$langcode]['name'][0], $field->value, format_string('%entity_type: The entity name has been correctly stored for language %langcode.', $args));
// Fields for the default entity langcode are seen as language neutral.
$field_langcode = ($langcode == $entity->language()->id) ? Language::LANGCODE_NOT_SPECIFIED : $langcode;
$this->assertEqual($field_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expected langcode %langcode.', $args));
$this->assertEqual($properties[$langcode]['user_id'][0], $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored for language %langcode.', $args));
}
......@@ -459,7 +487,9 @@ function testEntityTranslationAPI() {
$instance['default_value_function'] = 'entity_test_field_default_value';
$instance->save();
$translation = $entity->addTranslation($langcode2);
$this->assertEqual($translation->get($this->field_name)->value, $this->field_name . '_' . $langcode2, 'Language-aware default values correctly populated.');
$field = $translation->get($this->field_name);
$this->assertEqual($field->value, $this->field_name . '_' . $langcode2, 'Language-aware default values correctly populated.');
$this->assertEqual($field->getLangcode(), $langcode2, 'Field object has the expected langcode.');
}
}
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