summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2018-04-30 14:43:54 (GMT)
committerAlex Pott2018-04-30 14:43:54 (GMT)
commit62fb120619aedb8908acdba49190ea68323b8284 (patch)
tree9ac9323d9b4d9e5121782c6565e0cf05b1f3bd4f
parent51afa6813ab0fc215b196822df8d8426477a0633 (diff)
Issue #2961986 by Sam152, Berdir, tstoeckler: The ContentEntityBase entity key cache is purged incorrectly when two keys exist for one field
-rw-r--r--core/lib/Drupal/Core/Entity/ContentEntityBase.php8
-rw-r--r--core/modules/system/tests/modules/entity_test/entity_test.module3
-rw-r--r--core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php13
-rw-r--r--core/tests/Drupal/KernelTests/Core/Entity/EntityKeysTest.php56
4 files changed, 75 insertions, 5 deletions
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 4e00f27..ff59d92 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -772,11 +772,11 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C
* {@inheritdoc}
*/
public function onChange($name) {
- // Check if the changed name is the value of an entity key and if the value
- // of that is currently cached, if so, reset it. Exclude the bundle from
- // that check, as it ready only and must not change, unsetting it could
+ // Check if the changed name is the value of any entity keys and if any of
+ // those values are currently cached, if so, reset it. Exclude the bundle
+ // from that check, as it ready only and must not change, unsetting it could
// lead to recursions.
- if ($key = array_search($name, $this->getEntityType()->getKeys())) {
+ foreach (array_keys($this->getEntityType()->getKeys(), $name, TRUE) as $key) {
if ($key != 'bundle') {
if (isset($this->entityKeys[$key])) {
unset($this->entityKeys[$key]);
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 8b4f2ba..d7dc635 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -101,6 +101,9 @@ function entity_test_entity_type_alter(array &$entity_types) {
if (!$state->get('entity_test_new')) {
unset($entity_types['entity_test_new']);
}
+
+ $entity_test_definition = $entity_types['entity_test'];
+ $entity_test_definition->set('entity_keys', $state->get('entity_test.entity_keys', []) + $entity_test_definition->getKeys());
}
/**
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php
index 9f8c5b0..771d81a 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php
@@ -109,7 +109,7 @@ class EntityTest extends ContentEntityBase implements EntityOwnerInterface {
],
]);
- return $fields;
+ return $fields + \Drupal::state()->get($entity_type->id() . '.additional_base_field_definitions', []);
}
/**
@@ -164,4 +164,15 @@ class EntityTest extends ContentEntityBase implements EntityOwnerInterface {
return $this->get('name')->value;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function getEntityKey($key) {
+ // Typically this protected method is used internally by entity classes and
+ // exposed publicly through more specific getter methods. So that test cases
+ // are able to set and access entity keys dynamically, update the visibility
+ // of this method to public.
+ return parent::getEntityKey($key);
+ }
+
}
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityKeysTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityKeysTest.php
new file mode 100644
index 0000000..834f04c
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityKeysTest.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Drupal\KernelTests\Core\Entity;
+
+use Drupal\Core\Field\BaseFieldDefinition;
+use Drupal\entity_test\Entity\EntityTest;
+
+/**
+ * Test the behavior of entity keys.
+ *
+ * @group entity
+ */
+class EntityKeysTest extends EntityKernelTestBase {
+
+ /**
+ * Test the cache when multiple keys reference a single field.
+ *
+ * @dataProvider multipleKeysCacheTestCases
+ */
+ public function testMultipleKeysCache($translatable) {
+ $this->state->set('entity_test.additional_base_field_definitions', [
+ 'test_field' => BaseFieldDefinition::create('string')->setTranslatable($translatable),
+ ]);
+ $this->state->set('entity_test.entity_keys', [
+ 'key_1' => 'test_field',
+ 'key_2' => 'test_field',
+ ]);
+ drupal_flush_all_caches();
+ $this->installEntitySchema('entity_test');
+
+ $entity = EntityTest::create([]);
+
+ $entity->set('test_field', 'foo');
+ $this->assertEquals('foo', $entity->getEntityKey('key_1'));
+ $this->assertEquals('foo', $entity->getEntityKey('key_2'));
+
+ $entity->set('test_field', 'bar');
+ $this->assertEquals('bar', $entity->getEntityKey('key_1'));
+ $this->assertEquals('bar', $entity->getEntityKey('key_2'));
+ }
+
+ /**
+ * Data provider for ::testMultipleKeysCache.
+ */
+ public function multipleKeysCacheTestCases() {
+ return [
+ 'translatable Entity Key' => [
+ TRUE,
+ ],
+ 'Non-translatable entity key' => [
+ FALSE,
+ ],
+ ];
+ }
+
+}