/** * Constructor * * @param State $state State the caused the exception * @param string $setName Name of the state the object was expecting * @param \Exception $previous Optional previous exception */ public function __construct(State $state, $setName, \Exception $previous = null) { // Call the super constructor parent::__construct(sprintf('Trying to set state with name "%s" when object was expecting a state with name "%s"', $state->getName(), $setName), 0, $previous); // Set the properties $this->state = $state; $this->setName = $setName; }
public function testMoveTo() { $dummy = new DummyContext(); $start = new \DateTime(); // Test Simple Terminal State $instance = new WorkflowInstanceEntity(); $state = new State('one'); $instance = $state->moveTo($dummy, $instance); $this->assertNotNull($instance); $this->assertInstanceOf('TyHand\\WorkflowBundle\\Entity\\WorkflowInstanceEntity', $instance); $this->assertEquals('one', $instance->getStateName()); $this->assertGreaterThanOrEqual($start, $instance->getStateDate()); $this->assertTrue($instance->isComplete()); // Test Simple NonTerminal State $instance = new WorkflowInstanceEntity(); $state = new State('two'); $stateB = new State('B'); $trigger = new EventTrigger('go', 'B'); $trigger->setState($stateB); $state->addEventTrigger($trigger); $instance = $state->moveTo($dummy, $instance); $this->assertNotNull($instance); $this->assertInstanceOf('TyHand\\WorkflowBundle\\Entity\\WorkflowInstanceEntity', $instance); $this->assertEquals('two', $instance->getStateName()); $this->assertGreaterThanOrEqual($start, $instance->getStateDate()); $this->assertFalse($instance->isComplete()); // Test State with Actions $instance = new WorkflowInstanceEntity(); $state = new State('three'); $state->addAction(function ($context) { $context->increment(); }); $this->assertEquals(1, $dummy->getNum()); $instance = $state->moveTo($dummy, $instance); $this->assertNotNull($instance); $this->assertInstanceOf('TyHand\\WorkflowBundle\\Entity\\WorkflowInstanceEntity', $instance); $this->assertEquals('three', $instance->getStateName()); $this->assertGreaterThanOrEqual($start, $instance->getStateDate()); $this->assertEquals(2, $dummy->getNum()); $this->assertTrue($instance->isComplete()); // Test State with Conditions that eval to true $instance = new WorkflowInstanceEntity(); $state = new State('four'); $stateB = new State('B'); $stateC = new State('C'); $condition = new Condition(function ($context) { return true; }, 'B', 'C'); $condition->setTrueState($stateB); $condition->setFalseState($stateC); $state->addCondition($condition); $instance = $state->moveTo($dummy, $instance); $this->assertNotNull($instance); $this->assertInstanceOf('TyHand\\WorkflowBundle\\Entity\\WorkflowInstanceEntity', $instance); $this->assertEquals('B', $instance->getStateName()); $this->assertGreaterThanOrEqual($start, $instance->getStateDate()); $this->assertTrue($instance->isComplete()); // Test State with conditions that eval to false $instance = new WorkflowInstanceEntity(); $state = new State('four'); $stateB = new State('B'); $stateC = new State('C'); $condition = new Condition(function ($context) { return false; }, 'B', 'C'); $condition->setTrueState($stateB); $condition->setFalseState($stateC); $state->addCondition($condition); $instance = $state->moveTo($dummy, $instance); $this->assertNotNull($instance); $this->assertInstanceOf('TyHand\\WorkflowBundle\\Entity\\WorkflowInstanceEntity', $instance); $this->assertEquals('C', $instance->getStateName()); $this->assertGreaterThanOrEqual($start, $instance->getStateDate()); $this->assertTrue($instance->isComplete()); }
/** * Set the value of The followup state * * @param State state * * @return self */ public function setState(State $state) { if ($state->getName() === $this->stateName) { $this->state = $state; } else { throw new StateDoesNotMatchNameException($state, $this->stateName); } return $this; }
public function testOnWorkflowEvent() { // Create a test workflow $workflow = new Workflow('test', 'TyHand\\WorkflowBundle\\Tests\\DummyContext'); $stateA = new State('A'); $stateB = new State('B'); $stateC = new State('C'); $triggerA1 = new EventTrigger('go', 'B'); $triggerA1->setState($stateB); $triggerA2 = new EventTrigger('skip', 'C'); $triggerA2->setState($stateC); $triggerB1 = new EventTrigger('go', 'C'); $triggerB1->setState($stateC); $stateA->addEventTrigger($triggerA1); $stateA->addEventTrigger($triggerA2); $stateB->addEventTrigger($triggerB1); $workflow->addState($stateA); $workflow->addState($stateB); $workflow->addState($stateC); $workflow->setInitialState($stateA); // Create a mock workflow manager $mockManager = $this->getMockBuilder('TyHand\\WorkflowBundle\\Workflow\\WorkflowManager')->disableOriginalConstructor()->setMethods(array('getWorkflow'))->getMock(); $mockManager->expects($this->any())->method('getWorkflow')->with($this->equalTo('test'))->will($this->returnValue($workflow)); // create a mock object manager $mockObjectManager = $this->getMockBuilder('Doctrine\\ORM\\EntityManager')->disableOriginalConstructor()->setMethods(array('flush'))->getMock(); $mockObjectManager->expects($this->any())->method('flush')->will($this->returnValue(true)); // create the listener $listener = new WorkflowEventListener($mockManager, $mockObjectManager); // Test 1 (A -> B -> C) $dummyContext = new DummyContext(); $instance = $workflow->start($dummyContext); $this->assertEquals('A', $instance->getStateName()); $event = new WorkflowEvent($dummyContext, 'test', 'go'); $listener->onWorkflowEvent($event); $this->assertEquals('B', $instance->getStateName()); $event = new WorkflowEvent($dummyContext, 'test', 'go'); $listener->onWorkflowEvent($event); $this->assertEquals('C', $instance->getStateName()); // Test 2 (A -> C) $dummyContext = new DummyContext(); $instance = $workflow->start($dummyContext); $this->assertEquals('A', $instance->getStateName()); $event = new WorkflowEvent($dummyContext, 'test', 'skip'); $listener->onWorkflowEvent($event); $this->assertEquals('C', $instance->getStateName()); // Test 3 (A -> B -> C & A -> B) $dummyContext = new DummyContext(); $instance = $workflow->start($dummyContext); $this->assertEquals('A', $instance->getStateName()); $event = new WorkflowEvent($dummyContext, 'test', 'go'); $listener->onWorkflowEvent($event); $this->assertEquals('B', $instance->getStateName()); $instance2 = $workflow->start($dummyContext); $this->assertEquals('A', $instance2->getStateName()); $event = new WorkflowEvent($dummyContext, 'test', 'go'); $listener->onWorkflowEvent($event); $this->assertEquals('C', $instance->getStateName()); $this->assertEquals('B', $instance2->getStateName()); // Test 4 (A -> B -> B) $dummyContext = new DummyContext(); $instance = $workflow->start($dummyContext); $this->assertEquals('A', $instance->getStateName()); $event = new WorkflowEvent($dummyContext, 'test', 'go'); $listener->onWorkflowEvent($event); $this->assertEquals('B', $instance->getStateName()); $event = new WorkflowEvent($dummyContext, 'test', 'skip'); $listener->onWorkflowEvent($event); $this->assertEquals('B', $instance->getStateName()); // Test 5 (A -> A) $dummyContext = new DummyContext(); $instance = $workflow->start($dummyContext); $this->assertEquals('A', $instance->getStateName()); $event = new WorkflowEvent($dummyContext, 'test', 'jump'); $listener->onWorkflowEvent($event); $this->assertEquals('A', $instance->getStateName()); }
/** * Add a state to the workflow * * @param State $state State * * @return self */ public function addState(State $state) { // Check for name uniqueness if (array_key_exists($state->getName(), $this->states)) { throw new StateNameAlreadyUsedException($state->getName()); } $this->states[$state->getName()] = $state; return $this; }
/** * Get the name of the state being built * * @return string State name */ public function getStateName() { return $this->state->getName(); }
/** * @expectedException \TyHand\WorkflowBundle\Exceptions\ContextOverWorkflowLimitException * @expectedExceptionMessage This workflow only allows a context to have 2 active instances */ public function testStartContextWorkflowActiveLimitException() { $dummy = new DummyContext(); $workflow = new Workflow('test', 'TyHand\\WorkflowBundle\\Tests\\DummyContext'); $stateA = new State('A'); $stateB = new State('B'); $trigger = new EventTrigger('go', 'B'); $trigger->setState($stateB); $stateA->addEventTrigger($trigger); $workflow->addState($stateA); $workflow->addState($stateB); $workflow->setInitialState($stateA); $workflow->setActiveInstanceLimit(2); $instance = $workflow->start($dummy); // Mark instance 1 to be complete to test that only active is being checked $instance->setIsComplete(false); $instance2 = $workflow->start($dummy); $instance3 = $workflow->start($dummy); $this->assertTrue(true); // Checkpoint check $instance4 = $workflow->start($dummy); }