Problem/Motivation

The DrupalKernel requires knowing about a $root property and has separate code to determine the $sitePath. This logic is currently primarily captured within DrupalKernel which does allow providing $app_root. However, setting the $sitePath can only be done through setSitePath under specific circumstances. It really should be general configuration for the kernel.

It should really not be a concern for the DrupalKernel itself to figure out what the layout is of the Drupal file system. It should only be provided with the right information to act on. What the layout of the application is on disk really is a concern that depends on the runtime.

There are currently a lot of places within Drupal that duplicate some of the functionality around app root or site path. Specifically in tests, lower level bootstrap or install logic, and front-controllers.

With the introduction of Symfony runtime in #3313404: Use symfony/runtime for less bespoke bootstrap/compatibility with varied runtime environments we now have a place to determine these kinds of environmental dependencies in a way that can be swapped out by the application built on Drupal if desirable.

Another concern is that CLI tools, such as Drush, or background processes, like Cron, may be doing things without serving an active request. In those cases it's still important for Drupal to have application context for the things it's doing like the $base_url and $base_path so that even outside of a request context it can properly generate links (e.g. in a notification email).

Tools like Drush currently have to create a fake request to get Drupal to properly set the base_uri and base_path, even though they already have the information and it's thus redundant for Drupal to parse this from a request.

This originally started as an idea in #2529170-104: [PP-1] Remove DrupalKernel::initializeRequestGlobals and replace base_root, base_url and base_path with a service. However, replacing all usages of the globals is in itself already a large task and the structure to contain the app context information and standardising root and siteDirectory uses in tests to that new structure, is big enough that this was split out to its own issue.

Steps to reproduce

Proposed resolution

Introduce a low level \Drupal\Core\AppContext class that initially contains:

  • string $appRoot - The path of the application root.
  • string $sitePath -The current site path directory.
  • string $baseUrl - The base URL of the application.
  • string $basePath - The path part of the base URL.

The logic that currently exists within DrupalKernel to determine this should be moved into Drupal\Core\Runtime\DrupalRuntime in a way that it can be easily reused by e.g. Drupal\Tests\DrupalTestCaseTrait. DrupalKernel will be adjusted to receive this $app_context as required constructor input.

Existing logic outside of DrupalKernel should be standardised to use the same shared code to determine the application context but may overwrite the site path of the application context (e.g. in tests).

Front-controllers should be able to easily retrieve AppContext $app_context as a resolved argument from the runtime to pass this to the kernel.

Applications that have different layout requirements now have a single object that they can instantiate to determine how the DrupalKernel and Drupal services deal with the file system. In case an existing application wants to change its layout, it can replace the instantiation of the default AppContext instance by building and/or configuring a runtime class for their application with different behavior.

This change relates to a bunch of existing issues and would make those easier to achieve.

That issue is introducing a composer plugin that knows where Drupal core is installed. By letting the plugin provide the app root path, the Drupal core directory can be moved to a different location (e.g. using symlinks for easier development).

The overlap between that issue and this one is in standardising code outside of DrupalKernel on using a shared logic to determine the $app_root. However, they're otherwise complementary issues: this issue tries to pull the logic for $app_root outside of the DrupalKernel, that issue wants to change how $app_root is determined based on the environment, rather than by magic path magic.

This issue contains forwards compatibility for 1792310 by having AppContextTrait::getApplicationRoot check for the newly introduced DrupalInstalled::getAppRoot, and using it if it exists.

This issue aims to standardise the way app root is determined, so that 1792310's introduction of DrupalInstalled::getAppRoot takes effect across the codebase.

That issue rightly identifies that $app_root is used with different intentions. There is for example a difference in using it to find the web root of the Drupal application to serve files on the web versus trying to determine the location of files in Drupal core so they can be loaded in the Drupal application.

This issue introduces the concept of the AppContext which can be initially extended with getter methods that both return $app_root but allow us to better document the intent of code using the application root value. Then as a follow-up it would be possible to return different path values and allow different parts of the Drupal application to be moved around.

That issue is what this one is originally split off from. The most important part of that issue, the usage of $base_url, $base_path, $base_secure_url (derived from $base_url), and $base_insecure_url (derived from $base_url), can now be accessed from the AppContext, rather than relying on globals. The scope of that issue would thus change to ensuring that the places that are currently using the global have access to the app context.

The $base_root is actually taken directly from $request and all use cases in Drupal core seem to have access to the $request where it's used, so those can be easily replaced in that issue.

That issue wants to move bootEnvironment out of DrupalKernel. Booting the environment is a task of the runtime and not of the kernel. One challenge up til now is that booting the environment depends on the app root.

This issue removes the dependency of the app root on the DrupalKernel and makes it available in the runtime. This means that it becomes trivial to move the environment boot into the runtime as well, since that now has all the necessary information in AppContext.

The SAPIAdapter concept in that issue was essentially a prototype of what the Symfony Runtime and Runner concepts provide us.

Remaining tasks

User interface changes

Introduced terminology

API changes

  • AppContext is introduced as container for Drupal application context and replaces DrupalKernel's standalone root and sitePath properties as well as providing a standardised way to set or receive $base_url and $base_path.
  • AppContextTrait is introduced to help in constructing AppContext from the DrupalRuntime or alternative runtime implementations as well as test classes..
  • Providing or omitting a string $app_root to DrupalKernel::__construct is deprecated. A mandatory AppContext instance should be provided instead
  • DrupalKernel::findSitePath is deprecated. Use the Runtime to determine the site path through AppContext instead.
  • DrupalKernel::setSitePath is deprecated, provide the site path to the DrupalKernel using AppContext instead.
  • Calling DrupalKernel::bootEnvironment without an $app_root is deprecated, provide the app_root from AppContext instead.
  • It's possible to disable multi-site discovery and restrict to the sites/default site path by setting extra.runtime.disable_multisite in your composer.json to TRUE.

Data model changes

Release notes snippet

Issue fork drupal-3590337

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

kingdutch created an issue.