Quantcast
Channel: Issues for Drupal core
Viewing all 297150 articles
Browse latest View live

Add validation constraints to contact.form.*

$
0
0

Problem/Motivation

Contact form entity is not yet fully validatable:

.vendor/bin/drush config:inspect --filter-keys=contact.form.feedback --detail --list-constraints
➜  🤖 Analyzing…

 Legend for Data: 
  ✅❓  → Correct primitive type, detailed validation impossible.
  ✅✅  → Correct primitive type, passed all validation constraints.
 -------------------------------------------------- --------- ------------- ------ --------------------------------------------------------------------------------------------- 
  Key                                                Status    Validatable   Data   Validation constraints                                                                       
 -------------------------------------------------- --------- ------------- ------ --------------------------------------------------------------------------------------------- 
  contact.form.feedback                              Correct   87%           ✅❓   ValidKeys: '<infer>'                                                                         
   contact.form.feedback:                            Correct   Validatable   ✅✅   ValidKeys: '<infer>'                                                                         
   contact.form.feedback:_core                       Correct   Validatable   ✅✅   ValidKeys:                                                                                   
                                                                                      - default_config_hash                                                                      
   contact.form.feedback:_core.default_config_hash   Correct   Validatable   ✅✅   NotNull: {  }                                                                                
                                                                                    Regex: '/^[a-zA-Z0-9\-_]+$/'                                                                 
                                                                                    Length: 43                                                                                   
                                                                                    ↣ PrimitiveType: {  }                                                                        
   contact.form.feedback:dependencies                Correct   Validatable   ✅✅   ValidKeys: '<infer>'                                                                         
   contact.form.feedback:id                          Correct   Validatable   ✅✅   Length:                                                                                      
                                                                                      max: 32                                                                                    
                                                                                    ↣ PrimitiveType: {  }                                                                        
                                                                                    ↣ Regex:                                                                                     
                                                                                      pattern: '/^[a-z0-9_]+$/'                                                                  
                                                                                      message: 'The %value machine name is not valid.'                                           
   contact.form.feedback:label                       Correct   Validatable   ✅✅   Regex:                                                                                       
                                                                                      pattern: '/([^\PC])/u'                                                                     
                                                                                      match: false                                                                               
                                                                                      message: 'Labels are not allowed to span multiple lines or contain control characters.'    
                                                                                    NotBlank: {  }                                                                               
                                                                                    ↣ PrimitiveType: {  }                                                                        
   contact.form.feedback:langcode                    Correct   Validatable   ✅✅   NotNull: {  }                                                                                
                                                                                    Choice:                                                                                      
                                                                                      callback: 'Drupal\Core\TypedData\Plugin\DataType\LanguageReference::getAllValidLangcodes'↣ PrimitiveType: {  }                                                                        
   contact.form.feedback:message                     Correct   Validatable   ✅✅   Regex:                                                                                       
                                                                                      pattern: '/([^\PC\x09\x0a\x0d])/u'                                                         
                                                                                      match: false                                                                               
                                                                                      message: 'Text is not allowed to contain control characters, only visible characters.'↣ PrimitiveType: {  }                                                                        
   contact.form.feedback:recipients                  Correct   NOT           ✅❓   ⚠️  @todo Add validation constraints to config entity type: contact.form.*                   
   contact.form.feedback:recipients.0                Correct   Validatable   ✅✅   Email:                                                                                       
                                                                                      message: '%value is not a valid email address.'↣ PrimitiveType: {  }                                                                        
   contact.form.feedback:redirect                    Correct   NOT           ✅❓   ⚠️  @todo Add validation constraints to config entity type: contact.form.*                   
   contact.form.feedback:reply                       Correct   Validatable   ✅✅   Regex:                                                                                       
                                                                                      pattern: '/([^\PC\x09\x0a\x0d])/u'                                                         
                                                                                      match: false                                                                               
                                                                                      message: 'Text is not allowed to contain control characters, only visible characters.'↣ PrimitiveType: {  }                                                                        
   contact.form.feedback:status                      Correct   Validatable   ✅✅   ↣ PrimitiveType: {  }                                                                        
   contact.form.feedback:uuid                        Correct   Validatable   ✅✅   Uuid: {  }                                                                                   
                                                                                    ↣ PrimitiveType: {  }                                                                        
   contact.form.feedback:weight                      Correct   Validatable   ✅✅   Range:                                                                                       
                                                                                      min: -2147483648                                                                           
                                                                                      max: 2147483647                                                                            
                                                                                    FullyValidatable: null                                                                       
                                                                                    ↣ PrimitiveType: {  }                                                                        
 -------------------------------------------------- --------- ------------- ------ --------------------------------------------------------------------------------------------- 

Steps to reproduce

  1. Get a local git clone of Drupal core 11.x.
  2. composer require drupal/config_inspector— or manually install https://www.drupal.org/project/config_inspector/releases/2.1.5 or newer (which supports Drupal 11!)
  3. composer require drush/drush
  4. vendor/bin/drush config:inspect --filter-keys=contact.form.feedback --detail --list-constraints

Proposed resolution

Add validation constraints to missing properties.

This requires looking at the existing code and admin UI (if any) to understand which values could be considered valid. Eventually this needs to be reviewed by the relevant subsystem maintainer.

For examples, search *.schema.yml files for the string constraints:😊

Reach out to @borisson_ or @wimleers in the #distributions-and-recipes.

Remaining tasks

MR

User interface changes

None.

API changes

None.

Data model changes

More validation 🚀

Release notes snippet

None.


Add an 'instant' queue runner

$
0
0

Problem/Motivation

Drupal has two ways to handle long-running tasks:

1. Queue API, by default queues are run on cron, often sites run queues via jenkins on different schedules, there are projects like 'waiting queue' which aim to minimise the time before queue items are picked up.

2. Batch API - designed for the browser, although drush can also run batches, completely blocks the user's interaction with the site while it's running. Batches are user-specific so if one gets interrupted, that's pretty much it. Provides feedback, you know when it's finished.

From personal experience, the Queue API is great to work with and expectations are very clear. Batch API is hard to work with and debug.

In the UI, Batch API always blocking isn't necessarily optimal. Bulk operations on entities for example could be put into a queue, and there could be a progress bar in a block somewhere which runs down the queue, but allows the user to click around the rest of the site while that's happening. There are cases though like updates from the UI where things really do need to block and require strict ordering.

Proposed resolution

Add a browser queue runner. Will need a route that takes a queue name, fetches items and runs them (will need to set the current user to anonymous to match drush/cron) then reports back. This could use a 1px gif added only after POST requests.

Remaining tasks

User interface changes

API changes

Data model changes

Cron jobs fall into a couple of main categories:

- things that have to be run periodically and don't care about site events - mainly garbage collection like session and cache.
- batch processing of things - search indexing of new nodes, purging of deleted stuff.

For the latter case, these are increasingly moving to the queue API, although it's not 100% consistent in core.

Issues like #943772: field_delete_field() and others fail for inactive fields, and the one I can't find about indexing nodes for searching immediately, might be helped by a poor mans queue runner.

Drupal 7 has a poor mans cron. Currently the implementation is very basic - 1px gif/xhr requests were causing Drupal to be bootstrapped twice each request, and at one point there was a proposal to do ob_flush() during a shutdown function but this didn't take on, so we ended up just running cron inline instead, which is sucky but I argued for that in the end.

With the queue runner, it'd be more a case of setting $_SESSION['run_queues'] after a form submit, check that on the next page, if it's set, add the 1px gif or whatever to that page, which hits /queue_run with a token. This would only ever be triggered by form submissions so it'd not have the page caching issues of cron runs.

Things it could be useful for:

- field deletion
- mass deletes of other stuff
- operations that trigger menu rebuilds or similar expensive operations, that don't necessarily have to happen inline with the request - just very shortly afterwards.
- indexing nodes in the core search module immediately after posting instead of waiting for cron.

Numeric content inside square brackets within a node body recognised as a token with a type of int

$
0
0

Problem/Motivation

I have a piece of content that requires a time format to be entered within square brackets. Examples are [16:00] and [12:00].

This is being recognised as a token with a type of int, however Drupal\Core\Utility\Token->generate() requires the type to be a string.

Steps to reproduce

* Install Drupal 10.1.x
* Install and enable the token_filter module.
* Install and enable the hux module.
* Create and enable a custom module with a very basic hook_tokens().
* Create a basic page with some content including [16:00] and [12:00].
* Save the page, and attempt to view it.
* You'll be presented with a TypeError - Argument #1 ($type) must be of type string, int given.

Proposed resolution

In the doReplace() method of Drupal\Core\Utility\Token, cast the first argument to a string.
$replacements += $this->generate((string) $type, $tokens, $data, $options, $bubbleable_metadata);

Remaining tasks

* Create a failing test.
* Create patch.
* Ensure test is passing.

User interface changes

N/A

API changes

N/A

Data model changes

N/A

Release notes snippet

N/A

Use specific subject line in update emails

$
0
0

Postponing on #3276953: Add tests of new release emails

Problem/Motivation

I got an email titled New release(s) available for [my site's title]. However, the email body started with There was a problem checking available updates for Drupal.

Checking further, there were in fact no updates available.

  • If Drupal was unable to confirm the need for updates, the email title should not say "new releases available".
  • If Drupal has security updates pending, the email title should state that it is a security notice.

Steps to reproduce

Proposed resolution

When there is any security update available the subject contains "Security release(s) available for"
When all of the attempts to get release information fail, the subject contains "Failed to get release information for"
In all other cases the subject contains "New release(s) available for". In the case the body may still contain a message about failing to get release information.

Remaining tasks

Review
Commit

User interface changes

API changes

Data model changes

Release notes snippet

password and password_confirm children do not pick up #states or #attributes

$
0
0

I searched the issue queue but didn't see a duplicate. I apologize if I missed one!

D7 core does not seem to pass down #states or #attributes assigned to a parent password_confirm element, to it's children.
I was trying to turn autocomplete off for the password confirm field and add a state.

$form['password_field']['#pre_render'] = array('my_form_process_password_confirm');

function my_form_process_password_confirm($elements) {
  foreach (element_children($elements) as $element) {
    $elements[$element]['#attributes']['autocomplete'] = 'off';
    $elements[$element]['#states'] = array(
      'visible' => array(
      	':input[name="my_checkbox"]' => array('checked' => TRUE),
      ),
    );
  }

return $elements;
}

Proposed resolution

Add the states data selector to the wrapper attributes

Validation constraints error

$
0
0

Problem/Motivation

When I try to arrange text formats and editors settings I get the following error.

Symfony\Component\Validator\Exception\LogicException: The LangcodeRequiredIfTranslatableValues constraint can only operate on the root object being validated. in Drupal\Core\Config\Plugin\Validation\Constraint\LangcodeRequiredIfTranslatableValuesConstraintValidator->validate() (line 26 of var/www/html/mysite/web/core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraintValidator.php).

"To log in to this site, your browser must accept cookies from the domain" error message displayed when user goes back and reload the page

$
0
0

Problem/Motivation

The message "To log in to this site, your browser must accept cookies from the domain" is displayed to the user when they use "Back" button and refresh the page.

Steps to reproduce

1. Login with any user
2. Log out
3. Click to go back (Back button of the browser)
4. Reload the page
5. See the message

The message is quite confusing for the user when they perform the steps above as it doesn't make sense.

Is this by design?

GIF showing the steps and error

Also use text editor (CKEditor) for "summary" of a text field

$
0
0

Problem/Motivation

The Summary part of the textfield should have a WYSIWYG Editor because the format applies to body and summary.

Proposed resolution

@todo
- Lock down the format for summary in the widget. (?)

Remaining tasks

  1. Update this summary to accurately reflect the proposed change.
  2. Fix the existing test failures.
  3. Add new tests to cover the new functionality.
  4. Move this back to 'Needs review'
  5. Reviews/refinements.
  6. RTBC.
  7. Commit.

User interface changes

WYSIWYG editor available on the separate 'Summary' field on text areas that support them.

Before

After

API changes

TBD.

Data model changes

TBD, hopefully none.


Navigation: Fix LB placeholder label on navigation block page

$
0
0

Problem/Motivation

The font size of the placeholder label is large and breaks the UI.

Steps to reproduce

1. Go on /admin/config/user-interface/navigation-block page
2. Uncheck the checkbox "Show content preview"
3. See the Layout builder region in the sidebar
4. Font size is breaking the UI.

Proposed resolution

Remaining tasks

User interface changes

Before

API changes

Data model changes

Release notes snippet

If no icon for a top-level item is provided, use the first two letters

$
0
0

Problem/Motivation

If we use a default icon, then all new menu items who don't supply a custom icon in code, will have the same icon, which is very confusing.

Steps to reproduce

Proposed resolution

Instead of a default icon, use the first two letters of the menu item name.

Remaining tasks

User interface changes

API changes

Data model changes

Provide users with the option to select an appropriate moderation state when reverting to a previous revision

$
0
0

Problem/Motivation

When reverting to a previous revision of an item of content, the new revision created matches the moderation state of the revision being reverted.

While this keeps the integrity of the workflow intact, since content can only be recreated in a state that was valid at some previous point in time, it may not always be what users expect and it limits the utility of reverting in general, since certain revisions can only be recreated and immediately published or can only be recreated and reverted back to a draft.

Proposed resolution

A few proposals have been made to address this issue:

@catch in #17 (paraphrasing):

  • Only allow reverts to default revisions
  • Alter the access for the revert action to also require some kind of content_moderation permission
  • Leave it as is, but probably with some messaging

@jhedstrom in #18:

  • Could we simply add the moderation select list to the revert confirmation form?

@Sam152 in #30:

  • Building on adding a moderation select list to the revert screen, but introducing additional permissions for reverting to each state.

Remaining tasks

Agree and implement an approach.

User interface changes

API changes

Data model changes

Allow WEBP quality to be configurable in GD2 image manipulation toolkit settings

$
0
0

Problem/Motivation

According to php documentation when converting image to webp quality argument can be passed to set the quality of the image.
In gd.php default is set to 80% and there is no way to configure or change this value.
function imagewebp($image, $to = null, $quality = 80): bool {}

Steps to reproduce

Go to admin/config/media/image-toolkit
Select GD2 for image processing
Only JPEG quality is configurable not WEBP.

Proposed resolution

Make the quality settings configurable and pass the configured value to imagewebp().

User interface changes

When selected GD2 to process images add an additional field to take the WEBP quality value similar to ones taking JPEG.

Release announcements should show up in Google over release notes

Remove the red color of the 'required' asterisk.

$
0
0

Problem:

Only local images are allowed.

Currently the asterisk that is added to the label of required form elements is colored red. This is not the best core default: it attracts too much attention and red sends the wrong message (red = error).

Solution:

remove the CSS bit that adds the red color.

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue categoryTask since it's not a bug, but change in a way content is displayed
Issue priorityNormal
Unfrozen changesUnfrozen since it changes only CSS

Passes beta evaluation process, committable to 8.0.x

More link is missing in pager when using the "Some" pager and there are more records than shown

$
0
0

Problem/Motivation

The "More link" won't render under the Views pager when using the "some" pager and there are more records.

In file web/core/modules/views/src/Plugin/views/pager/Some.php, the function postExecute() overwrite the total_items, which was set correctly in file web/core/modules/views/src/Plugin/views/pager/PagerPluginBase.php, function executeCountQuery().

This bug could be introduced by https://www.drupal.org/project/drupal/issues/3265798
See another user report in https://www.drupal.org/project/drupal/issues/3265798#comment-15159116

Steps to reproduce

  1. Create a View with more than 3 records
  2. Under the "Pager" option, select "Display a specified number of items" and set "3" items for "Use pager"
  3. select "Yes" for "More link"

You cannot see the more link in the preview. To enforce, you must use "Always display the more link" in the "More link" setting.


OOP hooks using event dispatcher

$
0
0

Problem/Motivation

For a very long time we wanted to introduce hooks in some OOP manner. The following goals altogether however have proven elusive

  1. No magic naming in the implementations.
  2. A hook implementation should be simple and have minimal boilerplate.
  3. Calling any hook without defining anything should be possible as it is now.
  4. Reordering hooks should be doable.
  5. Relative reordering should be easier. ckeditor5_module_implements_alter is ouch.
  6. Minimal added code to core.

Proposed resolution

Big kudos to EclipseGc for realizing the Symfony EventDispatcherInterface has a getListeners method which allows us to call listeners any way we want. Unlike dispatch this allows us to call listeners with any arguments we want without defining an event object. dpi pioneered attributes for hooks on Hux. I also advocate for attributes but simpler. In short:

namespace Drupal\node\Hook;
class NodeHooks {
  #[Hook('user_cancel')]
  public function userCancel($edit, UserInterface $account, $method) {

In detail:

  1. Hook implementations go into Drupal\modulename\Hook namespace (subdirectories work too). Familiar pattern from plugins. These are automatically registered as autowired services with the class name as the service id. This makes for minimal boilerplate. If autowire doesn't suffice -- should be very rare -- they can be registered manually as well, the service id is the class name.
  2. Hook implementations needs to be marked with a Hook attribute. This is new. Either on a method #[Hook('user_cancel')] or on the class #[Hook('user_cancel', method: 'UserCancel')]. If the class Hook doesn't specify a method, __invoke is the default method.
  3. The attribute supports a priority as well: #[Hook('user_cancel', priority: -20)]. The priority defaults to such values as to keep module order.
  4. The edge case of "implementing a hook on behalf of another module" is also supported by simply specifying the module in the attribute. It defaults to the defining module.
  5. This attribute is patterned on the Symfony AsEventListener attribute which is shipped with the event dispatcher but it is only used in the full Symfony framework.
  6. Multiple implementations are totally allowed on multiple axis: one method can implement multiple hooks by adding a Hook attribute for each. One module can implement a hook as many times as it wants in as many classes as it wants. This allows, for example, adding form_alter implementations firing on other conditions than form id without touching any existing implementation. For now I exempted the hooks fired via ModuleHandler::invoke from this, documentation would be needed for those, luckily very few such are used runtime: library_build_info, mail and help. For example, help expects a string return, it's not even clear what multiple implementations could mean in this case. Also, ModuleHandler::invoke is used as a replacement for a failure-tolerant $function() call, once again it's not at all clear what multiple replacements could mean.
  7. All the implementations are stored in a container parameter. This is a multidimensional array with keys for hook, class, method and the values are module and priority. To reorder, use a service provider alter and change the priority. A proof of concept of how ckeditor5_module_implements_alter will look after is provided. I also added a helper method which retrieves all the priorities for a given hook to make absolute ordering easier for now. Before/after is certainly a possibility in a followup.
  8. Old style procedural calls are integrated into the new system. Separate hook caching is removed, everything is now stored in the container. I suggest contrib and custom could start converting hooks to new style and have the procedural implementation call the new style which is, again, available as a service. The attribute supports a "replaces" key for this purposes. This allows maintaining one hook implementation code while being compatible with a wide array of Drupal versions. I suppose since interfaces for autowire got added for D10.1, the floor would be D10.1 which is just as well, I believe D10.0 is out of support already.
  9. Not much code is needed and a lot of is BC: due to the vast simplification of ModuleHandler, core/lib/Drupal/Core only becomes 72 lines longer. This is enough for the new attribute, gathering all the implementation data, registering them as event subscribers and firing them as needed. Once the BC layers are removed, it'll be significantly negative. Luckily we didn't need to provide any new facility for hook_module_implements_alter() as service provider alter can do it nor any sorting because event dispatcher does that.
  10. If loading all hook classes at build time becomes a problem we already have an issue for that: #3395260: Investigate possibilities to parse attributes without reflection .
  11. For API documentation purposes, it is possible to create a separate attribute class for each and move the doxygen to the constructor. An example of such an attribute is provided in HookFormAlter (without moving the doxygen for now).

The attached PR contains a PoC for a conversion of ckeditor alter, one node hook manually converted showing how autowire would work. I have a quick-and-dirty conversion script which eventually needs to become a rector rule but it allows interested parties to see the future.

Remaining tasks

  1. A framework manager needs to review per 61.
  2. While more tests could be written, the difficulty of getting the current test harness to pass proves there is already ample testing already. This is a decision for the community to make.

User interface changes

API changes

Oh my.

Data model changes

Release notes snippet

Move to new test path in NodeTest as per todo.

$
0
0

Problem/Motivation

Parent issue works as designed, we need to move along and try and execute: /Users/bjorn/projects/drupal/core/modules/jsonapi/tests/src/Functional/NodeTest.php:341. Which is a todo to remove some code when the issue is closed.

Steps to reproduce

Proposed resolution

Remove the code, enable new code as per comment in referenced line. See if all is good.

Remaining tasks

Remove the code
See all is happy and fine
...
Profit ;)

User interface changes

API changes

Data model changes

Release notes snippet

Nested modals don't work: opening a modal from a modal closes the original

$
0
0

Issue Summary

  • #46 Describes the problem as to why the issue is happening which generally narrows down to hard coding of html ids for modal opening and closing command.
  • #48 Provides a solution so that each open and close command can work with separate modal ids, It also provides a solution for media library form.
  • #73 Extracts the open and close command modifications from #48 so that it can be merged with core first and then for each individual case a separate issue and patch can be added.

Proposed resolution

  • Review and merge #73 or #48 in core.
  • Create individual issues for each possible use case like media library, Ckeditor etc.
  • Add the change records.

Original Post

I am currently looking into running CKEditor in a modal dialog using the Drupal Modal API.

At this moment it is working OK, but there is a problem with the link and image modals which can be triggered from the CKEditor interface. Those also use the Modal API and when triggering one of these functions, the modal containing CKEditor is fully closed.

Is there any way to open de link/image modal without closing the CKEditor modal? It seems like it is possible to define the HTML element to which the modal should append when triggering. When overriding this setting ('appendTo' => '#foo'), even the link/image modals are appended to #foo (instead of the default '#drupal-modal').

Any ideas on how to get this to work?
Thanks for your support.

Claro: Autocomplete dropdown bleeds through sticky table header

$
0
0

Problem/Motivation

Autocomplete dropdown of 'Authored by' search filter shows behind the content list table header.

Steps to reproduce

1. In Drupal 11.x, ensure that the admin content view (/admin/structure/views/view/content) contains the exposed filter criteria for "Authored by".
2. Go to /admin/content page.
3. Search any username in the 'Authored by' filter.
4. Observe the auto-complete behavior.

Proposed resolution

Apply z-index:500; to .ui-front class to fix this issue

Remaining tasks

User interface changes

Before Patch

After Patch

API changes

Data model changes

Release notes snippet

Wrong DRUPAL_ROOT with non-standard code structure

$
0
0

Problem/Motivation

When Drupal in installed in a non-standard installation structure, DRUPAL_ROOT is defined incorrectly and various parts of Drupal don't work.

This is important because the standard way of developing a Composer package, by defining a path repository in a project to symlink a git clone of the package, isn't currently possible with Drupal core.

Definitions

- project root: the folder where the root composer.json is
- app root (also drupal root): The folder where Drupal's entry-point index.php is. This is where the HTTP request to Drupal is made. Typically PROJECT_ROOT/web.
- scaffolding: The process which copies files into the app root when Drupal is installed with Composer. This is done by a Composer plugin within Drupal.
- Composer symlinking: The technique of using a 'path' repository for a package which points to a local git clone of the package. This causes Composer to symlink the package from the git clone into its location in the project. This is a method used to develop a package which needs to be used in the context of a Composer project -- such as Drupal core.

There are various kinds of installation structures for Drupal, depending on where and how Drupal core is installed:

- drupal/recommended-project: drupal scaffolded into the web/ folder.
- plain git clone of Drupal core, with `composer install` run at its root.
- drupal/legacy-project: drupal scaffolded into the project root.
- drupal core symlinked in by Composer, such as with the joachim-n/drupal-core-development-project Composer template. (This is the best way to develop a Composer package within a project -- see https://medium.com/pvtl/local-composer-package-development-47ac5c0e5bb4.)
- drupal installed in vendor/ - this is not possible because of other issues, and will not be fixed here, but this issue should aim to make DRUPAL_ROOT correct for this structure.

What causes the problem

We use Composer to install Drupal into the app root rather than /vendor, and Drupal
expects to find files like settings.php and extensions in the app root. Because of this, code in a Drupal project falls into several 'zones':

- Composer autoloader
- Composer vendor code
- Drupal core
- Drupal scaffolded files such as index.php and update.php
- Drupal settings, files, and extensions

These different zones don't all know how to get hold of code in the other zones:

- The autoloader always knows how to load Composer vendor code, and Drupal core code, because Composer installed it.
- Composer vendor code, e.g. Drush, knows the location of the Composer autoloader relative to itself, because it knows it's in vendor/foo/bar. But it has to make assumptions for the location of Drupal core or scaffolded files.
- Drupal core doesn't know the location of anything, because where it was installed is defined in composer.json. It has to make assumptions about how to get to the autoloader. It does that with a special autoload.php file at the root of the Drupal repository. (For the drupal/recommended-project template, an autoload.php is scaffolded into web/ so that it can go one level up and find the vendor folder. In drupal/legacy-project Drupal's include() loads the repository's autoload.php, and in drupal/recommended-project the same include() loads the scaffolded autoload.php.)
- Drupal core has to make assumptions about how to find its settings.
- Composer vendor code has to make assumptions about how to find Drupal settings. This affects things like Drush and Drupal Console.
- Drupal's scaffolded files can know about all code locations, since they are written by the scaffold plugin during Composer installation. During this process we can get the location of anything from Composer, and write it into the scaffolded files.
- Drupal settings.php file: knows the location of scaffolded index.php, as that is fixed relative to itself.

These assumptions all break in non-standard installation structures. In particular, the use of __DIR__ in these assumptions breaks when Drupal is symlinked into a project.

Fixing this is difficult because Drupal has MANY different entry points:

- HTTP request to the index.php file which is scaffolded into the app root
- HTTP request to scaffolded install.php
- HTTP request to scaffolded update.php
- HTTP request to core/rebuild.php, which is not scaffolded.
- tests run with phpunit
- tests run with run-tests.sh (this case doesn't really count, as run-tests.sh is only meant for Drupal CI, whose installation structure is a known quantity: see #3228531: document run-tests.sh as not intended for public consumption)
- code in a Composer package (e.g. Drush or Console) bookstraps Drupal
- scripts in core/scripts
- HTTP request to core/modules/statistics/statistics.php (yay! special case!)

Proposed resolution

Various approaches have been tried (see old branches in the issue fork). But ultimately, there's only one thing we can rely on: Composer knows the location of everything, because it installs everything.

Asking Composer runtime API every page load is potentially a performance hit, but it's simple to have Composer write a file containing the data we need during Composer installation.

So the plan is as follows:

1. For Composer vendor code which needs to find Drupal, add a new Composer plugin which is inside core, whose sole job is to write the locations class file into the plugin's own folder. Make the plugin required by core, so it's always present, even in projects that don't use the scaffold plugin. And nobody else needs to worry about defining it, as to change the location values you set them in composer.json.

The file is written as a class, so that it can always be loaded by Composer. (Making it a plain file registered as a Composer autoload 'file' item causes problems with package dependency hierarchy.) This class currently only defines one constant, but #3208975: split the concept of DRUPAL_ROOT/app root into app root and Drupal web root could expand on that.

This plugin should always be installed with Drupal, whether using the drupal/recommended-project or drupal/legacy-project templates, or running Composer on a git clone of core.

Deprecate the $app_root parameter to DrupalKernel, since DrupalKernel uses the plugin.

2. For code in Drupal core which needs to get to the autoloader, replace all uses of __DIR__ with code which uses the actual path of the executed file. This is to prevent PHP from resolving symlinks.

API changes

- New Composer plugin in Drupal core
- new DrupalLocations class, which 3rd party code can use to find Drupal's location
- DrupalKernel's $app_root parameter in various methods is deprecated
- DrupalKernel::guessApplicationRoot is deprecated and renamed. This is protected but Drush uses it, for instance.

Original summary

I usually link drupal inside my www directory like seen in the following ls output.
I think symlinking like that is not unusual, as it helps with version controlling of own projects.

core -> ../drupalcheckout/core
.htaccess
../drupalcheckout/index.php
../drupalcheckout/modules
profiles
robots.txt -> ../drupalcheckout/robots.txt
sites
themes -> ../drupalcheckout/themes

i've attached a script which will setup such an environment in the current directory.

With this setup BASE_ROOT in install.php will be set to the drupalcheckout directory.
Install then tries to find a settings.php in ../drupalcheckout/sites/default and not ./sites/default.

same Problem and fix should be considered for update.php and authorize.php

related discussions:
#1055856: Optimize settings.php discovery
#484554: Stop relying on Apache for determining the current path

Viewing all 297150 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>