Closed (fixed)
Project:
Drupal core
Version:
8.1.x-dev
Component:
entity system
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
11 Feb 2016 at 10:19 UTC
Updated:
4 May 2016 at 08:24 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
dawehnerHere is a quick start.
Comment #3
dawehnerSome intermediate work
Comment #5
wim leersIf
entityis part of it the interface name, shouldn't this extendEntityInterface?Otherwise (if it's generic), shouldn't this be called
RevisionableInterface?Then again, we already have
\Drupal\Core\Entity\RevisionableInterface. So, should this then beRevisionableWithMetadataInterface extends RevisionableInterface?Comment #6
dawehnerWell, we wanted to avoid to create the crazy hierarchy of interfaces. To be clear, this is not another type of revisionable entity, it is just one with additional features.
RevisionableWithMetadataInterfaceWell, does this name tells you anything about what is in there? The interface name we have chosen, has IMHO some more semantic in there.Comment #7
wim leersThat is exactly like saying
NewInterface extends ExistingInterface.Comment #8
dawehnerIMHO the distinction is vertical vs. horizontal extendibility.
Comment #9
dawehnerBut sure, let's ask others.
Comment #10
berdirThis is consistent with EntityOwnerInterface, EntityChangedInterface and others. 1+ to not extend. extends EntityInterface actually wouldn't help much since most are content entities
Comment #11
wim leersI did not ask for
extends EntityInterface(which I agree would not make much sense). I am asking forextends RevisionableInterface.Comment #12
wim leersI'm asking for that because the interface being introduced here makes no sense on its own. It only makes sense in combination with the already existing
RevisionableInterface.How does
EntityRevisionLogInterfacemake sense without agetRevisionId()method (necessary to load a revision) or asetNewRevision()method (necessary to call before calling the newsetRevisionLogMessage()orsetRevisionUserId()can make sense)?Comment #13
dawehner@Wim Leers
You asked for both ...
Extended also the test coverage
Comment #14
wim leersSorry for not being more clear. I think "entity" shouldn't be part of the name. For the same reasons you and Berdir state: because it's not extending
EntityInterface. BecauseRevisionableInterfaceis not extendingEntityInterface. Because none of this is entity-specific.Comment #16
dawehnerOh yeah, let's do that. In the meantime, let's also fix the test coverage.
Comment #17
dawehnerComment #18
wim leersSuper nit: don't we usually have a newline between these?
Comment doesn't really make sense.
These aren't really about logging, right?
Only this one is.
I wonder if
RichRevisionableInterfaceor something like that is better. But that feels even more weird. So I think "log" is ok. Would be great if others could chime in on that.Super nit: two newlines, should be one.
Comment #19
wim leersHm, on second thought…
What if we split this off into
RevisionOwnerInterface extends RevisionsableInterface.(revision-level interface to match the entity-level
\Drupal\user\EntityOwnerInterface)Then you have two interfaces: one for a revision owner, and one for a log message + creation time. It feels like that's a step in the right direction.
Finally:
"creation"
but
NodeInterfaceuses "created".Comment #20
dawehnerWe talked about that before. We wanted to avoid to go back to crazy granular interfaces. Why would you ever care about log messages, when you don't care who created them?
So do you really like 'createdTime'. IMHO node module should not be seen necessarily as good example.
Comment #21
wim leersGood points.
But doesn't that mean that all of this really should be merged into
RevisionableInterface? I understand that's not possible for BC reasons. But if that's where we want to go eventually, then the docs should say that, and should document that as a@todofor Drupal 9. If there are good reasons for them to be separate, we should document that rationale on the interface.That's all I care about: something that makes sense in the larger set of interfaces, and that has documentation explaining its rationale for posterity.
Comment #22
dawehnerWell, I disagree that every revision needs to have this additional information. When you are a pure API entity, you might really not care about those bits.
Comment #23
wim leersThat's fine. Let's just document that rationale on this new interface. That's all I'm saying :)
Comment #24
dawehnerSure, volunteers should step forward.
Comment #25
amateescu commentedThis new content entity base class is not very helpful when you want to add revision log capability to an existing entity class.
How about providing a trait instead?
Comment #26
amateescu commentedSorry, didn't mean to change the status.
Comment #27
bojanz commented@amateescu
You extend the new base class, instead of adding the trait? You are changing your class either way.
The reason why we went with a base class is because "revisionable" is one of those fundamental behaviors that really deserves one, instead of multiple traits.
Comment #28
amateescu commentedMy point was that you can not extend both the new base class *and* the original entity class :)
Edit: for example when the original entity class contains a lot of specific logic/code that you don't want to duplicate.
Comment #29
dawehner@amateescu Which original entity class beside
ContentEntityBase?Comment #30
dawehnerI mean sure, we could also provide both the base class and the trait.
Comment #31
bojanz commentedI still don't see the use case. You extended ContentEntityBase before, now you extend RevisionableContentEntityBase.
Swapping an existing entity type's class to add additional methods is probably not a use case we need to concern ourselves with?
Comment #32
dawehnerYeah this is basically my point. If this is hard, I don't see a problem with that. Well @amateescu disagrees and will provide a patch.
Comment #33
amateescu commentedThat's exactly what Multiversion has to do, swap all content entity classes in order to add extra revision functionality, so my opinion is that core can and should be a bit more helpful in this regard.
Here's what I had in mind.
Comment #34
dawehnerI still think this is a wrong workaround, but sure people can disagree. It seems to be that we are trying to make the normal case harder and the special case easier. Not sure this is the right strategy.
Comment #35
amateescu commentedHow is the normal case harder? IMO both cases are covered by default with that approach.
Comment #36
fagoI'd agree with amateescu - adding revision support to some other module seems to be something very realistic. The trait needs to document it's "implementing" the interface though and cannot use @inheritdoc but must point
to the interface methods the "old-way" with a FQDN method reference.
I wanted to point you to an example, but I did not find any. There were all removed by #2502621: Replace implement notes with inheritdoc tag - but that was wrong imo, so I re-opened that issue.
Comment #37
fagoWe can have both. Just make a base class which uses the trait.
Edit: i.e, add RevisionableContentEntityBase that has the trait + just adds the field definitions in via a regular method override. That's not worse than having it directly in the base class imo.
Comment #38
amateescu commentedNote that the patch in #33 still has the new RevisionableContentEntityBase class, but it's empty and just uses the trait. However, overriding baseFieldDefinitions() in this class is not needed if we keep the code added to ContentEntityBase::baseFieldDefinitions().
Comment #39
dawehnerSure, if we think this code in ContentEntityBase itself is fine, let's go with it. I'm just a bit uncomfortable with that kind of code.
Comment #41
amateescu commentedI was also wondering about these two. Since our base field definitions include revision_created and revision_user by default, is there really a way for these methods to return NULL?
If so, then the code in the trait has to be adjusted in that regard and check for the existence of the fields before trying to get their value.
Also, should it rather be "revision owner" instead of "revision user", in order to be consistent with EntityOwnerInterface?
Comment #42
dawehnerWell, originally the point was that we have the interface but don't require people to implement every method. Regarding revision owner vs. user, at least in the terminology of core having several different owners of an entity IMHO doesn't make sense. It is just the user who created the revision, IMHO more explicit than owner, because owner has some domain meaning in other areas, like locking of entities.
Comment #43
bojanz commentedThis is a hack.
Let our new base class call the trait method, instead of doing black magic.
Comment #44
dawehnerWorking on that.
Comment #45
dawehnerWell, it seemed to be that this hack even never worked.
Comment #46
amateescu commentedIt is working, I tested it manually with the Term entity class.
I don't see how that would work, every method from an interface needs to have an implementation. And the current implementation of
getRevisionUser()andgetRevisionCreationTime()would not return NULL but throw an exception if those fields are not there.I disagree :) Any other opinions?
Comment #47
amateescu commentedDiscussed with @bojanz and @dawehner on IRC and I'll drop my argument for the "hack". In this regard, #45 is fine, but we still need to fix #41..
Comment #48
dawehnerI care about the interface, the rest is sort of an implementation detail for me. @amateescu please take it over
Comment #49
amateescu commentedOk then, fixed those return types and the docs for the trait as well. The patch looks ready to me.
Comment #50
dawehnerThank you
Comment #52
catchCommitted/pushed to 8.2.x and cherry-picked to 8.1.x. Thanks!
Comment #55
amateescu commentedShould we make Node and BlockContent implement the new interface? Maybe in #2248983: Define the revision metadata base fields in the entity annotation in order for the storage to create them only in the revision table.
Comment #56
wim leers#55: Closely related: #2678492: Convert the node revision converter to the generic entity one.
Comment #57
catchComment #58
bojanz commentedShould we rename the issue to clarify that we introduced an entity base class as well (RevisionableContentEntityBase)? That's the important part for most people.
Comment #59
dawehnerfeel free to do that.
Comment #61
xjmThis issue is missing a change record. (We should add change records for noteworthy API additions.)
Comment #62
dawehnerI'll write one for all of the 4 entity related ones: https://www.drupal.org/node/2709511
Comment #63
dawehnerAdded stuff to the change record. Feel free to improve it.