Loading core/lib/Drupal/Component/Annotation/Doctrine/StaticReflectionParser.php +8 −2 Original line number Diff line number Diff line Loading @@ -205,7 +205,7 @@ protected function parse() break; case T_CLASS: // Convert the attributes to fully qualified names. $this->classAttributes = array_map(fn($name) => strtolower($this->fullySpecifyName($name)), $attributeNames); $this->classAttributes = array_map(fn($name) => $this->fullySpecifyName($name), $attributeNames); if ($last_token !== T_PAAMAYIM_NEKUDOTAYIM && $last_token !== T_NEW) { $this->docComment['class'] = $docComment; $docComment = ''; Loading Loading @@ -346,7 +346,13 @@ public function getStaticReflectionParserForDeclaringClass($type, $name) public function hasClassAttribute(string $attribute): bool { $this->parse(); return in_array('\\' . ltrim(strtolower($attribute), '\\'), $this->classAttributes, TRUE); foreach ($this->classAttributes as $classAttribute) { if (is_a($classAttribute, $attribute, TRUE)) { return TRUE; } } return FALSE; } /** Loading core/tests/Drupal/Tests/Component/Annotation/Doctrine/Fixtures/Attribute/Nonexistent.php 0 → 100644 +9 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\Component\Annotation\Doctrine\Fixtures\Attribute; // @phpstan-ignore-next-line #[NonexistentAttribute] final class Nonexistent { } core/tests/Drupal/Tests/Component/Annotation/Doctrine/Fixtures/ExtraAttributes/ExampleAttribute.php +1 −1 Original line number Diff line number Diff line Loading @@ -3,6 +3,6 @@ namespace Drupal\Tests\Component\Annotation\Doctrine\Fixtures\ExtraAttributes; #[\Attribute] final class ExampleAttribute final class ExampleAttribute extends ExampleParentAttribute { } core/tests/Drupal/Tests/Component/Annotation/Doctrine/Fixtures/ExtraAttributes/ExampleParentAttribute.php 0 → 100644 +8 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\Component\Annotation\Doctrine\Fixtures\ExtraAttributes; #[\Attribute] class ExampleParentAttribute { } core/tests/Drupal/Tests/Component/Annotation/Doctrine/StaticReflectionParserTest.php +8 −5 Original line number Diff line number Diff line Loading @@ -15,8 +15,10 @@ class StaticReflectionParserTest extends TestCase { /** * @testWith ["AttributeClass", "\\Attribute", true] * ["AttributeClass", "attribute", true] * ["AttributeClass", "Attribute", true] * ["AttributeClass", "\\DoesNotExist", false] * ["Nonexistent", "NonexistentAttribute", false] * ["MultipleAttributes", "Attribute", true] * ["MultipleAttributes", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\Attribute\\AttributeClass", true] * ["MultipleAttributes", "DoesNotExist", false] Loading @@ -26,15 +28,16 @@ class StaticReflectionParserTest extends TestCase { * ["UsedAsQualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleAttribute", true] * ["Qualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleAttribute", true] * ["Relative", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\Attribute\\SubDir\\SubDirAttribute", true] * ["FullyQualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] * ["Used", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] * ["UsedAs", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] * ["UsedAsQualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] * ["Qualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] */ public function testAttribute(string $class, string $attribute_class, bool $expected) { $finder = MockFileFinder::create(__DIR__ . '/Fixtures/Attribute/' . $class . '.php'); $parser = new StaticReflectionParser('\\Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\Attribute\\' . $class, $finder); $this->assertSame($expected, $parser->hasClassAttribute($attribute_class), "'$class' has '$attribute_class'"); // Attribute names and namespaces are case-insensitive in PHP. Practically // Composer autoloading makes this untrue but builtins like \Attribute are // case-insensitive so we should support that. $this->assertSame($expected, $parser->hasClassAttribute(strtoupper($attribute_class)), "'$class' has '$attribute_class'"); $this->assertSame($expected, $parser->hasClassAttribute($attribute_class), "'$class' has attribute that is a '$attribute_class'"); } } Loading
core/lib/Drupal/Component/Annotation/Doctrine/StaticReflectionParser.php +8 −2 Original line number Diff line number Diff line Loading @@ -205,7 +205,7 @@ protected function parse() break; case T_CLASS: // Convert the attributes to fully qualified names. $this->classAttributes = array_map(fn($name) => strtolower($this->fullySpecifyName($name)), $attributeNames); $this->classAttributes = array_map(fn($name) => $this->fullySpecifyName($name), $attributeNames); if ($last_token !== T_PAAMAYIM_NEKUDOTAYIM && $last_token !== T_NEW) { $this->docComment['class'] = $docComment; $docComment = ''; Loading Loading @@ -346,7 +346,13 @@ public function getStaticReflectionParserForDeclaringClass($type, $name) public function hasClassAttribute(string $attribute): bool { $this->parse(); return in_array('\\' . ltrim(strtolower($attribute), '\\'), $this->classAttributes, TRUE); foreach ($this->classAttributes as $classAttribute) { if (is_a($classAttribute, $attribute, TRUE)) { return TRUE; } } return FALSE; } /** Loading
core/tests/Drupal/Tests/Component/Annotation/Doctrine/Fixtures/Attribute/Nonexistent.php 0 → 100644 +9 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\Component\Annotation\Doctrine\Fixtures\Attribute; // @phpstan-ignore-next-line #[NonexistentAttribute] final class Nonexistent { }
core/tests/Drupal/Tests/Component/Annotation/Doctrine/Fixtures/ExtraAttributes/ExampleAttribute.php +1 −1 Original line number Diff line number Diff line Loading @@ -3,6 +3,6 @@ namespace Drupal\Tests\Component\Annotation\Doctrine\Fixtures\ExtraAttributes; #[\Attribute] final class ExampleAttribute final class ExampleAttribute extends ExampleParentAttribute { }
core/tests/Drupal/Tests/Component/Annotation/Doctrine/Fixtures/ExtraAttributes/ExampleParentAttribute.php 0 → 100644 +8 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\Component\Annotation\Doctrine\Fixtures\ExtraAttributes; #[\Attribute] class ExampleParentAttribute { }
core/tests/Drupal/Tests/Component/Annotation/Doctrine/StaticReflectionParserTest.php +8 −5 Original line number Diff line number Diff line Loading @@ -15,8 +15,10 @@ class StaticReflectionParserTest extends TestCase { /** * @testWith ["AttributeClass", "\\Attribute", true] * ["AttributeClass", "attribute", true] * ["AttributeClass", "Attribute", true] * ["AttributeClass", "\\DoesNotExist", false] * ["Nonexistent", "NonexistentAttribute", false] * ["MultipleAttributes", "Attribute", true] * ["MultipleAttributes", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\Attribute\\AttributeClass", true] * ["MultipleAttributes", "DoesNotExist", false] Loading @@ -26,15 +28,16 @@ class StaticReflectionParserTest extends TestCase { * ["UsedAsQualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleAttribute", true] * ["Qualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleAttribute", true] * ["Relative", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\Attribute\\SubDir\\SubDirAttribute", true] * ["FullyQualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] * ["Used", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] * ["UsedAs", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] * ["UsedAsQualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] * ["Qualified", "Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\ExtraAttributes\\ExampleParentAttribute", true] */ public function testAttribute(string $class, string $attribute_class, bool $expected) { $finder = MockFileFinder::create(__DIR__ . '/Fixtures/Attribute/' . $class . '.php'); $parser = new StaticReflectionParser('\\Drupal\\Tests\\Component\\Annotation\\Doctrine\\Fixtures\\Attribute\\' . $class, $finder); $this->assertSame($expected, $parser->hasClassAttribute($attribute_class), "'$class' has '$attribute_class'"); // Attribute names and namespaces are case-insensitive in PHP. Practically // Composer autoloading makes this untrue but builtins like \Attribute are // case-insensitive so we should support that. $this->assertSame($expected, $parser->hasClassAttribute(strtoupper($attribute_class)), "'$class' has '$attribute_class'"); $this->assertSame($expected, $parser->hasClassAttribute($attribute_class), "'$class' has attribute that is a '$attribute_class'"); } }