Skip to content

Commit

Permalink
Merge pull request #687 from patchlevel/use-reflection-for-child-prop…
Browse files Browse the repository at this point in the history
…erty

Use reflection for accessing child aggregates, add test case which covers private child aggregates
  • Loading branch information
DanielBadura authored Feb 7, 2025
2 parents 11d0832 + 53320e8 commit d0ea850
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 9 deletions.
5 changes: 5 additions & 0 deletions baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,11 @@
<code><![CDATA[PersonalInformation]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Integration/ChildAggregate/Views.php">
<PropertyNotSetInConstructor>
<code><![CDATA[Views]]></code>
</PropertyNotSetInConstructor>
</file>
<file src="tests/Integration/PersonalData/PersonalDataTest.php">
<MixedArgument>
<code><![CDATA[$row['payload']]]></code>
Expand Down
30 changes: 23 additions & 7 deletions src/Aggregate/AggregateRootAttributeBehaviour.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ protected function apply(object $event): void
if (count($parts) === 2) {
[$property, $method] = $parts;

/** @var ChildAggregate $child */
$child = $this->$property;
$child->$method($event);
$child = $this->getChildAggregateByPropertyName($property);

if ($child !== null) {
$child->$method($event);
}
} else {
$this->$method($event);
}
Expand All @@ -65,17 +67,31 @@ private function passRecorderToChildAggregates(): void
$metadata = static::metadata();
$this->recorder ??= $this->recordThat(...);

Check warning on line 68 in src/Aggregate/AggregateRootAttributeBehaviour.php

View workflow job for this annotation

GitHub Actions / Mutation tests (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "AssignCoalesce": --- Original +++ New @@ @@ private function passRecorderToChildAggregates() : void { $metadata = static::metadata(); - $this->recorder ??= $this->recordThat(...); + $this->recorder = $this->recordThat(...); foreach ($metadata->childAggregates as $propertyName) { $child = $this->getChildAggregateByPropertyName($propertyName); if ($child === null) {

foreach ($metadata->childAggregates as $property) {
if (!isset($this->{$property})) {
foreach ($metadata->childAggregates as $propertyName) {
$child = $this->getChildAggregateByPropertyName($propertyName);

if ($child === null) {
continue;
}

/** @var ChildAggregate $child */
$child = $this->{$property};
$child->setRecorder($this->recorder);
}
}

private function getChildAggregateByPropertyName(string $propertyName): ChildAggregate|null
{
$reflectionProperty = new ReflectionProperty($this::class, $propertyName);

if (!$reflectionProperty->isInitialized($this)) {
return null;
}

/** @var ChildAggregate|null $child */
$child = $reflectionProperty->getValue($this);

return $child;
}

public function aggregateRootId(): AggregateRootId
{
if ($this->cachedAggregateRootId instanceof AggregateRootId) {

Check warning on line 97 in src/Aggregate/AggregateRootAttributeBehaviour.php

View workflow job for this annotation

GitHub Actions / Mutation tests (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "InstanceOf_": --- Original +++ New @@ @@ } public function aggregateRootId() : AggregateRootId { - if ($this->cachedAggregateRootId instanceof AggregateRootId) { + if (false) { return $this->cachedAggregateRootId; } $metadata = static::metadata();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public function testSuccessful(): void
$profileId = ProfileId::generate();
$profile = Profile::create($profileId, 'John');
$profile->changeName('Snow');
$profile->trackView();
$repository->save($profile);

$result = $this->connection->fetchAssociative(
Expand All @@ -92,8 +93,9 @@ public function testSuccessful(): void

self::assertInstanceOf(Profile::class, $profile);
self::assertEquals($profileId, $profile->aggregateRootId());
self::assertSame(2, $profile->playhead());
self::assertSame(3, $profile->playhead());
self::assertSame('Snow', $profile->name());
self::assertSame(1, $profile->views());
}

public function testSnapshot(): void
Expand Down Expand Up @@ -154,13 +156,15 @@ public function testSnapshot(): void
$profile = $repository->load($profileId);

$profile->changeName('Snow');
$profile->trackView();
$repository->save($profile);

$profile = $repository->load($profileId);

self::assertInstanceOf(Profile::class, $profile);
self::assertEquals($profileId, $profile->aggregateRootId());
self::assertSame(2, $profile->playhead());
self::assertSame(3, $profile->playhead());
self::assertSame('Snow', $profile->name());
self::assertSame(1, $profile->views());
}
}
15 changes: 15 additions & 0 deletions tests/Integration/ChildAggregate/Events/ViewTracked.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Tests\Integration\ChildAggregate\Events;

use Patchlevel\EventSourcing\Attribute\Event;

#[Event('profile.view_tracked')]
final class ViewTracked
{
public function __construct()
{
}
}
14 changes: 14 additions & 0 deletions tests/Integration/ChildAggregate/Profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ final class Profile extends BasicAggregateRoot
#[ChildAggregate]
protected PersonalInformation $personalInformation;

#[ChildAggregate]
private Views $views;

public static function create(ProfileId $id, string $name): self
{
$self = new self();
Expand All @@ -35,15 +38,26 @@ protected function applyProfileCreated(ProfileCreated $event): void
{
$this->id = $event->profileId;
$this->personalInformation = new PersonalInformation($event->name);
$this->views = new Views();
}

public function name(): string
{
return $this->personalInformation->name();
}

public function views(): int
{
return $this->views->views();
}

public function changeName(string $name): void
{
$this->personalInformation->changeName($name);
}

public function trackView(): void
{
$this->views->trackView();
}
}
32 changes: 32 additions & 0 deletions tests/Integration/ChildAggregate/Views.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Patchlevel\EventSourcing\Tests\Integration\ChildAggregate;

use Patchlevel\EventSourcing\Aggregate\BasicChildAggregate;
use Patchlevel\EventSourcing\Attribute\Apply;
use Patchlevel\EventSourcing\Tests\Integration\ChildAggregate\Events\ViewTracked;

final class Views extends BasicChildAggregate
{
public function __construct(private int $views = 0)
{
}

#[Apply(ViewTracked::class)]
public function applyNameChanged(ViewTracked $event): void
{
$this->views++;
}

public function views(): int
{
return $this->views;
}

public function trackView(): void
{
$this->recordThat(new ViewTracked());
}
}

0 comments on commit d0ea850

Please sign in to comment.