/** * @test */ public function shouldAcceptMultipleCallableTypes() { //there are diverse ways to use callables: closures, anonymous function, instance methods //static methods. //https://php.net/manual/en/functions.anonymous.php //https://php.net/manual/en/language.types.callable.php $context = new Context(new Identifier('123', 'foo-machine')); $event = 'foo'; $a = new State('a'); $b = new State('b'); //scenario 1: Closure without variables from the parent scope $transition_callable = function ($entity) { $entity->setEntityId('234'); }; $t = new Transition($a, $b, $event, null, null, null, $transition_callable); $this->assertEquals('123', $context->getEntityId()); $t->process($context); $this->assertEquals('234', $context->getEntityId()); //scenario 2: Closure with Inheriting variables from the parent scope $x = 4; $transition_callable = function ($entity) use(&$x) { $x += 1; }; $t = new Transition($a, $b, $event, null, null, null, $transition_callable); $this->assertEquals(4, $x); $t->process($context); $this->assertEquals(5, $x); //scenario 3: Anonymous function / literal $context->getIdentifier()->setEntityId('123'); $t = new Transition($a, $b, $event, null, null, null, function ($entity) { $entity->setEntityId('234'); }); $this->assertEquals('123', $context->getEntityId()); $t->process($context); $this->assertEquals('234', $context->getEntityId()); //scenario 4: instance method invocation (method as string) $helper = new CallableHelper(); $transition_callable = array($helper, 'increaseInstanceId'); $t = new Transition($a, $b, $event, null, null, null, $transition_callable); $this->assertEquals(0, $helper->instance_id); $t->process($context); $this->assertEquals(1, $helper->instance_id); $t->process($context); $this->assertEquals(2, $helper->instance_id); //scenario 5: static method invocation in array (use fully qualified name) $helper = new CallableHelper(); $transition_callable = array('izzum\\statemachine\\CallableHelper', 'increaseId'); $t = new Transition($a, $b, $event, null, null, null, $transition_callable); $this->assertEquals(0, CallableHelper::$id); $t->process($context); $this->assertEquals(1, CallableHelper::$id); //scenario 6: static method invocation in string (use fully qualified name) //THIS IS THE WAY TO be able to specify a callable in a configuration file. $helper = new CallableHelper(); $transition_callable = 'izzum\\statemachine\\CallableHelper::increaseId'; $t = new Transition($a, $b, $event, null, null, null, $transition_callable); $this->assertEquals(1, CallableHelper::$id); $t->process($context); $this->assertEquals(2, CallableHelper::$id); //scenario 7: wrap an existing method in a closure (this is THE way to reuse an existing method) function jo($entity) { $entity->setEntityId($entity->getEntityId() + 1); } $callable = function ($context) { jo($context); }; $context->getIdentifier()->setEntityId('123'); $t = new Transition($a, $b, $event, null, null, null, $callable); $this->assertEquals('123', $context->getEntityId()); $t->process($context); $this->assertEquals('124', $context->getEntityId()); }
/** * @test */ public function shouldEnterWithCallable() { $state = new State('a'); $context = new Context(new Identifier('123', 'foo-machine')); $event = 'foo'; $callable = function ($entity) { $entity->setEntityId('234'); }; $state->setEntryCallable($callable); $this->assertEquals('123', $context->getEntityId()); $state->exitAction($context); $this->assertEquals('123', $context->getEntityId()); $state->entryAction($context); $this->assertEquals('234', $context->getEntityId()); }
/** * test the factory method with all parameters provided * implicitely tests the constructor */ public function testContext() { $entity_id = "id1"; $machine = "test machine"; $identifier = new Identifier($entity_id, $machine); $builder = new EntityBuilder(); $io = new Memory(); // all parameters $o = new Context($identifier, $builder, $io); $this->assertEquals($entity_id, $o->getEntityId()); $this->assertEquals($machine, $o->getMachine()); $this->assertNull($o->getStateMachine()); $this->assertTrue(is_a($o->getPersistenceAdapter(), 'izzum\\statemachine\\persistence\\Memory')); $this->assertTrue(is_a($o->getBuilder(), 'izzum\\statemachine\\EntityBuilder')); $this->assertEquals($identifier, $o->getEntity()); $this->assertTrue(is_string($o->getEntityId())); $this->assertTrue(is_string($o->toString())); $this->assertContains($entity_id, $o->toString()); $this->assertContains($machine, $o->toString()); $this->assertContains('izzum\\statemachine\\Context', $o->toString()); // even though we have a valid reader, the state machine does not exist. $this->assertEquals(State::STATE_UNKNOWN, $o->getState()); $this->assertTrue($o->setState(State::STATE_NEW, 'this is an informational message about why we set this state: we set this state to new for a unittest'), 'added'); $this->assertFalse($o->setState(State::STATE_NEW), 'already there'); // for coverage. $statemachine = new StateMachine($o); $this->assertNull($o->setStateMachine($statemachine)); $this->assertContains('Context', $o . '', '__toString()'); }