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.
Suggested commit message:
git commit -m 'Issue #2409209 by dawehner, mpdonadio, xjm, Wim Leers, hussainweb: Replace all _url() calls beside the one in _l()'
Problem/Motivation
This issue is critical because is a hard blocker to #2343669: Remove _l() and _url(), which is necessary before release because the legacy API does not properly support the D8 link APIs and routing system.
Replace all _url() calls in views.module:
grep -wr '_url(' core/modules/views core/modules/views/src/Form/ViewsExposedForm.php: $form['#action'] = _url($view->display_handler->getUrl()); core/modules/views/src/Plugin/views/display/DisplayPluginBase.php: $path = check_url(_url($path, $url_options)); core/modules/views/src/Plugin/views/field/FieldPluginBase.php: // Make sure that paths which were run through _url() work as well. core/modules/views/src/Plugin/views/row/RssFields.php: $item->link = _url($this->getField($row_index, $this->options['link_field']), array('absolute' => TRUE)); core/modules/views/src/Plugin/views/row/RssFields.php: $item_guid = _url($item_guid, array('absolute' => TRUE)); core/modules/views/src/Plugin/views/style/Opml.php: $url = _url($this->view->getUrl(NULL, $path), $url_options); core/modules/views/src/Plugin/views/style/Rss.php: $url = _url($this->view->getUrl(NULL, $path), $url_options); core/modules/views/views.theme.inc: $variables['rows'][$id]->url = _url($view->getUrl($args, $base_path), $url_options); core/modules/views/views.theme.inc: $variables['rows'][$id]->url = _url($view->getUrl($args, $base_path), $url_options); core/modules/views/views.theme.inc: $variables['link'] = check_url(_url($path, $url_options)); core/modules/views/views.tokens.inc: $replacements[$original] = _url($path, $url_options);
Proposed resolution
Fix it
Remaining tasks
User interface changes
API changes
Comment | File | Size | Author |
---|---|---|---|
#108 | interdiff-106-108.txt | 1.28 KB | mpdonadio |
#108 | replace_all_url-2409209-108.patch | 68.88 KB | mpdonadio |
#106 | interdiff-102-106.txt | 3.44 KB | mpdonadio |
#106 | replace_all_url-2409209-106.patch | 68.88 KB | mpdonadio |
#102 | interdiff-90-102.txt | 4.27 KB | mpdonadio |
Comments
Comment #1
Crell CreditAttribution: Crell commented#2364157: Replace most existing _url calls with Url objects looks like it's covering Views already. Is this child issue still necessary?
Comment #2
dawehnerThis issue was filed as a follow up for the _url issue.
Comment #3
Crell CreditAttribution: Crell commentedIf it's a follow-up it should probably be marked postponed. Doing so, and updating the issue summary.
Comment #4
dawehnerIts independent, why would it have to be postponed on it?
Comment #5
Crell CreditAttribution: Crell commentedAvoiding conflicts?
Comment #6
dawehnerHow? we convert code which uses _url() calls which are in different contexts that other _url() functions.
Comment #7
webchickFor the record, this is still valid even after #2364157: Replace most existing _url calls with Url objects. Updated the issue summary with a current grep. (Sorry, I don't know how to make it fancy-looking like mpdonadio had it.)
Comment #8
dawehnerLet's try to work on it a bit.
Comment #9
dawehner@mpdonadio and @dawehner pair programmed on that.
Comment #10
dawehnerUpdate issue summary
Comment #11
tim.plunkett:)
I think DisplayRouterInterface should extend this now
URL, not URl
Where is our wonderful comment? Also, how is Url going to behave with this?
There are a bunch of these
user-path:, apparently (here and elsewhere)
Isn't getInternalPath deprecated? ;)
Comment #13
dawehnerThat one is tricky ... sadly ... we literally want the path, as the o
Comment #15
RavindraSingh CreditAttribution: RavindraSingh commentedComment #16
RavindraSingh CreditAttribution: RavindraSingh commentedComment #17
dawehner.
Comment #18
RavindraSingh CreditAttribution: RavindraSingh commentedRerolled the patch.
Comment #20
hussainweb@RavindraSingh: Rerolled which patch? The file size is very different from other patches.
Comment #22
dawehnerThank you for trying to.
Did you maybe mixed something up? The patchsize decreased etc. and there was no commit in the meantime, so well.
I'll try yo fix the failures
Comment #23
dawehner@mpdonadio was working on it.
Comment #24
xjmI'll pick this up again.
Note that #18 is not a correct patch.
Comment #25
xjmFiled #2417865: Add a Views DisplayPluginInterface to make the patch scope more manageable.
Comment #26
xjmFixing a bunch of unit tests and starting to fix
PathPluginBase
.Comment #28
xjmSilly typo.
Comment #29
dawehnerNote: We have a unit test in
PathPluginBaseTest
Note:
$item->link
contains the rendered and stripped url already.... getInternalPath() is bad but its exactly what we want here. I think its fine for this patch ... getting rid of _url() and _l() is a good thing.
Comment #31
xjmViews is full of crying.
Comment #33
dawehnerHere is an interdiff which fixes quite some of the remaining failures.
Comment #34
hussainwebI have not reviewed the changes in #33 entirely, but I did see one change that kind of conflicted with another approach I was trying. I will try to incorporate changes in #33 in the next patch but I just wanted to put this to the test for now.
Comment #35
prashantgoel CreditAttribution: prashantgoel commentedI have used diff from @dawehner. Lets see the test bot results.
Comment #36
hussainwebI am just summarizing the differences in patches in #34 and #35 (which is from an interdiff in #33).
This is from the interdiff in #33 and in patch in #35. This looks somewhat different from the previous approach. The reason this failed in previous patch (which called
getUrl()
on the$view
directly) was that it did not handle linked displays the way it was handled before (viagetPath()
method).In the patch in #34, I wrote a new method
getRoutedDisplay()
which does the same thing for displays and used it along withgetPath()
call (which we should be able to remove after refactoring, maybe a follow-up).Comment #39
dawehner@hussainweb
You made a good point with the link displays!
Comment #40
hussainweb@dawehner: Thanks! I am now stuck with views which don't have any linked displays at all. Previously, _url() function would return the
<front>
path if the path isnull
. Now, we are throwing an exception.I am thinking of catching the exception in ViewsExposedForm and using
Url::fromRoute('<front>')
for that. I am trying a local test first and then posting a patch. Does the approach sound reasonable?Comment #41
hussainwebI introduced a new method called
ViewExecutable::hasUrl()
which does a similar check without throwing an exception, so there is nothing to catch. What do you think?Comment #43
xjmHi @hussainweb, are you currently working further on this? I don't want to duplicate work again. :)
Comment #44
hussainweb@xjm: Yes, I am. I am trying to figure out the exceptions thrown from
renderMoreLink()
. I will unassign myself at the end of the day.Comment #45
YesCT CreditAttribution: YesCT commented@prashantgoel Thanks for helping with this critical. It is great to see everyone focusing on getting drupal 8 released.
To work on an issue that is assigned to someone, please get into irc in #drupal-contribute and say something to in the public channel using the person's irc name. This allows for coordination when work in moving fast and ongoing. If they are not in irc, try using their d.o contact form to communicate.
http://drupal.org/irc and https://www.drupal.org/irc/usage
Comment #46
hussainwebI tracked down a few exceptions/failures to another issue with views and I have raised a critical bug at #2418163: Recent content view "more" link configuration is malformed. I don't think there is any need to postpone this as there are other unrelated failures that can be fixed. Particularly, failures in
Drupal\node\Tests\NodeBlockFunctionalTest
will be fixed when the other issue goes in.I am calling it a day and unassigning as promised.
Comment #47
webchickOk, #2418163: Recent content view "more" link configuration is malformed is in. Should be unblocked now!
Comment #48
hussainweb@webchick: Thanks! Doing a retest now.
Comment #51
xjmOnly 48 fails now, nice. ;)
Comment #52
RavindraSingh CreditAttribution: RavindraSingh commentedYes, it seems improved now.
Drupal\Tests\views\Unit\ViewExecutableTest::testGetUrlWithPlaceholdersAndArgs InvalidArgumentException: You cannot create a URL to a display without routes. /var/lib/drupaltestbot/sites/default/files/checkout/core/modules/views/src/ViewExecutable.php:1743 /var/lib/drupaltestbot/sites/default/files/checkout/core/modules/views/tests/src/Unit/ViewExecutableTest.php:173
This is something that is not allowing to create a route for test page in ViewExecutableTest.php.
@hussainweb, on last patch added by me seems I missed something. Apologies for the same.
Comment #53
hussainweb@RavindraSingh: No need for apologies. We are all working to get this thing through. :)
I will resume later during the day, unless someone beats me to it. :)
Comment #54
dawehnerJust a small step forward.
Comment #56
Wim LeersFixed most test failures. Only the failures in
BasicTest
remain. Fixed none of the exceptions; they're all because the router doesn't know about the test view's routes, even though it should AFAICT. Still debugging.Things I can't fix, should be fixed by others on this issue:
Missing docs.
A more explanatory, less informal comment would be better here :)
Good call.
Comment #58
Wim LeersTurns out those routes are missing because we're dynamically manipulating views in tests… without saving them. Simple solution: just save them after manipulating them. Except none of them can be saved, because all of them violate config schemas. IOW: it's incredible that the tests have been passing at all… :(
Currently fixing those violations; tedious job, so it will take some time, so assigning to myself to ensure nobody else does the same work.
Comment #59
dawehnerYou know, I disagree. Your objects should work, as they are. Just imagine if the following code doesn't work:
Just saying, those objects should work without their underlying storage, if possible.
Comment #60
Wim LeersThis fixes all those exceptions. That leaves only the 2 failures in
BasicTest
. Hoping dawehner can fix those.Comment #62
Wim LeersAgreed in principle. But there is a problem with that, both in case of Views and Nodes/all other entities, we don't actually know if the test data is valid. And then we're not sure we're actually testing what the "real" entity contains/behaves like, we're testing a test version of it, that was valid at some point, but perhaps not anymore.
(This has caused problems elsewhere too.)
But, no matter, because in the above, I'm only saving those views that truly need to be saved.
Comment #63
dawehnerIt turns out that its good, that we have tests.
Comment #65
Wim Leers#63's interdiff was right, but was applied to #54 instead of #60. Rerolling.
Comment #66
xjmWow, it's green! Great work everyone. Did a quick scan:
Docs. :)
I believe @dawehner suggested we should remove this method -- on the other hand, since this is green now anyway, followup?
Note for reviewers: Updated test coverage is moved to the phpunit tests.
Isn't getInternalPath() deprecated?
Comment #67
dawehnerThank you for the review! Working on it
Comment #68
Wim LeersAlso see my review in #56.
Comment #69
dawehnerOpened up a follow up: #2419121: Deprecate $display->getUrlInfo() and replace it with $display->getUrl()
I still don't understand how token API works here, but it wants a path, so this is kinda the only partially official way to do it, IMHO.
This is existing documentation :P
Comment #71
dawehnerReroll.
Comment #72
dawehnerLet's fix that particular comment as well.
Comment #73
dawehneri'll fix the patch size.
Comment #74
dawehnerComment #75
Wim LeersTwo super tiny nitpicks
for when you reroll the patch to fix the patch sizethat can be fixed upon commit. RTBCwhen you've done that— I think I still can RTBC it since all I did was fix some test failures. I didn't do any work on the actual patch.s/it is itself/it returns itself/
s/view/View/
?
Comment #76
dawehnerLet me quickly address that.
Comment #77
xjmPolishing the docs a bit; will upload shortly.
Comment #78
xjmHmm, is this the correct behavior actually? If I put an exposed form in a block, do I expect to be redirected to the front page, or the page I'm currently on? I'd say the latter.
Why are we not checking
hasUrl()
here too?Setting back to NR for clarification, at least.
Comment #79
mpdonadioRe #78-1, I agree that this should be `<current>` and not `<front>`. I am also a little concerned that we had passing tests. Is there a test that would catch this (view w/ exposed form as a block on a page)? Or is this just an artifact of how `WebTestBase::drupalPostForm(NULL, $edit, ...)` works?
Comment #80
xjmAre we even using this anymore? It seems everywhere we're just calling straight through to the view. Edit: Lost some lines from the code snippet.
Comment #81
xjmDoing a few more things actually.
Comment #82
xjmlol w is close to x
Comment #83
xjmHmm, I don't think so. "Views" is the name of the module, so capitalized. "A view" is just a thing. We don't say "a Term" or "a Node" so I think it's just "a view". OTOH we are probably totally inconsistent either way. ;)
Comment #84
xjmThis public variable is documented, but never written in core outside tests. What's the usecase? Do we still need it?
Sorry for all the little comments; keep finding new questions as I work through the patch.
Comment #85
xjmShould the fallback behavior here really be to return true? I'd think if a view has no displays with valid routes and no other way of setting the URL, it's not linkable. I guess we could add a test.
Comment #86
xjmSo there's a recursive behavior here. What happens if you have two displays that somehow reference each other as the linked display? ;)
In the current behavior of getRoutedDisplay(), I don't think a non-routed display can ever be returned, so the instanceof check might be redundant.
Comment #87
xjmMeanwhile, some docs and a minor refactoring for self-documentingness of the code. Doesn't include any changes for #78 and beyond.
Comment #89
xjm....duh
Comment #92
xjmSome day I will learn to listen to the little red squiggles in PHPStorm.
Comment #93
xjmComment #94
xjmMissing closing curly.
Comment #95
dawehner+2 to document this!
Should we use $view_id.$display_id here? Maybe this explains it a bit better.
Does this method has to be public? I just see on usecase of it. +1 though for doing it.
sad PHP.
Comment #96
xjmDiscussed with @webchick, @effulgentsia, @alexpott, and @catch. This issue has been triaged as critical by the maintainers because it is a hard blocker to #2343669: Remove _l() and _url(), which in turn is necessary before release because the legacy API does not properly support the D8 link APIs and routing system.
Comment #97
RavindraSingh CreditAttribution: RavindraSingh commented@dawehner, For 2nd. I think this is fine to use view_id.display_id
* view_id.display_id and the values are the route names.
Comment #98
dawehner@RavindraSingh
Well, there is fine and there is making it easy for people to understand what is going on.
@xjm Do you have time to fix those bits?
Comment #99
dawehnerTried to answer a couple of those good questions.
If you look at the current code in HEAD, the flow of code would return an empty string ... which afaik returns
$basepath
basically.I guess we should actually move this logic into View::getUrl(), given that this kinda worked before as well.
Well, even if we don't do anymore, I think its good to have a method on the display, given that a view is just a collection of display, which each has an URL or not.
Given that you are in the domain of views already here, "a view" should not be confusing, much like "a node" is also not confusing for people.
Ctools in D7 used override_path itself, but at the same time I think
override_url
could be helpful to place for example an exposed form at some random place.It would be always nice to have a test, what kind of question is that ;)
You pretty much end up with just displays with have a DisplayRouterInterface, see:
Well, getRoutedDisplay() also allows to return NULL, don't we want to ensure that we check it? Note: The documentation of that method should tell that
it returns DisplayRouterInterface instead.
Comment #100
mpdonadioI'll work on the last few bits of review, and have something posted tonight.
Comment #101
dawehner@mpdonadio++
Comment #102
mpdonadioOK, I think this addresses all actionable feedback from #78 onward that wasn't taken care of already, or just answered in a comment. I may have missed something (lots of comments); if so, mention it and I will add it. One of the comments mentions the potential for a new test, but I didn't do that (wasn't in a test writing mood tonight...).
Re view.$view_id.$display_id, given the general confusion around routes we are going to start having from devs, I think this does make things clearer.
I don't see how moving this to ViewExecutable::getUrl() would make sense, as we throw an exception when a particular view/display doesn't have a URL? Added the check, and made the fallback the URL for current page.
In DisplayPluginBase::getRoutedDisplay(), I added a comment and an explicit `return null` to match the docblock. I know this it the default behavior of PHP, but since we explicitly mention it in the docblock, we should explicitly do so in the code.
Comment #106
mpdonadioLooks like we need to adjust for #2417647: Add leading slash to paths within 'user-path:' URIs, to allow 'user-path:' URIs to point to the <none> route. Technically, this is a hand edit of my last patch so I could be sure to limit to the scope of this issue, but it applies cleanly and interdiffs appropriately.
Comment #107
dawehnerOne more nitpick.
We use NULL IMHO.
Comment #108
mpdonadioUppercased per Drupal coding standards in both the code, comment, and docblock.
Comment #109
dawehnerThank you!
Comment #110
webchickAwesome. Getting this one in while it's hot!
Committed and pushed to 8.0.x. Thanks!
Comment #112
xjmWOOOOO
Comment #113
Wim Leersmpdonadio+++++++++++