Issue #2431329 by plach: Make (content) translation language available as a field definition
parent
1483ef1034
commit
dc3d8a01b8
|
@ -81,6 +81,13 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
|
|||
*/
|
||||
protected $langcodeKey;
|
||||
|
||||
/**
|
||||
* The default langcode entity key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultLangcodeKey;
|
||||
|
||||
/**
|
||||
* Language code identifying the entity active language.
|
||||
*
|
||||
|
@ -144,6 +151,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
|
|||
$this->entityTypeId = $entity_type;
|
||||
$this->entityKeys['bundle'] = $bundle ? $bundle : $this->entityTypeId;
|
||||
$this->langcodeKey = $this->getEntityType()->getKey('langcode');
|
||||
$this->defaultLangcodeKey = $this->getEntityType()->getKey('default_langcode');
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
// If the key matches an existing property set the value to the property
|
||||
|
@ -242,6 +250,13 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
|
|||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDefaultTranslation() {
|
||||
return $this->activeLangcode === LanguageInterface::LANGCODE_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -543,14 +558,38 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
|
|||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
switch ($name) {
|
||||
case $this->langcodeKey:
|
||||
if ($this->isDefaultTranslation()) {
|
||||
// Update the default internal language cache.
|
||||
$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);
|
||||
}
|
||||
else {
|
||||
// @todo Allow the translation language to be changed. See
|
||||
// https://www.drupal.org/node/2443989.
|
||||
$items = $this->get($this->langcodeKey);
|
||||
if ($items->value != $this->activeLangcode) {
|
||||
$items->setValue($this->activeLangcode, FALSE);
|
||||
$message = String::format('The translation language cannot be changed (@langcode).', array('@langcode' => $this->activeLangcode));
|
||||
throw new \LogicException($message);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case $this->defaultLangcodeKey:
|
||||
// @todo Use a standard method to make the default_langcode field
|
||||
// read-only. See https://www.drupal.org/node/2443991.
|
||||
if (isset($this->values[$this->defaultLangcodeKey])) {
|
||||
$this->get($this->defaultLangcodeKey)->setValue($this->isDefaultTranslation(), FALSE);
|
||||
$message = String::format('The default translation flag cannot be changed (@langcode).', array('@langcode' => $this->activeLangcode));
|
||||
throw new \LogicException($message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -684,6 +723,8 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
|
|||
$values[$name] = $field->getValue();
|
||||
}
|
||||
}
|
||||
$values[$this->langcodeKey] = $langcode;
|
||||
$values[$this->defaultLangcodeKey] = FALSE;
|
||||
|
||||
$this->translations[$langcode]['status'] = static::TRANSLATION_CREATED;
|
||||
$translation = $this->getTranslation($langcode);
|
||||
|
@ -691,7 +732,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
|
|||
|
||||
foreach ($values as $name => $value) {
|
||||
if (isset($definitions[$name]) && $definitions[$name]->isTranslatable()) {
|
||||
$translation->$name = $value;
|
||||
$translation->values[$name][$langcode] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -401,14 +401,35 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa
|
|||
protected function buildBaseFieldDefinitions($entity_type_id) {
|
||||
$entity_type = $this->getDefinition($entity_type_id);
|
||||
$class = $entity_type->getClass();
|
||||
$keys = array_filter($entity_type->getKeys());
|
||||
|
||||
// Fail with an exception for non-fieldable entity types.
|
||||
if (!$entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) {
|
||||
throw new \LogicException(String::format('Getting the base fields is not supported for entity type @type.', array('@type' => $entity_type->getLabel())));
|
||||
}
|
||||
|
||||
// Retrieve base field definitions and assign them the entity type provider.
|
||||
// Retrieve base field definitions.
|
||||
/** @var FieldStorageDefinitionInterface[] $base_field_definitions */
|
||||
$base_field_definitions = $class::baseFieldDefinitions($entity_type);
|
||||
|
||||
// Make sure translatable entity types are correctly defined.
|
||||
if ($entity_type->isTranslatable()) {
|
||||
// The langcode field should always be translatable if the entity type is.
|
||||
if (isset($keys['langcode']) && isset($base_field_definitions[$keys['langcode']])) {
|
||||
$base_field_definitions[$keys['langcode']]->setTranslatable(TRUE);
|
||||
}
|
||||
// A default_langcode field should always be defined.
|
||||
if (!isset($base_field_definitions[$keys['default_langcode']])) {
|
||||
$base_field_definitions[$keys['default_langcode']] = BaseFieldDefinition::create('boolean')
|
||||
->setLabel($this->t('Default translation'))
|
||||
->setDescription($this->t('A flag indicating whether this is the default translation.'))
|
||||
->setTranslatable(TRUE)
|
||||
->setRevisionable(TRUE)
|
||||
->setDefaultValue(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign base field definitions the entity type provider.
|
||||
$provider = $entity_type->getProvider();
|
||||
foreach ($base_field_definitions as $definition) {
|
||||
// @todo Remove this check once FieldDefinitionInterface exposes a proper
|
||||
|
@ -450,15 +471,32 @@ class EntityManager extends DefaultPluginManager implements EntityManagerInterfa
|
|||
|
||||
// Ensure defined entity keys are there and have proper revisionable and
|
||||
// translatable values.
|
||||
$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)));
|
||||
foreach (array_intersect_key($keys, array_flip(['id', 'revision', 'uuid', 'bundle'])) as $key => $field_name) {
|
||||
if (!isset($base_field_definitions[$field_name])) {
|
||||
throw new \LogicException(String::format('The @field field definition does not exist and it is used as @key entity key.', array(
|
||||
'@field' => $base_field_definitions[$field_name]->getLabel(),
|
||||
'@key' => $key,
|
||||
)));
|
||||
}
|
||||
if (isset($base_field_definitions[$field_name]) && in_array($key, array('id', 'revision', 'uuid', 'bundle', 'langcode')) && $base_field_definitions[$field_name]->isTranslatable()) {
|
||||
throw new \LogicException(String::format('The @field field cannot be translatable as it is used as @key entity key.', array('@field' => $base_field_definitions[$field_name]->getLabel(), '@key' => $key)));
|
||||
if ($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,
|
||||
)));
|
||||
}
|
||||
if ($base_field_definitions[$field_name]->isTranslatable()) {
|
||||
throw new \LogicException(String::format('The @field field cannot be translatable as it is used as @key entity key.', array(
|
||||
'@field' => $base_field_definitions[$field_name]->getLabel(),
|
||||
'@key' => $key,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure translatable entity types define the "langcode" field properly.
|
||||
if ($entity_type->isTranslatable() && (!isset($keys['langcode']) || !isset($base_field_definitions[$keys['langcode']]) || !$base_field_definitions[$keys['langcode']]->isTranslatable())) {
|
||||
throw new \LogicException(String::format('The @entity_type entity type cannot be translatable as it does not define a translatable "langcode" field.', array('@entity_type' => $entity_type->getLabel())));
|
||||
}
|
||||
|
||||
return $base_field_definitions;
|
||||
}
|
||||
|
||||
|
|
|
@ -238,6 +238,7 @@ class EntityType implements EntityTypeInterface {
|
|||
'revision' => '',
|
||||
'bundle' => '',
|
||||
'langcode' => '',
|
||||
'default_langcode' => 'default_langcode',
|
||||
);
|
||||
$this->handlers += array(
|
||||
'access' => 'Drupal\Core\Entity\EntityAccessControlHandler',
|
||||
|
|
|
@ -192,6 +192,14 @@ interface FieldableEntityInterface extends EntityInterface {
|
|||
*
|
||||
* @param string $field_name
|
||||
* The name of the field which is changed.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* When trying to assign a value to the language field that matches an
|
||||
* existing translation.
|
||||
* @throws \LogicException
|
||||
* When trying to change:
|
||||
* - The language of a translation.
|
||||
* - The value of the flag identifying the default translation object.
|
||||
*/
|
||||
public function onChange($field_name);
|
||||
|
||||
|
|
|
@ -182,8 +182,8 @@ class Tables implements TablesInterface {
|
|||
|
||||
$table = $this->ensureEntityTable($index_prefix, $sql_column, $type, $langcode, $base_table, $entity_id_field, $entity_tables);
|
||||
|
||||
// If there is a field storage (some specifiers are not, like
|
||||
// default_langcode), check for case sensitivity.
|
||||
// If there is a field storage (some specifiers are not), check for case
|
||||
// sensitivity.
|
||||
if ($field_storage) {
|
||||
$column = $field_storage->getMainPropertyName();
|
||||
$base_field_property_definitions = $field_storage->getPropertyDefinitions();
|
||||
|
|
|
@ -66,6 +66,13 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
*/
|
||||
protected $langcodeKey = FALSE;
|
||||
|
||||
/**
|
||||
* The default language entity key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultLangcodeKey = FALSE;
|
||||
|
||||
/**
|
||||
* The base table of the entity.
|
||||
*
|
||||
|
@ -200,7 +207,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
if ($translatable) {
|
||||
$this->dataTable = $this->entityType->getDataTable() ?: $this->entityTypeId . '_field_data';
|
||||
$this->langcodeKey = $this->entityType->getKey('langcode');
|
||||
$this->defaultLangcodeKey = $this->entityType->getKey('default_langcode') ?: 'default_langcode';
|
||||
$this->defaultLangcodeKey = $this->entityType->getKey('default_langcode');
|
||||
}
|
||||
if ($revisionable && $translatable) {
|
||||
$this->revisionDataTable = $this->entityType->getRevisionDataTable() ?: $this->entityTypeId . '_field_revision';
|
||||
|
@ -342,11 +349,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
// the data table.
|
||||
$table_mapping
|
||||
->setFieldNames($this->baseTable, $key_fields)
|
||||
->setFieldNames($this->dataTable, array_values(array_diff($all_fields, array($this->uuidKey))))
|
||||
// Add the denormalized 'default_langcode' field to the mapping. Its
|
||||
// value is identical to the query expression
|
||||
// "base_table.langcode = data_table.langcode"
|
||||
->setExtraColumns($this->dataTable, array('default_langcode'));
|
||||
->setFieldNames($this->dataTable, array_values(array_diff($all_fields, array($this->uuidKey))));
|
||||
}
|
||||
elseif ($revisionable && $translatable) {
|
||||
// The revisionable multilingual layout stores key field values in the
|
||||
|
@ -356,31 +359,20 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
// holds the data field values for all non-revisionable fields. The data
|
||||
// field values of revisionable fields are denormalized in the data
|
||||
// table, as well.
|
||||
$table_mapping->setFieldNames($this->baseTable, array_values(array_diff($key_fields, array($this->langcodeKey))));
|
||||
$table_mapping->setFieldNames($this->baseTable, array_values($key_fields));
|
||||
|
||||
// Like in the multilingual, non-revisionable case the UUID is not
|
||||
// in the data table. Additionally, do not store revision metadata
|
||||
// fields in the data table.
|
||||
$data_fields = array_values(array_diff($all_fields, array($this->uuidKey), $revision_metadata_fields));
|
||||
$table_mapping
|
||||
->setFieldNames($this->dataTable, $data_fields)
|
||||
// Add the denormalized 'default_langcode' field to the mapping. Its
|
||||
// value is identical to the query expression
|
||||
// "base_langcode = data_table.langcode" where "base_langcode" is
|
||||
// the language code of the default revision.
|
||||
->setExtraColumns($this->dataTable, array('default_langcode'));
|
||||
$table_mapping->setFieldNames($this->dataTable, $data_fields);
|
||||
|
||||
$revision_base_fields = array_merge(array($this->idKey, $this->revisionKey, $this->langcodeKey), $revision_metadata_fields);
|
||||
$table_mapping->setFieldNames($this->revisionTable, $revision_base_fields);
|
||||
|
||||
$revision_data_key_fields = array($this->idKey, $this->revisionKey, $this->langcodeKey);
|
||||
$revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields, array($this->langcodeKey));
|
||||
$table_mapping
|
||||
->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields))
|
||||
// Add the denormalized 'default_langcode' field to the mapping. Its
|
||||
// value is identical to the query expression
|
||||
// "revision_table.langcode = data_table.langcode".
|
||||
->setExtraColumns($this->revisionDataTable, array('default_langcode'));
|
||||
$table_mapping->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields));
|
||||
}
|
||||
|
||||
// Add dedicated tables.
|
||||
|
@ -673,12 +665,14 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
|
||||
$table_mapping = $this->getTableMapping();
|
||||
if ($this->revisionDataTable) {
|
||||
// Find revisioned fields that are not entity keys.
|
||||
$fields = array_diff($table_mapping->getFieldNames($this->revisionDataTable), $table_mapping->getFieldNames($this->baseTable));
|
||||
// Find revisioned fields that are not entity keys. Exclude the langcode
|
||||
// key as the base table holds only the default language.
|
||||
$base_fields = array_diff($table_mapping->getFieldNames($this->baseTable), array($this->langcodeKey));
|
||||
$fields = array_diff($table_mapping->getFieldNames($this->revisionDataTable), $base_fields);
|
||||
|
||||
// Find fields that are not revisioned or entity keys. Data fields have
|
||||
// the same value regardless of entity revision.
|
||||
$data_fields = array_diff($table_mapping->getFieldNames($this->dataTable), $fields, $table_mapping->getFieldNames($this->baseTable));
|
||||
$data_fields = array_diff($table_mapping->getFieldNames($this->dataTable), $fields, $base_fields);
|
||||
if ($data_fields) {
|
||||
$fields = array_merge($fields, $data_fields);
|
||||
$query->leftJoin($this->dataTable, 'data', "(revision.$this->idKey = data.$this->idKey)");
|
||||
|
@ -703,10 +697,9 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
|
||||
// Field values in default language are stored with
|
||||
// LanguageInterface::LANGCODE_DEFAULT as key.
|
||||
$langcode = empty($values['default_langcode']) ? $values[$this->langcodeKey] : LanguageInterface::LANGCODE_DEFAULT;
|
||||
$langcode = empty($values[$this->defaultLangcodeKey]) ? $values[$this->langcodeKey] : LanguageInterface::LANGCODE_DEFAULT;
|
||||
$translations[$id][$langcode] = TRUE;
|
||||
|
||||
|
||||
foreach ($fields as $field_name) {
|
||||
$columns = $table_mapping->getColumnNames($field_name);
|
||||
// Do not key single-column fields by property name.
|
||||
|
@ -776,13 +769,13 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
// apply to the default language. See http://drupal.org/node/1866330.
|
||||
// Default to the original entity language if not explicitly specified
|
||||
// otherwise.
|
||||
if (!array_key_exists('default_langcode', $values)) {
|
||||
$values['default_langcode'] = 1;
|
||||
if (!array_key_exists($this->defaultLangcodeKey, $values)) {
|
||||
$values[$this->defaultLangcodeKey] = 1;
|
||||
}
|
||||
// If the 'default_langcode' flag is explicitly not set, we do not care
|
||||
// whether the queried values are in the original entity language or not.
|
||||
elseif ($values['default_langcode'] === NULL) {
|
||||
unset($values['default_langcode']);
|
||||
elseif ($values[$this->defaultLangcodeKey] === NULL) {
|
||||
unset($values[$this->defaultLangcodeKey]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1156,8 +1149,6 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
$table_name = $this->dataTable;
|
||||
}
|
||||
$record = $this->mapToStorageRecord($entity, $table_name);
|
||||
$record->{$this->langcodeKey} = $entity->language()->getId();
|
||||
$record->default_langcode = intval($record->{$this->langcodeKey} == $entity->getUntranslated()->language()->getId());
|
||||
return $record;
|
||||
}
|
||||
|
||||
|
@ -1171,7 +1162,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
|||
* The revision id.
|
||||
*/
|
||||
protected function saveRevision(EntityInterface $entity) {
|
||||
$record = $this->mapToStorageRecord($entity, $this->revisionTable);
|
||||
$record = $this->mapToStorageRecord($entity->getUntranslated(), $this->revisionTable);
|
||||
|
||||
$entity->preSaveRevision($this, $record);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Drupal\Core\Entity\Sql;
|
|||
|
||||
use Drupal\Component\Utility\String;
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Database\DatabaseException;
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityStorageException;
|
||||
|
@ -163,7 +164,6 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
|||
$storage_definition->hasCustomStorage() != $original->hasCustomStorage() ||
|
||||
$storage_definition->getSchema() != $original->getSchema() ||
|
||||
$storage_definition->isRevisionable() != $original->isRevisionable() ||
|
||||
$storage_definition->isTranslatable() != $original->isTranslatable() ||
|
||||
$table_mapping->allowsSharedTableStorage($storage_definition) != $table_mapping->allowsSharedTableStorage($original) ||
|
||||
$table_mapping->requiresDedicatedTableStorage($storage_definition) != $table_mapping->requiresDedicatedTableStorage($original)
|
||||
) {
|
||||
|
@ -386,8 +386,17 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
|||
// Only configurable fields currently support purging, so prevent deletion
|
||||
// of ones we can't purge if they have existing data.
|
||||
// @todo Add purging to all fields: https://www.drupal.org/node/2282119.
|
||||
if (!($storage_definition instanceof FieldStorageConfigInterface) && $this->storage->countFieldData($storage_definition, TRUE)) {
|
||||
throw new FieldStorageDefinitionUpdateForbiddenException('Unable to delete a field with data that can\'t be purged.');
|
||||
try {
|
||||
if (!($storage_definition instanceof FieldStorageConfigInterface) && $this->storage->countFieldData($storage_definition, TRUE)) {
|
||||
throw new FieldStorageDefinitionUpdateForbiddenException('Unable to delete a field with data that cannot be purged.');
|
||||
}
|
||||
}
|
||||
catch (DatabaseException $e) {
|
||||
// This may happen when changing field storage schema, since we are not
|
||||
// able to use a table mapping matching the passed storage definition.
|
||||
// @todo Revisit this once we are able to instantiate the table mapping
|
||||
// properly. See https://www.drupal.org/node/2274017.
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve a table mapping which contains the deleted field still.
|
||||
|
@ -506,13 +515,6 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
|||
$schema[$table_name] = array_merge_recursive($schema[$table_name], $this->getSharedTableFieldSchema($storage_definition, $table_name, $column_names));
|
||||
}
|
||||
}
|
||||
|
||||
// Add the schema for extra fields.
|
||||
foreach ($table_mapping->getExtraColumns($table_name) as $column_name) {
|
||||
if ($column_name == 'default_langcode') {
|
||||
$this->addDefaultLangcodeSchema($schema[$table_name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process tables after having gathered field information.
|
||||
|
@ -726,25 +728,6 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
|||
return $foreign_keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the schema for the 'default_langcode' metadata field.
|
||||
*
|
||||
* @param array $schema
|
||||
* The table schema to add the field schema to, passed by reference.
|
||||
*
|
||||
* @return array
|
||||
* A schema field array for the 'default_langcode' metadata field.
|
||||
*/
|
||||
protected function addDefaultLangcodeSchema(&$schema) {
|
||||
$schema['fields']['default_langcode'] = array(
|
||||
'description' => 'Boolean indicating whether field values are in the default entity language.',
|
||||
'type' => 'int',
|
||||
'size' => 'tiny',
|
||||
'not null' => TRUE,
|
||||
'default' => 1,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads stored schema data for the given entity type definition.
|
||||
*
|
||||
|
|
|
@ -13,13 +13,21 @@ namespace Drupal\Core\TypedData;
|
|||
interface TranslatableInterface {
|
||||
|
||||
/**
|
||||
* Returns the default language.
|
||||
* Returns the translation language.
|
||||
*
|
||||
* @return \Drupal\Core\Language\LanguageInterface
|
||||
* The language object.
|
||||
*/
|
||||
public function language();
|
||||
|
||||
/**
|
||||
* Checks whether the translation is the default one.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the translation is the default one, FALSE otherwise.
|
||||
*/
|
||||
public function isDefaultTranslation();
|
||||
|
||||
/**
|
||||
* Returns the languages the data is translated to.
|
||||
*
|
||||
|
|
|
@ -167,6 +167,7 @@ class BlockContent extends ContentEntityBase implements BlockContentInterface {
|
|||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language'))
|
||||
->setDescription(t('The custom block language code.'))
|
||||
->setTranslatable(TRUE)
|
||||
->setRevisionable(TRUE)
|
||||
->setDisplayOptions('view', array(
|
||||
'type' => 'hidden',
|
||||
|
|
|
@ -224,6 +224,7 @@ class Comment extends ContentEntityBase implements CommentInterface {
|
|||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language'))
|
||||
->setDescription(t('The comment language code.'))
|
||||
->setTranslatable(TRUE)
|
||||
->setDisplayOptions('view', array(
|
||||
'type' => 'hidden',
|
||||
))
|
||||
|
|
|
@ -102,7 +102,7 @@ function _content_translation_form_language_content_settings_form_alter(array &$
|
|||
foreach ($fields as $field_name => $definition) {
|
||||
// Allow to configure only fields supporting multilingual storage.
|
||||
// We skip our own fields as they are always translatable.
|
||||
if (!empty($storage_definitions[$field_name]) && $storage_definitions[$field_name]->isTranslatable() && $storage_definitions[$field_name]->getProvider() != 'content_translation') {
|
||||
if (!empty($storage_definitions[$field_name]) && $storage_definitions[$field_name]->isTranslatable() && $storage_definitions[$field_name]->getProvider() != 'content_translation' && $field_name != $entity_type->getKey('langcode') && $field_name != $entity_type->getKey('default_langcode')) {
|
||||
$form['settings'][$entity_type_id][$bundle]['fields'][$field_name] = array(
|
||||
'#label' => $definition->getLabel(),
|
||||
'#type' => 'checkbox',
|
||||
|
|
|
@ -360,6 +360,7 @@ class MenuLinkContent extends ContentEntityBase implements MenuLinkContentInterf
|
|||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language'))
|
||||
->setDescription(t('The menu link language code.'))
|
||||
->setTranslatable(TRUE)
|
||||
->setDisplayOptions('view', array(
|
||||
'type' => 'hidden',
|
||||
))
|
||||
|
|
|
@ -353,6 +353,7 @@ class Node extends ContentEntityBase implements NodeInterface {
|
|||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language'))
|
||||
->setDescription(t('The node language code.'))
|
||||
->setTranslatable(TRUE)
|
||||
->setRevisionable(TRUE)
|
||||
->setDisplayOptions('view', array(
|
||||
'type' => 'hidden',
|
||||
|
|
|
@ -95,21 +95,24 @@ class EntitySerializationTest extends NormalizerTestBase {
|
|||
'type' => array(
|
||||
array('value' => 'entity_test_mulrev'),
|
||||
),
|
||||
'created' => array(
|
||||
array('value' => $this->entity->created->value),
|
||||
),
|
||||
'user_id' => array(
|
||||
array('target_id' => $this->values['user_id']),
|
||||
),
|
||||
'revision_id' => array(
|
||||
array('value' => 1),
|
||||
),
|
||||
'default_langcode' => array(
|
||||
array('value' => TRUE),
|
||||
),
|
||||
'field_test_text' => array(
|
||||
array(
|
||||
'value' => $this->values['field_test_text']['value'],
|
||||
'format' => $this->values['field_test_text']['format'],
|
||||
),
|
||||
),
|
||||
'created' => array(
|
||||
array('value' => $this->entity->created->value),
|
||||
),
|
||||
);
|
||||
|
||||
$normalized = $this->serializer->normalize($this->entity);
|
||||
|
@ -175,10 +178,11 @@ class EntitySerializationTest extends NormalizerTestBase {
|
|||
'langcode' => '<langcode><value>en</value></langcode>',
|
||||
'name' => '<name><value>' . $this->values['name'] . '</value></name>',
|
||||
'type' => '<type><value>entity_test_mulrev</value></type>',
|
||||
'created' => '<created><value>' . $this->entity->created->value . '</value></created>',
|
||||
'user_id' => '<user_id><target_id>' . $this->values['user_id'] . '</target_id></user_id>',
|
||||
'revision_id' => '<revision_id><value>' . $this->entity->getRevisionId() . '</value></revision_id>',
|
||||
'default_langcode' => '<default_langcode><value>1</value></default_langcode>',
|
||||
'field_test_text' => '<field_test_text><value>' . $this->values['field_test_text']['value'] . '</value><format>' . $this->values['field_test_text']['format'] . '</format></field_test_text>',
|
||||
'created' => '<created><value>' . $this->entity->created->value . '</value></created>',
|
||||
);
|
||||
// Sort it in the same order as normalised.
|
||||
$expected = array_merge($normalized, $expected);
|
||||
|
|
|
@ -163,6 +163,7 @@ class Shortcut extends ContentEntityBase implements ShortcutInterface {
|
|||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language'))
|
||||
->setDescription(t('The language code of the shortcut.'))
|
||||
->setTranslatable(TRUE)
|
||||
->setDisplayOptions('view', array(
|
||||
'type' => 'hidden',
|
||||
))
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\system\Tests\Entity;
|
||||
|
||||
use Drupal\Component\Utility\String;
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
@ -147,6 +148,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
*/
|
||||
protected function doTestMultilingualProperties($entity_type) {
|
||||
$langcode_key = $this->entityManager->getDefinition($entity_type)->getKey('langcode');
|
||||
$default_langcode_key = $this->entityManager->getDefinition($entity_type)->getKey('default_langcode');
|
||||
$name = $this->randomMachineName();
|
||||
$uid = mt_rand(0, 127);
|
||||
$langcode = $this->langcodes[0];
|
||||
|
@ -249,16 +251,16 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$this->assertEqual(count($entities), 2, format_string('%entity_type: Two entities correctly loaded by name.', array('%entity_type' => $entity_type)));
|
||||
// @todo The default language condition should go away in favor of an
|
||||
// explicit parameter.
|
||||
$entities = entity_load_multiple_by_properties($entity_type, array('name' => $properties[$langcode]['name'][0], 'default_langcode' => 0));
|
||||
$entities = entity_load_multiple_by_properties($entity_type, array('name' => $properties[$langcode]['name'][0], $default_langcode_key => 0));
|
||||
$this->assertEqual(count($entities), 1, format_string('%entity_type: One entity correctly loaded by name translation.', array('%entity_type' => $entity_type)));
|
||||
$entities = entity_load_multiple_by_properties($entity_type, array($langcode_key => $default_langcode, 'name' => $name));
|
||||
$this->assertEqual(count($entities), 1, format_string('%entity_type: One entity correctly loaded by name and language.', array('%entity_type' => $entity_type)));
|
||||
|
||||
$entities = entity_load_multiple_by_properties($entity_type, array($langcode_key => $langcode, 'name' => $properties[$langcode]['name'][0]));
|
||||
$this->assertEqual(count($entities), 0, format_string('%entity_type: No entity loaded by name translation specifying the translation language.', array('%entity_type' => $entity_type)));
|
||||
$entities = entity_load_multiple_by_properties($entity_type, array($langcode_key => $langcode, 'name' => $properties[$langcode]['name'][0], 'default_langcode' => 0));
|
||||
$entities = entity_load_multiple_by_properties($entity_type, array($langcode_key => $langcode, 'name' => $properties[$langcode]['name'][0], $default_langcode_key => 0));
|
||||
$this->assertEqual(count($entities), 1, format_string('%entity_type: One entity loaded by name translation and language specifying to look for translations.', array('%entity_type' => $entity_type)));
|
||||
$entities = entity_load_multiple_by_properties($entity_type, array('user_id' => $properties[$langcode]['user_id'][0], 'default_langcode' => NULL));
|
||||
$entities = entity_load_multiple_by_properties($entity_type, array('user_id' => $properties[$langcode]['user_id'][0], $default_langcode_key => NULL));
|
||||
$this->assertEqual(count($entities), 2, format_string('%entity_type: Two entities loaded by uid without caring about property translatability.', array('%entity_type' => $entity_type)));
|
||||
|
||||
// Test property conditions and orders with multiple languages in the same
|
||||
|
@ -313,6 +315,9 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$default_langcode = $this->langcodes[0];
|
||||
$langcode = $this->langcodes[1];
|
||||
$langcode_key = $this->entityManager->getDefinition($entity_type)->getKey('langcode');
|
||||
$default_langcode_key = $this->entityManager->getDefinition($entity_type)->getKey('default_langcode');
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $this->entityManager
|
||||
->getStorage($entity_type)
|
||||
->create(array('name' => $this->randomMachineName(), $langcode_key => LanguageInterface::LANGCODE_NOT_SPECIFIED));
|
||||
|
@ -324,12 +329,13 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
// Verify that we obtain the entity object itself when we attempt to
|
||||
// retrieve a translation referring to it.
|
||||
$translation = $entity->getTranslation($langcode);
|
||||
$this->assertEqual($entity, $translation, 'The translation object corresponding to a non-default language is the entity object itself when the entity is language-neutral.');
|
||||
$this->assertIdentical($entity, $translation, 'The translation object corresponding to a non-default language is the entity object itself when the entity is language-neutral.');
|
||||
$entity->{$langcode_key}->value = $default_langcode;
|
||||
$translation = $entity->getTranslation($default_langcode);
|
||||
$this->assertEqual($entity, $translation, 'The translation object corresponding to the default language (explicit) is the entity object itself.');
|
||||
$this->assertIdentical($entity, $translation, 'The translation object corresponding to the default language (explicit) is the entity object itself.');
|
||||
$translation = $entity->getTranslation(LanguageInterface::LANGCODE_DEFAULT);
|
||||
$this->assertEqual($entity, $translation, 'The translation object corresponding to the default language (implicit) is the entity object itself.');
|
||||
$this->assertIdentical($entity, $translation, 'The translation object corresponding to the default language (implicit) is the entity object itself.');
|
||||
$this->assertTrue($entity->{$default_langcode_key}->value, 'The translation object is the default one.');
|
||||
|
||||
// Create a translation and verify that the translation object and the
|
||||
// original object behave independently.
|
||||
|
@ -340,18 +346,57 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$this->assertNotIdentical($entity, $translation, 'The entity and the translation object differ from one another.');
|
||||
$this->assertTrue($entity->hasTranslation($langcode), 'The new translation exists.');
|
||||
$this->assertEqual($translation->language()->getId(), $langcode, 'The translation language matches the specified one.');
|
||||
$this->assertEqual($translation->{$langcode_key}->value, $langcode, 'The translation field language value matches the specified one.');
|
||||
$this->assertFalse($translation->{$default_langcode_key}->value, 'The translation object is not the default one.');
|
||||
$this->assertEqual($translation->getUntranslated()->language()->getId(), $default_langcode, 'The original language can still be retrieved.');
|
||||
$translation->name->value = $name_translated;
|
||||
$this->assertEqual($entity->name->value, $name, 'The original name is retained after setting a translated value.');
|
||||
$entity->name->value = $name;
|
||||
$this->assertEqual($translation->name->value, $name_translated, 'The translated name is retained after setting the original value.');
|
||||
|
||||
// Save the translation and check that the expecte hooks are fired.
|
||||
// Save the translation and check that the expected hooks are fired.
|
||||
$translation->save();
|
||||
$hooks = $this->getHooksInfo();
|
||||
$this->assertEqual($hooks['entity_translation_insert'], $langcode, 'The generic entity translation insertion hook has fired.');
|
||||
$this->assertEqual($hooks[$entity_type . '_translation_insert'], $langcode, 'The entity-type-specific entity translation insertion hook has fired.');
|
||||
|
||||
// Verify that changing translation language causes an exception to be
|
||||
// thrown.
|
||||
$message = 'The translation language cannot be changed.';
|
||||
try {
|
||||
$translation->{$langcode_key}->value = $this->langcodes[2];
|
||||
$this->fail($message);
|
||||
}
|
||||
catch (\LogicException $e) {
|
||||
$this->pass($message);
|
||||
}
|
||||
|
||||
// Verify that reassigning the same translation language is allowed.
|
||||
$message = 'The translation language can be reassigned the same value.';
|
||||
try {
|
||||
$translation->{$langcode_key}->value = $langcode;
|
||||
$this->pass($message);
|
||||
}
|
||||
catch (\LogicException $e) {
|
||||
$this->fail($message);
|
||||
}
|
||||
|
||||
// Verify that changing the default translation flag causes an exception to
|
||||
// be thrown.
|
||||
$message = 'The default translation flag cannot be changed.';
|
||||
foreach ($entity->getTranslationLanguages() as $t_langcode => $language) {
|
||||
$translation = $entity->getTranslation($t_langcode);
|
||||
$default = $translation->isDefaultTranslation();
|
||||
try {
|
||||
$translation->{$default_langcode_key}->value = !$default;
|
||||
$this->fail($message);
|
||||
}
|
||||
catch (\LogicException $e) {
|
||||
$this->pass($message);
|
||||
}
|
||||
$this->assertEqual($translation->{$default_langcode_key}->value, $default);
|
||||
}
|
||||
|
||||
// Check that after loading an entity the language is the default one.
|
||||
$entity = $this->reloadEntity($entity);
|
||||
$this->assertEqual($entity->language()->getId(), $default_langcode, 'The loaded entity is the original one.');
|
||||
|
@ -588,9 +633,16 @@ class EntityTranslationTest extends EntityLanguageTestBase {
|
|||
$this->assertTrue(!isset($base_field_definitions['id']->translatable), 'Translatability for the <em>id</em> field is not defined.');
|
||||
$this->assertFalse($definitions['id']->isTranslatable(), 'Field translatability is disabled by default.');
|
||||
|
||||
// Check that entity ids and langcode fields cannot be translatable.
|
||||
foreach (array('id', 'uuid', 'revision_id', 'type', 'langcode') as $name) {
|
||||
$this->state->set('entity_test.field_definitions.translatable', array($name => TRUE));
|
||||
// Check that entity id keys have the expect translatability.
|
||||
$translatable_fields = array(
|
||||
'id' => TRUE,
|
||||
'uuid' => TRUE,
|
||||
'revision_id' => TRUE,
|
||||
'type' => TRUE,
|
||||
'langcode' => FALSE,
|
||||
);
|
||||
foreach ($translatable_fields as $name => $translatable) {
|
||||
$this->state->set('entity_test.field_definitions.translatable', array($name => $translatable));
|
||||
$this->entityManager->clearCachedFieldDefinitions();
|
||||
$message = format_string('Field %field cannot be translatable.', array('%field' => $name));
|
||||
|
||||
|
|
|
@ -77,7 +77,8 @@ class EntityTest extends ContentEntityBase implements EntityOwnerInterface {
|
|||
|
||||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language code'))
|
||||
->setDescription(t('The language code of the test entity.'));
|
||||
->setDescription(t('The language code of the test entity.'))
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
$fields['name'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('Name'))
|
||||
|
|
|
@ -34,6 +34,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
* "bundle" = "type",
|
||||
* "label" = "name",
|
||||
* "langcode" = "custom_langcode_key",
|
||||
* "default_langcode" = "custom_default_langcode_key",
|
||||
* },
|
||||
* links = {
|
||||
* "canonical" = "/entity_test_mul_langcode_key/manage/{entity_test_mul_langcode_key}",
|
||||
|
|
|
@ -121,6 +121,7 @@ class Term extends ContentEntityBase implements TermInterface {
|
|||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language'))
|
||||
->setDescription(t('The term language code.'))
|
||||
->setTranslatable(TRUE)
|
||||
->setDisplayOptions('view', array(
|
||||
'type' => 'hidden',
|
||||
))
|
||||
|
|
|
@ -345,7 +345,7 @@ abstract class AccountForm extends ContentEntityForm {
|
|||
* The current state of the form.
|
||||
*/
|
||||
public function syncUserLangcode($entity_type_id, UserInterface $user, array &$form, FormStateInterface &$form_state) {
|
||||
$user->langcode = $user->preferred_langcode;
|
||||
$user->getUntranslated()->langcode = $user->preferred_langcode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -474,7 +474,8 @@ class User extends ContentEntityBase implements UserInterface {
|
|||
|
||||
$fields['langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Language code'))
|
||||
->setDescription(t('The user language code.'));
|
||||
->setDescription(t('The user language code.'))
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
$fields['preferred_langcode'] = BaseFieldDefinition::create('language')
|
||||
->setLabel(t('Preferred language code'))
|
||||
|
|
|
@ -36,6 +36,20 @@ class EntityManagerTest extends UnitTestCase {
|
|||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* The entity type definition.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entityType;
|
||||
|
||||
/**
|
||||
* An instance of the test entity.
|
||||
*
|
||||
* @var \Drupal\Tests\Core\Entity\EntityManagerTestEntity|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* The plugin discovery.
|
||||
*
|
||||
|
@ -146,17 +160,48 @@ class EntityManagerTest extends UnitTestCase {
|
|||
$this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
|
||||
$this->controllerResolver = $this->getClassResolverStub();
|
||||
|
||||
$this->container = $this->getContainerWithCacheTagsInvalidator($this->cacheTagsInvalidator);
|
||||
|
||||
$this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
|
||||
|
||||
$this->typedDataManager = $this->getMockBuilder('\Drupal\Core\TypedData\TypedDataManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$map = [
|
||||
['field_item:boolean', TRUE, ['class' => 'Drupal\Core\Field\Plugin\Field\FieldType\BooleanItem']],
|
||||
];
|
||||
|
||||
$this->typedDataManager->expects($this->any())
|
||||
->method('getDefinition')
|
||||
->willReturnMap($map);
|
||||
|
||||
$this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
|
||||
$this->installedDefinitions = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreInterface');
|
||||
|
||||
$this->container = $this->getContainerWithCacheTagsInvalidator($this->cacheTagsInvalidator);
|
||||
$this->container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
|
||||
\Drupal::setContainer($this->container);
|
||||
|
||||
$field_type_manager = $this->getMock('Drupal\Core\Field\FieldTypePluginManagerInterface');
|
||||
$field_type_manager->expects($this->any())
|
||||
->method('getDefaultStorageSettings')
|
||||
->willReturn(array());
|
||||
$field_type_manager->expects($this->any())
|
||||
->method('getDefaultFieldSettings')
|
||||
->willReturn(array());
|
||||
|
||||
$string_translation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface');
|
||||
|
||||
$map = [
|
||||
['cache_tags.invalidator', 1, $this->cacheTagsInvalidator],
|
||||
['plugin.manager.field.field_type', 1, $field_type_manager],
|
||||
['string_translation', 1, $string_translation],
|
||||
['typed_data_manager', 1, $this->typedDataManager],
|
||||
];
|
||||
|
||||
$this->container->expects($this->any())
|
||||
->method('get')
|
||||
->willReturnMap($map);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -521,6 +566,100 @@ class EntityManagerTest extends UnitTestCase {
|
|||
$this->assertSame($expected, $this->entityManager->getFieldStorageDefinitions('test_entity_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getBaseFieldDefinitions() method with a translatable entity type.
|
||||
*
|
||||
* @covers ::getBaseFieldDefinitions
|
||||
* @covers ::buildBaseFieldDefinitions
|
||||
*
|
||||
* @dataProvider providerTestGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode
|
||||
*/
|
||||
public function testGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode($default_langcode_key) {
|
||||
$this->setUpEntityWithFieldDefinition(FALSE, 'id', array('langcode' => 'langcode', 'default_langcode' => $default_langcode_key));
|
||||
|
||||
$field_definition = $this->getMockBuilder('Drupal\Core\Field\BaseFieldDefinition')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$field_definition->expects($this->atLeastOnce())
|
||||
->method('isTranslatable')
|
||||
->willReturn(TRUE);
|
||||
|
||||
$entity_class = get_class($this->entity);
|
||||
$entity_class::$baseFieldDefinitions += array('langcode' => $field_definition);
|
||||
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('isTranslatable')
|
||||
->willReturn(TRUE);
|
||||
|
||||
$definitions = $this->entityManager->getBaseFieldDefinitions('test_entity_type');
|
||||
|
||||
$this->assertTrue(isset($definitions[$default_langcode_key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode() {
|
||||
return [
|
||||
['default_langcode'],
|
||||
['custom_default_langcode_key'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getBaseFieldDefinitions() method with a translatable entity type.
|
||||
*
|
||||
* @covers ::getBaseFieldDefinitions
|
||||
* @covers ::buildBaseFieldDefinitions
|
||||
*
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage The Test entity type cannot be translatable as it does not define a translatable "langcode" field.
|
||||
*
|
||||
* @dataProvider providerTestGetBaseFieldDefinitionsTranslatableEntityTypeLangcode
|
||||
*/
|
||||
public function testGetBaseFieldDefinitionsTranslatableEntityTypeLangcode($provide_key, $provide_field, $translatable) {
|
||||
$keys = $provide_key ? array('langcode' => 'langcode') : array();
|
||||
$this->setUpEntityWithFieldDefinition(FALSE, 'id', $keys);
|
||||
|
||||
if ($provide_field) {
|
||||
$field_definition = $this->getMockBuilder('Drupal\Core\Field\BaseFieldDefinition')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$field_definition->expects($this->any())
|
||||
->method('isTranslatable')
|
||||
->willReturn($translatable);
|
||||
|
||||
$entity_class = get_class($this->entity);
|
||||
$entity_class::$baseFieldDefinitions += array('langcode' => $field_definition);
|
||||
}
|
||||
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('isTranslatable')
|
||||
->willReturn(TRUE);
|
||||
$this->entityType->expects($this->atLeastOnce())
|
||||
->method('getLabel')
|
||||
->willReturn('Test');
|
||||
|
||||
$this->entityManager->getBaseFieldDefinitions('test_entity_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testGetBaseFieldDefinitionsTranslatableEntityTypeLangcode().
|
||||
*
|
||||
* @return array
|
||||
* Test data.
|
||||
*/
|
||||
public function providerTestGetBaseFieldDefinitionsTranslatableEntityTypeLangcode() {
|
||||
return [
|
||||
[FALSE, TRUE, TRUE],
|
||||
[TRUE, FALSE, TRUE],
|
||||
[TRUE, TRUE, FALSE],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getBaseFieldDefinitions() method with caching.
|
||||
*
|
||||
|
@ -667,6 +806,10 @@ class EntityManagerTest extends UnitTestCase {
|
|||
public function testGetBaseFieldDefinitionsInvalidDefinition() {
|
||||
$langcode_definition = $this->setUpEntityWithFieldDefinition(FALSE, 'langcode', array('langcode' => 'langcode'));
|
||||
$langcode_definition->expects($this->once())
|
||||
->method('isTranslatable')
|
||||
->will($this->returnValue(FALSE));
|
||||
|
||||
$this->entityType->expects($this->any())
|
||||
->method('isTranslatable')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
|
@ -725,19 +868,20 @@ class EntityManagerTest extends UnitTestCase {
|
|||
* A field definition object.
|
||||
*/
|
||||
protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $field_definition_id = 'id', $entity_keys = array()) {
|
||||
$entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
|
||||
$entity = $this->getMockBuilder('Drupal\Tests\Core\Entity\EntityManagerTestEntity')
|
||||
$this->entityType = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
|
||||
|
||||
$this->entity = $this->getMockBuilder('Drupal\Tests\Core\Entity\EntityManagerTestEntity')
|
||||
->disableOriginalConstructor()
|
||||
->getMockForAbstractClass();
|
||||
$entity_class = get_class($entity);
|
||||
$entity_class = get_class($this->entity);
|
||||
|
||||
$entity_type->expects($this->any())
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getClass')
|
||||
->will($this->returnValue($entity_class));
|
||||
$entity_type->expects($this->any())
|
||||
$this->entityType->expects($this->any())
|
||||
->method('getKeys')
|
||||
->will($this->returnValue($entity_keys));
|
||||
$entity_type->expects($this->any())
|
||||
->will($this->returnValue($entity_keys + array('default_langcode' => 'default_langcode')));
|
||||
$this->entityType->expects($this->any())
|
||||
->method('isSubclassOf')
|
||||
->with($this->equalTo('\Drupal\Core\Entity\FieldableEntityInterface'))
|
||||
->will($this->returnValue(TRUE));
|
||||
|
@ -762,14 +906,14 @@ class EntityManagerTest extends UnitTestCase {
|
|||
$override_entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
|
||||
$override_entity_type->expects($this->any())
|
||||
->method('getClass')
|
||||
->will($this->returnValue(get_class($entity)));
|
||||
->will($this->returnValue(get_class($this->entity)));
|
||||
|
||||
$override_entity_type->expects($this->any())
|
||||
->method('getHandlerClass')
|
||||
->with('storage')
|
||||
->will($this->returnValue('\Drupal\Tests\Core\Entity\TestConfigEntityStorage'));
|
||||
|
||||
$this->setUpEntityManager(array('test_entity_type' => $entity_type, 'base_field_override' => $override_entity_type));
|
||||
$this->setUpEntityManager(array('test_entity_type' => $this->entityType, 'base_field_override' => $override_entity_type));
|
||||
|
||||
return $field_definition;
|
||||
}
|
||||
|
@ -1059,7 +1203,7 @@ class EntityManagerTest extends UnitTestCase {
|
|||
->will($this->returnValue($entity_class));
|
||||
$entity_type->expects($this->any())
|
||||
->method('getKeys')
|
||||
->will($this->returnValue(array()));
|
||||
->will($this->returnValue(array('default_langcode' => 'default_langcode')));
|
||||
$entity_type->expects($this->any())
|
||||
->method('id')
|
||||
->will($this->returnValue('test_entity_type'));
|
||||
|
@ -1202,7 +1346,7 @@ class EntityManagerTest extends UnitTestCase {
|
|||
->will($this->returnValue($entity_class));
|
||||
$entity_type->expects($this->any())
|
||||
->method('getKeys')
|
||||
->will($this->returnValue(array()));
|
||||
->will($this->returnValue(array('default_langcode' => 'default_langcode')));
|
||||
$entity_type->expects($this->any())
|
||||
->method('id')
|
||||
->will($this->returnValue('test_entity_type'));
|
||||
|
|
|
@ -38,7 +38,7 @@ class EntityTypeTest extends UnitTestCase {
|
|||
*/
|
||||
public function testGetKeys($entity_keys, $expected) {
|
||||
$entity_type = $this->setUpEntityType(array('entity_keys' => $entity_keys));
|
||||
$this->assertSame($expected, $entity_type->getKeys());
|
||||
$this->assertSame($expected + ['default_langcode' => 'default_langcode'], $entity_type->getKeys());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -89,7 +89,6 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
|
|||
* @covers ::getFieldUniqueKeys
|
||||
* @covers ::getFieldForeignKeys
|
||||
* @covers ::getFieldSchemaData
|
||||
* @covers ::addDefaultLangcodeSchema
|
||||
* @covers ::processBaseTable
|
||||
* @covers ::processIdentifierSchema
|
||||
*/
|
||||
|
@ -321,13 +320,6 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
|
|||
'type' => 'int',
|
||||
'not null' => FALSE,
|
||||
),
|
||||
'default_langcode' => array(
|
||||
'description' => 'Boolean indicating whether field values are in the default entity language.',
|
||||
'type' => 'int',
|
||||
'size' => 'tiny',
|
||||
'not null' => TRUE,
|
||||
'default' => 1,
|
||||
),
|
||||
),
|
||||
'primary key' => array('id'),
|
||||
'unique keys' => array(
|
||||
|
|
|
@ -643,7 +643,6 @@ class SqlContentEntityStorageTest extends UnitTestCase {
|
|||
$expected = array();
|
||||
$actual = $mapping->getExtraColumns('entity_test');
|
||||
$this->assertEquals($expected, $actual);
|
||||
$expected = array('default_langcode');
|
||||
$actual = $mapping->getExtraColumns('entity_test_field_data');
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
@ -704,7 +703,6 @@ class SqlContentEntityStorageTest extends UnitTestCase {
|
|||
$expected = array();
|
||||
$actual = $mapping->getExtraColumns('entity_test');
|
||||
$this->assertEquals($expected, $actual);
|
||||
$expected = array('default_langcode');
|
||||
$actual = $mapping->getExtraColumns('entity_test_field_data');
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
@ -761,13 +759,13 @@ class SqlContentEntityStorageTest extends UnitTestCase {
|
|||
);
|
||||
$this->assertEquals($expected, $mapping->getTableNames());
|
||||
|
||||
// The language code is not stored on the base table, but on the revision
|
||||
// table.
|
||||
// The default language code is stored on the base table.
|
||||
$expected = array_values(array_filter(array(
|
||||
$entity_keys['id'],
|
||||
$entity_keys['revision'],
|
||||
$entity_keys['bundle'],
|
||||
$entity_keys['uuid'],
|
||||
$entity_keys['langcode'],
|
||||
)));
|
||||
$actual = $mapping->getFieldNames('entity_test');
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
@ -803,7 +801,6 @@ class SqlContentEntityStorageTest extends UnitTestCase {
|
|||
$this->assertEquals($expected, $actual);
|
||||
$actual = $mapping->getExtraColumns('entity_test_revision');
|
||||
$this->assertEquals($expected, $actual);
|
||||
$expected = array('default_langcode');
|
||||
$actual = $mapping->getExtraColumns('entity_test_field_data');
|
||||
$this->assertEquals($expected, $actual);
|
||||
$actual = $mapping->getExtraColumns('entity_test_field_revision');
|
||||
|
@ -891,13 +888,13 @@ class SqlContentEntityStorageTest extends UnitTestCase {
|
|||
);
|
||||
$this->assertEquals($expected, $mapping->getTableNames());
|
||||
|
||||
// The language code is not stored on the base table, but on the revision
|
||||
// table.
|
||||
// The default language code is not stored on the base table.
|
||||
$expected = array_values(array_filter(array(
|
||||
$entity_keys['id'],
|
||||
$entity_keys['revision'],
|
||||
$entity_keys['bundle'],
|
||||
$entity_keys['uuid'],
|
||||
$entity_keys['langcode'],
|
||||
)));
|
||||
$actual = $mapping->getFieldNames('entity_test');
|
||||
$this->assertEquals($expected, $actual);
|
||||
|
@ -933,7 +930,6 @@ class SqlContentEntityStorageTest extends UnitTestCase {
|
|||
$this->assertEquals($expected, $actual);
|
||||
$actual = $mapping->getExtraColumns('entity_test_revision');
|
||||
$this->assertEquals($expected, $actual);
|
||||
$expected = array('default_langcode');
|
||||
$actual = $mapping->getExtraColumns('entity_test_field_data');
|
||||
$this->assertEquals($expected, $actual);
|
||||
$actual = $mapping->getExtraColumns('entity_test_field_revision');
|
||||
|
|
Loading…
Reference in New Issue