Problem/Motivation

Related to #3608029: 3.x: Drupal 11.4 compatibility fixes (purl subrequest visibility + RouteProvider constructor signature).

2.x currently declares core_version_requirement: ^10.1 || ^11, a single unbroken range spanning Drupal 10.1 through 11.x.

Starting with Drupal 11.4, core's http_kernel.basic service (Symfony\Component\HttpKernel\HttpKernel) changed its RequestStack constructor argument from Drupal's real @request_stack service to null (see the comment on that service definition in core.services.yml). Symfony's raw HttpKernel then keeps its own private, internal RequestStack for push()/pop(), separate from Drupal's request_stack service.

RequestSubscriber::onRequest() dispatches purl's stripped-prefix subrequest directly against the raw kernel ($event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST)), bypassing DrupalKernel::preHandle()/KernelPreHandle entirely. On Drupal 11.4+ this makes the subrequest invisible to Drupal's request_stack service for its whole lifecycle, so \Drupal::routeMatch(), \Drupal::request(), and CurrentRouteMatch resolve to the wrong request (or a null route) while purl's subrequest controller executes (see #3608029 for full symptoms/fix).

None of this occurs on 10.1–11.3, where http_kernel.basic still uses Drupal's real request_stack, so purl's existing 2.x subrequest code is correct there and needs no change. The actual fix in #3608029 requires Drupal core >=11.4 to ship cleanly (no runtime version branching), so 2.x should not receive that fix. Instead 2.x needs its core_version_requirement tightened so Composer never resolves it onto a broken 11.4+ site, plus a regression test proving 2.x remains correct on its own supported range.

Steps to reproduce

  • Install purl 2.x on a site running Drupal core 11.4 or later.
  • Configure any path-prefix modifier/provider.
  • Visit a URL matching that prefix.
  • Observe Error: Call to a member function getOptions() on null in PurlNodeContextRoutes::purlCheckNodeContext(), or any other code reading \Drupal::routeMatch() during the request resolving incorrectly.

Proposed resolution

  • Update purl.info.yml's core_version_requirement to exclude 11.4+ (e.g. ^10.1 || >=11 <11.4).
  • Add tests/src/Kernel/PurlSubrequestRequestStackTest.php plus a companion minimal fixture module tests/modules/purl_subrequest_test (a provider plugin exposing one fixed path-prefix modifier, a route, and a controller reporting \Drupal::request()->getPathInfo(), \Drupal::routeMatch()->getRouteName(), whether getRouteObject() is null, and whether the current request equals the main request). The test performs a real in-process request through the prefixed path and asserts the subrequest's own controller sees itself — not the main request — as current.
  • No RequestSubscriber source change is needed for this test to pass on 2.x.

Remaining tasks

  • Confirm exact core_version_requirement syntax for the upper bound
  • Add the kernel test + fixture module (patch/MR to follow)
  • Add/confirm a CI job pinned to Drupal 11.3 specifically (current .gitlab-ci.yml tests 10.3/11.0, neither of which pins the 11.3→11.4 boundary this issue is about)
  • Release as a 2.x point release

User interface changes

None.

API changes

None — test and composer-constraint only.

Data model changes

None.

Issue fork purl-3608542

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

freelock created an issue. See original summary.

freelock’s picture

Status: Active » Needs review

Merge error is against the ancient "master" branch, merges fine into 8.x-1.x -- but shouldn't we have a 2.0.x branch?