Skip to content
Snippets Groups Projects
Commit 6c786e6a authored by Jan Kuchař's avatar Jan Kuchař
Browse files

Basket (green): Add ability to restore basket from historical events

parent cad429ab
Branches
No related tags found
No related merge requests found
<?php
/**
* Collection of domain events
*/
class AggregateHistory extends ArrayObject {
private $aggregateId;
public function __construct($aggregateId, DomainEvents $domainEvents)
{
$this->aggregateId = $aggregateId;
// type check for IDomainEvent[]
array_filter((array) $domainEvents, function(IDomainEvent $domainEvent) {});
parent::__construct((array) $domainEvents);
}
/**
* @return array|null|object
*/
public function getAggregateId()
{
return $this->aggregateId;
}
}
\ No newline at end of file
<?php
abstract class AbstractAggregate
{
/**
* @param \IDomainEvent $domainEvent
* @return string
*/
private function getApplyMethodForDomainEvent(IDomainEvent $domainEvent)
{
return "apply" . get_class($domainEvent);
}
/**
* Apply domain event if this aggregate accepts this event
* @param \IDomainEvent $domainEvent
* @internal
*/
public function applyIfAccepts(IDomainEvent $domainEvent) {
if(method_exists($this, $this->getApplyMethodForDomainEvent($domainEvent))) {
$this->apply($domainEvent);
}
}
/**
* Apply domain event; if objects does not accepts this event -> fail
* @param \IDomainEvent $domainEvent
*/
public function apply(IDomainEvent $domainEvent) {
$method = $this->getApplyMethodForDomainEvent($domainEvent);
$this->$method($domainEvent);
}
}
\ No newline at end of file
<?php <?php
final class Basket implements RecordsEvents final class Basket extends AbstractAggregate implements RecordsEvents
{ {
/** @var BasketId $basketId */ /** @var BasketId $basketId */
...@@ -29,6 +29,17 @@ final class Basket implements RecordsEvents ...@@ -29,6 +29,17 @@ final class Basket implements RecordsEvents
return $basket; return $basket;
} }
public static function reconstituteFrom(AggregateHistory $aggregateHistory)
{
$basketId = $aggregateHistory->getAggregateId();
$basket = new static($basketId);
foreach($aggregateHistory as $event) {
$basket->apply($event);
}
return $basket;
}
// ------------- public interface -------------- // ------------- public interface --------------
public function addProduct(ProductId $productId, $name) public function addProduct(ProductId $productId, $name)
{ {
...@@ -40,11 +51,7 @@ final class Basket implements RecordsEvents ...@@ -40,11 +51,7 @@ final class Basket implements RecordsEvents
new ProductWasAddedToBasket($this->basketId, $productId, $name) new ProductWasAddedToBasket($this->basketId, $productId, $name)
); );
// Update internal tracked state // Internal state NOT changed directly @see apply() method
if(!$this->isProductInBasket($productId)) {
$this->itemsCountById[(string)$productId] = 0;
}
$this->itemsCountById[(string)$productId]++;
} }
public function removeProduct(ProductId $productId) public function removeProduct(ProductId $productId)
...@@ -59,8 +66,34 @@ final class Basket implements RecordsEvents ...@@ -59,8 +66,34 @@ final class Basket implements RecordsEvents
new ProductWasRemovedFromBasket($this->basketId, $productId) new ProductWasRemovedFromBasket($this->basketId, $productId)
); );
// Update internal tracked state // Internal state NOT changed directly @see apply() method
$this->itemsCountById[(string)$productId]--; }
// --------- object state transitions based on incoming events ---------
/**
* @param \ProductWasAddedToBasket $productWasAddedToBasket
*/
public function applyProductWasAddedToBasket(ProductWasAddedToBasket $productWasAddedToBasket)
{
$productId = $productWasAddedToBasket->getProductId();
if (!$this->isProductInBasket($productId)) {
$this->itemsCountById[(string) $productId] = 0;
}
$this->itemsCountById[(string) $productId]++;
}
/**
* @param \ProductWasRemovedFromBasket $productWasRemovedFromBasket
*/
public function applyProductWasRemovedFromBasket(ProductWasRemovedFromBasket $productWasRemovedFromBasket)
{
$productId = $productWasRemovedFromBasket->getProductId();
$this->itemsCountById[(string) $productId]--;
}
public function applyBasketWasPickedUp()
{
} }
// ------------ guarding helpers -------------------- // ------------ guarding helpers --------------------
...@@ -93,6 +126,7 @@ final class Basket implements RecordsEvents ...@@ -93,6 +126,7 @@ final class Basket implements RecordsEvents
private function recordThat(IDomainEvent $domainEvent) private function recordThat(IDomainEvent $domainEvent)
{ {
$this->recordedEvents[] = $domainEvent; $this->recordedEvents[] = $domainEvent;
$this->apply($domainEvent);
} }
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment