Commit d988a30f authored by Dries's avatar Dries

Issue #1810370 by plach, kfritsche, berdir, alexpott, xjm, chx: Entity...

Issue #1810370 by plach, kfritsche, berdir, alexpott, xjm, chx: Entity Translation API improvements.
parent 0329b221
...@@ -240,6 +240,35 @@ function hook_entity_update(Drupal\Core\Entity\EntityInterface $entity) { ...@@ -240,6 +240,35 @@ function hook_entity_update(Drupal\Core\Entity\EntityInterface $entity) {
->execute(); ->execute();
} }
/**
* Acts after storing a new entity translation.
*
* @param \Drupal\Core\Entity\EntityInterface $translation
* The entity object of the translation just stored.
*/
function hook_entity_translation_insert(\Drupal\Core\Entity\EntityInterface $translation) {
$variables = array(
'@language' => $translation->language()->name,
'@label' => $translation->getUntranslated()->label(),
);
watchdog('example', 'The @language translation of @label has just been stored.', $variables);
}
/**
* Acts after deleting an entity translation from the storage.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The original entity object.
*/
function hook_entity_translation_delete(\Drupal\Core\Entity\EntityInterface $translation) {
$languages = language_list();
$variables = array(
'@language' => $languages[$langcode]->name,
'@label' => $entity->label(),
);
watchdog('example', 'The @language translation of @label has just been deleted.', $variables);
}
/** /**
* Act before entity deletion. * Act before entity deletion.
* *
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\DatabaseStorageController; use Drupal\Core\Entity\DatabaseStorageController;
use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\TypedData\ComplexDataInterface;
use Drupal\Component\Uuid\Uuid; use Drupal\Component\Uuid\Uuid;
use Drupal\Core\Database\Connection; use Drupal\Core\Database\Connection;
...@@ -289,6 +288,7 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) { ...@@ -289,6 +288,7 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) {
$data = $query->execute(); $data = $query->execute();
$field_definition = \Drupal::entityManager()->getFieldDefinitions($this->entityType); $field_definition = \Drupal::entityManager()->getFieldDefinitions($this->entityType);
$translations = array();
if ($this->revisionTable) { if ($this->revisionTable) {
$data_fields = array_flip(array_diff(drupal_schema_fields_sql($this->entityInfo['revision_table']), drupal_schema_fields_sql($this->entityInfo['base_table']))); $data_fields = array_flip(array_diff(drupal_schema_fields_sql($this->entityInfo['revision_table']), drupal_schema_fields_sql($this->entityInfo['base_table'])));
} }
...@@ -302,6 +302,7 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) { ...@@ -302,6 +302,7 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) {
// Field values in default language are stored with // Field values in default language are stored with
// Language::LANGCODE_DEFAULT as key. // Language::LANGCODE_DEFAULT as key.
$langcode = empty($values['default_langcode']) ? $values['langcode'] : Language::LANGCODE_DEFAULT; $langcode = empty($values['default_langcode']) ? $values['langcode'] : Language::LANGCODE_DEFAULT;
$translations[$id][$langcode] = TRUE;
foreach ($field_definition as $name => $definition) { foreach ($field_definition as $name => $definition) {
// Set only translatable properties, unless we are dealing with a // Set only translatable properties, unless we are dealing with a
...@@ -317,7 +318,7 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) { ...@@ -317,7 +318,7 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) {
foreach ($entities as $id => $values) { foreach ($entities as $id => $values) {
$bundle = $this->bundleKey ? $values[$this->bundleKey][Language::LANGCODE_DEFAULT] : FALSE; $bundle = $this->bundleKey ? $values[$this->bundleKey][Language::LANGCODE_DEFAULT] : FALSE;
// Turn the record into an entity class. // Turn the record into an entity class.
$entities[$id] = new $this->entityClass($values, $this->entityType, $bundle); $entities[$id] = new $this->entityClass($values, $this->entityType, $bundle, array_keys($translations[$id]));
} }
} }
} }
...@@ -367,6 +368,9 @@ public function save(EntityInterface $entity) { ...@@ -367,6 +368,9 @@ public function save(EntityInterface $entity) {
$entity->postSave($this, TRUE); $entity->postSave($this, TRUE);
$this->invokeFieldMethod('update', $entity); $this->invokeFieldMethod('update', $entity);
$this->invokeHook('update', $entity); $this->invokeHook('update', $entity);
if ($this->dataTable) {
$this->invokeTranslationHooks($entity);
}
} }
else { else {
$return = drupal_write_record($this->entityInfo['base_table'], $record); $return = drupal_write_record($this->entityInfo['base_table'], $record);
...@@ -412,7 +416,7 @@ public function save(EntityInterface $entity) { ...@@ -412,7 +416,7 @@ public function save(EntityInterface $entity) {
*/ */
protected function saveRevision(EntityInterface $entity) { protected function saveRevision(EntityInterface $entity) {
$return = $entity->id(); $return = $entity->id();
$default_langcode = $entity->language()->id; $default_langcode = $entity->getUntranslated()->language()->id;
if (!$entity->isNewRevision()) { if (!$entity->isNewRevision()) {
// Delete to handle removed values. // Delete to handle removed values.
...@@ -422,9 +426,9 @@ protected function saveRevision(EntityInterface $entity) { ...@@ -422,9 +426,9 @@ protected function saveRevision(EntityInterface $entity) {
->execute(); ->execute();
} }
$languages = $this->dataTable ? $entity->getTranslationLanguages(TRUE) : array($default_langcode => $entity->language()); $languages = $this->dataTable ? $entity->getTranslationLanguages() : array($default_langcode => $entity->language());
foreach ($languages as $langcode => $language) { foreach ($languages as $langcode => $language) {
$translation = $entity->getTranslation($langcode, FALSE); $translation = $entity->getTranslation($langcode);
$record = $this->mapToRevisionStorageRecord($translation); $record = $this->mapToRevisionStorageRecord($translation);
$record->langcode = $langcode; $record->langcode = $langcode;
$record->default_langcode = $langcode == $default_langcode; $record->default_langcode = $langcode == $default_langcode;
...@@ -511,7 +515,7 @@ protected function mapToStorageRecord(EntityInterface $entity) { ...@@ -511,7 +515,7 @@ protected function mapToStorageRecord(EntityInterface $entity) {
* @return \stdClass * @return \stdClass
* The record to store. * The record to store.
*/ */
protected function mapToRevisionStorageRecord(ComplexDataInterface $entity) { protected function mapToRevisionStorageRecord(EntityInterface $entity) {
$record = new \stdClass(); $record = new \stdClass();
$definitions = $entity->getPropertyDefinitions(); $definitions = $entity->getPropertyDefinitions();
foreach (drupal_schema_fields_sql($this->entityInfo['revision_table']) as $name) { foreach (drupal_schema_fields_sql($this->entityInfo['revision_table']) as $name) {
...@@ -534,10 +538,10 @@ protected function mapToRevisionStorageRecord(ComplexDataInterface $entity) { ...@@ -534,10 +538,10 @@ protected function mapToRevisionStorageRecord(ComplexDataInterface $entity) {
* The record to store. * The record to store.
*/ */
protected function mapToDataStorageRecord(EntityInterface $entity, $langcode) { protected function mapToDataStorageRecord(EntityInterface $entity, $langcode) {
$default_langcode = $entity->language()->id; $default_langcode = $entity->getUntranslated()->language()->id;
// Don't use strict mode, this way there's no need to do checks here, as // Don't use strict mode, this way there's no need to do checks here, as
// non-translatable properties are replicated for each language. // non-translatable properties are replicated for each language.
$translation = $entity->getTranslation($langcode, FALSE); $translation = $entity->getTranslation($langcode);
$definitions = $translation->getPropertyDefinitions(); $definitions = $translation->getPropertyDefinitions();
$schema = drupal_get_schema($this->entityInfo['data_table']); $schema = drupal_get_schema($this->entityInfo['data_table']);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
use Drupal\Component\Uuid\Uuid; use Drupal\Component\Uuid\Uuid;
use Drupal\Core\Language\Language; use Drupal\Core\Language\Language;
use Drupal\Core\TypedData\TranslatableInterface;
use Drupal\Core\TypedData\TypedDataInterface; use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\user\UserInterface; use Drupal\user\UserInterface;
use IteratorAggregate; use IteratorAggregate;
...@@ -294,10 +295,13 @@ public function language() { ...@@ -294,10 +295,13 @@ public function language() {
/** /**
* Implements \Drupal\Core\TypedData\TranslatableInterface::getTranslation(). * Implements \Drupal\Core\TypedData\TranslatableInterface::getTranslation().
*
* @return \Drupal\Core\Entity\EntityInterface
*/ */
public function getTranslation($langcode, $strict = TRUE) { public function getTranslation($langcode) {
// @todo: Replace by EntityNG implementation once all entity types have been // @todo: Replace by EntityNG implementation once all entity types have been
// converted to use the entity field API. // converted to use the entity field API.
return $this;
} }
/** /**
...@@ -588,4 +592,46 @@ public static function postLoad(EntityStorageControllerInterface $storage_contro ...@@ -588,4 +592,46 @@ public static function postLoad(EntityStorageControllerInterface $storage_contro
public function preSaveRevision(EntityStorageControllerInterface $storage_controller, \stdClass $record) { public function preSaveRevision(EntityStorageControllerInterface $storage_controller, \stdClass $record) {
} }
/**
* {@inheritdoc}
*/
public function getUntranslated() {
return $this->getTranslation(Language::LANGCODE_DEFAULT);
}
/**
* {@inheritdoc}
*/
public function hasTranslation($langcode) {
$translations = $this->getTranslationLanguages();
return isset($translations[$langcode]);
}
/**
* {@inheritdoc}
*/
public function addTranslation($langcode, array $values = array()) {
// @todo Config entities do not support entity translation hence we need to
// move the TranslatableInterface implementation to EntityNG. See
// http://drupal.org/node/2004244
}
/**
* {@inheritdoc}
*/
public function removeTranslation($langcode) {
// @todo Config entities do not support entity translation hence we need to
// move the TranslatableInterface implementation to EntityNG. See
// http://drupal.org/node/2004244
}
/**
* {@inheritdoc}
*/
public function initTranslation($langcode) {
// @todo Config entities do not support entity translation hence we need to
// move the TranslatableInterface implementation to EntityNG. See
// http://drupal.org/node/2004244
}
} }
...@@ -138,7 +138,7 @@ public function &__get($name) { ...@@ -138,7 +138,7 @@ public function &__get($name) {
// Language::LANGCODE_DEFAULT. This is necessary as EntityNG always keys // Language::LANGCODE_DEFAULT. This is necessary as EntityNG always keys
// default language values with Language::LANGCODE_DEFAULT while field API // default language values with Language::LANGCODE_DEFAULT while field API
// expects them to be keyed by langcode. // expects them to be keyed by langcode.
$langcode = $this->decorated->language()->id; $langcode = $this->decorated->getUntranslated()->language()->id;
if ($langcode != Language::LANGCODE_DEFAULT && isset($this->decorated->values[$name]) && is_array($this->decorated->values[$name])) { if ($langcode != Language::LANGCODE_DEFAULT && isset($this->decorated->values[$name]) && is_array($this->decorated->values[$name])) {
if (isset($this->decorated->values[$name][Language::LANGCODE_DEFAULT]) && !isset($this->decorated->values[$name][$langcode])) { if (isset($this->decorated->values[$name][Language::LANGCODE_DEFAULT]) && !isset($this->decorated->values[$name][$langcode])) {
$this->decorated->values[$name][$langcode] = &$this->decorated->values[$name][Language::LANGCODE_DEFAULT]; $this->decorated->values[$name][$langcode] = &$this->decorated->values[$name][Language::LANGCODE_DEFAULT];
...@@ -424,8 +424,8 @@ public function getTranslationLanguages($include_default = TRUE) { ...@@ -424,8 +424,8 @@ public function getTranslationLanguages($include_default = TRUE) {
/** /**
* Forwards the call to the decorated entity. * Forwards the call to the decorated entity.
*/ */
public function getTranslation($langcode, $strict = TRUE) { public function getTranslation($langcode) {
return $this->decorated->getTranslation($langcode, $strict); return $this->decorated->getTranslation($langcode);
} }
/** /**
...@@ -526,12 +526,6 @@ public function onChange($property_name) { ...@@ -526,12 +526,6 @@ public function onChange($property_name) {
$this->decorated->onChange($property_name); $this->decorated->onChange($property_name);
} }
/**
* Forwards the call to the decorated entity.
*/
public function isTranslatable() {
return $this->decorated->isTranslatable();
}
/** /**
* Forwards the call to the decorated entity. * Forwards the call to the decorated entity.
...@@ -588,4 +582,47 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont ...@@ -588,4 +582,47 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont
*/ */
public static function postLoad(EntityStorageControllerInterface $storage_controller, array $entities) { public static function postLoad(EntityStorageControllerInterface $storage_controller, array $entities) {
} }
/**
* Forwards the call to the decorated entity.
*/
public function isTranslatable() {
return $this->decorated->isTranslatable();
}
/**
* Forwards the call to the decorated entity.
*/
public function getUntranslated() {
return $this->decorated->getUntranslated();
}
/**
* Forwards the call to the decorated entity.
*/
public function hasTranslation($langcode) {
return $this->decorated->hasTranslation($langcode);
}
/**
* Forwards the call to the decorated entity.
*/
public function addTranslation($langcode, array $values = array()) {
return $this->decorated->addTranslation($langcode, $values);
}
/**
* Forwards the call to the decorated entity.
*/
public function removeTranslation($langcode) {
$this->decorated->removeTranslation($langcode);
}
/**
* Forwards the call to the decorated entity.
*/
public function initTranslation($langcode) {
$this->decorated->initTranslation($langcode);
}
} }
...@@ -146,6 +146,11 @@ protected function init(array &$form_state) { ...@@ -146,6 +146,11 @@ protected function init(array &$form_state) {
// module-provided form handlers there. // module-provided form handlers there.
$form_state['controller'] = $this; $form_state['controller'] = $this;
// Ensure we act on the translation object corresponding to the current form
// language.
$this->entity = $this->getTranslatedEntity($form_state);
// Prepare the entity to be presented in the entity form.
$this->prepareEntity(); $this->prepareEntity();
$form_display = entity_get_render_form_display($this->entity, $this->getOperation()); $form_display = entity_get_render_form_display($this->entity, $this->getOperation());
...@@ -188,7 +193,7 @@ public function form(array $form, array &$form_state) { ...@@ -188,7 +193,7 @@ public function form(array $form, array &$form_state) {
// new entities. // new entities.
$form['langcode'] = array( $form['langcode'] = array(
'#type' => 'value', '#type' => 'value',
'#value' => !$entity->isNew() ? $entity->langcode : language_default()->id, '#value' => !$entity->isNew() ? $entity->getUntranslated()->language()->id : language_default()->id,
); );
} }
return $form; return $form;
...@@ -393,7 +398,6 @@ public function delete(array $form, array &$form_state) { ...@@ -393,7 +398,6 @@ public function delete(array $form, array &$form_state) {
*/ */
public function getFormLangcode(array $form_state) { public function getFormLangcode(array $form_state) {
$entity = $this->entity; $entity = $this->entity;
$translations = $entity->getTranslationLanguages();
if (!empty($form_state['langcode'])) { if (!empty($form_state['langcode'])) {
$langcode = $form_state['langcode']; $langcode = $form_state['langcode'];
...@@ -402,6 +406,7 @@ public function getFormLangcode(array $form_state) { ...@@ -402,6 +406,7 @@ public function getFormLangcode(array $form_state) {
// If no form langcode was provided we default to the current content // If no form langcode was provided we default to the current content
// language and inspect existing translations to find a valid fallback, // language and inspect existing translations to find a valid fallback,
// if any. // if any.
$translations = $entity->getTranslationLanguages();
$langcode = language(Language::TYPE_CONTENT)->id; $langcode = language(Language::TYPE_CONTENT)->id;
$fallback = language_multilingual() ? language_fallback_get_candidates() : array(); $fallback = language_multilingual() ? language_fallback_get_candidates() : array();
while (!empty($langcode) && !isset($translations[$langcode])) { while (!empty($langcode) && !isset($translations[$langcode])) {
...@@ -411,14 +416,14 @@ public function getFormLangcode(array $form_state) { ...@@ -411,14 +416,14 @@ public function getFormLangcode(array $form_state) {
// If the site is not multilingual or no translation for the given form // If the site is not multilingual or no translation for the given form
// language is available, fall back to the entity language. // language is available, fall back to the entity language.
return !empty($langcode) ? $langcode : $entity->language()->id; return !empty($langcode) ? $langcode : $entity->getUntranslated()->language()->id;
} }
/** /**
* Implements \Drupal\Core\Entity\EntityFormControllerInterface::isDefaultFormLangcode(). * Implements \Drupal\Core\Entity\EntityFormControllerInterface::isDefaultFormLangcode().
*/ */
public function isDefaultFormLangcode(array $form_state) { public function isDefaultFormLangcode(array $form_state) {
return $this->getFormLangcode($form_state) == $this->entity->language()->id; return $this->getFormLangcode($form_state) == $this->entity->getUntranslated()->language()->id;
} }
/** /**
...@@ -447,13 +452,11 @@ protected function submitEntityLanguage(array $form, array &$form_state) { ...@@ -447,13 +452,11 @@ protected function submitEntityLanguage(array $form, array &$form_state) {
$entity_type = $entity->entityType(); $entity_type = $entity->entityType();
if (field_has_translation_handler($entity_type)) { if (field_has_translation_handler($entity_type)) {
$form_langcode = $this->getFormLangcode($form_state);
// If we are editing the default language values, we use the submitted // If we are editing the default language values, we use the submitted
// entity language as the new language for fields to handle any language // entity language as the new language for fields to handle any language
// change. Otherwise the current form language is the proper value, since // change. Otherwise the current form language is the proper value, since
// in this case it is not supposed to change. // in this case it is not supposed to change.
$current_langcode = $entity->language()->id == $form_langcode ? $form_state['values']['langcode'] : $form_langcode; $current_langcode = $this->isDefaultFormLangcode($form_state) ? $form_state['values']['langcode'] : $this->getFormLangcode($form_state);
foreach (field_info_instances($entity_type, $entity->bundle()) as $instance) { foreach (field_info_instances($entity_type, $entity->bundle()) as $instance) {
$field_name = $instance['field_name']; $field_name = $instance['field_name'];
...@@ -489,10 +492,22 @@ public function buildEntity(array $form, array &$form_state) { ...@@ -489,10 +492,22 @@ public function buildEntity(array $form, array &$form_state) {
* Implements \Drupal\Core\Entity\EntityFormControllerInterface::getEntity(). * Implements \Drupal\Core\Entity\EntityFormControllerInterface::getEntity().
*/ */
public function getEntity() { public function getEntity() {
// @todo Pick the proper translation object based on the form language here.
return $this->entity; return $this->entity;
} }
/**
* Returns the translation object corresponding to the form language.
*
* @param array $form_state
* A keyed array containing the current state of the form.
*/
protected function getTranslatedEntity(array $form_state) {
$langcode = $this->getFormLangcode($form_state);
$translation = $this->entity->getTranslation($langcode);
// Ensure that the entity object is a BC entity if the original one is.
return $this->entity instanceof EntityBCDecorator ? $translation->getBCEntity() : $translation;
}
/** /**
* Implements \Drupal\Core\Entity\EntityFormControllerInterface::setEntity(). * Implements \Drupal\Core\Entity\EntityFormControllerInterface::setEntity().
*/ */
...@@ -521,7 +536,7 @@ protected function prepareInvokeAll($hook, array &$form_state) { ...@@ -521,7 +536,7 @@ protected function prepareInvokeAll($hook, array &$form_state) {
if (function_exists($function)) { if (function_exists($function)) {
// Ensure we pass an updated translation object and form display at // Ensure we pass an updated translation object and form display at
// each invocation, since they depend on form state which is alterable. // each invocation, since they depend on form state which is alterable.
$args = array($this->getEntity(), $this->getFormDisplay($form_state), $this->operation, &$form_state); $args = array($this->getTranslatedEntity($form_state), $this->getFormDisplay($form_state), $this->operation, &$form_state);
call_user_func_array($function, $args); call_user_func_array($function, $args);
} }
} }
......
...@@ -61,11 +61,10 @@ public function buildEntity(array $form, array &$form_state) { ...@@ -61,11 +61,10 @@ public function buildEntity(array $form, array &$form_state) {
// edited by this form. Values of fields handled by field API are copied // edited by this form. Values of fields handled by field API are copied
// by field_attach_extract_form_values() below. // by field_attach_extract_form_values() below.
$values_excluding_fields = $info['fieldable'] ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values']; $values_excluding_fields = $info['fieldable'] ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values'];
$translation = $entity->getTranslation($this->getFormLangcode($form_state), FALSE); $definitions = $entity->getPropertyDefinitions();
$definitions = $translation->getPropertyDefinitions();
foreach ($values_excluding_fields as $key => $value) { foreach ($values_excluding_fields as $key => $value) {
if (isset($definitions[$key])) { if (isset($definitions[$key])) {
$translation->$key = $value; $entity->$key = $value;
} }
} }
......
...@@ -323,4 +323,15 @@ public function getNGEntity(); ...@@ -323,4 +323,15 @@ public function getNGEntity();
*/ */
public function isTranslatable(); public function isTranslatable();
/**
* Marks the translation identified by the given language code as existing.
*
* @todo Remove this as soon as translation metadata have been converted to
* regular fields.
*
* @param string $langcode
* The language code identifying the translation to be initialized.
*/
public function initTranslation($langcode);
} }
This diff is collapsed.
...@@ -234,4 +234,26 @@ public function invokeFieldItemPrepareCache(EntityInterface $entity) { ...@@ -234,4 +234,26 @@ public function invokeFieldItemPrepareCache(EntityInterface $entity) {
} }
} }
/**
* Checks translation statuses and invoke the related hooks if needed.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity being saved.
*/
protected function invokeTranslationHooks(EntityInterface $entity) {
$translations = $entity->getTranslationLanguages(FALSE);
$original_translations = $entity->original->getTranslationLanguages(FALSE);
$all_translations = array_keys($translations + $original_translations);
// Notify modules of translation insertion/deletion.
foreach ($all_translations as $langcode) {
if (isset($translations[$langcode]) && !isset($original_translations[$langcode])) {
$this->invokeHook('translation_insert', $entity->getTranslation($langcode));
}
elseif (!isset($translations[$langcode]) && isset($original_translations[$langcode])) {
$this->invokeHook('translation_delete', $entity->getTranslation($langcode));
}
}
}
} }
<
<?php
/**
* @file
* Contains \Drupal\Core\Entity\Plugin\DataType\EntityTranslation.
*/
namespace Drupal\Core\Entity\Plugin\DataType;
use Drupal\Core\TypedData\Annotation\DataType;
use Drupal\Core\Annotation\Translation;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\AccessibleInterface;
use Drupal\Core\TypedData\ComplexDataInterface;
use Drupal\Core\TypedData\TypedData;
use ArrayIterator;
use IteratorAggregate;
use InvalidArgumentException;
/**
* Allows accessing and updating translated entity fields.
*
* Via this object translated entity fields may be read and updated in the same
* way as untranslatable entity fields on the entity object.
*
* @DataType(
* id = "entity_translation",
* label = @Translation("Entity translation"),
* description = @Translation("A translation of an entity.")
* )
*/
class EntityTranslation extends TypedData implements IteratorAggregate, AccessibleInterface, ComplexDataInterface {
/**
* The array of translated fields, each being an instance of
* \Drupal\Core\Entity\FieldInterface.
*
* @var array
*/
protected $fields = array();
/**
* Whether the entity translation acts in strict mode.
*
* @var boolean
*/
protected $strict = TRUE;
/**
* Returns whether the entity translation acts in strict mode.
*
* @return boolean
* Whether the entity translation acts in strict mode.
*/
public function getStrictMode() {
return $this->strict;
}
/**
* Sets whether the entity translation acts in strict mode.
*
* @param boolean $strict
* Whether the entity translation acts in strict mode.
*
* @see \Drupal\Core\TypedData\TranslatableInterface::getTranslation()
*/
public function setStrictMode($strict = TRUE) {
$this->strict = $strict;
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::getValue().
*/
public function getValue() {
// The plain value of the translation is the array of translated field
// objects.
return $this->fields;
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::setValue().
*/
public function setValue($values, $notify = TRUE) {
// Notify the parent of any changes to be made.
if ($notify && isset($this->parent)) {
$this->parent->onChange($this->name);
}
$this->fields = $values;
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::getString().
*/
public function getString() {
$strings = array();
foreach ($this->getProperties() as $property) {
$strings[] = $property->getString();
}
return implode(', ', array_filter($strings));
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::get().
*/
public function get($property_name) {
$definitions = $this->getPropertyDefinitions();
if (!isset($definitions[$property_name])) {
throw new InvalidArgumentException(format_string('Field @name is unknown or not translatable.', array('@name' => $property_name)));
}
return $this->fields[$property_name];
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::set().
*/
public function set($property_name, $value, $notify = TRUE) {
$this->get($property_name)->setValue($value, FALSE);
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::getProperties().
*/
public function getProperties($include_computed = FALSE) {
$properties = array();
foreach ($this->getPropertyDefinitions() as $name => $definition) {
if ($include_computed || empty($definition['computed'])) {