Problem/Motivation
Drupal core 11.4 added a YamlCacheCollector parameter to the LibraryDiscoveryParser constructor as part of #3486503 (change record: #3593451). The new parameter replaces some uses of FileCache with a persistent cache.file_parsing bin backed by FileParsingCacheCollectorBase.
PatternLibraryParserBase extends LibraryDiscoveryParser and passes arguments through to parent::__construct(). On Drupal 11.4, the parent constructor expects YamlCacheCollector as an additional parameter. Without it, the container falls back to a deprecated service lookup that triggers a ServiceNotFoundException for libraries.parsing_cache in environments where the container is not fully available (unit tests, early bootstrap).
On Drupal 10, the YamlCacheCollector class does not exist. The parameter type hint, parent::__construct() call arity, service definition, and PHPStan configuration must all remain compatible with both Drupal 10.3+ and 11.4+.
Three issues surface from this change:
- The parent class
LibraryDiscoveryParserstores the application root as$this->rootin Drupal 10 via manual assignment, but Drupal 11.4 changes how this property is declared.PatternLibraryParserBasesubclasses reference$this->rootthroughout. To maintain cross-version compatibility, the child class must declare its ownprotected string $rootproperty and assign it explicitly in the constructor body rather than relying on constructor promotion or the parent's property declaration. The native type must not appear on the constructor parameter itself, or PHP emits a fatal error ("Type must not be defined") when the child's property conflicts with the parent's declaration. - The
patternkit.asset.library.parser.baseservice definition must pass thelibrary.parsing_cacheservice soYamlCacheCollectorreachesparent::__construct()on Drupal 11.4. The service reference must use the optional prefix (@?library.parsing_cache) so the container injectsNULLon Drupal 10 where the service does not exist. - PHPStan suppressions with
reportUnmatched: falseare needed for the cross-version type errors (YamlCacheCollectorclass not found, extra constructor parameter count). Unit test factories must conditionally createYamlCacheCollectormocks usingclass_exists()guards, following the same pattern already established forComponentPluginManager.
Steps to reproduce
- Install Patternkit on Drupal 11.4.
- Clear caches (
drush cr). - Observe a PHP fatal error in
PatternLibraryParserBase::__construct()related to the$rootproperty type conflict, or aServiceNotFoundExceptionforlibraries.parsing_cache. - Alternatively, run
phpunit tests/src/Unit/on a Drupal 11.4 environment and observe multipleServiceNotFoundExceptionfailures.
Proposed resolution
Update PatternLibraryParserBase and its service definition for cross-version compatibility with both Drupal 10.3+ and 11.4+.
Constructor changes
src/Asset/PatternLibraryParserBase.php:
- Remove the native type from the
$rootconstructor parameter to avoid the PHP fatal error when the parent's property declaration differs across core versions. - Add an explicit
protected $rootproperty declaration (untyped, matching the parent) and assign it in the constructor body. This preserves the$this->rootreferences used by parser subclasses, independent of how the parent class stores the application root. - Add a nullable
?YamlCacheCollector $yaml_cache_collector = NULLparameter and pass it through toparent::__construct(). - Add the
@paramdocblock entry for the new parameter.
Service definition
patternkit.services.yml:
- Add
@?library.parsing_cache(optional service reference) to thepatternkit.asset.library.parser.baseabstract service arguments, positioned before the existing optional@?plugin.manager.sdcargument. The@?prefix injectsNULLon Drupal 10 where the service does not exist, matching the established pattern.
PHPStan cross-version suppressions
phpstan.neon:
- Suppress the invalid type error for
YamlCacheCollectoron Drupal 10 where the class does not exist. - Suppress the "invoked with 8 parameters" error for
parent::__construct()which only accepts 7 parameters on Drupal 10. - Use
reportUnmatched: falseon both suppressions so they do not cause failures when running PHPStan against Drupal 11.4 where the types are valid.
Unit test compatibility
tests/src/Unit/Asset/PatternLibraryParser/PatternLibraryParserTestBase.php:
- Add a
$yamlCacheCollectorproperty with aclass_exists(YamlCacheCollector::class)guard insetUpParserDependencies(), following the existing pattern used for$componentPluginManager. - Pass the mock (or
NULL) to bothgetParserInstance()andgetPartialMock()factory methods.
Remaining tasks
- Review and test the merge request.
- CI validation on both Drupal 10 and 11.4.
User interface changes
None.
Introduced terminology
None.
API changes
PatternLibraryParserBase::__construct() gains a new nullable ?YamlCacheCollector parameter before the existing optional $componentPluginManager parameter. Any code that instantiates a PatternLibraryParserBase subclass directly (rather than through the service container) must pass the new argument. In practice, all parser instances are created via services.yml and this change is transparent.
Data model changes
None.
Release notes snippet
Patternkit is now compatible with Drupal 11.4. The PatternLibraryParserBase constructor has been updated to accept the new YamlCacheCollector service introduced in Drupal core 11.4 (#3486503) while remaining backward compatible with Drupal 10.3+. Sites upgrading to Drupal 11.4 should update Patternkit to this release to avoid PHP fatal errors during cache rebuilds.
Issue fork patternkit-3604089
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:
- 3604089-drupal-11.4-compatibility
changes, plain diff MR !196
Comments
Comment #3
sluceroComment #5
sluceroResolution for this issue was included in the MR for #3587714: Revert Reusable Block Support Removal Until Later Release as commit 909c29, so as of merging in MR !190 this issue is resolved for inclusion in the 9.1.3 release.
See #3542304: Patternkit 9.1.3 Release Plan.