Commit 4f24c916 authored by catch's avatar catch

Issue #2734345 by danmuzyka, hchonov, Jo Fitzgerald, GoZ,...

Issue #2734345 by danmuzyka, hchonov, Jo Fitzgerald, GoZ, kristiaanvandeneynde, Berdir, alexpott: Comments: entity_id base field not overridden correctly in comment bundle field definitions for comment bundles attached to different entity target_type
parent d7d4998c
......@@ -838,4 +838,21 @@ public function setStorageRequired($required) {
return $this;
}
/**
* Magic method: Implements a deep clone.
*/
public function __clone() {
parent::__clone();
// The itemDefinition (\Drupal\Core\Field\TypedData\FieldItemDataDefinition)
// has a property fieldDefinition, which is a recursive reference to the
// parent BaseFieldDefinition, therefore the reference to the old object has
// to be overwritten with a reference to the cloned one.
$this->itemDefinition->setFieldDefinition($this);
// Reset the static cache of the field property definitions in order to
// ensure that the clone will reference different field property definitions
// objects.
$this->propertyDefinitions = NULL;
}
}
......@@ -3,7 +3,6 @@
namespace Drupal\Core\Field\TypedData;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
/**
......@@ -14,7 +13,7 @@
* by the field definitions, this class does not benefit and thus does not
* extend from MapDefinition or ComplexDataDefinitionBase.
*/
class FieldItemDataDefinition extends DataDefinition implements ComplexDataDefinitionInterface {
class FieldItemDataDefinition extends DataDefinition implements FieldItemDataDefinitionInterface {
/**
* The field definition the item definition belongs to.
......@@ -74,13 +73,18 @@ public function getMainPropertyName() {
}
/**
* Gets the field item's field definition.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface
* The field definition for this field item.
* {@inheritdoc}
*/
public function getFieldDefinition() {
return $this->fieldDefinition;
}
/**
* {@inheritdoc}
*/
public function setFieldDefinition($field_definition) {
$this->fieldDefinition = $field_definition;
return $this;
}
}
<?php
namespace Drupal\Core\Field\TypedData;
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
/**
* Interface for field item data definitions.
*
* @ingroup typed_data
*/
interface FieldItemDataDefinitionInterface extends ComplexDataDefinitionInterface {
/**
* Gets the field item's field definition.
*
* @return \Drupal\Core\Field\FieldDefinitionInterface
* The field definition for this field item.
*/
public function getFieldDefinition();
/**
* Sets the field item's field definition.
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The new field definition to assign to this item definition.
*
* @return static
* The object itself for chaining.
*
* @internal
* Should not be used in user code. It allows to overwrite the item
* definition property of the cloned field definition.
*/
public function setFieldDefinition($field_definition);
}
......@@ -108,4 +108,13 @@ public function setItemDefinition(DataDefinitionInterface $definition) {
return $this;
}
/**
* Magic method: Implements a deep clone.
*/
public function __clone() {
// Ensure the itemDefinition property is actually cloned by overwriting the
// original reference.
$this->itemDefinition = clone $this->itemDefinition;
}
}
<?php
namespace Drupal\Tests\comment\Kernel;
use Drupal\comment\Entity\CommentType;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests that comment bundles behave as expected.
*
* @group comment
*/
class CommentBundlesTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['comment', 'node', 'taxonomy', 'user'];
/**
* Entity type ids to use for target_entity_type_id on comment bundles.
*
* @var array
*/
protected $targetEntityTypes;
/**
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->entityFieldManager = $this->container->get('entity_field.manager');
$this->installEntitySchema('comment');
// Create multiple comment bundles,
// each of which has a different target entity type.
$this->targetEntityTypes = [
'comment' => 'Comment',
'node' => 'Node',
'taxonomy_term' => 'Taxonomy Term',
];
foreach ($this->targetEntityTypes as $id => $label) {
CommentType::create([
'id' => 'comment_on_' . $id,
'label' => 'Comment on ' . $label,
'target_entity_type_id' => $id,
])->save();
}
}
/**
* Test that the entity_id field is set correctly for each comment bundle.
*/
public function testEntityIdField() {
$field_definitions = [];
foreach (array_keys($this->targetEntityTypes) as $id) {
$bundle = 'comment_on_' . $id;
$field_definitions[$bundle] = $this->entityFieldManager
->getFieldDefinitions('comment', $bundle);
}
// Test that the value of the entity_id field for each bundle is correct.
foreach ($field_definitions as $bundle => $definition) {
$entity_type_id = str_replace('comment_on_', '', $bundle);
$target_type = $definition['entity_id']->getSetting('target_type');
$this->assertEquals($entity_type_id, $target_type);
// Verify that the target type remains correct
// in the deeply-nested object properties.
$nested_target_type = $definition['entity_id']->getItemDefinition()->getFieldDefinition()->getSetting('target_type');
$this->assertEquals($entity_type_id, $nested_target_type);
}
}
}
......@@ -46,6 +46,34 @@ public function testBaseFieldSettings() {
$this->assertEqual($base_field->getSettings(), $expected_settings);
}
/**
* Tests the base field settings on a cloned base field definition object.
*/
public function testBaseFieldSettingsOnClone() {
$base_field = BaseFieldDefinition::create('test_field');
// Check that the default settings have been populated.
$expected_settings = [
'test_field_storage_setting' => 'dummy test string',
'changeable' => 'a changeable field storage setting',
'unchangeable' => 'an unchangeable field storage setting',
'translatable_storage_setting' => 'a translatable field storage setting',
'test_field_setting' => 'dummy test string',
'translatable_field_setting' => 'a translatable field setting',
];
$this->assertEquals($expected_settings, $base_field->getSettings());
// Clone the base field object and change one single setting using
// setSettings() on the cloned base field and check that it has been
// changed only on the cloned object.
$clone_base_field = clone $base_field;
$expected_settings_clone = $expected_settings;
$expected_settings_clone['changeable'] = $expected_settings['changeable'] . ' (clone)';
$clone_base_field->setSetting('changeable', $expected_settings_clone['changeable']);
$this->assertEquals($expected_settings, $base_field->getSettings());
$this->assertEquals($expected_settings_clone, $clone_base_field->getSettings());
}
/**
* @covers \Drupal\field\Entity\FieldStorageConfig::getSettings
* @covers \Drupal\field\Entity\FieldStorageConfig::setSettings
......
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