diff --git a/src/EventManager.php b/src/EventManager.php index 7bef581..5563820 100644 --- a/src/EventManager.php +++ b/src/EventManager.php @@ -11,7 +11,7 @@ use LotGD\Core\EventHandler; use LotGD\Core\Exceptions\ClassNotFoundException; use LotGD\Core\Exceptions\SubscriptionNotFoundException; use LotGD\Core\Exceptions\WrongTypeException; -use LotGD\Core\Events\EventContextDataContainer; +use LotGD\Core\Events\EventContextData; /** * Manages a simple publish/subscribe system based on regular expressions @@ -35,9 +35,10 @@ class EventManager * are run. * * @param string $event The name of the event to publish. - * @param EventContextDataContainer $contextData The Data context + * @param EventContextData $contextData The Data context + * @return EventContextData The changed data. */ - public function publish(string $event, EventContextDataContainer $contextData): EventContextDataContainer + public function publish(string $event, EventContextData $contextData): EventContextData { // For right now, implement the naive approach of iterating every entry // in the subscription database, checking the regular expression. We @@ -56,9 +57,9 @@ class EventManager $eventContext = new EventContext($event, $s->getPattern(), $contextData); $returnedEventContext = $class::handleEvent($this->g, $eventContext); - if ($returnedEventContext->hasDataChanged($contextData)) { - $contextData = $returnedEventContext->getData(); - } + // Overwrite contextData - contextData might be the same if nothing has changed, + // or might reference a completely new object the event handler changed a value. + $contextData = $returnedEventContext->getData(); } } diff --git a/src/Events/EventContext.php b/src/Events/EventContext.php index ed235e2..6c14e40 100644 --- a/src/Events/EventContext.php +++ b/src/Events/EventContext.php @@ -2,7 +2,6 @@ declare(strict_types=1); namespace LotGD\Core\Events; -use LotGD\Core\Exceptions\ArgumentException; /** @@ -20,12 +19,12 @@ class EventContext * EventContext constructor. * @param string $event The published event * @param string $matchingPattern The matching pattern - * @param EventContextDataContainer $data + * @param EventContextData $data */ public function __construct( string $event, string $matchingPattern, - EventContextDataContainer $data + EventContextData $data ) { $this->event = $event; $this->matchingPattern = $matchingPattern; @@ -62,9 +61,9 @@ class EventContext /** * Returns the immutable data container. - * @return EventContextDataContainer + * @return EventContextData */ - public function getData(): EventContextDataContainer + public function getData(): EventContextData { return $this->data; } @@ -100,10 +99,10 @@ class EventContext /** * Checks if given original data is the same as currently held within this context. - * @param EventContextDataContainer $originalData + * @param EventContextData $originalData * @return bool */ - public function hasDataChanged(EventContextDataContainer $originalData): bool + public function hasDataChanged(EventContextData $originalData): bool { return $this->data === $originalData ? false : true; } diff --git a/src/Events/EventContextData.php b/src/Events/EventContextData.php index c204668..b5ea142 100644 --- a/src/Events/EventContextData.php +++ b/src/Events/EventContextData.php @@ -3,12 +3,134 @@ declare(strict_types=1); namespace LotGD\Core\Events; +use LotGD\Core\Exceptions\ArgumentException; /** - * Data container for default, unspecific data without any sanitizing on the given fields. + * EventContextDataContainer to provide a basic structure for managing contextual data of an event. + * + * This class must be immutable and returns always a new instance of itself for any change. * @package LotGD\Core\Events + * @immutable */ -class EventContextData extends EventContextDataContainer +class EventContextData { + private $data; + /** + * Creates a new instance of a data container. + * + * Sub types can change this method to force certain parameters. + * @param array $data + * @return EventContextData + */ + public static function create(array $data): self + { + return new static($data); + } + + /** + * protected constructor.. + * @see self::create + * @param array $data + */ + protected function __construct(array $data) + { + $this->data = $data; + } + + /** + * Returns true if container has a certain field. + * @param string $field + * @return bool + */ + public function has(string $field): bool + { + return array_key_exists($field, $this->data); + } + + /** + * Returns the value of a field. + * @param string $field + * @return mixed + */ + public function get(string $field) + { + if ($this->has($field)) { + return $this->data[$field]; + } else { + $this->throwException($field); + } + } + + /** + * Sets a field to a new value and returns a new data container + * @param string $field + * @param $value + * @return EventContextData + */ + public function set(string $field, $value): self + { + if ($this->has($field)) { + $data = $this->data; + $data[$field] = $value; + + return new static($data); + } else { + $this->throwException($field); + } + } + + /** + * Sets multiple fields at once + * @param array $data array of $field=>$value pairs + * @return EventContextData + */ + public function setFields(array $data): self + { + $data = $this->data; + + foreach ($data as $field => $value) { + if ($this->has($field)) { + $data[$field] = $value; + } else { + $this->throwException($field); + } + } + + return new static($data); + } + + /** + * Returns a list of fields in this context + * @return array + */ + private function getListOfFields(): array + { + return array_keys($this->data); + } + + /** + * Returns a comma separated string with all allowed fields, for debugging reasons. + * @return string + */ + private function getFormattedListOfFields(): string + { + return substr( + implode(", ", $this->getListOfFields()), + 0, + -2 + ); + } + + /** + * internal use only - throws an ArgumentException a field is given that's not valid. + * @param $field + * @throws ArgumentException + */ + private function throwException($field) + { + throw new ArgumentException( + "{$field} is not valid in this context, only {$this->getFormattedListOfFields()} are allowed." + ); + } } \ No newline at end of file diff --git a/src/Events/EventContextDataContainer.php b/src/Events/EventContextDataContainer.php deleted file mode 100644 index 7961b52..0000000 --- a/src/Events/EventContextDataContainer.php +++ /dev/null @@ -1,136 +0,0 @@ -data = $data; - } - - /** - * Returns true if container has a certain field. - * @param string $field - * @return bool - */ - public function has(string $field): bool - { - return array_key_exists($field, $this->data); - } - - /** - * Returns the value of a field. - * @param string $field - * @return mixed - */ - public function get(string $field) - { - if ($this->has($field)) { - return $this->data[$field]; - } else { - $this->throwException($field); - } - } - - /** - * Sets a field to a new value and returns a new data container - * @param string $field - * @param $value - * @return EventContextDataContainer - */ - public function set(string $field, $value): self - { - if ($this->has($field)) { - $data = $this->data; - $data[$field] = $value; - - return new static($data); - } else { - $this->throwException($field); - } - } - - /** - * Sets multiple fields at once - * @param array $data array of $field=>$value pairs - * @return EventContextDataContainer - */ - public function setFields(array $data): self - { - $data = $this->data; - - foreach ($data as $field => $value) { - if ($this->has($field)) { - $data[$field] = $value; - } else { - $this->throwException($field); - } - } - - return new static($data); - } - - /** - * Returns a list of fields in this context - * @return array - */ - private function getListOfFields(): array - { - return array_keys($this->data); - } - - /** - * Returns a comma separated string with all allowed fields, for debugging reasons. - * @return string - */ - private function getFormattedListOfFields(): string - { - return substr( - implode(", ", $this->getListOfFields()), - 0, - -2 - ); - } - - /** - * internal use only - throws an ArgumentException a field is given that's not valid. - * @param $field - * @throws ArgumentException - */ - private function throwException($field) - { - throw new ArgumentException( - "{$field} is not valid in this context, only {$this->getFormattedListOfFields()} are allowed." - ); - } -} \ No newline at end of file diff --git a/src/Events/NavigateToScene.php b/src/Events/NavigateToSceneData.php similarity index 97% rename from src/Events/NavigateToScene.php rename to src/Events/NavigateToSceneData.php index 14a03e1..7b1e089 100644 --- a/src/Events/NavigateToScene.php +++ b/src/Events/NavigateToSceneData.php @@ -23,7 +23,7 @@ use LotGD\Core\Models\Viewpoint; * redirect Scene|null * @package LotGD\Core\Events */ -class NavigateToScene extends EventContextDataContainer +class NavigateToSceneData extends EventContextData { /** * NavigateToScene constructor. diff --git a/src/Events/NewViewpoint.php b/src/Events/NewViewpointData.php similarity index 96% rename from src/Events/NewViewpoint.php rename to src/Events/NewViewpointData.php index 0752861..aca58be 100644 --- a/src/Events/NewViewpoint.php +++ b/src/Events/NewViewpointData.php @@ -16,7 +16,7 @@ use LotGD\Core\Models\Scene; * scene Scene|null * @package LotGD\Core\Events */ -class NewViewpoint extends EventContextDataContainer +class NewViewpointData extends EventContextData { /** * NewViewpoint constructor. diff --git a/src/Game.php b/src/Game.php index f0c57bf..7202b83 100644 --- a/src/Game.php +++ b/src/Game.php @@ -5,8 +5,8 @@ namespace LotGD\Core; use DateTime; use Doctrine\ORM\EntityManagerInterface; -use LotGD\Core\Events\NavigateToScene; -use LotGD\Core\Events\NewViewpoint; +use LotGD\Core\Events\NavigateToSceneData; +use LotGD\Core\Events\NewViewpointData; use Monolog\Logger; use LotGD\Core\Models\{ @@ -194,7 +194,7 @@ class Game if ($v === null) { // No viewpoint set up for this user. Run the hook to find the default // scene. - $contextData = NewViewpoint::create([ + $contextData = NewViewpointData::create([ 'character' => $this->getCharacter(), 'scene' => null ]); @@ -295,7 +295,7 @@ class Game // Let and installed listeners (ie modules) make modifications to the // new viewpoint, including the ability to redirect the user to // a different scene, by setting $context['redirect'] to a new scene. - $contextData = NavigateToScene::create([ + $contextData = NavigateToSceneData::create([ 'referrer' => $referrer, 'viewpoint' => $viewpoint, 'scene' => $scene, diff --git a/tests/GameTest.php b/tests/GameTest.php index 3b01ca5..358020c 100644 --- a/tests/GameTest.php +++ b/tests/GameTest.php @@ -9,7 +9,7 @@ use Monolog\Logger; use Monolog\Handler\NullHandler; use LotGD\Core\{ - Action, ActionGroup, Bootstrap, Configuration, ComposerManager, DiceBag, EventHandler, EventManager, Events\NewViewpoint, Game, TimeKeeper, ModuleManager + Action, ActionGroup, Bootstrap, Configuration, ComposerManager, DiceBag, EventHandler, EventManager, Events\NewViewpointData, Game, TimeKeeper, ModuleManager }; use LotGD\Core\Models\{ Character, Viewpoint, Scene @@ -29,10 +29,10 @@ class DefaultSceneProvider implements EventHandler { switch ($context->getEvent()) { case 'h/lotgd/core/default-scene': - if (!$context->hasDataType(NewViewpoint::class)) { + if (!$context->hasDataType(NewViewpointData::class)) { throw new \Exception(sprintf( "Context was expected to be %s, %s instead.", - NewViewpoint::class, + NewViewpointData::class, get_class($context->getData()) )); }