/** * {@inheritDoc} */ public function load(StateMachine $stateMachine) { //decode the json in a php object structure $decoded = yaml_parse($this->getYaml(), false); //yaml decoding returns a php array. $name = $stateMachine->getContext()->getMachine(); $found = false; $data = null; if (is_array(@$decoded['machines'])) { foreach ($decoded['machines'] as $data) { if ($data['name'] === $name) { $found = true; break; } } } if (!$found) { //no name match found throw new Exception(sprintf('no machine data found for "%s" in yaml. seems like a wrong configuration.', $name), Exception::BAD_LOADERDATA); } //accessing an array with an @ error suppresion operator ('shut the f**k up' operator), //allows you to get properties, even if they do not exist, without notices. //this lets us be a little lazy in mapping the array properties to the state and transition properties $states = array(); foreach ($data['states'] as $state) { $tmp = new State($state['name'], $state['type'], @$state['entry_command'], @$state['exit_command'], @$state['entry_callable'], @$state['exit_callable']); $tmp->setDescription(@$state['description']); $states[$tmp->getName()] = $tmp; } $transitions = array(); foreach ($data['transitions'] as $transition) { $tmp = new Transition($states[$transition['state_from']], $states[$transition['state_to']], @$transition['event'], @$transition['rule'], @$transition['command'], @$transition['guard_callable'], @$transition['transition_callable']); $tmp->setDescription(@$transition['description']); $transitions[] = $tmp; } //delegate to loader $loader = new LoaderArray($transitions); return $loader->load($stateMachine); }
/** * {@inheritDoc} * This is an implemented method from the Loader interface. * All other methods are actually implemented methods from the Adapter * class. */ public function load(StateMachine $statemachine) { $data = $this->getLoaderData($statemachine->getContext()->getMachine()); // delegate to LoaderArray $loader = new LoaderArray($data); $loader->load($statemachine); }
/** * {@inheritDoc} */ public function load(StateMachine $stateMachine) { //load the xml in a php object structure. suppres warning with @ operator since we explicitely check the return value $xml = @simplexml_load_string($this->getXML()); if ($xml === false) { //could not load throw new Exception(sprintf('could not load xml data. check the xml format'), Exception::BAD_LOADERDATA); } $name = $stateMachine->getContext()->getMachine(); $found = false; $data = null; foreach ($xml->machine as $data) { if ((string) @$data->name === $name) { $found = true; break; } } if (!$found) { //no name match found throw new Exception(sprintf('no machine data found for %s in xml. seems like a wrong configuration.', $name), Exception::BAD_LOADERDATA); } //accessing xml as an object with the @ error suppresion operator ('shut the f**k up' operator) //allows you to get properties, even if they do not exist, without notices. //this let's us be a littlebit lazy since we know some nonessential properties could not be there $states = array(); foreach ($data->states->state as $state) { $tmp = new State((string) $state->name, (string) $state->type, (string) @$state->entry_command, (string) @$state->exit_command, (string) @$state->entry_callable, (string) @$state->exit_callable); $tmp->setDescription((string) @$state->description); $states[$tmp->getName()] = $tmp; } $transitions = array(); foreach ($data->transitions->transition as $transition) { $tmp = new Transition($states[(string) @$transition->state_from], $states[(string) @$transition->state_to], (string) @$transition->event, (string) @$transition->rule, (string) @$transition->command, (string) @$transition->guard_callable, (string) @$transition->transition_callable); $tmp->setDescription((string) @$transition->description); $transitions[] = $tmp; } //delegate to loader $loader = new LoaderArray($transitions); return $loader->load($stateMachine); }
/** * {@inheritDoc} */ public function load(StateMachine $stateMachine) { //decode the json in a php object structure $decoded = json_decode($this->getJSON(), false); if (!$decoded) { //could not decode (make sure that fully qualified names are escaped with //2 backslashes: \\izzum\\commands\\Null and that only double quotes are used. throw new Exception(sprintf('could not decode json data. did you only use double quotes? check the json format against %s', 'http://jsonlint.com/'), Exception::BAD_LOADERDATA); } $name = $stateMachine->getContext()->getMachine(); $found = false; if (is_array(@$decoded->machines)) { foreach ($decoded->machines as $data) { if ($data->name === $name) { $found = true; break; } } } if (!$found) { //no name match found throw new Exception(sprintf('no machine data found for %s in json. seems like a wrong configuration.', $name), Exception::BAD_LOADERDATA); } //accessing json as an object with an @ error suppresion operator ('shut the f**k up' operator), //allows you to get properties, even if they do not exist, without notices. //this lets us be a little lazy in mapping the json properties to the state and transition properties $states = array(); foreach ($data->states as $state) { $tmp = new State($state->name, $state->type, @$state->entry_command, @$state->exit_command, @$state->entry_callable, @$state->exit_callable); $tmp->setDescription(@$state->description); $states[$tmp->getName()] = $tmp; } $transitions = array(); foreach ($data->transitions as $transition) { $tmp = new Transition($states[$transition->state_from], $states[$transition->state_to], @$transition->event, @$transition->rule, @$transition->command, @$transition->guard_callable, @$transition->transition_callable); $tmp->setDescription(@$transition->description); $transitions[] = $tmp; } //delegate to loader $loader = new LoaderArray($transitions); return $loader->load($stateMachine); }
/** * @test */ public function shouldAddRegexesLoaderOnlyWhenStatesAreSet() { $context = new Context(new Identifier(Identifier::NULL_ENTITY_ID, Identifier::NULL_STATEMACHINE)); $machine = new StateMachine($context); $transitions = array(); $s1 = new State("1"); $s2 = new State("2"); $s3 = new State("3"); //many to many $transitions[] = new Transition(new State('regex:/.*/'), new State('regex:/.*/')); $loader = new LoaderArray($transitions); $this->assertEquals(count($transitions), $loader->count()); $this->assertEquals(1, $loader->count()); $this->assertEquals(0, count($machine->getStates())); $this->assertEquals(0, count($machine->getTransitions())); $count = $loader->load($machine); $this->assertEquals(0, $count, 'nothing because there are no known states'); $this->assertTrue($machine->addState($s1)); $this->assertTrue($machine->addState($s2)); $this->assertTrue($machine->addState($s3)); $this->assertEquals(3, count($machine->getStates())); $this->assertFalse($machine->addState($s1)); $this->assertFalse($machine->addState($s2)); $this->assertFalse($machine->addState($s3)); $this->assertEquals(3, count($machine->getStates())); $count = $loader->load($machine); $this->assertEquals(6, count($machine->getTransitions())); $this->assertEquals(6, $count, 'regexes have matched all states and created a mesh'); $count = $loader->load($machine); $this->assertEquals(0, $count, 'transitions are not added since they have already been added'); $this->assertEquals(3, count($machine->getStates())); $this->assertEquals(6, count($machine->getTransitions())); }
/** * https://github.com/rolfvreijdenberger/izzum-statemachine/issues/7 * @test */ public function shouldFailConfigurationCheckForMachineWithBadCallables() { $transitions = array(); $s1 = new State("1"); $s1->setEntryCallable('foobar'); $s2 = new State("2"); $s2->setEntryCallable('foobar'); $s3 = new State("3"); $s3->setEntryCallable('foobar'); $transitions[] = new Transition($s1, $s2); $transitions[] = new Transition($s2, $s3); //3 states, 3 bad callables //2 transitions, 4 bad callables //total of 7 foreach ($transitions as $transition) { $transition->setGuardCallable('foobar'); $transition->setTransitionCallable('foobar'); } $loader = new LoaderArray($transitions); $context = new Context(new Identifier(Identifier::NULL_ENTITY_ID, Identifier::NULL_STATEMACHINE)); $machine = new StateMachine($context); $loader->load($machine); $exceptions = Utils::checkConfiguration($machine); $this->assertEquals(7, count($exceptions)); $this->assertTrue(true, 'basic machine with bad callables will be configured incorrectly'); }