Problem/Motivation

Follow-up from #2278017: When a content entity type providing module is uninstalled, the entities are not fully deleted, leaving broken reference: ContentUninstallValidator relies on ContentEntityStorage::hasData() but this currently resides in DynamicallyFieldableEntityStorageInterface, which is not required for content entities to implement.

Proposed resolution

As it makes sense generically, let's move it up to EntityStorageInterface. The implementation should work for config entities as well, but this needs tests.

Remaining tasks

Do.

User interface changes

-

API changes

- EntityStorageInterface::hasData() is added (moved up from DynamicallyFieldableEntityStorageInterface)

Comments

fago’s picture

Status: Postponed » Active
cilefen’s picture

Status: Active » Needs review
StatusFileSize
new2.04 KB

Status: Needs review » Needs work

The last submitted patch, 2: 2391829-2.patch, failed testing.

cilefen’s picture

Status: Needs work » Needs review
StatusFileSize
new464 bytes
new2.64 KB
plach’s picture

Way better :)

Can we add an implementation for ContentEntityNullStorage?

cilefen’s picture

@plach There already is one without this patch.

plach’s picture

Status: Needs review » Reviewed & tested by the community

Mmh, I should really get some rest. This looks ready to me :)

plach’s picture

Status: Reviewed & tested by the community » Needs review
+++ b/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php
@@ -202,6 +202,13 @@ protected function has($id, EntityInterface $entity) {
+    return FALSE;

Would it make sense to return this?

(bool) count($this->keyValueStore->getAll())

I'm wondering whether it could imply performance problems.

berdir’s picture

Possibly. The query implementation also uses getAll(), there is nothing else that we could use.

It's just a test implementation really, I hope nobody is going to use it for real data :)

yched’s picture

Status: Needs review » Reviewed & tested by the community

Yay - looks good indeed ?

fago’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
@@ -279,6 +279,13 @@ protected function has($id, EntityInterface $entity) {
+  public function hasData() {
+    return FALSE;
+  }

Why that? It should just run an entity query as for content entities + we need test coverage that hasData() works for for config entities.

yched’s picture

As a side note : #2392351: When an entity bundle config gets deleted, entities of that bundle break has a case for "are there existing entities *for that specific bundle* ?", and curently has to include dedicated code that almost duplicates ContentEntityStorage::hasData(), just adding an extra ->condition($entity_type->getKey('bundle'), $bundle)

Would be a nice thing to add as an optional param in ContentEntityStorage::hasData() ?

yched’s picture

And right, having the implemtation always returning FALSE for ConfigEntityStorage & KeyValueEntityStorage is a bit problematic.

- KeyValueEntityStorage would need to return count($this->keyValueStore->getAll()) != 0
Although, yeah, as mentioned above, that is kind of a perf drag :-/

From @Berdir #9:

KeyValueEntityStorage just a test implementation really, I hope nobody is going to use it for real data :)

OK, but nothing really hints that it's a test-only-do-not-use-for-real implementation :-).
It's not in a "test" directory or namespace, Drupal\Core\Entity\KeyValueStore makes it kind of "officially endorsed", and no comment or phpdoc say anything about that either.

So maybe the we should go with the getAll() approach for now, and open a separate issue to move that class to a test folder somewhere ?

- ConfigEntityStorage would need to return count($this->configFactory->listAll()) != 0
That's not as bad as KV::getAll(), since this only load keys into memory. Could still be 100's of entries just to answer "is there at least one ?". Making that more efficient means adding a new method to ConfigFactoryInterface & Config\StorageInterface, though.

berdir’s picture

OK, but nothing really hints that it's a test-only-do-not-use-for-real
implementation :-).
It's not in a "test" directory or namespace, Drupal\Core\Entity\KeyValueStore
makes it kind of "officially endorsed", and no comment or phpdoc say anything
about that either.

So maybe the we should go with the getAll() approach for now, and open a
separate issue to move that class to a test folder somewhere ?

/me points to @timplunkett ;)

I know and I'd be happy to do that.

berdir’s picture

StatusFileSize
new1019 bytes
new3.66 KB

Ok, here's a patch with implementation for config and keyvalue. I also added a test, this also runs for key value storage.

plach’s picture

Status: Needs work » Needs review
plach’s picture

Issue tags: +entity storage

The last submitted patch, 16: has-data-2391829-16-test-only.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 16: has-data-2391829-16.patch, failed testing.

cilefen’s picture

Status: Needs work » Needs review
StatusFileSize
new0 bytes

reroll

cilefen’s picture

StatusFileSize
new3.68 KB

oops

The last submitted patch, 21: 2391829-21.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 22: 2391829-22.patch, failed testing.

cilefen’s picture

+++ b/core/modules/config/src/Tests/ConfigEntityTest.php
@@ -39,6 +39,10 @@ class ConfigEntityTest extends WebTestBase {
+
+    $storage = \Drupal::entityManager()->getStorage('config_test');
+    $this->assertFalse($storage->hasData());

I think this test is failing because the config_test module sets some configurations objects on install.

The last submitted patch, 22: 2391829-22.patch, failed testing.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new5 KB
new3.31 KB

#25 is correct, so we simply need to move those assertions to a test that doesn't install config_test entities by default. And, since KeyValueEntityStorage is not used as a test config storage anymore, we need to add a dedicated test for that as well.

amateescu’s picture

StatusFileSize
new1.52 KB
new6.13 KB

And to show why this is still a major bug, I've added a simple test that tries to see if uninstalling a module which provides an entity type that doesn't use the SQL content entity storage is possible.

This simulates a user navigating to the module uninstall page and being presented with a nice fatal error:

Error: Call to undefined method Drupal\Core\Entity\KeyValueStore\KeyValueContentEntityStorage::hasData()

The test-only patch is also the interdiff.

amateescu’s picture

Issue tags: +Triaged for D8 major current state

The last submitted patch, 32: 2391829-32-test-only.patch, failed testing. View results

berdir’s picture

Patch looks good to me, but not sure if adding a method to EntityStorageInterface now is a BC break, since there is no default implemtentation then it would break alternative entity storage implementations. So possibly we need a separate interface now, with a @todo to merge it into the base interface in 9.x?

berdir’s picture

double post because of 5xx error

amateescu’s picture

@Berdir, isn't \Drupal\Core\Entity\EntityStorageBase the default implementation? We could move \Drupal\Core\Entity\ContentEntityStorageBase::hasData() to EntityStorageBase because that implementation is generic and it doesn't depend on anything else but the entity query, which is initialized in EntityStorageBase anyway.

berdir’s picture

Status: Needs review » Needs work

Yes, that makes sense, lets do that :)

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new7.53 KB
new1.4 KB

Done that ;)

berdir’s picture

Status: Needs review » Reviewed & tested by the community

Great, I think this is OK now for BC. We might still want to do a short change record?

amateescu’s picture

Sure thing, here it is: https://www.drupal.org/node/2907014

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.5.x and cherry-picked to 8.4.x. Thanks! Publishing the change record.

  • catch committed 7e427d5 on 8.5.x
    Issue #2391829 by amateescu, cilefen, Berdir, yched, fago:...

  • catch committed c8566b0 on 8.4.x
    Issue #2391829 by amateescu, cilefen, Berdir, yched, fago:...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.