Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Part of #1939994: Complete conversion of nodes to the new Entity Field API.
Re-upload of the latest patch, let's see if this still applies.
Comment | File | Size | Author |
---|---|---|---|
#39 | node-methods-2049039-39.patch | 174.77 KB | Berdir |
#39 | node-methods-2049039-39-pseudo-interdiff.txt | 34.45 KB | Berdir |
#26 | node-methods-2049039-26.patch | 172.74 KB | Berdir |
#26 | node-methods-2049039-26-interdiff.txt | 1.61 KB | Berdir |
#24 | node-methods-2049039-24.patch | 172.65 KB | Berdir |
Comments
Comment #1
fagoAs this was RTBC in #1939994: Complete conversion of nodes to the new Entity Field API setting to RTBC here again. This is straight conversion and ready to go.
(+1 on separating the search/replace things from other changes, so those are easier to review)
Comment #2
alexpottNeeds a reroll...
Comment #3
BerdirYeah, assumed as much, just haven't found the time yet to do so ;)
Here's a re-roll. Quite some conflicts, mostly due to user methods. Also had some fun rebasing my commits and found some more trivial method conversion to get in here. Not much luck in a useful interdiff, though, so here's just a raw diff between the two branches, in case you really want to know ;)
Comment #4
BerdirWhen looking at the remaining test failures, I found some cases that weren't converted yet, some of them new.
Comment #6
BerdirUps, that one got removed too early.
Comment #7
effulgentsia CreditAttribution: effulgentsia commentedI haven't reviewed the initial patch, but that was already RTBC'd in #1. The interdiffs since then look good, so back to RTBC.
Comment #8
effulgentsia CreditAttribution: effulgentsia commentedAlso, at this point in the D8 cycle, I think subitems of critical metas should also be critical (with the possible exception of routing conversions until we get those down to a smaller amount).
Comment #9
Berdir#6: node-methods-2049039-6.patch queued for re-testing.
Comment #11
BerdirRe-roll. Snippet in TestControllers that's not necessary anymore removed, otherwise identical.
Comment #13
Berdir#11: node-methods-2049039-11.patch queued for re-testing.
Comment #14
Berdir#11: node-methods-2049039-11.patch queued for re-testing.
Comment #16
fago#11: node-methods-2049039-11.patch queued for re-testing.
Comment #17
amateescu CreditAttribution: amateescu commentedWent through the patch line by line and could only find these small nitpicks. Nice job! :)
These two could use a small space there.
Didn't we remove the BC decorator for users a few hours ago?
I think this needs to be setChangedTime().
Comment needs to be rewrapped.
One of these two lines is lying. My bet is on the first one since we just changed loaders to return NULL instead of FALSE.
Same problem, but reverted :)
setChangedTime()?
Missing space.
Needs rewrapping.
Same here.
Afaik, $user->label() is not the same thing as user_format_name()..
Comment #18
BerdirThanks, great review!
- Updated the forum hooks, also found some things in there that weren't replaced yet that I missed because it's $entity and not $node. Replaced the entity type check with an interface check, as that gives me method autocompletion automatically within
- Removed the getBCEntity() calls.
- There is no setter for changed, but that's not supposed to be change, it's forcefully set by the storage controller. Those tests check that behavior.
- Fixed @return
- Rewritten/wrapped comments
- As discussed label() is the same as getUsername(), but a getUsername() makes more sense here.
Comment #20
BerdirOk, that NodeInterface check doesn't work well, especially not in the full conversion as the field system internally still uses the BC decorator and when removing the NodeBCDecorator, that no longer implements NodeInterface. And in this case, they were additionally broken because of my exceptionally stupid mistake, see mistake.
The comment fails are... more interesting, I have no idea how that doesn't fail atm.
Comment #21
chx CreditAttribution: chx commentedLooks good. I raised the weirdness of getAuthorId() but that's a performance shortcut to avoid loading a typeddata object and then getRevisionId() (vs id() and bundle()) but that is not introduced in here so I ran out of complaints
Comment #22
webchickYayyyy! :)
->bundle() makes sense for generic entity code, but we know we're dealing with nodes here. This is removing important semantic information and introducing a DX regression.
We should add a wrapper type() method on NodeInterface that calls bundle() to keep the code understandable.
Yeah, no. We're not introducing a variable "bundle" and exposing that to themers. :P This needs to be "type" as well.
Same deal here. This is called a "title" in the user interface and elsewhere. We need a title() wrapper method on NodeInterface and call it here.
Why is that randomly cast to an int?
This doesn't seem right; I thought we were removing calls to procedural functions like user_load()?
Also, this should be using the DRUPAL_ANONYMOUS_USER constant.
Comment #23
xjmTo clarify, this couples the
Node
class to the whole ofuser.module
.Comment #24
BerdirYes!. Note that this is not directly tied to this issue, it was already possible since we introduced the NodeBCDecorator. I only changed those where I touched the code anyway and could use the type hinting of the methods. We should open a follow-up issues to replace all remaining EntityInterface type hints and @param documentations. There are also quite a few that still use the Node class, often with an old namespace and without leading \.
As discussed with @xjm, I will introduce a getTitle() and getType() method, that is consistent with the setters that we already have. Not yet part of this patch, this is just a re-roll.
The int cast is because in the database query we need an integer 0/1, not a boolean, db queries explode when you try to do that. It's necessary now because isSticky(), as an is*() method, returns a boolean.
About the user_load(), I'm trying figure out where exactly is breaking, so this patch reverts that change, maybe we can fix it somehow down in typed data. The only alternative to user_load() would be a static call to \Drupal::entityManager(). That's not much better.
Comment #26
BerdirNice, the new tests there caught two existing bugs in the patch.
getType() is a problem :( We already have getType() on entities, derived from the TypedDataInterface, it returns something like entity:node:article. We wanted to remove those generic methods and TypedDataInterface, but that didn't happen :(
So we can't use that, which means that have to prefix it somehow, like getNodeType(), which would mean that the template variable would be node.nodetype. or getContentType(). Or we rename getType() in TypedDataInterface to getDataType() if we can't get rid of it completely.
Can we push this to a follow-up somehow?
Comment #27
xjmDiscussed with @Berdir in IRC. I think not subjecting themers to the word "bundle" is important to do in this issue so that we're not causing a TX regression. So, my recommendation is to use the method name
getContentType()
, which would yieldnode.contenttype
in the theme layer. I think that's a better method name anyway. They're not just "types"; they're "content types".@Berdir pointed out that we usually use
node_type
rather thancontent_type
in the codebase, so I'd also be okay withgetNodeType()
/node.nodetype
.I also still want to see the death of
TypedDataInterface
, and I think at least renaming that method togetDataType()
is potentially an allowable API change given that it's not a BC break to D7 and it solves some serious DX ick. We'd already considered that some of the typed sanity API changes might not land until after July 1. So I'd suggest filing/linking a followup for that (though we'll want a committer to weigh in on the API change).Comment #28
xjmRelated issue: #2056721: Remove TypedDataInterface::getType()
Comment #29
xjmLet's add an inline comment explaining that bit, then. And then we just need the method wrappers... I think I prefer the more explicit
getNodeType()
even if #2056721: Remove TypedDataInterface::getType() goes in, because it's more explicit and readable, especially with as vague a word as "type".Comment #30
xjmOh, and the followup bits are taken care of now.
Comment #31
msonnabaum CreditAttribution: msonnabaum commentedTypedData needs the rename, not Node. THis is a very clear example of a parent class getting in the way of the child, which is always the parent's fault. TypeData should not have methods as generic as "getType".
And while getNodeType is more explicit, it isn't explicit in a useful way. $node->getNodeType() is just silly.
Comment #32
xjmI disagree. There's still ambiguity between node types (page) and entity types (node), and when we can do such a simple thing to alleviate that confusion, why wouldn't we?
Comment #33
msonnabaum CreditAttribution: msonnabaum commentedThere's no ambiguity in the code. "type" has a very clear meaning in the domain of node. You shouldnt have to keep a class' inheritance chain in mind to understand it's interface.
Comment #34
xjmI'm more concerned about the terminology we use in actual real verbal conversations with actual real people trying to learn D8, and "node type" is the noun. There is a
NodeTypeInterface
and that's the objectgetNodeType()
should return.@msonnabaum and I have agreed to disagree, though, so I'll let that be my last remark on the subject. :)
Comment #35
webchickI agree with Mark, sorry. $node->getType() is just fine, and we should fixed TypedData API to quit being a jerk with its over-ambiguous names.
Comment #36
xjmIf that is the decision, that would make #2056721: Remove TypedDataInterface::getType() a soft blocker for this issue rather than just a good idea, so I've bumped its priority.
Comment #37
effulgentsia CreditAttribution: effulgentsia commentedFrom #33:
From #35:
I just want to point out that there's an implicit bias and an implicit assumption in this line of thinking.
The bias is that "the domain of the node" is the more important domain, presumably because it is the most specific. Within the domain of "entity",
$entity->getType()
(returning 'node', not 'article') would be equally sensible, but we made EntityInterface call that methodentityType()
, in order to retain clarity when working with subclasses. For the same reason, so long as we have a TypedDataInterface, I agree with changing its getType() to getDataType() (#2056721-14: Remove TypedDataInterface::getType()).The assumption is that nodes won't be subclassed any further. Which is true in D8 core, and possibly true for the duration of D8 contrib. However, suppose in D9, we do support further subclassing in some meaningful way. For example, maybe on a DrupalCon website, we want "Session" to be a node type, and then subclass that further into "Presentation", "Discussion", and "Lab". Would we then still consider it just fine for
$session->getType()
to return the node type, 'session', or would we then want to change NodeInterface::getType() to NodeInterface::getNodeType()?So, back to #33:
IMO, based on the above, that's actually an argument for calling it getNodeType(). But, I'm fine with calling it getType() in D8, since we actually *do* have the inheritance chain in mind, and therefore, know that node types are the end of that chain.
Comment #38
msonnabaum CreditAttribution: msonnabaum commentedI apologize for continuing this digression, but I feel it's necessary to clarify my thoughts on this.
Specific isn't how I would put it. It's about root-level concepts.
This is because Entity's role is that of a framework superclass. It's job is to provide shared functionality through inheritance, because that is currently our primary method of code sharing. A framework superclass has the responsibility to provide this while also staying out of the way of the subclass, because that subclass will act as the root of it's own conceptual hierarchy.
There are essentially two types of inheritance:
1. Code sharing
2. Specialization
Entities are 1. Node is not a specialization of Entity, it is simply an implementation of one (we didn't name it NodeEntity for a reason). If we treat Entities like 2, we're polluting our domain with implementation details. We have a tendency to do that (Block plugins), but we should try to fight it, because it's a big part of what makes Drupal so difficult to learn.
If there was a reason to subclass Node, it would likely be 2, where your specialization of Node could be used polymorphically wherever any code was working with Nodes. The name of a class like this would contain Node, and a prefix or suffix that communicated how it different.
Having another root hierarchy based on Node makes no sense. Nodes are a thing you can make new implementations of in a UI, and then specialize further using fields. If you want to create a new root hierarchy in code, you make a new entity type. If there's code you want to share with Node that you dont get from Entity, then we just found a new abstraction, which is a totally separate topic.
We have to be able to make these distinctions if we ever hope to have a comprehensible data model.
Comment #39
BerdirOk.
This ignores the fact that there's still a getType() method on the entity base class and re-defines/overrides it. Also adds a getTitle().
Used those two methods everywhere where changed calls in this patch, ignored existing code. No useful interdiff, just a raw diff between the last two patches.
Comment #40
Berdir#39: node-methods-2049039-39.patch queued for re-testing.
Comment #41
BerdirWent through this again, the blocker is in, I think this is ready, any final reviews? Strongly recommended to use git diff and --color-words for reviewing this.
Comment #43
Berdir#39: node-methods-2049039-39.patch queued for re-testing.
Comment #44
msonnabaum CreditAttribution: msonnabaum commentedLooks great to me.
Comment #45
Dries CreditAttribution: Dries commentedGreat API clean-up. Code looked perfect. Committed to 8.x.
Comment #47
BerdirRemoving sprint tag.