Problem/Motivation

The extension system exposes single-extension pathname accessors that return the path to an extension's .info.yml file:

- Drupal\Core\Extension\ExtensionList::getPathname($extension_name)
- Drupal\Core\Extension\ExtensionList::setPathname($extension_name, $pathname)
- Drupal\Core\Extension\ExtensionPathResolver::getPathname($type, $name)

These overlap confusingly with the path APIs most consumers actually want:

- ExtensionList::getPath() / ExtensionPathResolver::getPath() for an extension's directory.
- ExtensionList::getPathNames() for the full name → info-file-path map.

getPathname() returns the .info.yml path of a single extension, which almost no caller genuinely needs — they want the directory (getPath()), and the rare consumer that needs info-file paths can read the map from getPathNames(). setPathname() exists mainly to prime an internal cache and has no legitimate public use. Keeping these methods as first-class public API invites misuse and keeps an ambiguous surface alive.

This is a follow-up to #2934063: Remove the workaround in \Drupal\Core\Installer\ExtensionListTrait::setPathname(), which removes the installer-specific pathname workaround while keeping these methods working (so existing consumers are not broken). With the workaround gone, the single-extension pathname methods can be formally deprecated in favor of the path-based APIs.

Proposed resolution

Deprecate the single-extension pathname methods in **drupal:11.5.0**, removal in **drupal:13.0.0**, keeping them functional during the deprecation:

- Deprecate ExtensionList::getPathname() — no direct replacement. Callers needing a directory use getPath(); callers needing the info-file path read getPathNames().
- Deprecate ExtensionList::setPathname() — no public replacement; remains internal/BC-only.
- Deprecate ExtensionPathResolver::getPathname() — use ExtensionPathResolver::getPath().
- Update ExtensionPathResolver::getPath() to resolve directly through the typed extension list and handle core directly, instead of delegating through getPathname().
- Keep ExtensionPathResolver::getPathname() working by composing the info-file path from getPath() + /$name.info.yml, including the core/core.info.yml special case.
- Update core callers/tests that assert an extension **directory** to use getPath(), and those that need the full .info.yml path to use getPathNames().
- Add focused deprecation tests for all three methods.

Scope boundaries:

- No installer/service-wiring changes — that is #2934063: Remove the workaround in \Drupal\Core\Installer\ExtensionListTrait::setPathname().
- Do not blindly rewrite every getPathname() token in the repo. Many are calls on Extension objects, \SplFileInfo, uploaded files, or other unrelated APIs and must stay unchanged.
- Do not change DatabaseDriverList::getPathname() / setPathname() (a separate extension-list-like implementation) unless reviewers explicitly request it.

Remaining tasks

- Postpone on / rebase atop #2934063: Remove the workaround in \Drupal\Core\Installer\ExtensionListTrait::setPathname().
- Write a change record for the three deprecations.
- Review.

User interface changes

none

Introduced terminology

none

API changes

Deprecated for removal in drupal:13.0.0 (still functional in 11.5.0):

- ExtensionList::getPathname() — use getPath() (directory) or getPathNames() (info-file path map).
- ExtensionList::setPathname() — no public replacement; internal/BC-only.
- ExtensionPathResolver::getPathname() — use ExtensionPathResolver::getPath().

Data model changes

Release notes snippet

Issue fork drupal-3601481

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

andypost created an issue. See original summary.

andypost’s picture

Status: Active » Needs work

NW for reviews and approval