namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Table(name="pull_request") * @ORM\Entity(repositoryClass="AppBundle\Repository\PullRequestRepository") */ class PullRequest { /** * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\Column(type="string") */ private $currentPlace; /** * @return int */ public function getId() { return $this->id; } /** * @return PullRequest */ public function setCurrentPlace($currentPlace) { $this->currentPlace = $currentPlace; return $this; } /** * @return string */ public function getCurrentPlace() { return $this->currentPlace; } }
# app/config/config.yml framework: workflows: pull_request: type: 'state_machine' marking_store: type: 'single_state' argument: 'currentPlace' supports: - AppBundle\Entity\PullRequest places: - start - coding - travis - review - merged - closed transitions: submit: from: start to: travis update: from: [coding, travis, review] to: travis wait_for_review: from: travis to: review request_change: from: review to: coding accept: from: review to: merged reject: from: review to: closed reopen: from: closed to: review
use AppBundle\Entity\PullRequest; use Symfony\Component\Workflow\Exception\LogicException; $pullRequest = new PullRequest(); // $stateMachine = $this->getContainer()->get('state_machine.pull_request'); $stateMachine->can($pullRequest, 'submit'); //true $stateMachine->can($pullRequest, 'accept'); //false try { // start travis $stateMachine->apply($pullRequest, 'submit'); } catch(LogicException $workflowException) {} $stateMachine->can($pullRequest, 'update'); //true $stateMachine->can($pullRequest, 'wait_for_review'); //true $stateMachine->can($pullRequest, 'accept'); //false try { // update review $stateMachine->apply($pullRequest, 'wait_for_review'); } catch(LogicException $workflowException) {} $stateMachine->can($pullRequest, 'request_change'); //true $stateMachine->can($pullRequest, 'accept'); //true $stateMachine->can($pullRequest, 'reject'); //true $stateMachine->can($pullRequest, 'reopen'); //false try { // update review $stateMachine->apply($pullRequest, 'reject'); } catch(LogicException $workflowException) {} $stateMachine->can($pullRequest, 'request_change'); //false $stateMachine->can($pullRequest, 'accept'); //false $stateMachine->can($pullRequest, 'reject'); //false $stateMachine->can($pullRequest, 'reopen'); //true - pull request echo $pullRequest->getCurrentPlace(); //closed try { // - $stateMachine->apply($pullRequest, 'reject'); } catch(LogicException $workflowException) { echo ' !!! :('; } $stateMachine->apply($pullRequest, 'reopen'); echo $pullRequest->getCurrentPlace(); //review
use Doctrine\ORM\Mapping as ORM; /** * @ORM\Table(name="article") * @ORM\Entity(repositoryClass="AppBundle\Repository\ArticleRepository") */ class Article { /** * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\Column(type="simple_array") */ private $currentPlaces; public function getId() { return $this->id; } public function setCurrentPlaces($currentPlaces) { $this->currentPlaces = $currentPlaces; return $this; } public function getCurrentPlaces() { return $this->currentPlaces; } }
article: supports: - AppBundle\Entity\Article type: 'workflow' marking_store: type: 'multiple_state' argument: 'currentPlaces' places: - draft - wait_for_journalist - approved_by_journalist - wait_for_spellchecker - approved_by_spellchecker - published transitions: request_review: from: draft to: - wait_for_journalist - wait_for_spellchecker journalist_approval: from: wait_for_journalist to: approved_by_journalist spellchecker_approval: from: wait_for_spellchecker to: approved_by_spellchecker publish: from: - approved_by_journalist - approved_by_spellchecker to: published
$article = new Article(); $workflow = $this->getContainer()->get('workflow.article'); $workflow->apply($article, 'request_review'); /* array(2) { ["wait_for_journalist"]=> int(1) ["wait_for_spellchecker"]=> int(1) } */ var_dump($article->getCurrentPlaces()); //, ! $workflow->apply($article, 'journalist_approval'); /* array(2) { ["wait_for_spellchecker"]=> int(1) ["approved_by_journalist"]=> int(1) } */ var_dump($article->getCurrentPlaces()); var_dump($workflow->can($article, 'publish')); //false, $workflow->apply($article, 'spellchecker_approval'); var_dump($workflow->can($article, 'publish')); //true,
digraph workflow { ratio="compress" rankdir="LR" node [fontsize="9" fontname="Arial" color="#333333" fillcolor="lightblue" fixedsize="1" width="1"]; edge [fontsize="9" fontname="Arial" color="#333333" arrowhead="normal" arrowsize="0.5"]; place_start [label="start", shape=circle, style="filled"]; place_coding [label="coding", shape=circle]; place_travis [label="travis", shape=circle]; place_review [label="review", shape=circle]; place_merged [label="merged", shape=circle]; place_closed [label="closed", shape=circle]; transition_submit [label="submit", shape=box, shape="box", regular="1"]; transition_update [label="update", shape=box, shape="box", regular="1"]; transition_update [label="update", shape=box, shape="box", regular="1"]; transition_update [label="update", shape=box, shape="box", regular="1"]; transition_wait_for_review [label="wait_for_review", shape=box, shape="box", regular="1"]; transition_request_change [label="request_change", shape=box, shape="box", regular="1"]; transition_accept [label="accept", shape=box, shape="box", regular="1"]; transition_reject [label="reject", shape=box, shape="box", regular="1"]; transition_reopen [label="reopen", shape=box, shape="box", regular="1"]; place_start -> transition_submit [style="solid"]; transition_submit -> place_travis [style="solid"]; place_coding -> transition_update [style="solid"]; transition_update -> place_travis [style="solid"]; place_travis -> transition_update [style="solid"]; transition_update -> place_travis [style="solid"]; place_review -> transition_update [style="solid"]; transition_update -> place_travis [style="solid"]; place_travis -> transition_wait_for_review [style="solid"]; transition_wait_for_review -> place_review [style="solid"]; place_review -> transition_request_change [style="solid"]; transition_request_change -> place_coding [style="solid"]; place_review -> transition_accept [style="solid"]; transition_accept -> place_merged [style="solid"]; place_review -> transition_reject [style="solid"]; transition_reject -> place_closed [style="solid"]; place_closed -> transition_reopen [style="solid"]; transition_reopen -> place_review [style="solid"]; }
$dumper = new \Symfony\Component\Workflow\Dumper\GraphvizDumper(); echo $dumper->dump($stateMachine->getDefinition());
php bin/console workflow:dump pull_request > out.dot dot -Tpng out.dot -o graph.png
framework: workflows: article: audit_trail: true supports: - AppBundle\Entity\Article places: - draft - wait_for_journalist - approved_by_journalist - wait_for_spellchecker - approved_by_spellchecker - published transitions: request_review: guard: "is_fully_authenticated()" from: draft to: - wait_for_journalist - wait_for_spellchecker journalist_approval: guard: "is_granted('ROLE_JOURNALIST')" from: wait_for_journalist to: approved_by_journalist spellchecker_approval: guard: "is_fully_authenticated() and has_role('ROLE_SPELLCHECKER')" from: wait_for_spellchecker to: approved_by_spellchecker publish: guard: "is_fully_authenticated()" from: - approved_by_journalist - approved_by_spellchecker to: published
Source: https://habr.com/ru/post/325758/
All Articles