Commit 1ef413be authored by alexpott's avatar alexpott

Issue #2862463 by hchonov, Jo Fitzgerald, tstoeckler: Cloning an entity with...

Issue #2862463 by hchonov, Jo Fitzgerald, tstoeckler: Cloning an entity with initialized translations leaves $values pointing to the old entity object
parent 1e56b1fb
......@@ -1094,8 +1094,8 @@ public function __clone() {
// Ensure that the following properties are actually cloned by
// overwriting the original references with ones pointing to copies of
// them: enforceIsNew, newRevision, loadedRevisionId, fields, entityKeys and
// translatableEntityKeys.
// them: enforceIsNew, newRevision, loadedRevisionId, fields, entityKeys,
// translatableEntityKeys and values.
$enforce_is_new = $this->enforceIsNew;
$this->enforceIsNew = &$enforce_is_new;
......@@ -1114,16 +1114,19 @@ public function __clone() {
$translatable_entity_keys = $this->translatableEntityKeys;
$this->translatableEntityKeys = &$translatable_entity_keys;
foreach ($this->fields as $name => $values) {
$values = $this->values;
$this->values = &$values;
foreach ($this->fields as $name => $fields_by_langcode) {
$this->fields[$name] = [];
// Untranslatable fields may have multiple references for the same field
// object keyed by language. To avoid creating different field objects
// we retain just the original value, as references will be recreated
// later as needed.
if (!$definitions[$name]->isTranslatable() && count($values) > 1) {
$values = array_intersect_key($values, [LanguageInterface::LANGCODE_DEFAULT => TRUE]);
if (!$definitions[$name]->isTranslatable() && count($fields_by_langcode) > 1) {
$fields_by_langcode = array_intersect_key($fields_by_langcode, [LanguageInterface::LANGCODE_DEFAULT => TRUE]);
}
foreach ($values as $langcode => $items) {
foreach ($fields_by_langcode as $langcode => $items) {
$this->fields[$name][$langcode] = clone $items;
$this->fields[$name][$langcode]->setContext($name, $this->getTranslation($langcode)->getTypedData());
}
......
......@@ -219,4 +219,36 @@ public function testEntityKeysModifications() {
$this->assertEquals('clone-name', $clone->label());
}
/**
* Tests the field values after serializing an entity and its clone.
*/
public function testFieldValuesAfterSerialize() {
// Create a test entity with a translation, which will internally trigger
// entity cloning for the new translation and create references for some of
// the entity properties.
$entity = EntityTestMulRev::create([
'name' => 'original',
'language' => 'en',
]);
$entity->addTranslation('de');
$entity->save();
// Clone the entity.
$clone = clone $entity;
// Alter the name field value of the cloned entity object.
$clone->setName('clone');
// Serialize the entity and the cloned object in order to destroy the field
// objects and put the field values into the entity property $values, so
// that on accessing a field again it will be newly created with the value
// from the $values property.
serialize($entity);
serialize($clone);
// Assert that the original and the cloned entity both have different names.
$this->assertEquals('original', $entity->getName());
$this->assertEquals('clone', $clone->getName());
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment