Problem/Motivation

There are plugin annotations that are implemented as subclasses of other annotation classes in:

In each instance, the same plugin manager retrieves definitions for the plugins of the class and subclasses together. Currently, subclasses can not be handled because of this in Drupal\Core\Plugin\Discovery\AttributeDiscoveryWithAnnotations::parseClass():

    // Annotations use static reflection and are able to analyze a class that
    // extends classes or uses traits that do not exist. Attribute discovery
    // will trigger a fatal error with such classes, so only call it if the
    // class has a class attribute.
    if ($reflection_class->hasClassAttribute($this->pluginDefinitionAttributeName)) {
      return parent::parseClass($class, $fileinfo);
    }

hasClassAttribute returns TRUE if the Class .php file contains an attribute that is an exact string match for $this->pluginDefinitionAttributeName, case-insensitive. This means that plugins with the subclass attribute fail this check, and the class is not picked up as a plugin.

Steps to reproduce

Proposed resolution

Instead of using a case-insensitive exact string match, change implementation of hasClassAttribute to use is_a() to check that the attribute class is the same class or subclass of $this->pluginDefinitionAttributeName.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Issue fork drupal-3427388

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

godotislate created an issue. See original summary.

godotislate’s picture

Status: Active » Needs review

MR is hitting what looks like an unrelated test failure.

godotislate’s picture

Addressed MR comment. Failing test was resolved upstream.

berdir’s picture

Status: Needs review » Needs work

> 3427388-update-drupalcomponentannotationdoctrinestaticreflectionparserhasclassattribute-to

This might be the longest branch name I've ever seen, certainly the longest "word" in a branch name ever ;)

I usually just put the class name and not full namespace in issue titles, but I don't know if that's an official/common thing or just me ;)

I think the one thing I'd like to see is that this doesn't trigger a class not found error. I think we can test that if we add something like #NonExistingAttribute on one of the test classes, should just ignore that then. I'm not 100% sure I understand the docs around is_a() and when it does trigger the classloader and when not.

godotislate’s picture

This might be the longest branch name I've ever seen, certainly the longest "word" in a branch name ever ;)

I usually just put the class name and not full namespace in issue titles, but I don't know if that's an official/common thing or just me ;)

I have a habit of being as specific as possible, though there is no other StaticReflectionParser, so I really didn't need to. I regretted it once I saw the generated branch name.

I think the one thing I'd like to see is that this doesn't trigger a class not found error. I think we can test that if we add something like #NonExistingAttribute on one of the test classes, should just ignore that then. I'm not 100% sure I understand the docs around is_a() and when it does trigger the classloader and when not.

OK, that's what you meant before, because I saw there were tests cases for nonexistent attribute names, but it went the other way. Added a test case and class for that and pushed a commit. We'll see if PHPStan yells.

godotislate’s picture

Status: Needs work » Needs review

PHPStan didn't like the nonexistent class, but I set it to ignore that line, and we're green again.

berdir’s picture

Status: Needs review » Needs work

Sometimes we also ignore files through core/phpstan.neon.dist, I guess either works, also plenty of examples using a comment. All of those use a @phpstan-ignore-next-line though, with comment above as we don't do same-line comments, so I'd suggest to adjust that here as well. Also works as a class dockblock, per example in core/tests/Drupal/Tests/Core/Test/TestSuiteBaseTest.php.

berdir’s picture

Status: Needs work » Reviewed & tested by the community

I wrote basically the exact same changes while trying to get #3396166: Convert entity type discovery to PHP attributes working again, @alexpott also +1'd the changes in Slack, so I think this is ready and unblocks several issues.

alexpott’s picture

Version: 11.x-dev » 10.2.x-dev
Category: Task » Bug report
Status: Reviewed & tested by the community » Fixed

Committed and pushed 0356ea590c to 11.x and 0be35cacd6 to 10.3.x and cbbdff7008 to 10.2.x. Thanks!

Backported to 10.2.x as this is a bugfix - something works with annotations that doesn't with attributes. It'll help contrib the earlier this is works correctly.

Nice test coverage!

  • alexpott committed cbbdff70 on 10.2.x
    Issue #3427388 by godotislate, Berdir: Update Drupal\Component\...

  • alexpott committed 0be35cac on 10.3.x
    Issue #3427388 by godotislate, Berdir: Update Drupal\Component\...

  • alexpott committed 0356ea59 on 11.x
    Issue #3427388 by godotislate, Berdir: Update Drupal\Component\...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.