Commit b778bfd1 authored by alexpott's avatar alexpott

Issue #2143729 by tstoeckler, plach, jsbalsera, Berdir, mauzeh, damiankloip,...

Issue #2143729 by tstoeckler, plach, jsbalsera, Berdir, mauzeh, damiankloip, andypost: Entity definitions miss a language entity key
parent 847a50ac
......@@ -189,7 +189,7 @@ protected function doLoadMultiple(array $ids = NULL) {
*/
protected function doCreate(array $values) {
// Set default language to site default if not provided.
$values += array('langcode' => $this->languageManager->getDefaultLanguage()->getId());
$values += array($this->langcodeKey => $this->languageManager->getDefaultLanguage()->getId());
$entity = new $this->entityClass($values, $this->entityTypeId);
return $entity;
......
......@@ -67,6 +67,7 @@ public function __construct($definition) {
parent::__construct($definition);
// Always add a default 'uuid' key.
$this->entity_keys['uuid'] = 'uuid';
$this->entity_keys['langcode'] = 'langcode';
$this->handlers += array(
'storage' => 'Drupal\Core\Config\Entity\ConfigEntityStorage',
);
......
......@@ -9,6 +9,7 @@
use Drupal\Component\Utility\String;
use Drupal\Core\Entity\Plugin\DataType\EntityReference;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\TypedDataInterface;
......@@ -73,6 +74,13 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
*/
protected $languages;
/**
* The language entity key.
*
* @var string
*/
protected $langcodeKey;
/**
* Language code identifying the entity active language.
*
......@@ -135,6 +143,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
public function __construct(array $values, $entity_type, $bundle = FALSE, $translations = array()) {
$this->entityTypeId = $entity_type;
$this->entityKeys['bundle'] = $bundle ? $bundle : $this->entityTypeId;
$this->langcodeKey = $this->getEntityType()->getKey('langcode');
foreach ($values as $key => $value) {
// If the key matches an existing property set the value to the property
......@@ -190,6 +199,12 @@ protected function typedDataManager() {
protected function getLanguages() {
if (empty($this->languages)) {
$this->languages = $this->languageManager()->getLanguages(LanguageInterface::STATE_ALL);
// If the entity references a language that is not or no longer available,
// we return a mock language object to avoid disrupting the consuming
// code.
if (!isset($this->languages[$this->defaultLangcode])) {
$this->languages[$this->defaultLangcode] = new Language(array('id' => $this->defaultLangcode));
}
}
return $this->languages;
}
......@@ -485,24 +500,31 @@ public function language() {
*/
protected function setDefaultLangcode() {
// Get the language code if the property exists.
if ($this->hasField('langcode') && ($item = $this->get('langcode')) && isset($item->language)) {
// Try to read the value directly from the list of entity keys which got
// initialized in __construct(). This avoids creating a field item object.
if (isset($this->entityKeys['langcode'])) {
$this->defaultLangcode = $this->entityKeys['langcode'];
}
elseif ($this->hasField($this->langcodeKey) && ($item = $this->get($this->langcodeKey)) && isset($item->language)) {
$this->defaultLangcode = $item->language->getId();
$this->entityKeys['langcode'] = $this->defaultLangcode;
}
if (empty($this->defaultLangcode)) {
// Make sure we return a proper language object, if the entity has a
// langcode field, default to the site's default language.
if ($this->hasField('langcode')) {
if ($this->hasField($this->langcodeKey)) {
$this->defaultLangcode = $this->languageManager()->getDefaultLanguage()->getId();
}
else {
$this->defaultLangcode = LanguageInterface::LANGCODE_NOT_SPECIFIED;
}
}
// This needs to be initialized manually as it is skipped when instantiating
// the language field object to avoid infinite recursion.
if (!empty($this->fields['langcode'])) {
$this->fields['langcode'][LanguageInterface::LANGCODE_DEFAULT]->setLangcode($this->defaultLangcode);
if (!empty($this->fields[$this->langcodeKey])) {
$this->fields[$this->langcodeKey][LanguageInterface::LANGCODE_DEFAULT]->setLangcode($this->defaultLangcode);
}
}
......@@ -521,14 +543,6 @@ protected function updateFieldLangcodes($langcode) {
* {@inheritdoc}
*/
public function onChange($name) {
if ($name == 'langcode') {
$this->setDefaultLangcode();
if (isset($this->translations[$this->defaultLangcode])) {
$message = String::format('A translation already exists for the specified language (@langcode).', array('@langcode' => $this->defaultLangcode));
throw new \InvalidArgumentException($message);
}
$this->updateFieldLangcodes($this->defaultLangcode);
}
// Check if the changed name is the value of an entity key and if the value
// of that is currently cached, if so, reset it. Exclude the bundle from
// that check, as it ready only and must not change, unsetting it could
......@@ -538,6 +552,16 @@ public function onChange($name) {
unset($this->entityKeys[$key]);
}
}
// Update the default internal language cache.
if ($name == $this->langcodeKey) {
$this->setDefaultLangcode();
if (isset($this->translations[$this->defaultLangcode])) {
$message = String::format('A translation already exists for the specified language (@langcode).', array('@langcode' => $this->defaultLangcode));
throw new \InvalidArgumentException($message);
}
$this->updateFieldLangcodes($this->defaultLangcode);
}
}
/**
......@@ -656,7 +680,11 @@ public function addTranslation($langcode, array $values = array()) {
// Instantiate a new empty entity so default values will be populated in the
// specified language.
$entity_type = $this->getEntityType();
$default_values = array($entity_type->getKey('bundle') => $this->bundle(), 'langcode' => $langcode);
$default_values = array(
$entity_type->getKey('bundle') => $this->bundle(),
$this->langcodeKey => $langcode,
);
$entity = $this->entityManager()
->getStorage($this->getEntityTypeId())
->create($default_values);
......
......@@ -309,7 +309,8 @@ public function access($operation, AccountInterface $account = NULL, $return_as_
* {@inheritdoc}
*/
public function language() {
$language = $this->languageManager()->getLanguage($this->langcode);
$langcode = $this->{$this->getEntityType()->getKey('langcode')};
$language = $this->languageManager()->getLanguage($langcode);
if (!$language) {
// Make sure we return a proper language object.
$langcode = $this->langcode ?: LanguageInterface::LANGCODE_NOT_SPECIFIED;
......
......@@ -434,7 +434,7 @@ protected function buildBaseFieldDefinitions($entity_type_id) {
// Ensure defined entity keys are there and have proper revisionable and
// translatable values.
$keys = array_filter($entity_type->getKeys() + array('langcode' => 'langcode'));
$keys = array_filter($entity_type->getKeys());
foreach ($keys as $key => $field_name) {
if (isset($base_field_definitions[$field_name]) && in_array($key, array('id', 'revision', 'uuid', 'bundle')) && $base_field_definitions[$field_name]->isRevisionable()) {
throw new \LogicException(String::format('The @field field cannot be revisionable as it is used as @key entity key.', array('@field' => $base_field_definitions[$field_name]->getLabel(), '@key' => $key)));
......
......@@ -57,6 +57,13 @@ abstract class EntityStorageBase extends EntityHandlerBase implements EntityStor
*/
protected $uuidKey;
/**
* The name of the entity langcode property.
*
* @var string
*/
protected $langcodeKey;
/**
* The UUID service.
*
......@@ -82,6 +89,7 @@ public function __construct(EntityTypeInterface $entity_type) {
$this->entityType = $entity_type;
$this->idKey = $this->entityType->getKey('id');
$this->uuidKey = $this->entityType->getKey('uuid');
$this->langcodeKey = $this->entityType->getKey('langcode');
$this->entityClass = $this->entityType->getClass();
}
......
......@@ -236,7 +236,8 @@ public function __construct($definition) {
// Ensure defaults.
$this->entity_keys += array(
'revision' => '',
'bundle' => ''
'bundle' => '',
'langcode' => '',
);
$this->handlers += array(
'access' => 'Drupal\Core\Entity\EntityAccessControlHandler',
......
......@@ -105,12 +105,15 @@ public function getOriginalClass();
* entry can be omitted if this entity type exposes a single bundle (such
* that all entities have the same collection of fields). The name of this
* single bundle will be the same as the entity type.
* - label: The name of the property that contains the entity label. For
* example, if the entity's label is located in $entity->subject, then
* 'subject' should be specified here. If complex logic is required to
* build the label, a 'label_callback' should be defined instead (see the
* $label_callback block above for details).
* - uuid (optional): The name of the property that contains the universally
* - label: (optional) The name of the property that contains the entity
* label. For example, if the entity's label is located in
* $entity->subject, then 'subject' should be specified here. If complex
* logic is required to build the label, a 'label_callback' should be
* defined instead (see the $label_callback block above for details).
* - langcode: (optional) The name of the property that contains the
* language code. For instance, if the entity's language is located in
* $entity->langcode, then 'langcode' should be specified here.
* - uuid: (optional) The name of the property that contains the universally
* unique identifier of the entity, which is used to distinctly identify
* an entity across different systems.
*/
......
......@@ -94,7 +94,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
*/
public function doCreate(array $values = array()) {
// Set default language to site default if not provided.
$values += array('langcode' => $this->languageManager->getDefaultLanguage()->getId());
$values += array($this->getEntityType()->getKey('langcode') => $this->languageManager->getDefaultLanguage()->getId());
$entity = new $this->entityClass($values, $this->entityTypeId);
// @todo This is handled by ContentEntityStorageBase, which assumes
......
......@@ -262,8 +262,13 @@ protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $b
protected function addJoin($type, $table, $join_condition, $langcode) {
$arguments = array();
if ($langcode) {
$entity_type_id = $this->sqlQuery->getMetaData('entity_type');
$entity_type = $this->entityManager->getDefinition($entity_type_id);
// Only the data table follows the entity language key, dedicated field
// tables have an hard-coded 'langcode' column.
$langcode_key = $entity_type->getDataTable() == $table ? $entity_type->getKey('langcode') : 'langcode';
$placeholder = ':langcode' . $this->sqlQuery->nextPlaceholder();
$join_condition .= ' AND %alias.langcode = ' . $placeholder;
$join_condition .= ' AND %alias.' . $langcode_key . ' = ' . $placeholder;
$arguments[$placeholder] = $langcode;
}
return $this->sqlQuery->addJoin($type, $table, NULL, $join_condition, $arguments);
......
......@@ -186,7 +186,7 @@ protected function initTableLayout() {
$translatable = $this->entityType->isTranslatable();
if ($translatable) {
$this->dataTable = $this->entityType->getDataTable() ?: $this->entityTypeId . '_field_data';
$this->langcodeKey = $this->entityType->getKey('langcode') ?: 'langcode';
$this->langcodeKey = $this->entityType->getKey('langcode');
$this->defaultLangcodeKey = $this->entityType->getKey('default_langcode') ?: 'default_langcode';
}
if ($revisionable && $translatable) {
......@@ -682,7 +682,7 @@ protected function attachPropertyData(array &$entities) {
// Field values in default language are stored with
// LanguageInterface::LANGCODE_DEFAULT as key.
$langcode = empty($values['default_langcode']) ? $values['langcode'] : LanguageInterface::LANGCODE_DEFAULT;
$langcode = empty($values['default_langcode']) ? $values[$this->langcodeKey] : LanguageInterface::LANGCODE_DEFAULT;
$translations[$id][$langcode] = TRUE;
......@@ -1145,8 +1145,8 @@ protected function mapToDataStorageRecord(EntityInterface $entity, $table_name =
$table_name = $this->dataTable;
}
$record = $this->mapToStorageRecord($entity, $table_name);
$record->langcode = $entity->language()->getId();
$record->default_langcode = intval($record->langcode == $entity->getUntranslated()->language()->getId());
$record->{$this->langcodeKey} = $entity->language()->getId();
$record->default_langcode = intval($record->{$this->langcodeKey} == $entity->getUntranslated()->language()->getId());
return $record;
}
......
......@@ -879,9 +879,7 @@ protected function initializeDataTable(ContentEntityTypeInterface $entity_type)
$schema = array(
'description' => "The data table for $entity_type_id entities.",
// @todo Use the language entity key when https://drupal.org/node/2143729
// is in.
'primary key' => array($id_key, 'langcode'),
'primary key' => array($id_key, $entity_type->getKey('langcode')),
'indexes' => array(),
'foreign keys' => array(
$entity_type_id => array(
......@@ -917,9 +915,7 @@ protected function initializeRevisionDataTable(ContentEntityTypeInterface $entit
$schema = array(
'description' => "The revision data table for $entity_type_id entities.",
// @todo Use the language entity key when https://drupal.org/node/2143729
// is in.
'primary key' => array($revision_key, 'langcode'),
'primary key' => array($revision_key, $entity_type->getKey('langcode')),
'indexes' => array(),
'foreign keys' => array(
$entity_type_id => array(
......@@ -1397,7 +1393,7 @@ protected function getSharedTableFieldSchema(FieldStorageDefinitionInterface $st
$schema['fields'][$schema_field_name] = $column_schema;
$schema['fields'][$schema_field_name]['description'] = $field_description;
// Only entity keys are required.
$keys = $this->entityType->getKeys() + array('langcode' => 'langcode');
$keys = $this->entityType->getKeys();
// The label is an entity key, but label fields are not necessarily
// required.
// Because entity ID and revision ID are both serial fields in the base
......
......@@ -43,6 +43,7 @@
* entity_keys = {
* "id" = "fid",
* "label" = "title",
* "langcode" = "langcode",
* "uuid" = "uuid",
* }
* )
......
......@@ -35,6 +35,7 @@
* entity_keys = {
* "id" = "iid",
* "label" = "title",
* "langcode" = "langcode",
* }
* )
*/
......
......@@ -49,6 +49,7 @@
* "revision" = "revision_id",
* "bundle" = "type",
* "label" = "info",
* "langcode" = "langcode",
* "uuid" = "uuid"
* },
* bundle_entity_type = "block_content_type",
......
......@@ -43,6 +43,7 @@
* "id" = "cid",
* "bundle" = "comment_type",
* "label" = "subject",
* "langcode" = "langcode",
* "uuid" = "uuid"
* },
* links = {
......
......@@ -291,7 +291,7 @@ function content_translation_form_alter(array &$form, FormStateInterface $form_s
// Handle fields shared between translations when there is at least one
// translation available or a new one is being created.
if (!$entity->isNew() && (!isset($translations[$form_langcode]) || count($translations) > 1)) {
$langcode_key = $entity->getEntityType()->getKey('langcode') ?: 'langcode';
$langcode_key = $entity->getEntityType()->getKey('langcode');
foreach ($entity->getFieldDefinitions() as $field_name => $definition) {
if (isset($form[$field_name]) && $field_name != $langcode_key) {
$form[$field_name]['#multilingual'] = $definition->isTranslatable();
......
......@@ -145,9 +145,9 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En
}
// Locate the language widget.
$language_field = $this->entityType->getKey('langcode') ?: 'langcode';
if (isset($form[$language_field])) {
$language_widget = &$form[$language_field];
$langcode_key = $this->entityType->getKey('langcode');
if (isset($form[$langcode_key])) {
$language_widget = &$form[$langcode_key];
}
// If we are editing the source entity, limit the list of languages so that
......
......@@ -32,23 +32,13 @@
* entity_keys = {
* "id" = "fid",
* "label" = "filename",
* "langcode" = "langcode",
* "uuid" = "uuid"
* }
* )
*/
class File extends ContentEntityBase implements FileInterface {
/**
* The plain data values of the contained properties.
*
* Define default values.
*
* @var array
*/
protected $values = array(
'langcode' => array(LanguageInterface::LANGCODE_DEFAULT => array(0 => array('value' => LanguageInterface::LANGCODE_NOT_SPECIFIED))),
);
/**
* {@inheritdoc}
*/
......
......@@ -133,16 +133,17 @@ public function denormalize($data, $class, $format = NULL, array $context = arra
// Create the entity.
$typed_data_ids = $this->getTypedDataIds($data['_links']['type']);
$entity_type = $this->entityManager->getDefinition($typed_data_ids['entity_type']);
$langcode_key = $entity_type->getKey('langcode');
$values = array();
// Figure out the language to use.
if (isset($data['langcode'])) {
$values['langcode'] = $data['langcode'][0]['value'];
if (isset($data[$langcode_key])) {
$values[$langcode_key] = $data[$langcode_key][0]['value'];
// Remove the langcode so it does not get iterated over below.
unset($data['langcode']);
unset($data[$langcode_key]);
}
$entity_type = $this->entityManager->getDefinition($typed_data_ids['entity_type']);
if ($entity_type->hasKey('bundle')) {
$bundle_key = $entity_type->getKey('bundle');
$values[$bundle_key] = $typed_data_ids['bundle'];
......
......@@ -483,18 +483,18 @@ function language_form_system_regional_settings_alter(&$form, FormStateInterface
/**
* Implements hook_form_alter().
*/
function language_form_alter(&$form, FormStateInterface $form_state, $form_id) {
function language_form_alter(&$form, FormStateInterface $form_state) {
// Content entity forms may have added a langcode field. But content language
// configuration should decide if it should be exposed or not in the forms.
$form_object = $form_state->getFormObject();
if ($form_object instanceof ContentEntityFormInterface && isset($form['langcode'])) {
if ($form_object instanceof ContentEntityFormInterface) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity_type_id = $form_object->getEntity()->getEntityTypeId();
$bundle = $form_object->getEntity()->bundle();
$entity_type = Drupal::entityManager()->getDefinition($entity_type_id);
if ($entity_type->isTranslatable()) {
$language_configuration = ContentLanguageSettings::loadByEntityTypeBundle($entity_type_id, $bundle);
$form['langcode']['#access'] = $language_configuration->isLanguageAlterable();
$entity = $form_object->getEntity();
$entity_type = $entity->getEntityType();
$langcode_key = $entity_type->getKey('langcode');
if (isset($form[$langcode_key]) && $entity_type->isTranslatable()) {
$language_configuration = ContentLanguageSettings::loadByEntityTypeBundle($entity->getEntityTypeId(), $entity->bundle());
$form[$langcode_key]['#access'] = $language_configuration->isLanguageAlterable();
}
}
}
......@@ -520,11 +520,11 @@ function language_field_info_alter(&$info) {
* Implements hook_entity_field_access()
*/
function language_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
if ($field_definition->getName() == 'langcode') {
$langcode_key = $items->getEntity()->getEntityType()->getKey('langcode');
if ($field_definition->getName() == $langcode_key) {
$entity = $items->getEntity();
$config = ContentLanguageSettings::loadByEntityTypeBundle($entity->getEntityTypeId(), $entity->bundle());
return AccessResult::forbiddenIf(!$config->isLanguageAlterable());
}
return AccessResult::neutral();
}
......@@ -35,6 +35,7 @@
* entity_keys = {
* "id" = "id",
* "label" = "title",
* "langcode" = "langcode",
* "uuid" = "uuid",
* "bundle" = "bundle"
* },
......
......@@ -47,6 +47,7 @@
* "revision" = "vid",
* "bundle" = "type",
* "label" = "title",
* "langcode" = "langcode",
* "uuid" = "uuid"
* },
* bundle_entity_type = "node_type",
......
......@@ -134,13 +134,12 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
}
// Overwrite the received properties.
$langcode_key = $entity->getEntityType()->getKey('langcode');
foreach ($entity->_restPatchFields as $field_name) {
$field = $entity->get($field_name);
// It is not possible to set the language to NULL as it is automatically
// re-initialized. As it must not be empty, skip it if it is.
// @todo: Use the langcode entity key when available. See
// https://drupal.org/node/2143729.
if ($field_name == 'langcode' && $field->isEmpty()) {
if ($field_name == $langcode_key && $field->isEmpty()) {
continue;
}
if ($field->isEmpty() && !$original_entity->get($field_name)->access('delete')) {
......
......@@ -39,7 +39,8 @@
* "id" = "id",
* "uuid" = "uuid",
* "bundle" = "shortcut_set",
* "label" = "title"
* "label" = "title",
* "langcode" = "langcode",
* },
* links = {
* "canonical" = "entity.shortcut.canonical",
......
......@@ -17,12 +17,18 @@
*/
class EntityApiTest extends EntityUnitTestBase {
/**
* @inheritdoc
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('entity_test_rev');
$this->installEntitySchema('entity_test_mul');
$this->installEntitySchema('entity_test_mulrev');
foreach (entity_test_entity_types() as $entity_type_id) {
// The entity_test schema is installed by the parent.
if ($entity_type_id != 'entity_test') {
$this->installEntitySchema($entity_type_id);
}
}
}
/**
......
......@@ -44,13 +44,15 @@ public function testDefaultValues() {
/**
* Executes a test set for a defined entity type.
*
* @param string $entity_type
* @param string $entity_type_id
* The entity type to run the tests with.
*/
protected function assertDefaultValues($entity_type) {
$entity = entity_create($entity_type);
$this->assertEqual($entity->langcode->value, 'en', String::format('%entity_type: Default language', array('%entity_type' => $entity_type)));
$this->assertTrue(Uuid::isValid($entity->uuid->value), String::format('%entity_type: Default UUID', array('%entity_type' => $entity_type)));
protected function assertDefaultValues($entity_type_id) {
$entity = entity_create($entity_type_id);
$definition = $this->entityManager->getDefinition($entity_type_id);
$langcode_key = $definition->getKey('langcode');
$this->assertEqual($entity->{$langcode_key}->value, 'en', String::format('%entity_type: Default language', array('%entity_type' => $entity_type_id)));
$this->assertTrue(Uuid::isValid($entity->uuid->value), String::format('%entity_type: Default UUID', array('%entity_type' => $entity_type_id)));
$this->assertEqual($entity->name->getValue(), array(0 => array('value' => NULL)), 'Field has one empty value by default.');
}
......
......@@ -50,9 +50,12 @@ class EntityFieldTest extends EntityUnitTestBase {
protected function setUp() {
parent::setUp();
$this->installEntitySchema('entity_test_rev');
$this->installEntitySchema('entity_test_mul');
$this->installEntitySchema('entity_test_mulrev');
foreach (entity_test_entity_types() as $entity_type_id) {
// The entity_test schema is installed by the parent.
if ($entity_type_id != 'entity_test') {
$this->installEntitySchema($entity_type_id);
}
}
// Create the test field.
entity_test_install();
......@@ -154,7 +157,7 @@ protected function doTestReadWrite($entity_type) {
$this->assertEqual($new_user2->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual($new_user2->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type)));
// Change the assigned user by id.
// Change the assigned user by id.
$entity->user_id->first()->get('target_id')->setValue($new_user2->id());
$this->assertEqual($new_user2->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual($new_user2->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type)));
......@@ -222,19 +225,20 @@ protected function doTestReadWrite($entity_type) {
}
// Access the language field.
$this->assertEqual($langcode, $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual(\Drupal::languageManager()->getLanguage($langcode), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
$langcode_key = $this->entityManager->getDefinition($entity_type)->getKey('langcode');
$this->assertEqual($langcode, $entity->{$langcode_key}->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual(\Drupal::languageManager()->getLanguage($langcode), $entity->{$langcode_key}->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
// Change the language by code.
$entity->langcode->value = \Drupal::languageManager()->getDefaultLanguage()->getId();
$this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual(\Drupal::languageManager()->getDefaultLanguage(), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
$entity->{$langcode_key}->value = \Drupal::languageManager()->getDefaultLanguage()->getId();
$this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), $entity->{$langcode_key}->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual(\Drupal::languageManager()->getDefaultLanguage(), $entity->{$langcode_key}->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
// Revert language by code then try setting it by language object.
$entity->langcode->value = $langcode;
$entity->langcode->language = \Drupal::languageManager()->getDefaultLanguage();
$this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual(\Drupal::languageManager()->getDefaultLanguage(), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
$entity->{$langcode_key}->value = $langcode;
$entity->{$langcode_key}->language = \Drupal::languageManager()->getDefaultLanguage();
$this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), $entity->{$langcode_key}->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual(\Drupal::languageManager()->getDefaultLanguage(), $entity->{$langcode_key}->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
// Access the text field and test updating.
$this->assertEqual($entity->field_test_text->value, $this->entity_field_text, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type)));
......@@ -347,6 +351,7 @@ public function testSave() {
* The entity type to run the tests with.
*/
protected function doTestSave($entity_type) {
$langcode_key = $this->entityManager->getDefinition($entity_type)->getKey('langcode');
$entity = $this->createTestEntity($entity_type);
$entity->save();
$this->assertTrue((bool) $entity->id(), format_string('%entity_type: Entity has received an id.', array('%entity_type' => $entity_type)));
......@@ -357,8 +362,8 @@ protected function doTestSave($entity_type) {
// Access the name field.
$this->assertEqual(1, $entity->id->value, format_string('%entity_type: ID value can be read.', array('%entity_type' => $entity_type)));
$this->assertTrue(is_string($entity->uuid->value), format_string('%entity_type: UUID value can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual('en', $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual(\Drupal::languageManager()->getLanguage('en'), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual('en', $entity->{$langcode_key}->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual(\Drupal::languageManager()->getLanguage('en'), $entity->{$langcode_key}->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual($this->entity_user->id(), $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual($this->entity_user->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
$this->assertEqual($this->entity_field_text, $entity->field_test_text->value, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type)));
......@@ -399,7 +404,8 @@ protected function doTestIntrospection($entity_type) {
// Test deriving metadata from references.
$entity_definition = \Drupal\Core\Entity\TypedData\EntityDataDefinition::create($entity_type);
$reference_definition = $entity_definition->getPropertyDefinition('langcode')
$langcode_key = $this->entityManager->getDefinition($entity_type)->getKey('langcode');
$reference_definition = $entity_definition->getPropertyDefinition($langcode_key)
->getPropertyDefinition('language')
->getTargetDefinition();
$this->assertEqual($reference_definition->getDataType(), 'language');
......@@ -541,7 +547,9 @@ protected function doTestDataStructureInterfaces($entity_type) {
// Field format.
NULL,
);
$this->assertEqual($strings, $target_strings, format_string('%entity_type: All contained strings found.', array('%entity_type' => $entity_type)));
asort($strings);
asort($target_strings);
$this->assertEqual(array_values($strings), array_values($target_strings), format_string('%entity_type: All contained strings found.', array('%entity_type' => $entity_type)));
}
/**
......
......@@ -35,7 +35,7 @@ protected function setUp() {
function testFormCRUD() {
// All entity variations have to have the same results.
foreach (entity_test_entity_types() as $entity_type) {
$this->assertFormCRUD($entity_type);
$this->doTestFormCRUD($entity_type);
}
}
......@@ -56,7 +56,7 @@ function testEntityFormDisplayAlter() {
* @param string $entity_type
* The entity type to run the tests with.
*/
protected function assertFormCRUD($entity_type) {
protected function doTestFormCRUD($entity_type) {
$name1 = $this->randomMachineName(8);
$name2 = $this->randomMachineName(10);
......
......@@ -51,9 +51,12 @@ protected function setUp() {
$this->languageManager = $this->container->get('language_manager');
$this->installEntitySchema('entity_test_rev');
$this->installEntitySchema('entity_test_mul');
$this->installEntitySchema('entity_test_mulrev');
foreach (entity_test_entity_types() as $entity_type_id) {
// The entity_test schema is installed by the parent.