Skip to content

Commit d5fa8e1

Browse files
authored
Merge pull request #1487 from ondrejmirtes/trait-interface-property
Fixed property from interface implemented by trait
2 parents 683b41e + 8f5e710 commit d5fa8e1

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

src/Reflection/ReflectionClass.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,10 +1024,9 @@ private function getPropertiesConsideringAlreadyVisitedClasses(AlreadyVisitedCla
10241024
foreach ($trait->getPropertiesConsideringAlreadyVisitedClasses($alreadyVisitedClasses) as $traitProperty) {
10251025
$traitPropertyName = $traitProperty->getName();
10261026

1027-
if (
1028-
array_key_exists($traitPropertyName, $properties)
1029-
|| array_key_exists($traitPropertyName, $immediateProperties)
1030-
) {
1027+
$existingProperty = $immediateProperties[$traitPropertyName] ?? $properties[$traitPropertyName] ?? null;
1028+
1029+
if ($existingProperty !== null && ! $existingProperty->isAbstract()) {
10311030
continue;
10321031
}
10331032

test/unit/Reflection/ReflectionClassTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3169,4 +3169,46 @@ protected function hello(int $i): void
31693169
self::assertTrue($hello->isProtected());
31703170
self::assertCount(1, $hello->getParameters());
31713171
}
3172+
3173+
public function testInterfacePropertyImplementedInTrait(): void
3174+
{
3175+
$php = <<<'PHP'
3176+
<?php
3177+
3178+
interface TimestampsInterface
3179+
{
3180+
public \DateTimeImmutable $createdAt { get; }
3181+
}
3182+
3183+
trait Timestamps
3184+
{
3185+
public private(set) \DateTimeImmutable $createdAt {
3186+
get {
3187+
return $this->createdAt ??= new \DateTimeImmutable();
3188+
}
3189+
}
3190+
}
3191+
3192+
class Example implements TimestampsInterface
3193+
{
3194+
use Timestamps;
3195+
}
3196+
PHP;
3197+
3198+
$classInfo = (new DefaultReflector(new StringSourceLocator($php, $this->astLocator)))->reflectClass('Example');
3199+
3200+
self::assertTrue($classInfo->hasProperty('createdAt'));
3201+
3202+
/** @var trait-string $traitClassName */
3203+
$traitClassName = 'Timestamps';
3204+
/** @var class-string $className */
3205+
$className = 'Example';
3206+
3207+
$propertyInfo = $classInfo->getProperty('createdAt');
3208+
self::assertSame($traitClassName, $propertyInfo->getDeclaringClass()->getName());
3209+
self::assertSame($className, $propertyInfo->getImplementingClass()->getName());
3210+
self::assertFalse($propertyInfo->isVirtual());
3211+
self::assertTrue($propertyInfo->isPublic());
3212+
self::assertTrue($propertyInfo->isPrivateSet());
3213+
}
31723214
}

0 commit comments

Comments
 (0)