/**
  * 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;
 }
Example #2
0
 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());
 }
Example #3
0
 /**
  * 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());
 }
Example #5
0
 /**
  * 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;
 }
Example #6
0
 /**
  * Get the name of the state being built
  *
  * @return string State name
  */
 public function getStateName()
 {
     return $this->state->getName();
 }
Example #7
0
 /**
  * @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);
 }