Problem/Motivation
Discovered in #3412361: Mark Editor config schema as fully validatable.
That issue added validation for editor.editor.*:image_upload.scheme: that must be one of the registered StreamWrapperInterface::WRITE_VISIBLE stream wrappers.
However, it appears that in some scenarios, the public stream wrapper is present in \Drupal\Core\StreamWrapper\StreamWrapperManager::$info but absent from \Drupal\Core\StreamWrapper\StreamWrapperManager::$wrappers, which causes \Drupal\Core\StreamWrapper\StreamWrapperManager::getNames(StreamWrapperInterface::WRITE_VISIBLE) to return … nothing! 😱
Consequence: a validation error like this is generated:
The file storage you selected is not a visible, readable and writable stream wrapper. Possible choices: <em class="placeholder"></em>.
… because there are no possible choices 😅
Steps to reproduce
Remove
'editor.editor.*' => [
'image_upload.scheme' => [
'^The file storage you selected is not a visible, readable and writable stream wrapper\. Possible choices: <em class="placeholder"><\/em>\.$',
],
],
from \Drupal\Core\Config\Schema\SchemaCheckTrait::$ignoredPropertyPaths.
A number of tests will fail.
Proposed resolution
Fix \Drupal\Core\DrupalKernel::resetContainer() to maintain stream wrappers.
Remaining tasks
None
User interface changes
None.
API changes
None.
Data model changes
None.
Release notes snippet
N/A
| Comment | File | Size | Author |
|---|
Issue fork drupal-3416735
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
Comment #2
wim leersI wonder if #3416697: Remove install container definitions of FileSystem and StreamWrapperManager fixed this? 🤔
Comment #3
andypostIs it still needed?
Comment #4
omarlopesinoI am still having this problem using Drupal 11.x version. What I do to reproduce it is installing a Drupal recipe that adds a editor with a image upload configuration.
Comment #6
omarlopesinoI've added a MR that registers the stream wrapper information into
\Drupal\Core\StreamWrapper\StreamWrapperManager::$wrapperswhen the stream wrapper is being added. It fixes my problem.Please review if this can be a good solution. Let me know if it needs work / a different approach. Thanks!
Comment #7
smustgrave commentedThanks for working on this!
Even though a 1 liner the issue is marked major so think maybe we should add some kind of test coverage that shows the issue.
Then if we determine that fix addresses the problem we should update the issue summary.
Comment #10
herved commentedI stumbled on this issue because I found a scenario where stream wrappers are not registered properly.
When more than 1 module is enabled, stream wrappers are not registered, see https://git.drupalcode.org/project/drupal/-/blob/11.x/core/lib/Drupal/Co... which calls
$this->updateKernel([])and doesn't call\Drupal::service('stream_wrapper_manager')->register();after it.Notice that just above it we have a call to
::updateKerneland then it registers stream wrappers.That particular code seems to originate from #3416522: Add the ability to install multiple modules and only do a single container rebuild to ModuleInstaller.
This can cause all kind of issues.
In my case, I have a config import that has to enable more than 1 module and delete an image style, and noticed the image style folder is not being deleted, which should happen in
\Drupal\image\Entity\ImageStyle::postDeletebut stream wrappers are not registered.The same also happens when uninstalling a module:
::updateKernelis called but stream wrappers are not registered. So a config import that has to uninstall a module and delete an image style won't delete the corresponding folder.The IS only mentions "in some scenarios" for the original case reported, but module configs are installed right before the
updateKernelcall so I suspect it is the same scenario? when multiple modules are enabled at once? or a module is uninstalled?---
MR 10421 here seems to solve those cases as well, and seems like the most reliable way.
Perhaps we should delete
StreamWrapperManager::registerentirely?Comment #12
herved commentedStatic patch of MR 10421
Comment #13
damienmckennaComment #16
neptune-dc commentedAdded a test https://git.drupalcode.org/issue/drupal-3416735/-/compare/main...3416735...
It fails when
It passes when
Comment #17
neptune-dc commentedChanged to needs review.
Comment #19
borisson_I'm super confused by this as well, I see that you added some of the things I looked at in my review that made raise an eyebrow were added in a phpstan commit. It has so many things that should not be needed to satisfy our coding standards and phpstan rules.
Comment #20
smustgrave commentedI suspect maybe you aren’t picking up core standards? It’s a little slower but you can pull all that stuff out and rely on the pipeline.
The bracket being in line is really weird because that’s been a standard forever
Comment #21
borisson_You may need to point phpcs to the phpcs.xml file in the core directory so it runs with the correct standard, it looks like it may be defaulting to another standard?
Comment #22
neptune-dc commentedComment #23
smustgrave commentedLeft some comments on the MR, another problem I'm seeing is the MR is almost 2000 commits back :) should be rebased.
Pipeline needs to be passing to move forward.
Comment #24
neptune-dc commentedComment #30
alexpottI've just pushed a fix for this that I found while working on #3498026: RecipeRunner::processInstall() should allow for installing multiple modules at once ... also #3579611: StreamWrapperManager::getNames() and ::getDescription() broken will fix some of the other recent issues with stream wrappers.
Comment #31
alexpottComment #32
alexpottComment #33
borisson_Left one comment on the code because I don't really understand it, but test coverage looks to be good.
Comment #34
alexpottWell the problem we have is that when the container is reset the stream wrapper manager service loses the information about what wrappers have been registered because a new object is created. So we need to rebuild \Drupal\Core\StreamWrapper\StreamWrapperManager::$wrappers.
This leads to two thoughts... either we should unregister the wrappers during the container reset - or we should make \Drupal\Core\StreamWrapper\StreamWrapperManager::$wrappers a static. I think the first option is better as would allow a reset to remove a stream wrapper.
Comment #35
berdir#3575642: Always free up old container on rebuild, not only in the installer also adds support for an upstream feature so that Services can react to a reset, sounds like that might be useful for that?
Comment #36
alexpottActually I was wrong - new services are not going to be added to the container during a container reset... so I've removed the unregister and added a comment.
Comment #37
borisson_From reading the code and the comments here, as well as the thread on slack, this seems to make a lot of sense.
I looked at the rest of the lines in
$ignoredPropertyPaths, and the rest is search module and contact module, I think that means we can create a followup for this to remove all of them (and that functionality) after both of those are removed as well?Comment #40
catchCommitted/pushed to main and 11.x, thanks!