summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwebchick2012-09-20 06:15:55 (GMT)
committerwebchick2012-09-20 06:15:55 (GMT)
commit91c41b3f377f706874cca0d7daf70ecde8179012 (patch)
treef35cefdc6407b473b0362c78dc75658bf7d9720b
parentf2f1d888f693c095027c5a1d67ee61ca72e1dc1c (diff)
Issue #1738368 by Schnitzel, YesCT, Gábor Hojtsy, c31ck, sun, plach: Fixed Not possible to use the entity getter to retrieve non-translatable field values.
-rw-r--r--core/lib/Drupal/Core/Entity/Entity.php63
-rw-r--r--core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php20
2 files changed, 69 insertions, 14 deletions
diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index 1d22278..fb75ee2 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -184,7 +184,9 @@ class Entity implements EntityInterface {
$entity_info = $this->entityInfo();
if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) {
$field = field_info_field($property_name);
- $langcode = $this->getFieldLangcode($field, $langcode);
+ // Prevent getFieldLangcode() from throwing an exception in case a
+ // $langcode has been passed and it is invalid for the field.
+ $langcode = $this->getFieldLangcode($field, $langcode, FALSE);
return isset($this->{$property_name}[$langcode]) ? $this->{$property_name}[$langcode] : NULL;
}
else {
@@ -202,6 +204,7 @@ class Entity implements EntityInterface {
$entity_info = $this->entityInfo();
if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) {
$field = field_info_field($property_name);
+ // Throws an exception if the $langcode is invalid.
$langcode = $this->getFieldLangcode($field, $langcode);
$this->{$property_name}[$langcode] = $value;
}
@@ -213,9 +216,45 @@ class Entity implements EntityInterface {
}
/**
- * Determines the language code to use for accessing a field value in a certain language.
+ * Determines the language code for accessing a field value.
+ *
+ * The effective language code to be used for a field varies:
+ * - If the entity is language-specific and the requested field is
+ * translatable, the entity's language code should be used to access the
+ * field value when no language is explicitly provided.
+ * - If the entity is not language-specific, LANGUAGE_NOT_SPECIFIED should be
+ * used to access all field values.
+ * - If a field's values are non-translatable (shared among all language
+ * versions of an entity), LANGUAGE_NOT_SPECIFIED should be used to access
+ * them.
+ *
+ * There cannot be valid field values if a field is not translatable and the
+ * requested langcode is not LANGUAGE_NOT_SPECIFIED. Therefore, this function
+ * throws an exception in that case (or returns NULL when $strict is FALSE).
+ *
+ * @param string $field
+ * Field the language code is being determined for.
+ * @param string|null $langcode
+ * (optional) The language code attempting to be applied to the field.
+ * Defaults to the entity language.
+ * @param bool $strict
+ * (optional) When $strict is TRUE, an exception is thrown if the field is
+ * not translatable and the langcode is not LANGUAGE_NOT_SPECIFIED. When
+ * $strict is FALSE, NULL is returned and no exception is thrown. For
+ * example, EntityInterface::set() passes TRUE, since it must not set field
+ * values for invalid langcodes. EntityInterface::get() passes FALSE to
+ * determine whether any field values exist for a specific langcode.
+ * Defaults to TRUE.
+ *
+ * @return string|null
+ * The langcode if appropriate, LANGUAGE_NOT_SPECIFIED for non-translatable
+ * fields, or NULL when an invalid langcode was used in non-strict mode.
+ *
+ * @throws \InvalidArgumentException
+ * Thrown in case a $langcode other than LANGUAGE_NOT_SPECIFIED is passed
+ * for a non-translatable field and $strict is TRUE.
*/
- protected function getFieldLangcode($field, $langcode = NULL) {
+ protected function getFieldLangcode($field, $langcode = NULL, $strict = TRUE) {
// Only apply the given langcode if the entity is language-specific.
// Otherwise translatable fields are handled as non-translatable fields.
if (field_is_translatable($this->entityType, $field) && ($default_language = $this->language()) && !language_is_locked($this->langcode)) {
@@ -224,9 +263,21 @@ class Entity implements EntityInterface {
return isset($langcode) ? $langcode : $default_language->langcode;
}
else {
- // If there is a langcode defined for this field, just return it. Otherwise
- // return LANGUAGE_NOT_SPECIFIED.
- return (isset($this->langcode) ? $this->langcode : LANGUAGE_NOT_SPECIFIED);
+ // The field is not translatable, but the caller requested a specific
+ // langcode that does not exist.
+ if (isset($langcode) && $langcode !== LANGUAGE_NOT_SPECIFIED) {
+ if ($strict) {
+ throw new \InvalidArgumentException(format_string('Unable to resolve @langcode for non-translatable field @field_name. Use langcode LANGUAGE_NOT_SPECIFIED instead.', array(
+ '@field_name' => $field['field_name'],
+ '@langcode' => $langcode,
+ )));
+ }
+ else {
+ return NULL;
+ }
+ }
+ // The field is not translatable and no $langcode was specified.
+ return LANGUAGE_NOT_SPECIFIED;
}
}
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 805d52c..e5e5e2e 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
@@ -87,18 +87,22 @@ class EntityTranslationTest extends WebTestBase {
$value = $entity->get($this->field_name);
$this->assertEqual($value, array(0 => array('value' => 'default value')), 'Untranslated value retrieved.');
+ $message = "An exception is thrown when trying to set a field with an invalid language";
+
// Set the value in a certain language. As the entity is not
- // language-specific it should use the default language and so ignore the
- // specified language.
- $entity->set($this->field_name, array(0 => array('value' => 'default value2')), $this->langcodes[1]);
- $value = $entity->get($this->field_name);
- $this->assertEqual($value, array(0 => array('value' => 'default value2')), 'Untranslated value updated.');
- $this->assertFalse($entity->translations(), 'No translations are available');
+ // language-specific it will throw an exception.
+ try {
+ $entity->set($this->field_name, array(0 => array('value' => 'default value2')), $this->langcodes[1]);
+ $this->fail($message);
+ }
+ catch (Exception $e) {
+ $this->assertTrue($e instanceof InvalidArgumentException, $message);
+ }
- // Test getting a field value using the default language for a not
+ // Test getting a field value using a specific language for a not
// language-specific entity.
$value = $entity->get($this->field_name, $this->langcodes[1]);
- $this->assertEqual($value, array(0 => array('value' => 'default value2')), 'Untranslated value retrieved.');
+ $this->assertNull($value, 'Returned NULL for getter with invalid language.');
// Now, make the entity language-specific by assigning a language and test
// translating it.