Skip to content

Commit

Permalink
Merge pull request #1487 from ondrejmirtes/trait-interface-property
Browse files Browse the repository at this point in the history
Fixed property from interface implemented by trait
  • Loading branch information
Ocramius authored Feb 12, 2025
2 parents 683b41e + 8f5e710 commit d5fa8e1
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 4 deletions.
7 changes: 3 additions & 4 deletions src/Reflection/ReflectionClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -1024,10 +1024,9 @@ private function getPropertiesConsideringAlreadyVisitedClasses(AlreadyVisitedCla
foreach ($trait->getPropertiesConsideringAlreadyVisitedClasses($alreadyVisitedClasses) as $traitProperty) {
$traitPropertyName = $traitProperty->getName();

if (
array_key_exists($traitPropertyName, $properties)
|| array_key_exists($traitPropertyName, $immediateProperties)
) {
$existingProperty = $immediateProperties[$traitPropertyName] ?? $properties[$traitPropertyName] ?? null;

if ($existingProperty !== null && ! $existingProperty->isAbstract()) {
continue;
}

Expand Down
42 changes: 42 additions & 0 deletions test/unit/Reflection/ReflectionClassTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3169,4 +3169,46 @@ protected function hello(int $i): void
self::assertTrue($hello->isProtected());
self::assertCount(1, $hello->getParameters());
}

public function testInterfacePropertyImplementedInTrait(): void
{
$php = <<<'PHP'
<?php
interface TimestampsInterface
{
public \DateTimeImmutable $createdAt { get; }
}
trait Timestamps
{
public private(set) \DateTimeImmutable $createdAt {
get {
return $this->createdAt ??= new \DateTimeImmutable();
}
}
}
class Example implements TimestampsInterface
{
use Timestamps;
}
PHP;

$classInfo = (new DefaultReflector(new StringSourceLocator($php, $this->astLocator)))->reflectClass('Example');

self::assertTrue($classInfo->hasProperty('createdAt'));

/** @var trait-string $traitClassName */
$traitClassName = 'Timestamps';
/** @var class-string $className */
$className = 'Example';

$propertyInfo = $classInfo->getProperty('createdAt');
self::assertSame($traitClassName, $propertyInfo->getDeclaringClass()->getName());
self::assertSame($className, $propertyInfo->getImplementingClass()->getName());
self::assertFalse($propertyInfo->isVirtual());
self::assertTrue($propertyInfo->isPublic());
self::assertTrue($propertyInfo->isPrivateSet());
}
}

0 comments on commit d5fa8e1

Please sign in to comment.