Problem/Motivation
In #2957425: Allow the inline creation of non-reusable Custom Blocks in the layout builder we are having to get all the revision IDs for entity that we just know is revisionable.
We have generic code
$entity_type = $this->entityTypeManager->getDefinition($entity->getEntityTypeId());
if ($revision_table = $entity_type->getRevisionTable()) {
$query = $this->database->select($revision_table);
$query->condition($entity_type->getKey('id'), $entity->id());
$query->fields($revision_table, [$entity_type->getKey('revision')]);
$query->orderBy($entity_type->getKey('revision'), 'DESC');
return $query->execute()->fetchCol();
}
return [];
Proposed resolution
See Comment #43: we decided to deprecate this function instead of moving it to the parent class. That comment updated the issue title but not the issue summary. (It did add the tag for an issue summary update.)
See Comment #46: the deprecation was done as part of #3396062: Deprecate most methods on NodeStorage.
That should work for any revisionable entity. Can we move NodeStorageInterface::revisionIds on up to RevisionableStorageInterface and then implement this generic logic in \Drupal\Core\Entity\Sql\SqlContentEntityStorage?
Remaining tasks
Is this ok with BC policy.
Write patch
Tests
User interface changes
None
API changes
RevisionableStorageInterface would have ::revisionIds()
Data model changes
NOne
| Comment | File | Size | Author |
|---|---|---|---|
| #26 | interdiff_25-26.txt | 2.93 KB | capysara |
| #26 | 2986027-26.patch | 5.19 KB | capysara |
| #25 | reroll_diff_11-25.txt | 2.92 KB | ravi.shankar |
| #25 | 2986027-25.patch | 5.31 KB | ravi.shankar |
| #11 | interdiff-9-11.txt | 1.06 KB | tedbow |
Issue fork drupal-2986027
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 2986027-deprecate-nodestorageinterface-revisionids
compare
Comments
Comment #2
tedbowHere is initial patch. I noticed that
NodeStorageInterface::revisionIds()hard codes the order so I added this as an option argument.Comment #4
tedbowFixed ContentEntityNullStorage
Comment #6
tedbowFixed KeyValueContentEntityStorage
Comment #8
joachim commented@return docs don't match the possible NULL return.
Would an empty array here not be better DX, so you always have something iterable?
Comment #9
tedbow@joachim good catch. changed to return [].
Comment #10
gabesulliceThis is will help JSON API achieve solid support for the
content_moderationmodule.Shouldn't this also be
[]?Comment #11
tedbow#10 yep fixed and also in ContentEntityNullStorage
Bonus!
Comment #12
joachim commentedOne last thing, I hope:
We've lost the bit about them being in ascending order.
We need to keep that aspect to preserve BC.
So this should read something like:
> An array of the entity revision IDs, in ascending order.
Comment #13
longwaveThis isn't strictly true as the $order argument defines this, but why do we even need the $order argument anyway? Is there really a use case for returning them in reverse order? The caller can just use
array_reverse(), can't they?Comment #14
joachim commented> This isn't strictly true as the $order argument defines this
Oh DUH you're right. So the Node docs are actually incorrect, and the new docs are better.
> but why do we even need the $order argument anyway? Is there really a use case for returning them in reverse order? The caller can just use array_reverse(), can't they?
Also a good point, but we need to keep it for BC and deprecating it should be a separate issue.
Though isn't it quicker to order in SQL than PHP?
Based on that I'm going to say this is RTBC.
Comment #16
longwaveThe $order argument is new in this patch. NodeStorageInterface::revisionIds() always returns in ascending order (which is why the previous comment exists). It was added in #2 but with no real reason given, but to me this is technically a new feature and out of scope here, at least until we have a use for it.
Comment #23
capysara commentedI'm looking to get revision ids from entities other than nodes. Is there still interest in this patch? If so, it would have to be re-rolled and the comments in #16 need to be addressed.
To address #16, do we just need to remove the $order argument that was added? Or is it more complicated than that?
Comment #24
joachim commented> just need to remove the $order argument that was added
Yup.
And copy the bit from the node docs about the @return being in ascending order.
Comment #25
ravi.shankar commentedAdded reroll of patch #11 on Drupal 9.4.x.
Comment #26
capysara commentedThanks! That was fast on the re-roll! I updated the re-roll in #25 to remove the $order argument and add back in the docs about ascending order.
I tested this manually. For my use case, I created a custom views field that uses revisionIds to get the previous content moderation state for nodes, blocks, and media entities.
All 3 entity types worked as expected: I was able to use
revisionIdsto get a list of revision IDs for the block_content, media, and nodes.Comment #27
capysara commentedComment #28
joachim commentedLGTM.
Comment #29
catchSince this will be new code on the interface, could we add a return type hint?
Also looks like we still need some explicit test coverage here.
Comment #30
capysara commentedWhat do we need for "explicit test coverage"? Do we need another function like testPendingRevisions(), but for blocks (and/or other entity types?)? Or should testPending Revisions be more generic so it covers other revisionable entities?
Comment #31
catch@capysara there should be some existing test coverage of
SqlContentEntityStorageto add to,Drupal\KernelTests\Core\Entity\EntityRevisionsTestis probably a good place.Comment #32
berdirWhy do we need this method, can't this be done with an entity query?
Comment #33
tedbowreferencing the original issue.
@Berdir good point. I am not sure. Here is how did this without the public
function
for what is it is worth I made this issue in the middle of #2957425: Allow the inline creation of non-reusable Custom Blocks in the layout builder but by the end we didn't actually end up needing it
but I would say if we are going to leave `\Drupal\node\NodeStorage::revisionIds` it makes it much more sense to move it to
\Drupal\Core\Entity\Sql\SqlContentEntityStorage::revisionIds()because there shouldn't be anything special for nodes in this case. Other if we are not going to move it I think it would make sense to deprecate and remove\Drupal\node\NodeStorage::revisionIds()Comment #34
berdirYes, exactly, like that. Although I remember some issues with that in entity reference revisions.
But the revision ui issue also doesn't seem to need this.
Deprecating without direct replacement is definitely an option. This method likely predates entity query revision support
Comment #35
berdirRight, the issue I had was this: #2766135: EntityQuery with condition on the revision field leads to wrong results, this has been fixed. I'm sure there are other issues, one of the most important ones is entity query performance, but I think for this, using an entity query should be OK. I'd suggest we verify that by deprecating the method and replacing all calls to it with such an entity query.
Comment #36
tedbowCounter argument to removing the current method....
It looks like people do call it https://git.drupalcode.org/search?group_id=2&page=2&repository_ref=&scop...
and in some of the results you also see other Entity storage classes that are writting their own versions that they would not need if actually moved it
https://git.drupalcode.org/project/open_badges/-/blob/8.x-1.x/modules/is...
https://git.drupalcode.org/project/carousel_block/-/blob/8.x-1.x/src/Car...
many other examples
Comment #37
berdirThe search doesn't seem to work too well (getting a lot of endpoint requested too many times errors).
But almost all of those seem to be 1:1 copies of NodeStorage, and many callers (http://grep.xnddx.ru/search?text=-%3ErevisionIds%28) are 1:1 copies of the revision page controller.
And all custom methods won't be affected by deprecating the node storage method.
Comment #38
berdirI'd say if those results prove one thing, then that it would be good to get #2350939: Implement a generic revision UI into core, with a generic revision UI, most of that code wouldn't need to exist at all.
Comment #39
capysara commentedFWIW, I'm using this patch to replace some code like this, which (I believe) was borrowed from Media revisions UI.
I would be happy to see this patch move forward (and was planning to try to write some tests). I would also love to see #2350939: Implement a generic revision UI get into core! :)
Thoughts on the path forward for this one?
Comment #43
acbramley commentedCame up in slack and the advice from @berdir was to deprecate instead. I agree as it's minimal code to get a list of revision IDs using an entity query.
Comment #46
benjifisherThis issue was fixed as part of #3396062: Deprecate most methods on NodeStorage. The change record is https://www.drupal.org/node/3519187.