Skip to content

Add rules to detect missing CacheableMetadata parameter in entity operation methods and hooks#979

Merged
mglaman merged 13 commits intomainfrom
rule/entity-list-builder-operations-cacheability
Apr 22, 2026
Merged

Add rules to detect missing CacheableMetadata parameter in entity operation methods and hooks#979
mglaman merged 13 commits intomainfrom
rule/entity-list-builder-operations-cacheability

Conversation

@mglaman
Copy link
Copy Markdown
Owner

@mglaman mglaman commented Apr 15, 2026

Summary

Closes #930

Drupal 11.3 introduced a deprecation for EntityListBuilder::getOperations() and EntityListBuilder::getDefaultOperations() — both methods now accept an optional ?CacheableMetadata $cacheability = NULL second parameter (via a func_get_args() workaround until it becomes formal in Drupal 12.0.0). Custom subclasses that override these methods without the new parameter silently miss cacheability bubbling for access checks.

Similarly, hook_entity_operation and hook_entity_operation_alter now also accept a CacheableMetadata argument.

This PR adds rules to detect these outdated overrides and hook implementations:

EntityListBuilderOperationsCacheabilityRule: detects outdated overrides in EntityListBuilder subclasses.
HookEntityOperationCacheabilityRule and ProceduralHookEntityOperationCacheabilityRule: detects outdated hook_entity_operation(_alter) implementations.

All rules are registered behind the entityOperationsCacheabilityRule bleeding-edge flag.

• Version-gated: only fires for Drupal 11.3.x by reading \Drupal::VERSION; skips < 11.3 (parameter didn't exist yet) and >= 12 (PHPStan's native signature checking handles it once the parameter is formal).
• Error includes a tip linking to the change record https://www.drupal.org/node/3533080

Test plan

[ ] php vendor/bin/phpunit --filter=EntityListBuilderOperationsCacheabilityRuleTest — new test passes
[ ] php vendor/bin/phpunit — full suite green
[ ] php vendor/bin/phpstan analyze — no errors
[ ] php vendor/bin/phpcs — clean

mglaman and others added 4 commits April 15, 2026 16:27
…uilder subclasses

Closes #930

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…acheability parameter

Covers both OOP (#[Hook] attribute) and procedural hook implementations.
Procedural rule uses version_compare rather than ReflectionProvider since
api.php files are not loaded by default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new PHPStan bleeding-edge rules to detect Drupal 11.3.x cacheability-signature gaps where cacheability metadata is not bubbled due to outdated method/hook signatures.

Changes:

  • Introduces EntityListBuilderOperationsCacheabilityRule to flag EntityListBuilder/EntityListBuilderInterface subclasses overriding getOperations()/getDefaultOperations() without the new cacheability parameter (Drupal 11.3.x only).
  • Adds hook-focused cacheability rules for OOP (#[Hook]) and procedural hook implementations of hook_entity_operation / hook_entity_operation_alter.
  • Registers the new rules behind a bleeding-edge flag and adds PHPUnit fixtures/tests.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/Rules/Drupal/EntityListBuilderOperationsCacheabilityRule.php New rule to detect missing cacheability parameter in EntityListBuilder overrides (version-gated).
src/Rules/Drupal/HookEntityOperationCacheabilityRule.php New rule to detect missing cacheability parameter in #[Hook] OOP hook methods.
src/Rules/Drupal/ProceduralHookEntityOperationCacheabilityRule.php New rule to detect missing cacheability parameter in procedural hook implementations in .module/.inc.
tests/src/Rules/EntityListBuilderOperationsCacheabilityRuleTest.php Tests for the EntityListBuilder cacheability rule.
tests/src/Rules/HookEntityOperationCacheabilityRuleTest.php Tests for the OOP hook cacheability rule.
tests/src/Rules/ProceduralHookEntityOperationCacheabilityRuleTest.php Tests for the procedural hook cacheability rule.
tests/src/Rules/data/entity-list-builder-operations-cacheability.php Fixture classes for list builder override detection.
tests/src/Rules/data/hook-entity-operation-cacheability.php Fixture classes for #[Hook]-based hook detection.
tests/src/Rules/data/mymodule.module Fixture procedural hook implementations for .module detection.
rules.neon Registers the new rules and wires them behind a conditional flag.
extension.neon Adds a new configuration parameter and schema entry for the rule flag.
bleedingEdge.neon Enables the new rule flag in bleeding-edge defaults.

Comment thread rules.neon Outdated
Comment thread src/Rules/Drupal/EntityListBuilderOperationsCacheabilityRule.php Outdated
Comment thread src/Rules/Drupal/HookEntityOperationCacheabilityRule.php Outdated
Comment thread src/Rules/Drupal/ProceduralHookEntityOperationCacheabilityRule.php Outdated
Comment thread tests/src/Rules/HookEntityOperationCacheabilityRuleTest.php
Comment thread tests/src/Rules/EntityListBuilderOperationsCacheabilityRuleTest.php
mglaman and others added 2 commits April 15, 2026 16:51
The CI tests against Drupal ~11.2.0 where the version gate causes rules
to return no errors. Make expected errors conditional on the running
Drupal version so tests pass across the full version matrix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mglaman mglaman changed the title Add rule to detect missing CacheableMetadata parameter in EntityListBuilder subclasses Add rules to detect missing CacheableMetadata parameter in entity operation methods and hooks Apr 22, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Comment thread src/Rules/Drupal/HookEntityOperationCacheabilityRule.php Outdated
Comment thread src/Rules/Drupal/ProceduralHookEntityOperationCacheabilityRule.php Outdated
Comment thread src/Rules/Drupal/EntityListBuilderOperationsCacheabilityRule.php Outdated
Comment thread src/Rules/Drupal/EntityListBuilderOperationsCacheabilityRule.php Outdated
Comment thread src/Rules/Drupal/HookEntityOperationCacheabilityRule.php Outdated
Comment thread src/Rules/Drupal/ProceduralHookEntityOperationCacheabilityRule.php Outdated
mglaman and others added 3 commits April 22, 2026 13:53
Replace duplicated isValidCacheabilityParam() in three rules with a
general-purpose ParamHelper::isValidParam() that accepts any expected
FQCN and nullable constraint. Callers now own bounds checking via count().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Hooks have no shared interface contract, so PHPStan native method-signature
checking cannot catch missing cacheability params in Drupal 12+. Keep the
rule firing for any Drupal >= 11.3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mglaman mglaman merged commit a2ef88b into main Apr 22, 2026
14 of 15 checks passed
@mglaman mglaman deleted the rule/entity-list-builder-operations-cacheability branch April 22, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a rule for missing cacheability parameter in entity list builder sub classes

2 participants