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.

Comments

Tim Bozeman created an issue. See original summary.

tim bozeman’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new2.25 KB
larowlan’s picture

Can we add a test to demonstrate the bug and ensure the fixed behaviour is retained?

Thanks!

tim bozeman’s picture

Oh, good thinking! Here is testing a route like the example above where the bundle is resolved from a default route parameter via getParameters().

The last submitted patch, 5: test-only.patch, failed testing. View results

tim bozeman’s picture

Issue tags: -Needs tests
larowlan’s picture

tim bozeman’s picture

hmm, 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. 🤔

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new188 bytes

The 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.

tim bozeman’s picture

Version: 9.5.x-dev » 10.0.x-dev
Status: Needs work » Needs review
StatusFileSize
new2.2 KB

Rerolled for D10! 🚀

smustgrave’s picture

Status: Needs review » Needs work

Patch failed to apply.

mrinalini9’s picture

Status: Needs work » Needs review
StatusFileSize
new2.18 KB

Rerolled patch for 10.1.x branch, please review it.

Thanks!

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs Review Queue Initiative

Issue summary lines up with the solution in the patch
#5 shows that the test case covers the issue.

larowlan’s picture

Status: Reviewed & tested by the community » Needs work

The tests from #5 were lost somehow

tim bozeman’s picture

Status: Needs work » Needs review
StatusFileSize
new4.39 KB
new5.42 KB

Sorry about that! 😅
Here's the test and patch against 10.0.7.

The last submitted patch, 18: test-only.patch, failed testing. View results

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

#16 that was my mistake. See the tests have been added back.

larowlan’s picture

Status: Reviewed & tested by the community » Needs work

I'm not convinced this is the right fix.

If we look at \Drupal\Core\Routing\RouteMatch::getParameterNames raw parameters should include defaults.

However, the _raw_variables set in \Drupal\Core\Routing\Enhancer\ParamConversionEnhancer::copyRawVariables doesn't give the same treatment to defaults as \Drupal\Core\Routing\RouteMatch::getParameterNames

I think the fix should live in \Drupal\Core\Routing\Enhancer\ParamConversionEnhancer::copyRawVariables instead, to make the two of them consistent.

This should then render the change in this patch unnecessary and make the two internally consistent.

Thoughts?

tim bozeman’s picture

Title: EntityCreateAccessCheck should support default route parameters » copyRawVariables should support default route parameters
Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new1003 bytes
new1.86 KB

Ah 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!

tim bozeman’s picture

Issue summary: View changes

The last submitted patch, 22: test-only.patch, failed testing. View results

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Thanks 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.

larowlan’s picture

🔥 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.

  • larowlan committed ca0a26d2 on 10.1.x
    Issue #3277784 by Tim Bozeman, mrinalini9, larowlan: copyRawVariables...
larowlan’s picture

Title: copyRawVariables should support default route parameters » [Needs backport] copyRawVariables should support default route parameters

Committed to 10.1.x, so this is just awaiting backport post freeze

tim.plunkett’s picture

Component: entity system » routing system

Glad @larowlan's comment in #21 happened

tim bozeman’s picture

Me too! Here's a back port to 9.5

Thanks again! 🚀

  • larowlan committed 7e48dd85 on 10.0.x
    Issue #3277784 by Tim Bozeman, mrinalini9, larowlan: copyRawVariables...
larowlan’s picture

Version: 10.0.x-dev » 9.5.x-dev

Backported to 10.0.x

Requeued tests on 9.5.x as HEAD had a random fail

  • larowlan committed a894a04b on 9.5.x
    Issue #3277784 by Tim Bozeman, mrinalini9, larowlan: copyRawVariables...
larowlan’s picture

Title: [Needs backport] copyRawVariables should support default route parameters » copyRawVariables should support default route parameters
Status: Reviewed & tested by the community » Fixed

Backported to 9.5.x after green test run - thanks all

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

jensschuppe’s picture

Sorry 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_callbacks callback:

$route = new Route(
  '/' . $path . '/{extra}',
  [
    '_title' => isset($item['title']) ? $item['title'] : 'CiviCRM',
    '_controller' => 'Drupal\civicrm\Controller\CivicrmController::main',
    'args' => explode('/', $path),
    'extra' => '',
  ],
  [
    '_access' => 'TRUE',
    'extra' => '.+',
  ]
);

Notice the args key within the second argument ($defaults) passed to the Route constructor - all keys not starting with a _ inside that parameter are now (due to this change) eventually being treated as translation parameters (in Drupal/Core/Controller/TitleResolver.php:67), causing an array being considered a string and eventually resulting in a TypeError: 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 args key being an array just wrong here or did this issue introduce a regression? Is there documentation on what is allowed to be passed into a Route's defaults?

Edit: I think CiviCRM was wrong by making this args parameter 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.

tim bozeman’s picture

hmm, I don't know. 😬 The only documentation I could find didn't really specify if a default can be an array.

larowlan’s picture

@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

jensschuppe’s picture

@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.

larowlan’s picture

Thanks

jensschuppe’s picture

#3352384 seems to cover another issue, see #3358402 instead.