Problem/Motivation
We currently use an entity key "status" for entity types such as "node", but the field has to be manually added in the entity type's base field definitions.
Proposed resolution
Remove "Status" field from the entity type base field definition when it has the "status" entity key, and use a generic definition in ContentEntityBase.
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #40 | interdiff.txt | 608 bytes | timmillwood |
| #40 | 2810381-40.patch | 8.69 KB | timmillwood |
Comments
Comment #2
timmillwoodInitial patch.
Comment #3
timmillwoodComment #4
timmillwoodAdding comment entity type.
Comment #6
timmillwoodok, I guess comment module needs an upgrade path after adding status as an entity key.
Comment #7
timmillwoodAdding an upgrade path for comment module.
Comment #8
timmillwoodComment #10
timmillwoodComment #12
timmillwoodFixing REST test.
Comment #13
amateescu commentedNote that we also have #2009958: Introduce EntityStatusInterface to standardize how entities can be disabled which is trying to move the status concept to an interface.
Comment #14
timmillwoodI think it'd be awesome to have an EntityStatusInterface, and I hope everyone agrees that this is a separate issue and could be done independently. Also this issue is specifically looking at status being published/unpublished, and not in the other way users, files, config entities, etc use a status field. Therefore entity types with a status entity key will get a field for published/unpublished, and could in fact have another status field for another purpose.
Comment #15
dawehnerIs there a reason this doesn't yet add a
status() method or so?Comment #16
timmillwood@dawehner - I was looking at keeping this issue as a foundation, simply moving the base field and making use of the key. I guess #2009958: Introduce EntityStatusInterface to standardize how entities can be disabled would be a good place to add
status().Comment #17
dawehnerSorry, my comment in #15 haven't seen #13 and #14 yet. I agree this makes sense.
Comment #18
timmillwood#2811667: Introduce EntityPublishedInterface for content entities is adding the interface for this.
Comment #19
plachI think we should try to limit the amount of business logic we bake into
ContentEntityBaseto the very minimum, otherwise we are kind of limiting its purpose to very specific use cases, which is not what we want for a base class, I think. Or at very least we are adding code that won't be used in many cases.It would make more sense to me to implement this as a trait that can be individually used by entity types implementing the
EntityPublishedInterface.Comment #20
timmillwood@plach - I'm not sure if I agree, or not.
We currently have a couple of similar traits "EntityChangedTrait" and "RevisionLogEntityTrait", only "RevisionLogEntityTrait" defines base fields. So following that example it could work, however the part that makes it feel not right to me is the entity key.
In Node status is an entity key, and this patch makes status an entity key in Comment too. All base fields currently defined within ContentEntityBase are all entity keys, therefore I like the idea of carrying on putting entity key fields in ContentEntityBase.
I'd like to get to the point that the majority of entity types have a published/unpublished state and therefore use the status entity key and field.
Comment #21
timmillwoodAfter speaking to dixon_ and amateescu I think having the status field in ContentEntityBase is the best option. Mainly because it's linked to an entity key so the field is auto added to any entity type with that key, where as a trait would need to be manually added.
Comment #22
plachEntity keys are meant to provide a way to map generic business logic to the fields required to implement it without "crippling" subclasses with reserved field names. So the fact that
statusis an entity key does not automatically imply it should be part of content entity base, it's just a pointer that it probably makes sense as being used by a base class. IMHO thenodeentity type is currently abusing thestatusentity key (and it's doing it wrong, btw: http://cgit.drupalcode.org/drupal/tree/core/modules/node/src/Entity/Node...).What feels wrong to me here is the following bit: the majority of entity types. If we do this it must be something that we feel is an inherent and obvious part of the generic content entity business logic. However there are core entity types for which the concept of publishing simply makes no sense, at least according to their current implementation. In fact they may have a concept of status that does not map directly to the concept of publishing. If we add the status field to CEB, then the next natural step is making it implement
EntityPublishedInterface, which may quickly lead to a very confusing API in this case. TheUserandFileentity types are a clear example of this scenario.These are a few where a publishing status would make sense to me mostly when thinking to the "full site revisioning/previewing" problem space:
TermMenuLinkContentAnd a few more where I'm not even sure about that:
ContentModerationStateFeedItemMessageShortcutSo it seems to me that the end goal of this issue could use a broader discussion, unless it already happened and I missed it.
Comment #23
plachI forgot: if a trait is deemed a suboptimal DX, it would make a lot more sense to me from an architectural POV to have a base class extending
RevisionableContentEntityBasethat all entity types for which it clearly makes sense the publishing concept can inherit from, e.g.EditorialContentEntityBase.Comment #24
catchEither the trait or the additional base class in #23 makes sense to me. This looks like a 50/50 use case given the list of entities in #22.
Comment #25
timmillwoodA trait makes sense for many reasons, but the main thing that sways be away from it and towards putting this in ContentEntityBase is the entity key.
My main hit list for adding 'status' to are BlockContent, Term, and MenuLinkContent, this fix it to work properly in Node and Comment. In core (and in contrib) there are already fields called 'status', therefore we need to allow for alternative field names than 'status', thus I feel the entity key is needed. However we could equally do it without the entity key, as long as other entity types use the EntityPublishedInterface it doesn't really matter what they call the field
setPublished()andisPublished()will always work the same.Why does node even have status as an entity key?
Comment #26
timmillwoodHere's an initial look at how it could work as a trait.
Comment #28
timmillwoodNote to self: pay attention when naming interdiffs.
Comment #30
timmillwoodalso helps if I add the trait to the patch.
Comment #32
plachThanks for trying the trait approach!
This t() call is inconsistent with the previous line.
We can use
$entity_type->getKey('status')here to get the field name.And here we can assume the existence of a
::getEntityKey()method. We may even declare it as abstract if we want to be super strict.Comment #33
timmillwood@plach - as part of the patch in #30 I removed the entity keys. It doesn't seem like status really needs to be one, and as we're now adding it as a trait there is less chance of accidental field name clashes.
Comment #34
plachRemoving the
statuskey sounds like an API/BC break to me. Why can't we just keep it since it's not hard to do?Comment #35
timmillwoodThis should fix all the test fails in #30.
It also keeps the status entity key in Node, and doesn't add one to Comment.
Comment #36
plachThanks, almost there!
Missing PHP docs.
We could save a few method calls if we did something like this:
Since we have a default value, I guess
::getEntityKey()will return NULL only if the entity key is not defined.Same goes for the setter.
Are these changes required?
Comment #37
plachCan we always use
TranslatableMarkuphere?Comment #38
timmillwood#36 1. Done
#36 2. Done
#36 3. Yes, these changes are required, otherwise it fails the Rest module UpdateTest.
#37 Done
Comment #39
plachWon't this break if the entity type has a
statuskey different fromstatusand the field value is0orFALSE?Shouldn't we useisset()to ensure we have aNULLvalue?Comment #40
timmillwoodI guess.
Comment #41
plachLooks good, thanks
Comment #42
timmillwoodComment #43
amateescu commentedThis references #2811667: Introduce EntityPublishedInterface for content entities, which has been closed as a duplicate of #2789315: Create EntityPublishedInterface and use for Node and Comment so we might want to update the reference to point to the active issue.
Comment #45
catchThis looks really tidy to me. Committed/pushed to 8.3.x, thanks!
Comment #47
hchonovThe update function for the comment entity type introduced here is not really updating the cached field storage definition. A followup for this - #2841614: comment_update_8300 is not updating correctly the field storage definition of the status field.
Comment #48
timmillwood#2846830: Add changelog for Drupal 8.3.0