Skip to content

Commit

Permalink
Merge pull request #27 from matthiasnoback/improvements
Browse files Browse the repository at this point in the history
Improvements
  • Loading branch information
matthiasnoback authored May 15, 2019
2 parents 68b6147 + 522da05 commit 6c4a2eb
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 82 deletions.
3 changes: 3 additions & 0 deletions src/TalisOrm/Aggregate.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use TalisOrm\DomainEvents\EventRecordingCapabilities;

/**
* @see AggregateBehavior
*/
interface Aggregate extends Entity
{
/**
Expand Down
59 changes: 59 additions & 0 deletions src/TalisOrm/AggregateBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
declare(strict_types=1);

namespace TalisOrm;

use TalisOrm\DomainEvents\EventRecordingCapabilities;
use Webmozart\Assert\Assert;

trait AggregateBehavior
{
use EventRecordingCapabilities;

/**
* @var array
*/
private $deletedChildEntities = [];

/**
* @var bool
*/
private $isNew = true;

/**
* @var int
*/
private $aggregateVersion = 0;

public function deletedChildEntities(): array
{
$deletedChildEntities = $this->deletedChildEntities;

$this->deletedChildEntities = [];

return $deletedChildEntities;
}

private function deleteChildEntity(ChildEntity $childEntity)
{
$this->deletedChildEntities[] = $childEntity;
}

public function isNew(): bool
{
return $this->isNew;
}

public function markAsPersisted(): void
{
$this->isNew = false;
}

/**
* @return int
*/
public function aggregateVersion()
{
return $this->aggregateVersion;
}
}
16 changes: 10 additions & 6 deletions src/TalisOrm/AggregateRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function save(Aggregate $aggregate): void
$this->eventDispatcher->dispatch($aggregate->releaseEvents());
}

public function getById(string $aggregateClass, AggregateId $aggregateId): Aggregate
public function getById(string $aggregateClass, AggregateId $aggregateId, array $extraState = []): Aggregate
{
if (!is_a($aggregateClass, Aggregate::class, true)) {
throw new InvalidArgumentException(sprintf(
Expand All @@ -74,8 +74,9 @@ public function getById(string $aggregateClass, AggregateId $aggregateId): Aggre
}

$aggregateState = $this->getAggregateState($aggregateClass, $aggregateId);
$aggregateState = array_merge($aggregateState, $extraState);

$childEntitiesByType = $this->getChildEntitiesByType($aggregateClass, $aggregateId);
$childEntitiesByType = $this->getChildEntitiesByType($aggregateClass, $aggregateId, $aggregateState);

$aggregate = $aggregateClass::fromState($aggregateState, $childEntitiesByType);

Expand Down Expand Up @@ -116,8 +117,11 @@ private function getAggregateState(string $aggregateClass, AggregateId $aggregat
/**
* @return array[]
*/
private function getChildEntitiesByType(string $aggregateClass, AggregateId $aggregateId): array
{
private function getChildEntitiesByType(
string $aggregateClass,
AggregateId $aggregateId,
array $aggregateState
): array {
$childEntitiesByType = [];

foreach ($aggregateClass::childEntityTypes() as $childEntityType) {
Expand All @@ -127,8 +131,8 @@ private function getChildEntitiesByType(string $aggregateClass, AggregateId $agg
);

$childEntitiesByType[$childEntityType] = array_map(
function (array $childEntityState) use ($childEntityType) {
$childEntity = $childEntityType::fromState($childEntityState);
function (array $childEntityState) use ($childEntityType, $aggregateState) {
$childEntity = $childEntityType::fromState($childEntityState, $aggregateState);

$childEntity->markAsPersisted();

Expand Down
6 changes: 5 additions & 1 deletion src/TalisOrm/ChildEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace TalisOrm;

/**
* @see ChildEntityBehavior
*/
interface ChildEntity extends Entity
{
/**
Expand All @@ -16,7 +19,8 @@ interface ChildEntity extends Entity
* return $line;
*
* @param array $state
* @param array $aggregateState
* @return static
*/
public static function fromState(array $state);
public static function fromState(array $state, array $aggregateState);
}
23 changes: 23 additions & 0 deletions src/TalisOrm/ChildEntityBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);

namespace TalisOrm;

trait ChildEntityBehavior
{

/**
* @var bool
*/
private $isNew = true;

public function isNew(): bool
{
return $this->isNew;
}

public function markAsPersisted(): void
{
$this->isNew = false;
}
}
78 changes: 64 additions & 14 deletions test/TalisOrm/AbstractAggregateRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ public function it_saves_an_aggregate()
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$this->repository->save($aggregate);

Expand All @@ -81,14 +82,46 @@ public function it_saves_an_aggregate()
self::assertEquals([new OrderCreated()], $this->eventDispatcher->dispatchedEvents());
}

/**
* @test
*/
public function when_loading_an_aggregate_it_can_inject_some_extra_state(): void
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2019-05-15'),
$this->quantityPrecision()
);
$aggregate->addLine(
new LineNumber(1),
new ProductId('73d46c97-a71b-4e3c-9633-bb7a8603b301', 5),
new Quantity(10)
);
$this->repository->save($aggregate);

$fromDatabase = $this->repository->getById($aggregate->orderId());

/*
* The quantity precision doesn't come from the database, but from the array of extra state, provided by the
* `OrderTalisOrmRepository`.
*/
self::assertSame(2, $fromDatabase->quantityPrecision());

/*
* It's also available to the `fromState()` method of the `Line` child entity.
*/
self::assertSame(2, $fromDatabase->lines()[0]->quantityPrecision());
}

/**
* @test
*/
public function it_updates_an_aggregate()
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$this->repository->save($aggregate);

Expand All @@ -114,13 +147,15 @@ public function it_triggers_a_unique_constraint_exception_if_an_id_is_reused_for
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$this->repository->save($aggregate);

$aggregateWithSameId = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-04')
DateTimeUtil::createDateTimeImmutable('2018-10-04'),
$this->quantityPrecision()
);

$this->expectException(UniqueConstraintViolationException::class);
Expand All @@ -135,7 +170,8 @@ public function it_guards_against_concurrent_updates()
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$this->repository->save($aggregate);

Expand Down Expand Up @@ -166,7 +202,8 @@ public function it_guards_against_concurrent_updates_if_the_aggregate_has_a_lowe
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$this->repository->save($aggregate);

Expand Down Expand Up @@ -194,7 +231,8 @@ public function it_saves_an_aggregate_with_its_child_entities()
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$aggregate->addLine(
new LineNumber(1),
Expand Down Expand Up @@ -222,7 +260,8 @@ public function entities_will_only_be_marked_as_persisted_if_all_queries_within_
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$aggregate->addLine(
new LineNumber(1),
Expand Down Expand Up @@ -255,7 +294,8 @@ public function it_creates_multiple_child_entities_in_the_database()
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$aggregate->addLine(
new LineNumber(1),
Expand Down Expand Up @@ -289,7 +329,8 @@ public function it_updates_multiple_child_entities_in_the_database()
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$aggregate->addLine(
new LineNumber(1),
Expand Down Expand Up @@ -331,7 +372,8 @@ public function it_deletes_child_entities_that_have_been_removed_from_the_aggreg
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$aggregate->addLine(
new LineNumber(1),
Expand Down Expand Up @@ -369,7 +411,8 @@ public function it_deletes_an_aggregate_with_its_child_entities()
{
$aggregate = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$aggregate->addLine(
new LineNumber(1),
Expand All @@ -391,12 +434,14 @@ public function it_does_not_delete_all_aggregates_of_the_same_type()
{
$aggregate1 = Order::create(
new OrderId('91338a57-5c9a-40e8-b5e8-803e8175c7d7', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-03')
DateTimeUtil::createDateTimeImmutable('2018-10-03'),
$this->quantityPrecision()
);
$this->repository->save($aggregate1);
$aggregate2 = Order::create(
new OrderId('c8ee1ee6-7757-4661-81fb-5b327badbff8', 5),
DateTimeUtil::createDateTimeImmutable('2018-10-04')
DateTimeUtil::createDateTimeImmutable('2018-10-04'),
$this->quantityPrecision()
);
$this->repository->save($aggregate2);

Expand All @@ -409,4 +454,9 @@ public function it_does_not_delete_all_aggregates_of_the_same_type()
$this->expectException(AggregateNotFoundException::class);
$this->repository->getById($aggregate1->orderId());
}

private function quantityPrecision(): int
{
return 2;
}
}
Loading

0 comments on commit 6c4a2eb

Please sign in to comment.