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.
Problem/Motivation
As of https://docs.google.com/document/d/1BxgNvyIRcxYGzzA1DLkZ6A4-c8gGFixypNvP... we want to make clear which bits of the URL generation
machinery should be used.
Proposed resolution
* Add EntityInterface::buildUrl()::toUrl() and EntityInterface::buildLink()::toLink() and mark urlInfo(), url() and link() as deprecated
Remaining tasks
User interface changes
API changes
Additions:
- EntityInterface::toUrl() and a default implementation in Entity::toUrl()
- EntityInterface::toLink() and a default implementation in Entity::toLink()
Changes:
- EntityInterface::url() marked as deprecated for removal in 9.0.0
- EntityInterface::urlInfo() marked as deprecated for removal in 9.0.0
- EntityInterface::link() marked as deprecated for removal in 9.0.0
Data model changes
Justification for putting this in 8.0.0:
- There are far too many ways to generate URLs and links in Drupal 8. If we have one or two recommended ways to do it then it makes learning and timely maintenance easier.
- The existing URL generation method in Entity is misnamed and the existing link generation method returns a string, not a Link. At this stage changing the return type of a commonly used method in EntityInterface would cause an unjustified level of disruption.
- At this stage the risk of a significant impact on core is small. There is some risk of an impact on contrib, but not much unless an contrib-provided API has a name clash and has a lot of other modules relying on it. This means it would be much riskier to make this change in 8.1.
Disruption
This is a change to an interface, which is a BC break.
- Adding methods to an interface does mean that all modules that implement the interface without inheriting the base class must provide their own implementations. In this case the methods are sufficiently similar to existing methods (that will be deprecated) that implementation of the extra methods is a trial change.
- Originally the method names were specified as buildUrl and buildLink. These were hard to prove to be low disruption because they were already in use elsewhere in core. These have been changed to toUrl and toLink after verifying that these names were not in use.
- In the particular case of EntityInterface almost all implementation of the interface is done by inheriting the Entity class, either directly or indirectly. This limits the potential for disruption from this change.
- A BC layer would probably add more risk than it would mitigate.
Comment | File | Size | Author |
---|---|---|---|
#45 | 2606398_43.patch | 19.33 KB | chx |
#42 | interdiff.txt | 5.08 KB | chx |
#42 | 2606398_42.patch | 18.87 KB | chx |
#34 | 2606398-34-create-entity-toUrl-and-toLink.patch | 19.08 KB | anil280988 |
#31 | interdiff-2606398-26-31.txt | 1.43 KB | anil280988 |
Comments
Comment #2
dawehnerComment #3
sdstyles CreditAttribution: sdstyles at FFW commentedComment #5
anil280988 CreditAttribution: anil280988 at Publicis Sapient for Publicis Sapient commentedResubmitting the Patch.
Comment #7
blackra CreditAttribution: blackra at SK Plus commentedThe summary of this issue doesn't appear to make sense. As written, this is guaranteed to break unit tests (and Drupal in general). My understanding of this issue based on the linked document is that the intent is to:
Unfortunately life isn't quite that simple. The method name buildUrl() is already used in places derived from Entity and EntityInterface, in particular:
This will also break anything that implements the EntityInterface API without inheriting Entity.
Given the current RC state of Drupal, this change is a major API headache.
I am removing the Novice tag, because this needs clarification on the correct course of action.
Comment #8
dawehnerMHH its a shame that things are always complex :(
Comment #9
blackra CreditAttribution: blackra at SK Plus commentedIt seems to me that we have a key decision to make:
My favoured option is 2 with a prefix of 'to'. I have checked this for API conflicts and it has none inside Drupal core.
Comment #10
tim.plunkettI want to tag this rc target triage, but I think we need to make the choice outlined in #9 first.
Comment #11
blackra CreditAttribution: blackra at SK Plus commentedUnless anybody objects I'm going to work on a patch based on toUrl() and toLink() whilst awaiting a decision on the correct approach. My reasoning is that toUrl() can be easily refactored by to buildUrl() with a global search and replace, but going from buildUrl() to some other xxxUrl() is a nightmare.
I have already discovered that ViewUI implements EntityInterface but without inheriting Entity...
A separate piece of work that can be done in advance of a decision is a patch to rename buildUrl() in the image module and its interface. This would allow us to locate the things that depend on that.
Comment #12
blackra CreditAttribution: blackra at SK Plus commentedHere is the first patch. This creates toUrl(), toLink(). deprecates the old methods and updates the test-cases.
The files affected are:
In order to convert these to buildUrl() and buildLink() we can just do a search and replace. We will also need to replace ToUrl and ToLink with BuildUrl and BuildLink in method names in the unit test files.
I'm setting the status to 'Needs Review', but this is only a partial solution.
Comment #13
blackra CreditAttribution: blackra at SK Plus commentedThis is the patch to rename the image module buildUrl() to buildDerivativeUrl() cf createDerivative().
It also renames buildUri() to buildDerivativeUri() on the grounds that the two methods form a pair.
I hope I got most of the places where this is called from, but I still expect testing to break...
Comment #14
dawehnerThe more I think about it, toLink and toUrl is actuall quite well suited for what its doing, I mean its not the worst.
Let's better mention directly in the @deprecated what should be used instead. It makes it a bit easier to get it converted.
IMHO we should do something else here. ToLink should create a Link object
Comment #16
blackra CreditAttribution: blackra at SK Plus commentedDawehner, I agree with your comments.
Here is a new patch for adding the toUrl() and toLink() methods. toLink() now returns a Link, and the comments have been updated accordingly.
I also caught a bug (that the patch introduced) in ViewUI.
Comment #17
blackra CreditAttribution: blackra at SK Plus commentedJust in case we need this information later, the testbot failures on #13 indicate the following core modules have a dependency on buildUrl() in the image module:
Comment #18
dawehnerThose changes are wrong and out of scope
Comment #19
blackra CreditAttribution: blackra at SK Plus commentedThose changes weren't spurious. The reason they were there was because those lines were confusing PHPStorm when I was trying to debug those unit tests and the things they were testing. I ended up turning them into normal comments rather than type hints. That was probably the wrong thing to do, but I didn't understand what was going on at the time.
Since then I have found some information to suggest that they are a mixture of PHPStorm syntax:
/** @var Type $variable */
and the PHP standard (also supported by PHPStorm):
/* @var $variable Type */
So what we had was type hints with syntax errors.
Now the tests and the code they are testing are working, I could change the comments back (especially the testUrlInfo() instance, since that method is essentially unchanged), but I think it could be argued that the ones in the xxxToUrl() methods are in scope and should be fixed to the PHP standard (which they aren't in either the original or the current patch).
Comment #20
XanoCan someone update the issue summary with an explanation of why we break BC less than two weeks before the 8.0.0 release?
Alternatively we should think about adding this to a new interface so we can introduce the new functionality without breaking anything.
Comment #21
tim.plunkettComment #22
dawehnerWe won't break BC at all
Comment #23
XanoThis is an addition to an existing interface, which means any classes implementing this interface must implement the newly added methods. As such this is a BC break. If this is an accepted break, this must be documented as such.
Comment #24
dawehnerYou are right, well, one possible solution is to expand the interface and let people allow to call it, if they call it..
Another opportunity is well, to discourage people to call link() via documentation and tell them to create a link using
new Link()
Comment #25
blackra CreditAttribution: blackra at SK Plus commentedI think Xano's point is about implementation of interfaces. If your class implements EntityInterface but does not inherit Entity, you suddenly have an abstract class. Fortunately, if you have any automated tests this will fail testing so it is easy to spot, either in core or in contrib. Once found, this is trivial to fix.
There is a more subtle issue, which is probably higher risk of impact. That is modules that override the Url generation methods to change their behaviour (ConfigEntityBase is an example that overrides the default values for $rel and the language option). However, since nothing will currently be calling the new methods this has limited scope for causing trouble.
That is the case for low impact. We now have to make the case for why this change is important.
My understanding is that the reason for doing this is that having lots of different ways of creating URLs and links makes code harder to maintain. If we find a problem we have to fix it in lots of places. Having one recommended way of doing things plus half a dozen deprecated ways means that if an issue comes up, everybody knows that the recommended method is our priority. Since the switch to the recommended method is, in almost all cases, trivial this is a big benefit at little cost.
I'm sure dawehner and tim.plunkett will have more to add on this subject.
An additional factor relating to make this change now is that if we wait until 8.1 the potential impact on contrib will be much bigger because by that time contrib modules will be relying on each others APIs being stable.
Obviously we need to get this information, and more, into the issue summary.
Thinking about it the, @deprecateds should not be "removed before 9.0.0," they should be "removed in 9.0.0 or later". I will update those comments in an updated patch. We can't remove them in 8.x.x without breaking lots of things.
Comment #26
blackra CreditAttribution: blackra at SK Plus commentedHere is the corrected patch.
Comment #27
blackra CreditAttribution: blackra at SK Plus commentedComment #28
blackra CreditAttribution: blackra at SK Plus commentedComment #29
XanoExactly. Automated tests will help, but that still means we're introducing a BC break right before 8.0.0. Even if that is accepted, we should document that in the issue summary here before this is RTBC'ed.
The original form is correct, and is to be interpreted as in 9.0.x, before 9.0.0.
Comment #30
blackra CreditAttribution: blackra at SK Plus commentedUpdated the summary to try to improve it.
On the wording of the @deprecated tags, I guess that illustrates a cultural difference between the language of somebody working on core who sees 8.0.0 (and therefore 9.0.0) as being culmination of 5 years of work, and the language understood by somebody who normally works in site building and contrib (me) where 8.0.0 is the start of Drupal 8 and 9.0.0 is the start of Drupal 9.
How about "removed in 9.0.x" as something that will mean the same for both sets of Drupallers?
Comment #31
anil280988 CreditAttribution: anil280988 at Publicis Sapient for Publicis Sapient commentedChanging "removed in 9.0.0" to "removed in 9.0.x"
Comment #32
XanoThat is also incorrect. 9.0.x will continue to exist until after 9.0.0 has come out.
Please leave the message the way it was originally. It literally means that we remove it before the first stable Drupal 9 release, but only after we have already started working on Drupal 9.
It does not imply a break, it IS a break. Let's be honest and clear about this, however mitigated the break may be.
Comment #33
dawehnerWhile it is a break, how likely is it, that anyone implements the entity interface on its own? The system is not really designed around that idea at the moment, unlike some of the other interfaces out there, like some better written plugins.
This does not necessarily have to be a point PRO/CONTRA this issue, but it could be a indicator how high the actual result problem is.
Comment #34
anil280988 CreditAttribution: anil280988 at Publicis Sapient for Publicis Sapient commentedRe-rolling the patch,keeping "removed in 9.0.0" unchanged.
Comment #35
xjm@alexpott, @effulgentsia and I agreed on making this an RC target. This would need to go in today because of the entity interface change, so we should review and add a change record if possible.
Comment #36
XanoComment #37
XanoWhat is the purpose of this method override? It does not seem to do anything in its current state.
We already mark this deprecated using
@deprecated
, so we may want to keep the old description. Whatever we do, this must start with a verb.Should start with a verb. Maybe leave the old description intact here as well?
What does fully set up mean, and why do we document that here and not on the method that this warning is about?
Superfluous warning. The
::toLink()
method already documents its own return value.This method does not generate HTML.
Comment #38
xjmI should note that the reason we allowed the BC break of adding methods to the interface was that it's an edgecase to implement EntityInterface directly rather than using one of the base classes -- the entity system assumes in a lot of places that stuff is either content or config, so you'd already be fighting an uphill battle. And this is a priority because of the issues with the API surface. We would not however allow this change after this point.
Comment #39
xjmI'll work on drafting a change record.
Comment #40
xjmCreated https://www.drupal.org/node/2614344 for this issue and all the related issues. (I added the ones I found, though I believe there are others.)
Comment #41
chx CreditAttribution: chx commented#37
Comment #42
chx CreditAttribution: chx commentedInterdiff still against 34, sorry, one method too many nuked.
Comment #43
tim.plunkettThose overrides were to change the default param value from canonical to edit-form. Because that's the important route for config entities, which don't have a canonical.
Please put it back?
Comment #44
xjmWith an inline comment maybe that says why? :) I'll accept test coverage for that as a followup since it's not a part of this issue's scope, but the fact that the patch passes demonstrates missing coverage.
Comment #45
chx CreditAttribution: chx commentedComment #46
dawehnerThank you @chx
For me the patch looks alright, but yeah, its sad that we have to break BC here.
Comment #49
xjmThis all looks clean and correct to me now and it has CR enough for this patch at least. Only a couple nitpicks, none of which need block the issue and all of which could be fixed on commit:
Could be fixed on commit: we could add a similar comment there.
Nit: ID instead of id. Could be fixed on commit.
Could be fixed on commit: These need parens.
Of course, many usages remain in core of these methods. But at this point it is better to deprecate now and convert the usages later, since it is just a thin wrapper.
I'd consider this RTBC.
Comment #52
effulgentsia CreditAttribution: effulgentsia at Acquia commentedCrediting @xjm for the change record.
Comment #53
effulgentsia CreditAttribution: effulgentsia at Acquia commentedI pushed #45 as-is to 8.0.x. #49 and other docs improvements to this can be committed either before or after RC4 is tagged.
Comment #54
XanoThanks for working on this, and @xjm and @tim.plunkett for clarifying the changes!
I confirm the patch was committed with a proper commit message. However, the commit does not show up in this issue.
Comment #55
xjm@Xano, yeah, there was some issue with cgit yesterday which might be related. It'll show up eventually I think.