From fedc14f97a89664152677b1eb7792a63137643ba Mon Sep 17 00:00:00 2001 From: Oskar Hasinski Date: Fri, 8 Apr 2016 11:58:47 +0200 Subject: [PATCH 1/8] feat: extended the interface to return the properties --- src/Finite/Transition/TransitionInterface.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Finite/Transition/TransitionInterface.php b/src/Finite/Transition/TransitionInterface.php index f13676c..57f38d7 100644 --- a/src/Finite/Transition/TransitionInterface.php +++ b/src/Finite/Transition/TransitionInterface.php @@ -47,4 +47,10 @@ public function getName(); * @return callable */ public function getGuard(); + + /** + * Returns properties in the transition. + * return mixed + */ + public function getProperties(); } From f4a6ecfacf4535c5e856ba6f69744864ebbb9e12 Mon Sep 17 00:00:00 2001 From: Oskar Hasinski Date: Mon, 25 Jul 2016 17:09:49 +0200 Subject: [PATCH 2/8] added a method to list all callbacks. --- .../Resources/config/services.xml | 1 - src/Finite/Event/Callback/Callback.php | 22 ++++++- .../Event/Callback/CallbackSpecification.php | 8 +++ .../CallbackSpecificationInterface.php | 5 ++ src/Finite/StateMachine/StateMachine.php | 61 ++++++++++++++++++- 5 files changed, 92 insertions(+), 5 deletions(-) diff --git a/src/Finite/Bundle/FiniteBundle/Resources/config/services.xml b/src/Finite/Bundle/FiniteBundle/Resources/config/services.xml index 2045953..484ca1d 100644 --- a/src/Finite/Bundle/FiniteBundle/Resources/config/services.xml +++ b/src/Finite/Bundle/FiniteBundle/Resources/config/services.xml @@ -42,5 +42,4 @@ - diff --git a/src/Finite/Event/Callback/Callback.php b/src/Finite/Event/Callback/Callback.php index 414aabe..2138651 100644 --- a/src/Finite/Event/Callback/Callback.php +++ b/src/Finite/Event/Callback/Callback.php @@ -15,15 +15,15 @@ class Callback implements CallbackInterface private $specification; /** - * @var callable + * @var array callable */ private $callable; /** * @param CallbackSpecificationInterface $callbackSpecification - * @param callable $callable + * @param array $callable */ - public function __construct(CallbackSpecificationInterface $callbackSpecification, $callable) + public function __construct(CallbackSpecificationInterface $callbackSpecification, array $callable) { $this->specification = $callbackSpecification; $this->callable = $callable; @@ -37,6 +37,22 @@ public function getSpecification() return $this->specification; } + /** + * @return array callable + */ + public function getCallbacks() + { + return $this->callable; + } + + /** + * @return array + */ + public function getClauses() + { + return $this->specification->getClauses(); + } + /** * {@inheritdoc} */ diff --git a/src/Finite/Event/Callback/CallbackSpecification.php b/src/Finite/Event/Callback/CallbackSpecification.php index df4de77..c04edd9 100644 --- a/src/Finite/Event/Callback/CallbackSpecification.php +++ b/src/Finite/Event/Callback/CallbackSpecification.php @@ -63,6 +63,14 @@ public function isSatisfiedBy(TransitionEvent $event) $this->supportsClause('on', $event->getTransition()->getName()); } + /** + * @return array + */ + public function getClauses() + { + return $this->specs; + } + /** * @param string $clause * @param string $property diff --git a/src/Finite/Event/Callback/CallbackSpecificationInterface.php b/src/Finite/Event/Callback/CallbackSpecificationInterface.php index 7ad19dc..6297a21 100644 --- a/src/Finite/Event/Callback/CallbackSpecificationInterface.php +++ b/src/Finite/Event/Callback/CallbackSpecificationInterface.php @@ -19,4 +19,9 @@ interface CallbackSpecificationInterface * @return bool */ public function isSatisfiedBy(TransitionEvent $event); + + /** + * @return array + */ + public function getClauses(); } diff --git a/src/Finite/StateMachine/StateMachine.php b/src/Finite/StateMachine/StateMachine.php index b928cee..c8ecd4e 100644 --- a/src/Finite/StateMachine/StateMachine.php +++ b/src/Finite/StateMachine/StateMachine.php @@ -2,6 +2,7 @@ namespace Finite\StateMachine; +use Finite\Event\Callback\Callback; use Finite\Event\FiniteEvents; use Finite\Event\StateMachineEvent; use Finite\Event\TransitionEvent; @@ -65,6 +66,11 @@ class StateMachine implements StateMachineInterface */ protected $graph; + /** + * @var array + */ + protected $callbacks = []; + /** * @param object $object * @param EventDispatcherInterface $dispatcher @@ -93,7 +99,7 @@ public function initialize() $initialState = $this->stateAccessor->getState($this->object); } catch (Exception\NoSuchPropertyException $e) { throw new Exception\ObjectException(sprintf( - 'StateMachine can\'t be initialized because the defined property_path of object "%s" does not exist.', + 'StateMachine can\'t be initialized because the defined property_path of object "%s" does not exist.', get_class($this->object) ), $e->getCode(), $e); } @@ -395,4 +401,57 @@ private function dispatchTransitionEvent(TransitionInterface $transition, Transi $this->dispatcher->dispatch($transitionState.'.'.$this->getGraph().'.'.$transition->getName(), $event); } } + + /** + * @return array + */ + public function getCallbacks() + { + if (empty($this->callbacks)) { + $this->generateCallbacks(); + } + + return $this->callbacks; + } + + /** + * @return array + */ + protected function generateCallbacks() + { + $listeners = [ + FiniteEvents::PRE_TRANSITION, + FiniteEvents::POST_TRANSITION, + ]; + + $callbacks = []; + + foreach ($listeners as $listener) { + $events = $this->getDispatcher()->getListeners($listener); + + foreach ($events as $event) { + if ($event instanceof Callback) { + $eventCallbacks = $event->getCallbacks(); + $clauses = $event->getSpecification()->getClauses(); + + $callback = [ + 'class' => get_class($eventCallbacks[0]), + 'method' => $eventCallbacks[1], + ]; + + foreach ($clauses as $clauseKey => $clauseValue) { + if (!empty($clauseValue)) { + foreach ($clauseValue as $name) { + $callbacks[$name][$listener][$clauseKey][] = $callback; + } + } + } + } + } + } + + $this->callbacks = $callbacks; + + return $this->callbacks; + } } From 09ce3c080581c4c53487e5d5205dcafe7786b140 Mon Sep 17 00:00:00 2001 From: Oskar Hasinski Date: Mon, 25 Jul 2016 17:52:10 +0200 Subject: [PATCH 3/8] added a method to list all callbacks. --- .../Event/Callback/CallbackInterface.php | 15 +++++ src/Finite/StateMachine/StateMachine.php | 55 +++++++++++++------ .../StateMachine/StateMachineInterface.php | 5 ++ 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/src/Finite/Event/Callback/CallbackInterface.php b/src/Finite/Event/Callback/CallbackInterface.php index 31a612e..d3a621d 100644 --- a/src/Finite/Event/Callback/CallbackInterface.php +++ b/src/Finite/Event/Callback/CallbackInterface.php @@ -15,4 +15,19 @@ interface CallbackInterface * @param TransitionEvent $event */ public function __invoke(TransitionEvent $event); + + /** + * @return CallbackSpecificationInterface + */ + public function getSpecification(); + + /** + * @return array callable + */ + public function getCallbacks(); + + /** + * @return array + */ + public function getClauses(); } diff --git a/src/Finite/StateMachine/StateMachine.php b/src/Finite/StateMachine/StateMachine.php index c8ecd4e..0ea2d61 100644 --- a/src/Finite/StateMachine/StateMachine.php +++ b/src/Finite/StateMachine/StateMachine.php @@ -408,7 +408,7 @@ private function dispatchTransitionEvent(TransitionInterface $transition, Transi public function getCallbacks() { if (empty($this->callbacks)) { - $this->generateCallbacks(); + $this->setCallbacks(); } return $this->callbacks; @@ -417,7 +417,7 @@ public function getCallbacks() /** * @return array */ - protected function generateCallbacks() + protected function setCallbacks() { $listeners = [ FiniteEvents::PRE_TRANSITION, @@ -431,21 +431,7 @@ protected function generateCallbacks() foreach ($events as $event) { if ($event instanceof Callback) { - $eventCallbacks = $event->getCallbacks(); - $clauses = $event->getSpecification()->getClauses(); - - $callback = [ - 'class' => get_class($eventCallbacks[0]), - 'method' => $eventCallbacks[1], - ]; - - foreach ($clauses as $clauseKey => $clauseValue) { - if (!empty($clauseValue)) { - foreach ($clauseValue as $name) { - $callbacks[$name][$listener][$clauseKey][] = $callback; - } - } - } + $callbacks = array_merge($callbacks, $this->getCallbackData($event, $listener)); } } } @@ -454,4 +440,39 @@ protected function generateCallbacks() return $this->callbacks; } + + /** + * @param Callback $event + * @param string $listener + * + * @return array + */ + protected function getCallbackData(Callback $event, $listener) + { + $eventCallbacks = $event->getCallbacks(); + $clauses = $event->getSpecification()->getClauses(); + + $callback = [ + 'class' => get_class($eventCallbacks[0]), + 'method' => $eventCallbacks[1], + ]; + + $callbacks = []; + + foreach ($clauses as $clauseKey => $clauseValue) { + if (!empty($clauseValue)) { + foreach ($clauseValue as $name) { + $callbacks[] = [ + 'name' => $name, + 'listener' => $listener, + 'clause' => $clauseKey, + 'class' => $callback['class'], + 'method' => $callback['method'], + ]; + } + } + } + + return $callbacks; + } } diff --git a/src/Finite/StateMachine/StateMachineInterface.php b/src/Finite/StateMachine/StateMachineInterface.php index 6f82a6e..0f62af7 100644 --- a/src/Finite/StateMachine/StateMachineInterface.php +++ b/src/Finite/StateMachine/StateMachineInterface.php @@ -131,4 +131,9 @@ public function getGraph(); * @return bool */ public function findStateWithProperty($property, $value = null); + + /** + * @return array + */ + public function getCallbacks(); } From 6d0974f16411c66bc5985498a68616b2b15cadbe Mon Sep 17 00:00:00 2001 From: Oskar Hasinski Date: Tue, 26 Jul 2016 11:24:05 +0200 Subject: [PATCH 4/8] - added a method to list all callbacks. - added getCallbacks on state and transitions --- .../Compiler/ContainerCallbackPass.php | 11 ++- .../DependencyInjection/Configuration.php | 5 +- .../FiniteFiniteExtension.php | 3 +- src/Finite/Event/Callback/Callback.php | 7 ++ .../Event/Callback/CallbackSpecification.php | 8 +- src/Finite/Event/CallbackHandler.php | 20 ++-- src/Finite/Loader/ArrayLoader.php | 94 ++++++++++++++----- src/Finite/State/State.php | 34 ++++++- src/Finite/State/StateInterface.php | 5 + src/Finite/StateMachine/StateMachine.php | 60 +----------- .../StateMachine/StateMachineInterface.php | 5 + src/Finite/Transition/Transition.php | 18 +++- 12 files changed, 165 insertions(+), 105 deletions(-) diff --git a/src/Finite/Bundle/FiniteBundle/DependencyInjection/Compiler/ContainerCallbackPass.php b/src/Finite/Bundle/FiniteBundle/DependencyInjection/Compiler/ContainerCallbackPass.php index 9addf27..aa457d4 100644 --- a/src/Finite/Bundle/FiniteBundle/DependencyInjection/Compiler/ContainerCallbackPass.php +++ b/src/Finite/Bundle/FiniteBundle/DependencyInjection/Compiler/ContainerCallbackPass.php @@ -2,6 +2,7 @@ namespace Finite\Bundle\FiniteBundle\DependencyInjection\Compiler; +use Finite\Event\Callback\Callback; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -24,14 +25,14 @@ public function process(ContainerBuilder $container) $definition = $container->getDefinition($id); $config = $definition->getArgument(0); if (isset($config['callbacks'])) { - foreach (array('before', 'after') as $position) { + foreach (array(Callback::CLAUSE_BEFORE, Callback::CLAUSE_AFTER) as $position) { foreach ($config['callbacks'][$position] as &$callback) { if ( - is_array($callback['do']) - && 0 === strpos($callback['do'][0], '@') - && $container->hasDefinition(substr($callback['do'][0], 1)) + is_array($callback[Callback::CLAUSE_DO]) + && 0 === strpos($callback[Callback::CLAUSE_DO][0], '@') + && $container->hasDefinition(substr($callback[Callback::CLAUSE_DO][0], 1)) ) { - $callback['do'][0] = new Reference(substr($callback['do'][0], 1)); + $callback[Callback::CLAUSE_DO][0] = new Reference(substr($callback[Callback::CLAUSE_DO][0], 1)); } } } diff --git a/src/Finite/Bundle/FiniteBundle/DependencyInjection/Configuration.php b/src/Finite/Bundle/FiniteBundle/DependencyInjection/Configuration.php index 5a2b8d0..72e1962 100644 --- a/src/Finite/Bundle/FiniteBundle/DependencyInjection/Configuration.php +++ b/src/Finite/Bundle/FiniteBundle/DependencyInjection/Configuration.php @@ -2,6 +2,7 @@ namespace Finite\Bundle\FiniteBundle\DependencyInjection; +use Finite\Event\Callback\Callback; use Symfony\Component\Config\Definition\Builder\NodeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; @@ -86,8 +87,8 @@ protected function addTransitionSection(NodeBuilder $rootProto) protected function addCallbackSection(NodeBuilder $rootProto) { $callbacks = $rootProto->arrayNode('callbacks')->children(); - $this->addSubCallbackSection($callbacks, 'before'); - $this->addSubCallbackSection($callbacks, 'after'); + $this->addSubCallbackSection($callbacks, Callback::CLAUSE_BEFORE); + $this->addSubCallbackSection($callbacks, Callback::CLAUSE_AFTER); $callbacks->end()->end(); } diff --git a/src/Finite/Bundle/FiniteBundle/DependencyInjection/FiniteFiniteExtension.php b/src/Finite/Bundle/FiniteBundle/DependencyInjection/FiniteFiniteExtension.php index d28bfd0..a6d3626 100644 --- a/src/Finite/Bundle/FiniteBundle/DependencyInjection/FiniteFiniteExtension.php +++ b/src/Finite/Bundle/FiniteBundle/DependencyInjection/FiniteFiniteExtension.php @@ -2,6 +2,7 @@ namespace Finite\Bundle\FiniteBundle\DependencyInjection; +use Finite\Event\Callback\Callback; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader; @@ -68,7 +69,7 @@ protected function removeDisabledCallbacks(array $config) return $config; } - foreach (array('before', 'after') as $position) { + foreach (array(Callback::CLAUSE_BEFORE, Callback::CLAUSE_AFTER) as $position) { foreach ($config['callbacks'][$position] as $i => $callback) { if ($callback['disabled']) { unset($config['callbacks'][$position][$i]); diff --git a/src/Finite/Event/Callback/Callback.php b/src/Finite/Event/Callback/Callback.php index 2138651..7b5bb4b 100644 --- a/src/Finite/Event/Callback/Callback.php +++ b/src/Finite/Event/Callback/Callback.php @@ -9,6 +9,13 @@ */ class Callback implements CallbackInterface { + const CLAUSE_AFTER = 'after'; + const CLAUSE_BEFORE = 'before'; + const CLAUSE_FROM = 'from'; + const CLAUSE_TO = 'to'; + const CLAUSE_ON = 'on'; + const CLAUSE_DO = 'do'; + /** * @var CallbackSpecificationInterface */ diff --git a/src/Finite/Event/Callback/CallbackSpecification.php b/src/Finite/Event/Callback/CallbackSpecification.php index c04edd9..476b542 100644 --- a/src/Finite/Event/Callback/CallbackSpecification.php +++ b/src/Finite/Event/Callback/CallbackSpecification.php @@ -36,7 +36,7 @@ public function __construct(StateMachineInterface $sm, array $from, array $to, a $isExclusion = function ($str) { return 0 === strpos($str, '-'); }; $removeDash = function ($str) { return substr($str, 1); }; - foreach (array('from', 'to', 'on') as $clause) { + foreach (array(Callback::CLAUSE_FROM, Callback::CLAUSE_TO, Callback::CLAUSE_ON) as $clause) { $excludedClause = 'excluded_'.$clause; $this->specs[$excludedClause] = array_filter(${$clause}, $isExclusion); @@ -58,9 +58,9 @@ public function isSatisfiedBy(TransitionEvent $event) { return $event->getStateMachine() === $this->stateMachine && - $this->supportsClause('from', $event->getInitialState()->getName()) && - $this->supportsClause('to', $event->getTransition()->getState()) && - $this->supportsClause('on', $event->getTransition()->getName()); + $this->supportsClause(Callback::CLAUSE_FROM, $event->getInitialState()->getName()) && + $this->supportsClause(Callback::CLAUSE_TO, $event->getTransition()->getState()) && + $this->supportsClause(Callback::CLAUSE_ON, $event->getTransition()->getName()); } /** diff --git a/src/Finite/Event/CallbackHandler.php b/src/Finite/Event/CallbackHandler.php index d81595c..ec1e7ec 100644 --- a/src/Finite/Event/CallbackHandler.php +++ b/src/Finite/Event/CallbackHandler.php @@ -40,23 +40,23 @@ public function __construct(EventDispatcherInterface $dispatcher) $this->specResolver = new OptionsResolver(); $this->specResolver->setDefaults( array( - 'on' => self::ALL, - 'from' => self::ALL, - 'to' => self::ALL, + Callback::CLAUSE_ON => self::ALL, + Callback::CLAUSE_FROM => self::ALL, + Callback::CLAUSE_TO => self::ALL, ) ); - $this->specResolver->setAllowedTypes('on', array('string', 'array')); - $this->specResolver->setAllowedTypes('from', array('string', 'array')); - $this->specResolver->setAllowedTypes('to', array('string', 'array')); + $this->specResolver->setAllowedTypes(Callback::CLAUSE_ON, array('string', 'array')); + $this->specResolver->setAllowedTypes(Callback::CLAUSE_FROM, array('string', 'array')); + $this->specResolver->setAllowedTypes(Callback::CLAUSE_TO, array('string', 'array')); $toArrayNormalizer = function (Options $options, $value) { return (array) $value; }; - $this->specResolver->setNormalizer('on', $toArrayNormalizer); - $this->specResolver->setNormalizer('from', $toArrayNormalizer); - $this->specResolver->setNormalizer('to', $toArrayNormalizer); + $this->specResolver->setNormalizer(Callback::CLAUSE_ON, $toArrayNormalizer); + $this->specResolver->setNormalizer(Callback::CLAUSE_FROM, $toArrayNormalizer); + $this->specResolver->setNormalizer(Callback::CLAUSE_TO, $toArrayNormalizer); } /** @@ -109,7 +109,7 @@ protected function add($smOrCallback, $event, $callable = null, array $specs = a ); $specs = $this->specResolver->resolve($specs); - $callback = CallbackBuilder::create($smOrCallback, $specs['from'], $specs['to'], $specs['on'], $callable)->getCallback(); + $callback = CallbackBuilder::create($smOrCallback, $specs[Callback::CLAUSE_FROM], $specs[Callback::CLAUSE_TO], $specs[Callback::CLAUSE_ON], $callable)->getCallback(); $this->dispatcher->addListener($event, $callback); diff --git a/src/Finite/Loader/ArrayLoader.php b/src/Finite/Loader/ArrayLoader.php index d714984..a11a125 100644 --- a/src/Finite/Loader/ArrayLoader.php +++ b/src/Finite/Loader/ArrayLoader.php @@ -2,6 +2,7 @@ namespace Finite\Loader; +use Finite\Event\Callback\Callback; use Finite\Event\Callback\CallbackBuilderFactory; use Finite\Event\Callback\CallbackBuilderFactoryInterface; use Finite\Event\CallbackHandler; @@ -72,9 +73,9 @@ public function load(StateMachineInterface $stateMachine) $stateMachine->setStateAccessor(new PropertyPathStateAccessor($this->config['property_path'])); $stateMachine->setGraph($this->config['graph']); + $this->loadCallbacks($stateMachine); $this->loadStates($stateMachine); $this->loadTransitions($stateMachine); - $this->loadCallbacks($stateMachine); } /** @@ -87,6 +88,48 @@ public function supports($object, $graph = 'default') return $reflection->isInstance($object) && $graph === $this->config['graph']; } + /** + * @param $triggerName + * + * @return array + */ + protected function findCallbacksByTrigger($triggerName) + { + $callbacks = []; + + foreach ([Callback::CLAUSE_BEFORE, Callback::CLAUSE_AFTER] as $position) { + $callbacks[$position] = []; + + $callbacks[$position] = array_merge( + $callbacks[$position], + $this->findCallbacksByTriggerAndPosition($triggerName, $position) + ); + } + + return $callbacks; + } + + /** + * @param $triggerName + * @param $position + * + * @return array + */ + protected function findCallbacksByTriggerAndPosition($triggerName, $position) + { + $callbacks = []; + + foreach ($this->config['callbacks'][$position] as $callbackName => $callback) { + foreach ([Callback::CLAUSE_FROM, 'to', 'on'] as $caluse) { + if (!empty($callback[$caluse][1]) && $callback[$caluse][1] == $triggerName) { + $callbacks[] = [$callbackName => $callback]; + } + } + } + + return $callbacks; + } + /** * @param StateMachineInterface $stateMachine */ @@ -102,7 +145,13 @@ private function loadStates(StateMachineInterface $stateMachine) foreach ($this->config['states'] as $state => $config) { $config = $resolver->resolve($config); - $stateMachine->addState(new State($state, $config['type'], array(), $config['properties'])); + $stateMachine->addState(new State( + $state, + $config['type'], + [], + $config['properties'], + $this->findCallbacksByTrigger($state) + )); } } @@ -112,12 +161,12 @@ private function loadStates(StateMachineInterface $stateMachine) private function loadTransitions(StateMachineInterface $stateMachine) { $resolver = new OptionsResolver(); - $resolver->setRequired(array('from', 'to')); + $resolver->setRequired(array(Callback::CLAUSE_FROM, Callback::CLAUSE_TO)); $resolver->setDefaults(array('guard' => null, 'configure_properties' => null, 'properties' => array())); $resolver->setAllowedTypes('configure_properties', array('null', 'callable')); - $resolver->setNormalizer('from', function (Options $options, $v) { return (array) $v; }); + $resolver->setNormalizer(Callback::CLAUSE_FROM, function (Options $options, $v) { return (array) $v; }); $resolver->setNormalizer('guard', function (Options $options, $v) { return !isset($v) ? null : $v; }); $resolver->setNormalizer('configure_properties', function (Options $options, $v) { $resolver = new OptionsResolver(); @@ -136,10 +185,11 @@ private function loadTransitions(StateMachineInterface $stateMachine) $stateMachine->addTransition( new Transition( $transition, - $config['from'], + $config[Callback::CLAUSE_FROM], $config['to'], $config['guard'], - $config['configure_properties'] + $config['configure_properties'], + $this->findCallbacksByTrigger($transition) ) ); } @@ -154,7 +204,9 @@ private function loadCallbacks(StateMachineInterface $stateMachine) return; } - foreach (array('before', 'after') as $position) { + $stateMachine->setCallbacks($this->config['callbacks']); + + foreach (array(Callback::CLAUSE_BEFORE, Callback::CLAUSE_AFTER) as $position) { $this->loadCallbacksFor($position, $stateMachine); } } @@ -171,10 +223,10 @@ private function loadCallbacksFor($position, $stateMachine) $specs = $resolver->resolve($specs); $callback = $this->callbackBuilderFactory->createBuilder($stateMachine) - ->setFrom($specs['from']) - ->setTo($specs['to']) - ->setOn($specs['on']) - ->setCallable($specs['do']) + ->setFrom($specs[Callback::CLAUSE_FROM]) + ->setTo($specs[Callback::CLAUSE_TO]) + ->setOn($specs[Callback::CLAUSE_ON]) + ->setCallable($specs[Callback::CLAUSE_DO]) ->getCallback(); $this->callbackHandler->$method($callback); @@ -187,24 +239,24 @@ private function getCallbacksResolver() $resolver->setDefaults( array( - 'on' => array(), - 'from' => array(), - 'to' => array(), + Callback::CLAUSE_ON => array(), + Callback::CLAUSE_FROM => array(), + Callback::CLAUSE_TO => array(), ) ); - $resolver->setRequired(array('do')); + $resolver->setRequired(array(Callback::CLAUSE_DO)); - $resolver->setAllowedTypes('on', array('string', 'array')); - $resolver->setAllowedTypes('from', array('string', 'array')); - $resolver->setAllowedTypes('to', array('string', 'array')); + $resolver->setAllowedTypes(Callback::CLAUSE_ON, array('string', 'array')); + $resolver->setAllowedTypes(Callback::CLAUSE_FROM, array('string', 'array')); + $resolver->setAllowedTypes(Callback::CLAUSE_TO, array('string', 'array')); $toArrayNormalizer = function (Options $options, $value) { return (array) $value; }; - $resolver->setNormalizer('on', $toArrayNormalizer); - $resolver->setNormalizer('from', $toArrayNormalizer); - $resolver->setNormalizer('to', $toArrayNormalizer); + $resolver->setNormalizer(Callback::CLAUSE_ON, $toArrayNormalizer); + $resolver->setNormalizer(Callback::CLAUSE_FROM, $toArrayNormalizer); + $resolver->setNormalizer(Callback::CLAUSE_TO, $toArrayNormalizer); return $resolver; } diff --git a/src/Finite/State/State.php b/src/Finite/State/State.php index bc4c06b..4678df5 100644 --- a/src/Finite/State/State.php +++ b/src/Finite/State/State.php @@ -27,6 +27,13 @@ class State implements StateInterface */ protected $transitions; + /** + * Callbacks of the state + * + * @var array + */ + protected $callbacks; + /** * The state name. * @@ -39,12 +46,27 @@ class State implements StateInterface */ protected $properties; - public function __construct($name, $type = self::TYPE_NORMAL, array $transitions = array(), array $properties = array()) - { + /** + * State constructor. + * + * @param $name + * @param string $type + * @param array $transitions + * @param array $properties + * @param array $callbacks + */ + public function __construct( + $name, + $type = self::TYPE_NORMAL, + array $transitions = [], + array $properties = [], + array $callbacks = [] + ) { $this->name = $name; $this->type = $type; $this->transitions = $transitions; $this->properties = $properties; + $this->callbacks = $callbacks; } /** @@ -163,6 +185,14 @@ public function setProperties(array $properties) $this->properties = $properties; } + /** + * @return array + */ + public function getCallbacks() + { + return $this->callbacks; + } + /** * @return string */ diff --git a/src/Finite/State/StateInterface.php b/src/Finite/State/StateInterface.php index e497d29..fec4279 100644 --- a/src/Finite/State/StateInterface.php +++ b/src/Finite/State/StateInterface.php @@ -69,4 +69,9 @@ public function getTransitions(); * @deprecated Deprecated since version 1.0.0-BETA2. Use {@link StateMachine::can($transition)} instead. */ public function can($transition); + + /** + * @return array + */ + public function getCallbacks(); } diff --git a/src/Finite/StateMachine/StateMachine.php b/src/Finite/StateMachine/StateMachine.php index 0ea2d61..2e8db57 100644 --- a/src/Finite/StateMachine/StateMachine.php +++ b/src/Finite/StateMachine/StateMachine.php @@ -407,72 +407,14 @@ private function dispatchTransitionEvent(TransitionInterface $transition, Transi */ public function getCallbacks() { - if (empty($this->callbacks)) { - $this->setCallbacks(); - } - return $this->callbacks; } /** * @return array */ - protected function setCallbacks() + public function setCallbacks($callbacks) { - $listeners = [ - FiniteEvents::PRE_TRANSITION, - FiniteEvents::POST_TRANSITION, - ]; - - $callbacks = []; - - foreach ($listeners as $listener) { - $events = $this->getDispatcher()->getListeners($listener); - - foreach ($events as $event) { - if ($event instanceof Callback) { - $callbacks = array_merge($callbacks, $this->getCallbackData($event, $listener)); - } - } - } - $this->callbacks = $callbacks; - - return $this->callbacks; - } - - /** - * @param Callback $event - * @param string $listener - * - * @return array - */ - protected function getCallbackData(Callback $event, $listener) - { - $eventCallbacks = $event->getCallbacks(); - $clauses = $event->getSpecification()->getClauses(); - - $callback = [ - 'class' => get_class($eventCallbacks[0]), - 'method' => $eventCallbacks[1], - ]; - - $callbacks = []; - - foreach ($clauses as $clauseKey => $clauseValue) { - if (!empty($clauseValue)) { - foreach ($clauseValue as $name) { - $callbacks[] = [ - 'name' => $name, - 'listener' => $listener, - 'clause' => $clauseKey, - 'class' => $callback['class'], - 'method' => $callback['method'], - ]; - } - } - } - - return $callbacks; } } diff --git a/src/Finite/StateMachine/StateMachineInterface.php b/src/Finite/StateMachine/StateMachineInterface.php index 0f62af7..63d7046 100644 --- a/src/Finite/StateMachine/StateMachineInterface.php +++ b/src/Finite/StateMachine/StateMachineInterface.php @@ -132,6 +132,11 @@ public function getGraph(); */ public function findStateWithProperty($property, $value = null); + /** + * @return array + */ + public function setCallbacks($callbacks); + /** * @return array */ diff --git a/src/Finite/Transition/Transition.php b/src/Finite/Transition/Transition.php index 9e5e047..f18bae2 100644 --- a/src/Finite/Transition/Transition.php +++ b/src/Finite/Transition/Transition.php @@ -43,19 +43,26 @@ class Transition implements PropertiesAwareTransitionInterface */ protected $propertiesOptionsResolver; + /** + * @var array + */ + protected $callbacks; + /** * @param string $name * @param string|array $initialStates * @param string $state * @param callable|null $guard * @param OptionsResolver $propertiesOptionsResolver + * @param array $callbacks */ public function __construct( $name, $initialStates, $state, $guard = null, - OptionsResolver $propertiesOptionsResolver = null + OptionsResolver $propertiesOptionsResolver = null, + array $callbacks = [] ) { if (null !== $guard && !is_callable($guard)) { throw new \InvalidArgumentException('Invalid callable guard argument passed to Transition::__construct().'); @@ -66,6 +73,7 @@ public function __construct( $this->initialStates = (array) $initialStates; $this->guard = $guard; $this->propertiesOptionsResolver = $propertiesOptionsResolver ?: new OptionsResolver(); + $this->callbacks = $callbacks; } /** @@ -178,6 +186,14 @@ public function getProperties() ); } + /** + * @return array + */ + public function getCallbacks() + { + return $this->callbacks; + } + /** * @return string */ From 9c2e59745399c599e0fff3a6aac7bb0522a555a1 Mon Sep 17 00:00:00 2001 From: Oskar Hasinski Date: Tue, 26 Jul 2016 11:44:10 +0200 Subject: [PATCH 5/8] fixed find callbacks issue --- src/Finite/Loader/ArrayLoader.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Finite/Loader/ArrayLoader.php b/src/Finite/Loader/ArrayLoader.php index a11a125..6ad8fb8 100644 --- a/src/Finite/Loader/ArrayLoader.php +++ b/src/Finite/Loader/ArrayLoader.php @@ -120,9 +120,12 @@ protected function findCallbacksByTriggerAndPosition($triggerName, $position) $callbacks = []; foreach ($this->config['callbacks'][$position] as $callbackName => $callback) { - foreach ([Callback::CLAUSE_FROM, 'to', 'on'] as $caluse) { - if (!empty($callback[$caluse][1]) && $callback[$caluse][1] == $triggerName) { - $callbacks[] = [$callbackName => $callback]; + foreach ([Callback::CLAUSE_FROM, Callback::CLAUSE_TO, Callback::CLAUSE_ON] as $clause) { + if (!empty($callback[$clause])) { + if ((is_string($callback[$clause]) && $callback[$clause] === $triggerName) + || (is_array($callback[$clause]) && in_array($triggerName, $callback[$clause]))) { + $callbacks[] = [$callbackName => $callback]; + } } } } From 233263c917cd18527e640f759edee4dbc21fb9f4 Mon Sep 17 00:00:00 2001 From: Oskar Hasinski Date: Tue, 26 Jul 2016 11:46:43 +0200 Subject: [PATCH 6/8] fixed unittests issues --- src/Finite/Event/Callback/Callback.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Finite/Event/Callback/Callback.php b/src/Finite/Event/Callback/Callback.php index 7b5bb4b..3110341 100644 --- a/src/Finite/Event/Callback/Callback.php +++ b/src/Finite/Event/Callback/Callback.php @@ -28,9 +28,9 @@ class Callback implements CallbackInterface /** * @param CallbackSpecificationInterface $callbackSpecification - * @param array $callable + * @param $callable */ - public function __construct(CallbackSpecificationInterface $callbackSpecification, array $callable) + public function __construct(CallbackSpecificationInterface $callbackSpecification, $callable) { $this->specification = $callbackSpecification; $this->callable = $callable; From f6b716237a02eaecb2625744cd016043e8068bb9 Mon Sep 17 00:00:00 2001 From: Oskar Hasinski Date: Tue, 26 Jul 2016 12:15:43 +0200 Subject: [PATCH 7/8] fixed unit tests --- src/Finite/Loader/ArrayLoader.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Finite/Loader/ArrayLoader.php b/src/Finite/Loader/ArrayLoader.php index 6ad8fb8..0cf8722 100644 --- a/src/Finite/Loader/ArrayLoader.php +++ b/src/Finite/Loader/ArrayLoader.php @@ -119,6 +119,10 @@ protected function findCallbacksByTriggerAndPosition($triggerName, $position) { $callbacks = []; + if (empty($this->config['callbacks'][$position])) { + return $callbacks; + } + foreach ($this->config['callbacks'][$position] as $callbackName => $callback) { foreach ([Callback::CLAUSE_FROM, Callback::CLAUSE_TO, Callback::CLAUSE_ON] as $clause) { if (!empty($callback[$clause])) { From a59d8efb8422d8e6954f16272c572e82a78333b9 Mon Sep 17 00:00:00 2001 From: Oskar Hasinski Date: Tue, 26 Jul 2016 12:23:24 +0200 Subject: [PATCH 8/8] fixed unit tests --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3c7908c..c66b8b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,7 @@ language: php sudo: false +# disabled old php build (http://php.net/eol.php) php: - - 5.3 - - 5.4 - - 5.5 - 5.6 - 7 - hhvm