Skip to content

Instantly share code, notes, and snippets.

@boekkooi
Created September 14, 2015 08:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save boekkooi/d3b4bda2160f74657c56 to your computer and use it in GitHub Desktop.
Save boekkooi/d3b4bda2160f74657c56 to your computer and use it in GitHub Desktop.
ValueObject + Broadway
<?php
namespace Xoip\Component\ValueObject;
interface Collection extends \IteratorAggregate, \Countable
{
/**
* Adds an element at the end of the collection.
*
* @param ValueObject $object The object to add.
*
* @return boolean Always TRUE.
*/
public function add(ValueObject $object);
/**
* Removes the specified object from the collection, if it is found.
*
* @param mixed $object The object to remove.
* @return boolean TRUE if this collection contained the specified object, FALSE otherwise.
*/
public function remove(ValueObject $object);
/**
* Checks whether an object is contained in the collection.
*
* @param ValueObject $object The object to search for.
* @return boolean TRUE if the collection contains the object, FALSE otherwise.
*/
public function contains(ValueObject $object);
/**
* Gets a native PHP array representation of the collection.
*
* @return array
*/
public function toArray();
/**
* @inheritdoc
*/
public function getIterator();
}
<?php
namespace Xoip\Component\ValueObject;
final class CollectionHelper
{
/**
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* Resolve the changes that are need to the original to be the same as the target.
*
* @param ValueObject[]|\Traversable $original
* @param ValueObject[]|\Traversable $target
* @return array list($removed, $added)
*/
public static function resolveChanges($original, $target)
{
/** @var ValueObject[] $original */
if (!is_array($original) && !$original instanceof \Traversable) {
throw new \InvalidArgumentException('Expected $original to be a array or implement Traversable.');
}
/** @var ValueObject[] $target */
if (!is_array($target) && !$target instanceof \Traversable) {
throw new \InvalidArgumentException('Expected $target to be a array or implement Traversable.');
}
// Discover removed items
$removed = [];
foreach ($original as $originalObject) {
foreach ($target as $targetObject) {
if ($originalObject->equals($targetObject)) {
// Nothing changed
continue 2;
}
}
$removed[] = $originalObject;
}
// Add new items
$added = [];
foreach ($target as $targetObject) {
foreach ($original as $originalObject) {
if ($targetObject->equals($originalObject)) {
// Nothing changed
continue 2;
}
}
$added[] = $targetObject;
}
return [ $removed, $added ];
}
}
<?php
namespace Xoip\Component\ValueObject\EventSourced;
use Broadway\EventSourcing\AggregateRootAlreadyRegisteredException;
use Broadway\EventSourcing\EventSourcedAggregateRoot;
use Broadway\EventSourcing\EventSourcedEntityInterface;
use Xoip\Component\ValueObject\Collection;
use Xoip\Component\ValueObject\ValueObject;
use Xoip\Component\ValueObject\ValueObjectCollection as InternalValueObjectCollection;
abstract class ValueObjectCollection implements EventSourcedEntityInterface, Collection
{
/**
* @var object|null
*/
private $aggregateRoot;
/**
* @var InternalValueObjectCollection
*/
protected $collection;
/**
* Initializes a new ValueObjectCollection.
*/
public function __construct()
{
$this->collection = new InternalValueObjectCollection($objects = []);
}
/**
* Handles event if capable.
*
* @param $event
*/
public function handleRecursively($event)
{
$method = $this->getApplyMethod($event);
if (!method_exists($this, $method)) {
return;
}
$this->$method($event);
}
/**
* @inheritDoc
*/
public function registerAggregateRoot(EventSourcedAggregateRoot $aggregateRoot)
{
if (null !== $this->aggregateRoot && $this->aggregateRoot !== $aggregateRoot) {
throw new AggregateRootAlreadyRegisteredException();
}
$this->aggregateRoot = $aggregateRoot;
}
/**
* @inheritDoc
*/
public function contains(ValueObject $object)
{
return $this->collection->contains($object);
}
/**
* @inheritDoc
*/
public function toArray()
{
return $this->collection->toArray();
}
/**
* @inheritdoc
*/
public function getIterator()
{
return $this->collection->getIterator();
}
/**
* @inheritdoc
*/
public function count()
{
return $this->collection->count();
}
/**
* Applies an event. The event is added to the (parent) AggregateRoot's list of uncommitted events.
*
* @param $event
*/
protected function apply($event)
{
$this->aggregateRoot->apply($event);
}
/**
* Resolve the apply method name for a event
*
* @param string $event
* @return string
*/
private function getApplyMethod($event)
{
$classParts = explode('\\', get_class($event));
return 'apply' . end($classParts);
}
}
<?php
namespace Xoip\Component\ValueObject;
interface ValueObject
{
/**
* Returns TRUE if this value object is equal to another.
*
* @param mixed $other
* @return boolean
*/
public function equals($other);
}
<?php
namespace Xoip\Component\ValueObject;
class ValueObjectCollection implements Collection
{
/**
* @var ValueObject[]
*/
private $objects;
/**
* Initializes a new ValueObjectCollection.
*
* @param ValueObject[]|\Traversable $objects
*/
public function __construct($objects = [])
{
if (!is_array($objects) && !$objects instanceof \Traversable) {
throw new \InvalidArgumentException('Expected $objects to be a array or implement Traversable.');
}
$this->objects = is_array($objects) ? $objects : iterator_to_array($objects);
}
/**
* @inheritdoc
*/
public function add(ValueObject $object)
{
$this->objects[] = $object;
return true;
}
/**
* @inheritdoc
*/
public function remove(ValueObject $object)
{
$index = $this->indexOf($object);
if ($index === false) {
return false;
}
unset($this->objects[$index]);
return true;
}
/**
* @inheritdoc
*/
public function contains(ValueObject $object)
{
return $this->indexOf($object) !== false;
}
/**
* @inheritdoc
*/
protected function indexOf(ValueObject $object)
{
foreach ($this->objects as $i => $item) {
if ($item->equals($object)) {
return $i;
}
}
return false;
}
/**
* @inheritdoc
*/
public function toArray()
{
return $this->objects;
}
/**
* @inheritdoc
*/
public function getIterator()
{
return new \ArrayIterator($this->objects);
}
/**
* @inheritdoc
*/
public function count()
{
return count($this->objects);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment