This is a replacement issue for #2743303-22: EntityForm::getEntityFromRouteMatch() does not support route-level parameters.
Problem/Motivation
We recently changed from using _node_add_access which made me realize that _entity_create_access won't take a default parameter.
Steps to reproduce
Add a route that uses a default instead of a path slug.
my.node.add:
path: '/my/node/add/page'
defaults:
node_type: 'page'
_entity_form: 'node.default'
_title_callback: '\Drupal\node\Controller\NodeController::addPageTitle'
requirements:
_entity_create_access: 'node:{node_type}'
options:
_node_operation_route: TRUE
parameters:
node_type:
type: entity:node_type
When you load the page you should get a 403 Access denied.
Proposed resolution
Like larowlan suggested, we should make how ParamConversionEnhancer::copyRawVariables and RouteMatch::getParameterNames consistent by giving them the same treatment to defaults.
| Comment | File | Size | Author |
|---|---|---|---|
| #30 | 3277784-30-copy-raw-variables-default-parameter.patch | 1.88 KB | tim bozeman |
| #30 | test-only.patch | 1011 bytes | tim bozeman |
| #22 | 3277784-22-copy-raw-variables-default-parameter.patch | 1.86 KB | tim bozeman |
| #22 | test-only.patch | 1003 bytes | tim bozeman |
| #18 | 3277784-18-entity-create-access-check-default-paramater.patch | 5.42 KB | tim bozeman |
Comments
Comment #2
tim bozeman commentedComment #3
tim bozeman commentedComment #4
larowlanCan we add a test to demonstrate the bug and ensure the fixed behaviour is retained?
Thanks!
Comment #5
tim bozeman commentedOh, good thinking! Here is testing a route like the example above where the bundle is resolved from a default route parameter via
getParameters().Comment #7
tim bozeman commentedComment #8
larowlanShould we postpone this on #2743303: EntityForm::getEntityFromRouteMatch() does not support route-level parameters
Comment #9
tim bozeman commentedhmm, idk. I don't think it depends on that issue. It should be a benign change for the normal use cases and this new use case never worked before. I guess a 403 is nicer than an error, but the error would be less confusing if you were trying to use a default parameter. 🤔
Comment #12
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #13
tim bozeman commentedRerolled for D10! 🚀
Comment #14
smustgrave commentedPatch failed to apply.
Comment #15
mrinalini9 commentedRerolled patch for 10.1.x branch, please review it.
Thanks!
Comment #16
smustgrave commentedIssue summary lines up with the solution in the patch
#5 shows that the test case covers the issue.
Comment #17
larowlanThe tests from #5 were lost somehow
Comment #18
tim bozeman commentedSorry about that! 😅
Here's the test and patch against
10.0.7.Comment #20
smustgrave commented#16 that was my mistake. See the tests have been added back.
Comment #21
larowlanI'm not convinced this is the right fix.
If we look at
\Drupal\Core\Routing\RouteMatch::getParameterNamesraw parameters should include defaults.However, the
_raw_variablesset in\Drupal\Core\Routing\Enhancer\ParamConversionEnhancer::copyRawVariablesdoesn't give the same treatment to defaults as\Drupal\Core\Routing\RouteMatch::getParameterNamesI think the fix should live in
\Drupal\Core\Routing\Enhancer\ParamConversionEnhancer::copyRawVariablesinstead, to make the two of them consistent.This should then render the change in this patch unnecessary and make the two internally consistent.
Thoughts?
Comment #22
tim bozeman commentedAh yes, that's the right place to fix this! When we change it in
ParamConversionEnhancer->copyRawVariables()I no longer need the patch from #2743303-22: EntityForm::getEntityFromRouteMatch() does not support route-level parameters. Thanks for figuring that out @larowlan!Comment #23
tim bozeman commentedComment #25
smustgrave commentedThanks for updating issue summary too @Tim Bozeman
See the change suggested by @larowlan has been implemented and test-only patch shows the test coverage is still good.
Comment #26
larowlan🔥 Love it when we get to a simpler solution
This is on my list to commit once we get out of the freeze - which ends at 10pm Thursday in my timezone. There is a four day weekend here, so it likely won't be until Tuesday next week.
Comment #28
larowlanCommitted to 10.1.x, so this is just awaiting backport post freeze
Comment #29
tim.plunkettGlad @larowlan's comment in #21 happened
Comment #30
tim bozeman commentedMe too! Here's a back port to 9.5
Thanks again! 🚀
Comment #32
larowlanBackported to 10.0.x
Requeued tests on 9.5.x as HEAD had a random fail
Comment #34
larowlanBackported to 9.5.x after green test run - thanks all
Comment #36
jensschuppe commentedSorry for posting in a closed issue, just want to be sure this didn't introduce a regression in some form ...
The CiviCRM module has been doing this in a
route_callbackscallback:Notice the
argskey within the second argument ($defaults) passed to theRouteconstructor - all keys not starting with a_inside that parameter are now (due to this change) eventually being treated as translation parameters (inDrupal/Core/Controller/TitleResolver.php:67), causing an array being considered a string and eventually resulting in aTypeError: htmlspecialchars(): Argument #1 ($string) must be of type string, array given in htmlspecialchars() (Line 432 in /path/to/drupal/web/core/lib/Drupal/Component/Utility/Html.php).Is this
argskey being an array just wrong here or did this issue introduce a regression? Is there documentation on what is allowed to be passed into aRoute's defaults?Edit: I think CiviCRM was wrong by making this
argsparameter an array while route parameters should be strings or integers. There's now a PR for fixing that in the CiviCRM module. However, this is still different behavior than before 9.5.9.Comment #37
tim bozeman commentedhmm, I don't know. 😬 The only documentation I could find didn't really specify if a default can be an array.
Comment #38
larowlan@jensschuppe can you open a followup for that - I think default arguments can totally be arrays and as such that automagic '@arg' '%arg' should be checking if $value is a scalar - i.e. that sounds like a bug in TitleResolver in my book
Comment #39
jensschuppe commented@larowlan There's a new issue for the problem: #3352384
I also think that the bug is in
TitleResolver, at least in conjunction with the new behavior of Drupal 9.5.9 that all route defaults whose keys do not start with an underscore_are now automatically considered route parameters and thus get copied as arguments for title translation.Comment #40
larowlanThanks
Comment #41
jensschuppe commented#3352384 seems to cover another issue, see #3358402 instead.