Problem/Motivation
The installer carried a special-case workaround for extension pathnames.
\Drupal\Core\Installer\ExtensionListTrait and the
InstallerModuleExtensionList / InstallerThemeExtensionList subclasses kept a
static pathname cache, and install_begin_request(), InstallStorage and
ExtensionInstallStorage primed ExtensionList::setPathname() for the install
profile. This existed because early-install profile pathnames were not otherwise
resolvable across container rebuilds.
The base ExtensionList now resolves manually added pathnames ($addedPathNames)
directly, so the installer-specific machinery is redundant and can be removed.
Proposed resolution
- Remove profile pathname priming from install_begin_request(), InstallStorage and ExtensionInstallStorage.
- Resolve the active install profile through the profile extension list in ConfigInstaller.
- Seed ModuleExtensionList added pathnames directly instead of via setPathname().
- Stop NormalInstallerServiceProvider swapping in the installer-specific extension lists.
- Reduce InstallerModuleExtensionList, InstallerThemeExtensionList`and ExtensionListTrait to deprecated backward-compatibility shims (deprecated in 11.5.0, removed in 13.0.0) — see CR #3577846: Installer-specific extension list implementations are deprecated.
- Deprecate the now internal-only ExtensionList::setPathname() (deprecated in 11.5.0, removed in 13.0.0).
Remaining tasks
- file CR
- clean-up code
User interface changes
API changes
Deprecated in drupal:11.5.0, removed in drupal:13.0.0:
- `Drupal\Core\Installer\ExtensionListTrait` — no replacement; base extension
list behaviour provides the same functionality.
- `Drupal\Core\Installer\InstallerModuleExtensionList` — use
`Drupal\Core\Extension\ModuleExtensionList`.
- `Drupal\Core\Installer\InstallerThemeExtensionList` — use
`Drupal\Core\Extension\ThemeExtensionList`.
- `Drupal\Core\Extension\ExtensionList::setPathname()` — internal; no replacement.
Data model changes
| Comment | File | Size | Author |
|---|
Issue fork drupal-2934063
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:
- 2934063-remove-the-workaround
changes, plain diff MR !14808
- 2934063-rescoped
changes, plain diff MR !16088
Comments
Comment #10
quietone commentedThis is now in \Drupal\Core\Installer\ExtensionListTrait.
Comment #15
andypostComment #16
andypostWIP MR created, probably it depends on #3335756: Drop sequences table in Drupal 12
Comment #18
andypostrebased, ready to go
Comment #19
andypostcreated change record https://www.drupal.org/node/3577846
trying to remove remaining usage of
setPath()Comment #20
andypostthere's not a lot of usage in contrib so the method could be deprecated in followup
https://search.tresbien.tech/search?q=setPathname%5C(
Comment #21
andypostCodex summarized that variable still required overlay for scanned modules, maybe it make sense to file follow-up
The key distinction is:
-
$pathNamesinExtensionList:91means “the complete filename map is initialized”.-
$addedPathNames:94is the overlay for pathnames seeded from code.That matters because
getPathNames():423usesNULLon$pathNamesas its initialization sentinel. Once$pathNamesis non-NULL, Drupal assumes the full available-extension map is already known and does not load state or rescan.Why ModuleExtensionList cannot just write into
$pathNames:- %container.modules% only contains enabled modules, built by
DrupalKernel::getExtensionsParameter():1637.- extension.list.module must represent all available modules, not just enabled ones. ModuleExtensionList::doList():153 scans all modules, then marks installed status separately.
-
ModuleInstaller::install():135explicitly does reset()->getList() so newly added modules on disk are rediscovered.If you seed
$pathNameswith the enabled-module subset, you are tellingExtensionList“the full map is ready”, which is false. That is exactly whydriver_testdisappeared earlier: the partial container seed prevented full discovery.$addedPathNames is still doing one real job today:
-
ModuleExtensionList::__construct():79seeds enabled-module pathnames from%container.modules%as a fast path.-
getPath():552andgetPathname():523can then answer for installed modules without initializing the full filename cache.That fast path is not theoretical. It is what removed the extra query in the OpenTelemetry regressions you just found.
Comment #22
smustgrave commentedShould this be a D12 priority one?
Comment #23
catchThe test failure here looks non-random.
Comment #24
andypostFixed AJAX test, the cause:
core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php:70deliberately injectsfakeLibrary/fakeLibraryintodrupalSettings.ajaxPageState.libraries. On this branch,core/lib/Drupal/Core/Extension/ExtensionPathResolver.php:81now throws for unknown extensions instead of degrading through the olddirname(getPathname())behavior. That bubbles through library discovery during AJAX asset resolution, so the fake library kills the request withRuntimeException: Unable to complete AJAX request. The old job 9361908 andthe new job 9367508 are the same regression.
Comment #25
andypostneeds work to split it and revert changes in deprecated classes so any consumers will not break
Comment #26
andypostasked GPT to plan split it
## Summary
- Use 3 issues/MRs: one installer/pathname cleanup, one public API deprecation cleanup, one independent asset-library fix.
- Do not create separate issues for installer wrapper classes that are being deprecated.
- Deprecated installer classes should get only minimal BC/deprecation handling, not standalone refactoring.
## Issue 1: Remove installer pathname workaround
- Move the real behavior change into base extension-list handling so installer-specific static pathname caching is no longer needed.
- Stop the installer container from swapping in InstallerModuleExtensionList and InstallerThemeExtensionList.
- Remove installer/config/profile path priming workarounds from install and config storage code.
- Update related installer/profile kernel tests that manually seeded profile pathnames.
- Deprecate installer wrapper trait/classes as BC shims, but do not split their internals into separate work.
## Issue 2: Deprecate pathname APIs and update core usage
- Deprecate ExtensionList::getPathname(), ExtensionList::setPathname(), and ExtensionPathResolver::getPathname().
- Update core tests/callers to prefer getPath() for directories and getPathNames() when the info-file path is explicitly needed.
- Add focused deprecation coverage for the remaining deprecated API surface.
- Keep this separate from Issue 1 only because it is public API/deprecation-policy work and may need separate change-record review.
## Issue 3: Ignore unknown asset-library extensions
- Catch UnknownExtensionException in LibraryDiscoveryCollector.
- Return an empty library set for unknown client-supplied library extensions.
- Add focused unit coverage for unknown extension lookup.
## Test Plan
- Issue 1: installer/config/profile kernel tests, ExtensionListTest, PHPStan baseline check.
- Issue 2: ExtensionListTest, ExtensionPathResolverTest, deprecation tests, PHPCS/cspell for touched docs/messages.
- Issue 3: LibraryDiscoveryCollectorTest.
Comment #27
andypostCreated split #3601471: Ignore unknown client-supplied asset library extensions in LibraryDiscoveryCollector
and working on to split deprecation to re-scope properly
Comment #28
andypostand split out deprecation #3601481: Deprecate extension pathname APIs in favor of path-based lookups
Comment #30
andypostfile clean MR https://git.drupalcode.org/project/drupal/-/merge_requests/16088
Comment #31
andypostComment #32
andypost@alexpott I think it ready to go
Comment #33
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #35
longwaveMR!16088 looks nice and self contained and ready to go to me.
Comment #37
catchThis looks great, so much code removed/deprecated.
Committed/pushed to main, thanks!
Will need a backport MR for 11.x, looks like only one file conflicts.
Comment #39
andypostcherry-picked commit and added
InstallerThemeEngineExtensionListas it was removed from main via #3575467: Remove deprecations related to the theme engineusing previous MR but target now 11.x https://git.drupalcode.org/project/drupal/-/merge_requests/14808
Comment #40
longwaveBackport looks good, thanks @andypost.
Comment #42
catchCommitted/pushed to 11.x, thanks!
Comment #44
andypostCR updated, look ready for publishing