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