The example shows how workflow process can interact with a user through WEB.
mkdir ~/pvm-calculator
cd ~/pvm-calculator
# the dep on symfony is optional
composer req formapro/pvm:0.4.x-dev makasim/values:0.5.x-dev symfony/http-foundation:^4.1
# create such files with the code below
php -S localhost:8000
# open in browser http://localhost:8000/calculator.php
calculator.php
<?php
use Formapro\Pvm\DefaultBehaviorRegistry;
use Formapro\Pvm\Exception\WaitExecutionException;
use Formapro\Pvm\ProcessBuilder;
use Formapro\Pvm\ProcessEngine;
use Formapro\Pvm\Token;
use Formapro\Pvm\FileDAL;
use Formapro\Pvm\TokenTransition;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
require_once __DIR__.'/vendor/autoload.php';
$httpRequest = Request::createFromGlobals();
$fileDal = new FileDAL(__DIR__.'/store');
$process = null;
if ($httpRequest->get('token')) {
try {
$token = $fileDal->getToken($httpRequest->get('token'));
$process = $token->getProcess();
} catch (\InvalidArgumentException $e) {
}
}
if (false == $process) {
$process = (new ProcessBuilder())
->createNode('provide_a', 'a')->end()
->createNode('provide_b', 'b')->end()
->createNode('provide_operator', 'operator')->end()
->createNode('result', 'result')->end()
->createTransition('provide_a', 'provide_b')->end()
->createTransition('provide_b', 'provide_operator')->end()
->createTransition('provide_operator', 'result')->end()
->createStartTransition('provide_a')->end()
->getProcess()
;
$token = $fileDal->createProcessToken($process);
$token->addTransition(TokenTransition::createFor($process->getStartTransition(), 1));
}
$token->httpRequest = $httpRequest;
$registry = new DefaultBehaviorRegistry([
'a' => function(Token $token) {
/** @var Request $httpRequest */
$httpRequest = $token->httpRequest;
if ($token->getCurrentTransition()->isWaiting() && Request::METHOD_POST === $httpRequest->getMethod()) {
$token->setValue('a', $httpRequest->request->getInt('a'));
return;
}
$token->httpResponse = new Response('
<form method="post" action="'.$_SERVER['REQUEST_URI'].'?token='.$token->getId().'">
<label for="a">Select A:</label>
<input name="a" value="1" type="number" />
<input type="submit" title="Submit" />
</form>
');
throw new WaitExecutionException();
},
'b' => function(Token $token) {
/** @var Request $httpRequest */
$httpRequest = $token->httpRequest;
if ($token->getCurrentTransition()->isWaiting() && Request::METHOD_POST === $httpRequest->getMethod()) {
$token->setValue('b', $httpRequest->request->getInt('b'));
return;
}
$token->httpResponse = new Response('
<form method="post" action="'.$_SERVER['REQUEST_URI'].'">
<label for="b">Select B:</label>
<input name="b" value="2" type="number" />
<input type="submit" title="Submit" />
</form>
');
throw new WaitExecutionException();
},
'operator' => function(Token $token) {
/** @var Request $httpRequest */
$httpRequest = $token->httpRequest;
if ($token->getCurrentTransition()->isWaiting() && Request::METHOD_POST === $httpRequest->getMethod()) {
$token->setValue('operator', $httpRequest->request->get('operator'));
return;
}
$token->httpResponse = new Response('
<form method="post" action="'.$_SERVER['REQUEST_URI'].'">
<fieldset>
<legend>Select an operator:</legend>
<div>
<input type="radio" name="operator" value="+" checked />
<label for="huey">Addition "+"</label>
</div>
<div>
<input type="radio" name="operator" value="-" />
<label for="dewey">Subtraction "-"</label>
</div>
<div>
<input type="radio" name="operator" value="*" />
<label for="louie">Multiplication "*"</label>
</div>
</fieldset>
<input type="submit" title="Submit" />
</form>
');
throw new WaitExecutionException();
},
'result' => function(Token $token) {
$result = $token->getValue('result');
$operator = $token->getValue('operator');
$a = $token->getValue('a');
$b = $token->getValue('b');
if (false == $result) {
switch ($operator) {
case '+':
$result = $a + $b;
break;
case '-':
$result = $a - $b;
break;
case '*':
$result = $a * $b;
break;
default:
throw new \LogicException('Invalid operator');
}
$token->setValue('result', $result);
}
$token->httpResponse = new Response("
<p>The result of $a $operator $b equals <b>$result</b></p>
");
throw new WaitExecutionException();
},
]);
$engine = new ProcessEngine($registry, $fileDal);
$waitTokens = $engine->proceed($token);
/** @var Response $httpResponse */
$httpResponse = $waitTokens[0]->httpResponse;
echo $httpResponse->getContent();
{ "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Process.json", "id": "e467efcb-6035-4cd5-98ee-8aa1fe9b827c", "nodes": { "provide_a": { "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Node.json", "id": "provide_a", "behavior": "a" }, "provide_b": { "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Node.json", "id": "provide_b", "behavior": "b" }, "provide_operator": { "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Node.json", "id": "provide_operator", "behavior": "operator" }, "result": { "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Node.json", "id": "result", "behavior": "result" } }, "transitions": { "d066b5b2-5e9b-4cb8-a9fb-628a8a9109ae": { "id": "d066b5b2-5e9b-4cb8-a9fb-628a8a9109ae", "weight": 1, "async": false, "active": true, "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Transition.json", "from": "provide_a", "to": "provide_b" }, "c32b002c-1b15-4ee2-87da-9031ae262198": { "id": "c32b002c-1b15-4ee2-87da-9031ae262198", "weight": 1, "async": false, "active": true, "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Transition.json", "from": "provide_b", "to": "provide_operator" }, "26654deb-403d-47dd-8dc1-f046932b24f2": { "id": "26654deb-403d-47dd-8dc1-f046932b24f2", "weight": 1, "async": false, "active": true, "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Transition.json", "from": "provide_operator", "to": "result" }, "32c243c1-b724-4a80-b140-c5234afdc8e8": { "id": "32c243c1-b724-4a80-b140-c5234afdc8e8", "weight": 1, "async": false, "active": true, "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Transition.json", "to": "provide_a" } }, "outTransitions": { "provide_a": [ "d066b5b2-5e9b-4cb8-a9fb-628a8a9109ae" ], "provide_b": [ "c32b002c-1b15-4ee2-87da-9031ae262198" ], "provide_operator": [ "26654deb-403d-47dd-8dc1-f046932b24f2" ] }, "inTransitions": { "provide_b": [ "d066b5b2-5e9b-4cb8-a9fb-628a8a9109ae" ], "provide_operator": [ "c32b002c-1b15-4ee2-87da-9031ae262198" ], "result": [ "26654deb-403d-47dd-8dc1-f046932b24f2" ], "provide_a": [ "32c243c1-b724-4a80-b140-c5234afdc8e8" ] }, "tokens": { "02fb7f29-2a1d-4e05-8a67-badbee7e7b71": { "schema": "http:\/\/pvm.forma-pro.com\/schemas\/Token.json", "id": "02fb7f29-2a1d-4e05-8a67-badbee7e7b71", "transitions": [ { "schema": "http:\/\/pvm.forma-pro.com\/schemas\/TokenTransition.json", "id": "886c6b14-2b2d-4ae9-9936-bb2953396760", "transitionId": "32c243c1-b724-4a80-b140-c5234afdc8e8", "weight": 1, "state": "opened", "time": 16107339090958 }, { "schema": "http:\/\/pvm.forma-pro.com\/schemas\/TokenTransition.json", "id": "85a72eec-821b-4beb-bce0-b817db65f867", "transitionId": "32c243c1-b724-4a80-b140-c5234afdc8e8", "weight": 1, "state": "waiting", "time": 16107339090966, "reason": "" } ] } } }