Problem:
\Drupal\Core\Routing\RouteCompiler::compile($route) generates a \Drupal\Core\Routing\CompiledRoute object but without injecting the '$route' in it. This causes "Notice: Undefined property: Drupal\Core\Routing\CompiledRoute::$route" when the methodes getOptions, getDefaults and getRequirements are called.
The issue can be easily reproduced with enabled 'Devel' module on page devel/php:
$route = new \Symfony\Component\Routing\Route('/');
\Drupal\Core\Routing\RouteCompiler::compile($route)->getDefaults();
Steps to reproduce in Drupal 9
For Drupal 9, devel
module has removed the devel/php
page so you have to use the devel_php
module.
- Install devel and devel_php modules
- Login as admin
- Optional: Enable
All messages, with backtrace information -- /admin/config/development/logging
- Go to /devel/php
- Paste this code:
$route = new \Symfony\Component\Routing\Route('/'); \Drupal\Core\Routing\RouteCompiler::compile($route)->getDefaults();
- Note the error on the page
- Go to /admin/reports/dblog
- Note the error in the logs
Comment | File | Size | Author |
---|---|---|---|
#49 | 3074201-49.patch | 6.43 KB | jungle |
#49 | interdiff-47-49.txt | 834 bytes | jungle |
Comments
Comment #2
rkostov CreditAttribution: rkostov at FFW commentedpatch:
Comment #3
rkostov CreditAttribution: rkostov at FFW commentedComment #4
rkostov CreditAttribution: rkostov at FFW commentedComment #7
Kristen PolPatch still applies to 9.1.x.
Comment #8
Kristen PolThank for the issue and patch. I understand the changes in the code but I wonder if this has to be changed in 10.0.x since the constructor signature would change so anything extending
CompiledRoute
would break unless they updated their signature. I'll check with the #bugsmash team.Comment #9
mr.baileysAdded a quick test demonstrating the issue.
Comment #11
longwaveSo the docs for CompiledRoute say
This seems to imply that it is a simple value object that should not contain a reference to the original Route object itself.
Where are the getOptions, getDefaults and getRequirements methods useful? To create a CompiledRoute you need the original Route object anyway, so you can just call the methods on the original object? Should we just deprecate and remove these methods instead, as they can never work as it stands?
Comment #12
longwaveThe change suggested here is effectively undoing #2381505: Unserialize preloaded routes on the fly.
It looks like that issue should really have removed getOptions, getDefaults and getRequirements as well. The more I think about it the more I think we should just remove these methods now, as they have not worked since that issue above was committed in 2015, and so why even deprecate them?
Comment #13
mr.baileys@longwave: I think you are right, and the issue you linked to did remove other methods tied to the $route property (
getPath()
andgetRoute()
). RemovinggetOptions()
,getDefaults()
andgetRequirements()
seems to be the right approach.Comment #14
Kristen Pol@longwave and @mr.baileys Thanks for the updates and analysis. Makes sense to me. Tagging for Global2020 so maybe someone will grab this as it's pretty straightforward. :)
Comment #15
partyka CreditAttribution: partyka at Argonne National Laboratory commentedI'm trying to replicate this locally, but the steps aren't really clear to me. @mr.baileys, were you able to replicate this? If so, how? I do have 9.1 installed locally.
Comment #16
Kristen Pol@partyka I was able to reproduce in Drupal 9 using the steps that I've added to the issue summary.
Form error:
Call to a member function getDefaults() on null
Log error:
Comment #17
Kristen PolThough from #12 and #13, the approach seems to be:
so this issue summary could be rewritten for this focus.
Comment #18
mr.baileysI am not sure if we can get away with just removing those functions (since they haven't worked for a long while now), or if they need proper deprecations.
Comment #19
mr.baileysBriefly discussed this with @lendude on #bugsmash, who said:
So let's deprecate those functions instead of removing them.
Comment #20
partyka CreditAttribution: partyka at Argonne National Laboratory commentedComment #21
partyka CreditAttribution: partyka at Argonne National Laboratory commentedComment #22
partyka CreditAttribution: partyka at Argonne National Laboratory commentedComment #23
partyka CreditAttribution: partyka at Argonne National Laboratory commentedHere's a patch that:
1) Marks the methods as deprecated.
2) Removes the calls on the null object as it will never work (Note: I inspected the class tree and did not find anywhere that the `route` object was a property.
3) Adds tests for the deprecation.
Since this will be marked as removed in 10.0.0, does this also need to be removed in the 10 branch?
Regarding the deprecation notice... I'm unsure as to what a decent notice should be. The steps to reproduce use a chained call, so the deprecation notice can't really say "call on the original object".
Comment #24
partyka CreditAttribution: partyka at Argonne National Laboratory commentedDoh... #10 is a bad patch. here's a better one.
Comment #25
longwaveThanks for the patch! This is looking good and I think the "no direct replacement" message is OK, as these never would have worked properly anyway. A few minor comments:
This should be added to the getDefaults and getRequirements methods as well.
This doesn't seem relevant to this patch.
Extra blank line can be removed.
This line is indented incorrectly.
Comment #26
partyka CreditAttribution: partyka at Argonne National Laboratory commentedNew patch with the minor details fixed.
I've also corrected the node the @see statement is pointing to so that it points to the change record, and I've also updated the change record. -- https://www.drupal.org/node/3159706
Thanks for pointing out #2, you're correct it's irrelevant ... bad copy and paste. 🤦🏻♂️
Comment #27
partyka CreditAttribution: partyka at Argonne National Laboratory commentedComment #28
longwaveThanks for updating the patch. This is ready for RTBC but I have one question that I don't know the answer to:
I wonder if we should leave these broken return statements in place.
There is a chance (admittedly very small) that someone is doing
which would actually work right now, but is broken by this patch.
Comment #29
partyka CreditAttribution: partyka at Argonne National Laboratory commentedSo, if leave the broken return statements in place, the tests won't pass (locally, at least). Here's what happens when I run these tests locally (output slightly altered for clarity):
----
Testing each method using devel/php reveals the following:
getDefaults():
getOptions():
getRequirements():
----
Test with `drush php-eval`:
I'm not sure how this could have ever worked. All the commands cause drush to terminate abnormally with an error like
Error: Call to a member function getRequirements() on null
Comment #30
longwaveYeah, the only way is if someone did something like my suggestion in #28, we could mock a Route and add that to the test?
Comment #31
partyka CreditAttribution: partyka at Argonne National Laboratory commentedSo I added the mocked Route object in the setUp() method.
But, now that I think about this... maybe it makes more sense to add a conditional to these three methods to test if `route` has0 been set, and if so, to behave with the broken behavior. Route has no visibility, so it's conceivable that some one set it like you had.
Here's the latest patch just so you can see.
Comment #32
partyka CreditAttribution: partyka at Argonne National Laboratory commentedUpdate the patch so that we now test to see if the property has been dynamically set, and if it has been, to check to see if it's a route object, and if so, to behave like how it was implied to behave before. Otherwise, it will just return an empty string.
Comment #33
partyka CreditAttribution: partyka at Argonne National Laboratory commentedChanged from using prophesize to use the `createMock` method.
Comment #34
partyka CreditAttribution: partyka at Argonne National Laboratory commentedRemoved unused `use` statements.
Comment #35
partyka CreditAttribution: partyka at Argonne National Laboratory commentedI've noticed the code style issues, but before I create another patch, I have some questions about what's a good way to adjust the code so that the `\Drupal\Core\Routing\RouteCompiler::compile($route)->getDefaults();` methods don't produce errors, as well as handling the possibility that someone could have dynamically set the `route` variable:
I’m really uncertain what’s a good way to suppress error messages generated … I’m currently checking to see if it’s a Route object, but that might be too specific. I might be able to see if the method is set on the object by using Method Exists. That might be enough since the method takes no parameters. Thoughts?
---
Also, apologies for all the patches for the code style errors. I have PhpStorm set up for my website projects, but I didn't do that for core.
Comment #36
jungleJust a generic review
See https://www.drupal.org/pift-ci-job/1762580
Should move the comment to above the
@var
line as they are properties, for example:Missing
{@inheritdoc}
Should start with verb, 'Test' -> 'Tests'
Comment #37
Kristen Pol@partyka Thanks for the updates. I didn't properly review but did notice some formatting issues like extra blank lines. It is probably worth running things through the code sniffer for these.
Also, please always include an interdiff when you change patches so it's easier to understand what has changed and what has not changed: https://www.drupal.org/documentation/git/interdiff
Thanks.
UPDATE: I see I crossposted with @jungle and he gave a proper review. :)
Comment #38
jameszhang023 CreditAttribution: jameszhang023 commentedWorking on this.
Comment #39
jameszhang023 CreditAttribution: jameszhang023 commentedReview please, thanks.
Comment #40
jungleUnexpected whitespaces
Oh, double
;
, nice catch!Comment #41
Kristen PolBack to needs work to fix whitespace.
Comment #42
jameszhang023 CreditAttribution: jameszhang023 commentedApology, review please, thanks.
Comment #43
Kristen PolThanks for the update. The interdiff looks good but leaving status for additional review and testing.
Comment #44
partyka CreditAttribution: partyka at Argonne National Laboratory commented@Kristen Pol -- agreed about the code style, and apologies for that. I was waiting for a review on how to handle the changes to CompiledRoute so that we don't accidentally cause a BC break for someone (or agree that it's an acceptable BC break).
Comment #45
partyka CreditAttribution: partyka at Argonne National Laboratory commentedGenerated new patch to remove unused "use" statements, as well as generated an interdiff this time. :-)
Comment #46
longwaveI am not sure we need to do any of this. This issue is a task to deprecate these methods, as they haven't worked for some time. If we intend to fix them or alter their behaviour in any way it should be done in a separate issue (and even then, I don't think that is necessary, as we are just going to remove them in the future). I think this method and the other similar ones should just read:
Comment #47
partyka CreditAttribution: partyka at Argonne National Laboratory commented@longwave, I agree with you about it being un-necesssary. Attached is a new patch + interdiff.
Comment #48
longwaveCouple of minor coding standards issues left, but this looks good to me now!
Unused use.
Extra blank line.
Comment #49
jungleThanks @longwave for the review.
Addressing #48
Comment #50
longwaveThanks! I almost think we have too much test coverage now, but I guess these weren't tested before and it will all be removed together when Drupal 10 opens so it can't hurt.
Comment #52
longwaveRandom fail in CKEditorIntegrationTest, back to RTBC
Comment #53
catchCommitted 192e9df and pushed to 9.1.x. Thanks!
(fixed a 'deprecrated' typo on commit).
Comment #56
quietone CreditAttribution: quietone at PreviousNext commentedPublish the change record