Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #4 from dalanhurst/master

ConfigBasedRouter (with example) and Upgradeable Entities
  • Loading branch information...
commit 9f705be713990e2e223decd872ad6b74a5369dd8 2 parents 7be88af + e19f3fd
@spiralout authored
View
2  examples/example1/events.ini
@@ -0,0 +1,2 @@
+[EventEmployeeAdded]
+handlers[] = Welcomer
View
0  examples/example1/example1.php → examples/example1/example1a.php
File renamed without changes
View
46 examples/example1/example1b.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Example 2
+ *
+ * PHP Version 5.3
+ *
+ * @category Tracks
+ * @package Examples
+ * @subpackage Example2
+ * @author Sean Crystal <sean.crystal@gmail.com>
+ * @author Doug Hurst <dalan.hurst@gmail.com>
+ * @copyright 2011 Sean Crystal
+ * @license http://www.opensource.org/licenses/BSD-3-Clause BSD 3-Clause
+ * @link https://github.com/spiralout/Tracks
+ */
+
+require_once dirname(__DIR__).DIRECTORY_SEPARATOR.'bootstrap.php';
+require_once 'Employer.php';
+require_once 'Employee.php';
+require_once 'Position.php';
+require_once 'Welcomer.php';
+
+$repository = new \Tracks\EventStore\Repository(
+ new \Tracks\EventStore\EventStorage\Memory,
+ new \Tracks\EventHandler\ConfigBasedRouter(dirname(__FILE__).DIRECTORY_SEPARATOR.'events.ini'),
+ new \Tracks\EventStore\SnapshotStorage\Memory
+);
+
+$employer = new Employer;
+$employerGuid = $employer->create('Planet Express');
+$leelaGuid = $employer->addNewEmployee('Turanga Leela', 'Captain');
+$fryGuid = $employer->addNewEmployee('Philip Fry', 'Delivery Boy');
+
+$repository->save($employer);
+
+
+$employer = $repository->load($employerGuid);
+$employer->changeEmployeeTitle($fryGuid, 'Narwhal Trainer');
+
+$repository->save($employer);
+
+echo PHP_EOL.$employer->name.PHP_EOL;
+
+foreach ($employer->employees as $employee) {
+ echo ' - '.$employee->name.', '.$employee->position->title.PHP_EOL;
+}
View
111 library/Tracks/EventHandler/ConfigBasedRouter.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Tracks CQRS Framework
+ *
+ * PHP Version 5.3
+ *
+ * @category Tracks
+ * @package EventHandler
+ * @author Sean Crystal <sean.crystal@gmail.com>
+ * @copyright 2011 Sean Crystal
+ * @license http://www.opensource.org/licenses/BSD-3-Clause BSD 3-Clause
+ * @link https://github.com/spiralout/Tracks
+ */
+
+namespace Tracks\EventHandler;
+
+/**
+ * Routes to an event handler by referencing a lookup object
+ *
+ * Configuration should be INI-style in the format:
+ *
+ * [Event1Classname]
+ * handlers[] = EventHandler1Classname
+ * handlers[] = EventHandler2Classname
+ *
+ * [Event2Classname]
+ * handlers[] = EventHandler3Classname
+ * ...
+ *
+ * @category Tracks
+ * @package EventHandler
+ * @author Sean Crystal <sean.crystal@gmail.com>
+ * @author Doug Hurst <doug.hurst@gmail.com>
+ * @copyright 2011 Sean Crystal
+ * @license http://www.opensource.org/licenses/BSD-3-Clause BSD 3-Clause
+ * @link https://github.com/spiralout/Tracks
+ */
+class ConfigBasedRouter implements IEventRouter
+{
+ /**
+ * @var array An associative array of events to an array of handlers
+ */
+ private $_config;
+
+ /**
+ * @var array<IEventHandler> Associative array of Event Handlers
+ */
+ private $_handlers = array();
+
+ /**
+ * Route an event
+ *
+ * @param Tracks\Event\Base $event An Event
+ *
+ * @return null
+ */
+ public function route(\Tracks\Event\Base $event)
+ {
+ $eventClass = get_class($event);
+ if (isset($this->_handlers[$eventClass])) {
+ foreach ($this->_handlers[$eventClass] as $handler) {
+ $handler->execute($event);
+ }
+ } else if (isset($this->_config[$eventClass])) {
+ foreach ($this->_config[$eventClass]['handlers'] as $handlerClass) {
+ $this->addHandler($eventClass, new $handlerClass());
+ }
+ $this->route($event);
+ }
+ }
+
+ /**
+ * Add an event handler to the routing table
+ *
+ * @param string $eventClass The Event classname
+ * @param IEventHandler $handler An EventHandler
+ *
+ * @return null
+ */
+ public function addHandler($eventClass, $handler)
+ {
+ assert('is_string($eventClass)');
+ assert('class_exists($eventClass)');
+
+ if (!($handler instanceof IEventHandler)) {
+ throw new \LogicException('Event handlers must implement IEventHandler');
+ }
+
+ if (!isset($this->_handlers[$eventClass])) {
+ $this->_handlers[$eventClass] = array();
+ }
+
+ $this->_handlers[$eventClass][] = $handler;
+ }
+
+ /**
+ * Routing Configuration Mutator
+ *
+ * @param string $filename The configuration filename
+ *
+ * @return null
+ */
+ public function __construct($filename)
+ {
+ if (file_exists($filename)) {
+ $this->_config = parse_ini_file($filename, true);
+ } else {
+ throw new \InvalidArgumentException();
+ }
+ }
+}
View
11 library/Tracks/EventStore/SnapshotStorage/File.php
@@ -70,9 +70,14 @@ public function save(Entity $entity)
public function load(Guid $guid)
{
if (file_exists($this->_getFilename($guid))) {
- return unserialize(file_get_contents($this->_getFilename($guid)));
- } else {
- return null;
+ $entity = unserialize(file_get_contents($this->_getFilename($guid)));
+ if ($entity instanceof \Tracks\Model\IUpgradeable
+ && !$entity->isUpgraded()
+ ) {
+ $entity->upgradeModel();
+ $this->save($entity);
+ }
+ return $entity;
}
}
View
11 library/Tracks/EventStore/SnapshotStorage/Memory.php
@@ -41,9 +41,14 @@ class Memory implements ISnapshotStore
public function load(Guid $guid)
{
if (isset($this->_snapshots[(string) $guid])) {
- return $this->_snapshots[(string) $guid];
- } else {
- return null;
+ $entity = $this->_snapshots[(string) $guid];
+ if ($entity instanceof \Tracks\Model\IUpgradeable
+ && !$entity->isUpgraded()
+ ) {
+ $entity->upgradeModel();
+ $this->save($entity);
+ }
+ return $entity;
}
}
View
42 library/Tracks/Model/IUpgradeable.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Tracks CQRS Framework
+ *
+ * PHP Version 5.3
+ *
+ * @category Tracks
+ * @package Model
+ * @author Sean Crystal <sean.crystal@gmail.com>
+ * @copyright 2011 Sean Crystal
+ * @license http://www.opensource.org/licenses/BSD-3-Clause BSD 3-Clause
+ * @link https://github.com/spiralout/Tracks
+ */
+
+namespace Tracks\Model;
+
+/**
+ * Interface for Entities which can be upgraded
+ *
+ * @category Tracks
+ * @package Model
+ * @author Doug Hurst <dalan.hurst@gmail.com>
+ * @copyright 2011 Sean Crystal
+ * @license http://www.opensource.org/licenses/BSD-3-Clause BSD 3-Clause
+ * @link https://github.com/spiralout/Tracks
+ */
+interface IUpgradeable
+{
+ /**
+ * Returns true if all upgrades have been performed
+ *
+ * @return boolean
+ */
+ public function isUpgraded();
+
+ /**
+ * Perfom actions necessary to upgrade the domain model
+ *
+ * @return null
+ */
+ public function upgradeModel();
+}
Please sign in to comment.
Something went wrong with that request. Please try again.