/**
  * Finalize the workflow
  *
  * @return Workflow Constructed workflow
  */
 public function build()
 {
     // Build the workflow
     $workflow = new Workflow($this->workflowName, $this->contextClass);
     // Set the limits if they exist
     if ($this->activeLimit !== null) {
         $workflow->setActiveInstanceLimit($this->activeLimit);
     }
     if ($this->totalLimit !== null) {
         $workflow->setTotalInstanceLimit($this->totalLimit);
     }
     // Construct the map of states
     $stateMap = array();
     foreach ($this->stateBuilders as $stateName => $stateBuilder) {
         $stateMap[$stateName] = $stateBuilder->getUnbuiltState();
     }
     // Build each state
     foreach ($this->stateBuilders as $stateBuilder) {
         $workflow->addState($stateBuilder->build($stateMap));
     }
     // Set the Initial state
     if (!array_key_exists($this->initialStateName, $stateMap)) {
         throw new StateNotFoundException($this->initialStateName, array_keys($stateMap));
     }
     $workflow->setInitialState($stateMap[$this->initialStateName]);
     // Return the completed workflow
     return $workflow;
 }
 /**
  * @expectedException        \TyHand\WorkflowBundle\Exceptions\WorkflowNotFoundException
  * @expectedExceptionMessage Workflow with name "unicorn" was not found.  Names found are [ "manager_test" ]
  */
 public function testWorkflowNotFoundException()
 {
     // Create a dummy definition
     $workflow = new Workflow('manager_test', 'TyHand\\WorkflowBundle\\Tests\\DummyContext');
     $stateA = new State('A');
     $workflow->addState($stateA);
     $workflow->setInitialState($stateA);
     $mockBuilder = $this->getMockBuilder('TyHand\\WorkflowBundle\\Workflow\\Builder\\WorkflowBuilder')->disableOriginalConstructor()->setMethods(array('build'))->getMock();
     $mockBuilder->expects($this->any())->method('build')->will($this->returnValue($workflow));
     $mockDefinition = $this->getMockBuilder('TyHand\\WorkflowBundle\\Workflow\\AbstractWorkflowDefinition')->setMethods(array('getName', 'getContextClass', 'build'))->getMock();
     $mockDefinition->expects($this->any())->method('getName')->will($this->returnValue('manager_test'));
     $mockDefinition->expects($this->any())->method('getContextClass')->will($this->returnValue('TyHand\\WorkflowBundle\\Tests\\DummyContext'));
     $mockDefinition->expects($this->any())->method('build')->will($this->returnValue($mockBuilder));
     // Create the new manager
     $manager = new WorkflowManager();
     $manager->addWorkflowDefinition($mockDefinition);
     // Get a non-existent workflow
     $workflow = $manager->getWorkflow('unicorn');
 }
 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());
 }
 /**
  * @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);
 }