Commit a8677733 authored by catch's avatar catch
Browse files

Issue #1277776 by fago, plach, Gábor Hojtsy, aspilicious, brantwynn: Add...

Issue #1277776 by fago, plach, Gábor Hojtsy, aspilicious, brantwynn: Add generic field/property getters/setters (with optional language support) for entities.
parent 05b0eb5b
......@@ -92,6 +92,60 @@ public function label();
*/
public function uri();
/**
* Returns the default language of a language-specific entity.
*
* @return
* The language object of the entity's default language, or FALSE if the
* entity is not language-specific.
*
* @see EntityInterface::translations()
*/
public function language();
/**
* Returns the languages the entity is translated to.
*
* @return
* An array of language objects, keyed by language codes.
*
* @see EntityInterface::language()
*/
public function translations();
/**
* Returns the value of an entity property.
*
* @param $property_name
* The name of the property to return; e.g., 'title'.
* @param $langcode
* (optional) If the property is translatable, the language code of the
* language that should be used for getting the property. If set to NULL,
* the entity's default language is being used.
*
* @return
* The property value, or NULL if it is not defined.
*
* @see EntityInterface::language()
*/
public function get($property_name, $langcode = NULL);
/**
* Sets the value of an entity property.
*
* @param $property_name
* The name of the property to set; e.g., 'title'.
* @param $value
* The value to set, or NULL to unset the property.
* @param $langcode
* (optional) If the property is translatable, the language code of the
* language that should be used for getting the property. If set to
* NULL, the entity's default language is being used.
*
* @see EntityInterface::language()
*/
public function set($property_name, $value, $langcode = NULL);
/**
* Saves an entity permanently.
*
......@@ -138,6 +192,13 @@ public function entityInfo();
*/
class Entity implements EntityInterface {
/**
* The language code of the entity's default language.
*
* @var string
*/
public $langcode = LANGUAGE_NOT_SPECIFIED;
/**
* The entity type.
*
......@@ -246,6 +307,89 @@ public function uri() {
}
}
/**
* Implements EntityInterface::language().
*/
public function language() {
// @todo: Check for language.module instead, once Field API language
// handling depends upon it too.
return module_exists('locale') ? language_load($this->langcode) : FALSE;
}
/**
* Implements EntityInterface::translations().
*/
public function translations() {
$languages = array();
if ($this->entityInfo['fieldable'] && ($default_language = $this->language())) {
// Go through translatable properties and determine all languages for
// which translated values are available.
foreach (field_info_instances($this->entityType, $this->bundle()) as $field_name => $instance) {
$field = field_info_field($field_name);
if (field_is_translatable($this->entityType, $field) && isset($this->$field_name)) {
foreach ($this->$field_name as $langcode => $value) {
$languages[$langcode] = TRUE;
}
}
}
// Remove the default language from the translations.
unset($languages[$default_language->langcode]);
$languages = array_intersect_key(language_list(), $languages);
}
return $languages;
}
/**
* Implements EntityInterface::get().
*/
public function get($property_name, $langcode = NULL) {
// Handle fields.
if ($this->entityInfo['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) {
$field = field_info_field($property_name);
$langcode = $this->getFieldLangcode($field, $langcode);
return isset($this->{$property_name}[$langcode]) ? $this->{$property_name}[$langcode] : NULL;
}
else {
// Handle properties being not fields.
// @todo: Add support for translatable properties being not fields.
return isset($this->{$property_name}) ? $this->{$property_name} : NULL;
}
}
/**
* Implements EntityInterface::set().
*/
public function set($property_name, $value, $langcode = NULL) {
// Handle fields.
if ($this->entityInfo['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) {
$field = field_info_field($property_name);
$langcode = $this->getFieldLangcode($field, $langcode);
$this->{$property_name}[$langcode] = $value;
}
else {
// Handle properties being not fields.
// @todo: Add support for translatable properties being not fields.
$this->{$property_name} = $value;
}
}
/**
* Determines the language code to use for accessing a field value in a certain language.
*/
protected function getFieldLangcode($field, $langcode = NULL) {
// 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())) {
// For translatable fields the values in default language are stored using
// the language code of the default language.
return isset($langcode) ? $langcode : $default_language->langcode;
}
else {
// Non-translatable fields always use LANGUAGE_NOT_SPECIFIED.
return LANGUAGE_NOT_SPECIFIED;
}
}
/**
* Implements EntityInterface::save().
*/
......
......@@ -65,6 +65,138 @@ class EntityAPITestCase extends DrupalWebTestCase {
$all = entity_test_load_multiple(FALSE);
$this->assertTrue(empty($all), 'Deleted all entities.');
}
/**
* Tests Entity getters/setters.
*/
function testEntityGettersSetters() {
$entity = entity_create('entity_test', array('name' => 'test', 'uid' => NULL));
$this->assertNull($entity->get('uid'), 'Property is not set.');
$entity->set('uid', $GLOBALS['user']->uid);
$this->assertEqual($entity->uid, $GLOBALS['user']->uid, 'Property has been set.');
$value = $entity->get('uid');
$this->assertEqual($value, $entity->uid, 'Property has been retrieved.');
// Make sure setting/getting translations boils down to setting/getting the
// regular value as the entity and property are not translatable.
$entity->set('uid', NULL, 'en');
$this->assertNull($entity->uid, 'Language neutral property has been set.');
$value = $entity->get('uid', 'en');
$this->assertNull($value, 'Language neutral property has been retrieved.');
}
}
/**
* Tests entity translation.
*/
class EntityTranslationTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Entity Translation',
'description' => 'Tests entity translation functionality.',
'group' => 'Entity API',
);
}
function setUp() {
// Enable translations for the test entity type. We cannot use
// variable_set() here as variables are cleared by parent::setUp();
$GLOBALS['entity_test_translation'] = TRUE;
parent::setUp('entity_test', 'language', 'locale');
// Create a translatable test field.
$this->field_name = drupal_strtolower($this->randomName() . '_field_name');
$field = array(
'field_name' => $this->field_name,
'type' => 'text',
'cardinality' => 4,
'translatable' => TRUE,
);
field_create_field($field);
$this->field = field_read_field($this->field_name);
$instance = array(
'field_name' => $this->field_name,
'entity_type' => 'entity_test',
'bundle' => 'entity_test',
);
field_create_instance($instance);
$this->instance = field_read_instance('entity_test', $this->field_name, 'entity_test');
// Create test languages.
$this->langcodes = array();
for ($i = 0; $i < 3; ++$i) {
$language = (object) array(
'langcode' => 'l' . $i,
'name' => $this->randomString(),
);
$this->langcodes[$i] = $language->langcode;
language_save($language);
}
}
/**
* Tests language related methods of the Entity class.
*/
function testEntityLanguageMethods() {
$entity = entity_create('entity_test', array(
'name' => 'test',
'uid' => $GLOBALS['user']->uid,
));
$this->assertFalse($entity->language(), 'No entity language has been specified.');
$this->assertFalse($entity->translations(), 'No translations are available');
// Set the value in default language.
$entity->set($this->field_name, array(0 => array('value' => 'default value')));
// Get the value.
$value = $entity->get($this->field_name);
$this->assertEqual($value, array(0 => array('value' => 'default value')), 'Untranslated value retrieved.');
// 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');
// Test getting a field value using the default 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.');
// Now, make the entity language-specific by assigning a language and test
// translating it.
$entity->langcode = $this->langcodes[0];
$entity->{$this->field_name} = array();
$this->assertEqual($entity->language(), language_load($this->langcodes[0]), 'Entity language retrieved.');
$this->assertFalse($entity->translations(), 'No translations are available');
// Set the value in default language.
$entity->set($this->field_name, array(0 => array('value' => 'default value')));
// Get the value.
$value = $entity->get($this->field_name);
$this->assertEqual($value, array(0 => array('value' => 'default value')), 'Untranslated value retrieved.');
// Set a translation.
$entity->set($this->field_name, array(0 => array('value' => 'translation 1')), $this->langcodes[1]);
$value = $entity->get($this->field_name, $this->langcodes[1]);
$this->assertEqual($value, array(0 => array('value' => 'translation 1')), 'Translated value set.');
// Make sure the untranslated value stays.
$value = $entity->get($this->field_name);
$this->assertEqual($value, array(0 => array('value' => 'default value')), 'Untranslated value stays.');
$translations[$this->langcodes[1]] = language_load($this->langcodes[1]);
$this->assertEqual($entity->translations(), $translations, 'Translations retrieved.');
// Try to get a not available translation.
$value = $entity->get($this->field_name, $this->langcodes[2]);
$this->assertNull($value, 'A translation that is not available is NULL.');
}
}
/**
......
......@@ -57,6 +57,13 @@ function entity_test_schema() {
'default' => NULL,
'description' => "The {users}.uid of the associated user.",
),
'langcode' => array(
'description' => 'The {language}.langcode of the test entity.',
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
),
),
'indexes' => array(
'uid' => array('uid'),
......
......@@ -9,19 +9,21 @@
* Implements hook_entity_info().
*/
function entity_test_entity_info() {
$return = array(
'entity_test' => array(
'label' => t('Test entity'),
'entity class' => 'Entity',
'controller class' => 'EntityDatabaseStorageController',
'base table' => 'entity_test',
'fieldable' => TRUE,
'entity keys' => array(
'id' => 'id',
),
$items['entity_test'] = array(
'label' => t('Test entity'),
'entity class' => 'Entity',
'controller class' => 'EntityDatabaseStorageController',
'base table' => 'entity_test',
'fieldable' => TRUE,
'entity keys' => array(
'id' => 'id',
),
);
return $return;
// Optionally specify a translation handler for testing translations.
if (!empty($GLOBALS['entity_test_translation'])) {
$items['entity_test']['translation']['entity_test'] = TRUE;
}
return $items;
}
/**
......
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