Le composant workflow de Symfony, c'est graphement bien !

Le composant workflow de Symfony, c'est graphement bien !

Gérer les étapes de validation d’une application peut vite devenir un casse tête. Le composant Workflow de Symfony a été introduit en 3.2 pour simplifier la vie de tous les développeurs qui avaient besoin de gérer des graphs, processus de validation et/ou machines à états. J’ai eu l’occasion de m’y frotter sur le projet d’un grand compte et j’aimerais vous faire part de cette expérience. Vous décrire cette mise en place sera également l’occasion de dévoiler deux petites révolutions qui seront bientôt livrées à la communauté.

#Symfony_Live

8097e20a9d74d43f471aa7470d4e75c3?s=128

Hamza Amrouche

March 30, 2018
Tweet

Transcript

  1. Le composant workflow de Symfony, c’est graphement bien.

  2. Les-Tilleuls.coop Lead Dev Symfony chez Les-Tilleuls.coop Core Team Api-Platform Contributeur

    Symfony @cDaed Simperfit Bureau étendu AFUP Hamza Amrouche
  3. Les-Tilleuls.coop Les-Tilleuls.coop SCOP fondée en 2011 Détenue à 100% par

    ses salariés 25 coopérateurs, 97% de croissance On recrute à Amiens, Lille, Paris et Londres jobs@les-tilleuls.coop
  4. Les-Tilleuls.coop L’accompagnement des particuliers et des professionnels du bâtiment Groupe

    Adeo (Leroy Merlin) Équipe technique de 20 personnes (St Cloud) Quotatis est présent aujourd’hui au Symfony Live Quotatis
  5. Les-Tilleuls.coop

  6. Les-Tilleuls.coop demo quotatis projet

  7. Les-Tilleuls.coop La théorie des graphes A B D C

  8. Les-Tilleuls.coop La théorie des graphes A B C D

  9. Les-Tilleuls.coop La théorie des graphes A B C D

  10. Les-Tilleuls.coop La théorie des graphes A C D B

  11. Les-Tilleuls.coop La théorie des graphes A C 5 B

  12. Les-Tilleuls.coop A B 3 6 2 3 4 2 1

    5 2 La théorie des graphes
  13. Les-Tilleuls.coop A 3 6 2 3 4 2 1 5

    2 B La théorie des graphes
  14. Les-Tilleuls.coop 3 6 2 3 4 2 1 5 2

    A B La théorie des graphes
  15. Les-Tilleuls.coop La théorie Graphes

  16. Les-Tilleuls.coop La théorie des graphes

  17. Les-Tilleuls.coop La théorie Graphes Arbre

  18. Les-Tilleuls.coop Workflow Graphes Arbre La théorie

  19. Les-Tilleuls.coop Transitions Arcs Place Le réseau de pétri

  20. Les-Tilleuls.coop Transitions Arcs Place Le réseau de pétri

  21. Les-Tilleuls.coop Transitions Arcs Place Tokens Le réseau de pétri

  22. Les-Tilleuls.coop Transitions Arcs Place Tokens Le réseau de pétri

  23. Les-Tilleuls.coop Transitions Arcs Place Tokens Le réseau de pétri

  24. Les-Tilleuls.coop Le réseau de pétri

  25. Les-Tilleuls.coop Le réseau de pétri

  26. Les-Tilleuls.coop Le réseau de pétri

  27. Les-Tilleuls.coop Théorie Graphes Arbre Workflow Machine à états

  28. Les-Tilleuls.coop Une machine à états A D C t1 B

    t0b t0a
  29. Les-Tilleuls.coop Qu’est-ce que le composant Workflow ?

  30. Les-Tilleuls.coop

  31. Les-Tilleuls.coop

  32. Les-Tilleuls.coop Quelle est son utilité ?

  33. Les-Tilleuls.coop Place Transition A t0 Place B Arcs Arcs Un

    workflow classique worklow-net
  34. Les-Tilleuls.coop A t0 B C t1 D Un workflow single

    state
  35. Les-Tilleuls.coop A C B t0 Un workflow multiple state

  36. Les-Tilleuls.coop A D C t1 B t0b t0a Une machine

    à états
  37. Les-Tilleuls.coop $definition = new Definition([‘in_progress',‘to_validate'], [ new Transition( ‘to_validate', //

    transition name [‘in_progress’], // from place [‘to_validate'] // to place ) ], ‘in_progress' ); } Définition du workflow
  38. Les-Tilleuls.coop Définition du workflow

  39. Les-Tilleuls.coop workflows: project: type: 'state_machine' # 'workflow' # […] Définition

    du workflow
  40. Les-Tilleuls.coop workflows: project: type: 'state_machine' marking_store: type: single_state # […]

    Définition du workflow
  41. Les-Tilleuls.coop workflows: project: type: 'workflow' marking_store: type: multiple_state # […]

    Définition du workflow
  42. Les-Tilleuls.coop workflows: project: type: 'state_machine' marking_store: type: single_state arguments: -

    status Définition du workflow
  43. Les-Tilleuls.coop workflows: project: # […] supports: - AppBundle\Entity\Project places: -

    created - to_validate Définition du workflow
  44. Les-Tilleuls.coop workflows: project: # […] transitions: to_validate: from: created to:

    to_validate Définition du workflow
  45. Les-Tilleuls.coop bin/console workflow:dump project | dot -Tpng -o etc/project-graph.png http://graphviz.org/download/

    Graphviz
  46. Les-Tilleuls.coop Graphviz

  47. Les-Tilleuls.coop Le composant nous permet de garantir que les projets

    qui sont dans certains états (places) ont bien passé toutes les règles de validation. Merci au Workflow !
  48. Les-Tilleuls.coop Un workflow en prod

  49. Les-Tilleuls.coop Le can()

  50. Les-Tilleuls.coop Le apply()

  51. Les-Tilleuls.coop Les events !

  52. Les-Tilleuls.coop Les events public static function getSubscribedEvents() { return [

    'workflow.project.enter.to_validate'=> ['assignUser'], 'workflow.project.entered.validated' => ['sendToLegacy'], ]; }
  53. Les-Tilleuls.coop class BlogPostReviewListener implements EventSubscriberInterface { public function guardReview(GuardEvent $event)

    { $post = $event->getSubject(); $title = $post->title; if (!$title) { // Posts with no title should not be allowed $event->setBlocked(true); } } public static function getSubscribedEvents() { return ['workflow.blogpost.guard.to_review' => ['guardReview']]; } } Le guard event
  54. Les-Tilleuls.coop La vue <h3>Actions</h3> {% if workflow_can(post, 'publish') %} <a

    href="...">Publish article</a> {% endif %}
  55. Les-Tilleuls.coop {# Or loop through the enabled transitions #} {%

    for transition in workflow_transitions(post) %} <a href="...">{{ transition.name }}</a> {% endfor %} La vue
  56. Les-Tilleuls.coop {# Check if the object is in some specific

    place #} {% if workflow_has_marked_place(post, 'to_review') %} <p>This post is ready for review.</p> {% endif %} La vue
  57. Les-Tilleuls.coop {# Check if some place has been marked on

    the object #} {% if 'waiting_some_approval' in workflow_marked_places(post) %} <span class="label">PENDING</span> {% endif %} La vue
  58. Les-Tilleuls.coop Contexte Quotatis Quotatis permet aux personnes qui souhaitent faire

    des travaux de créer des projets, ceux-ci ont plusieurs états. Pour atteindre ces états il y a des conditions, qui ne sont remplies que si le projet est prêt.
  59. Les-Tilleuls.coop L’utilisation au quotidien

  60. Les-Tilleuls.coop En mode API Scenario: As authenticated user, I can

    set the project's status to "to_validate" Given I am authenticated as user And there is a newly created project When I set the project's status to "to_validate" Then I should get a project And the status should be "to_validate" And I should be assigned to the project L’utilisateur à travers l’application :
  61. Les-Tilleuls.coop L’API elle-même qui transforme le projet en « pending_search

    » lorsque qu’un appel à l’api « Legacy » est fait. // […] $project->setLeadReference((string) $xml->newid); if ($this->projectWorkflow->can($project, ‘pending_search’)) { $this->projectWorkflow->apply($project, ‘pending_search’); } // […] En mode API
  62. Les-Tilleuls.coop

  63. Les-Tilleuls.coop La « Legacy » qui transforme le projet en

    « found » lorsque le projet a trouvé son artisan.
 
 Via un simple PUT. En mode API
  64. Les-Tilleuls.coop private function checkStatusWorkflow(Project $data) { $content = json_decode($request->getContent(), true);

    if (isset($content[‘status’])) { return; } if ($this->projectWorkflow->can($data, $status)) { $this->projectWorkflow->apply($data, $status); return; } throw new BadRequestHttpException('status.not_in_workflow'); } En mode API
  65. Les-Tilleuls.coop Petite Démo

  66. Les-Tilleuls.coop demo

  67. Les-Tilleuls.coop Symfony 3.4 Symfony 4.1 http://symfony-workflow-demo.herokuapp.com

  68. Les-Tilleuls.coop Ajout des transitions blockers 3.4 : https://github.com/symfony/symfony/pull/23499

  69. Les-Tilleuls.coop framework: workflows: issue: marking_store: type: single_state arguments: - state

    supports: AppBundle\Entity\Project places: - created - to_valdate transitions: affect: guard: "is_valid(subject, [‘toValidate’]) » from: created to: to_validate
  70. Les-Tilleuls.coop Ajout des transitions blockers 4.1: https://github.com/symfony/symfony/pull/26076

  71. Les-Tilleuls.coop Ajout des transitions blockers $event->addTransitionBlocker( new TransitionBlocker('You can not

    validate the project. Try again tomorrow morning.') ); Exemple par Javier Eguiluz.
  72. Les-Tilleuls.coop Ajout des transitions blockers {# […] get the transition.name

    #} <ul> {% for blocker in workflow_build_transition_blocker_list(project, transition.name) %} <li> {{ blocker.message }} {% if blocker.parameters.expression is defined %} <code>{{ blocker.parameters.expression }}</code> {% endif %} </li> {% endfor %} </ul> Exemple par Javier Eguiluz.
  73. Les-Tilleuls.coop Plus de contraintes sur le nom des places 4.1:

    https://github.com/symfony/symfony/pull/26079
  74. Les-Tilleuls.coop Before weird: places: - a' - é! - b\"(\"

    supports: AppBundle\Entity\Project transitions: - from: a' name: "{}" to: é! type: workflow Exemple par Grégoire Pineau. The place "é!" contains invalid characters.
  75. Les-Tilleuls.coop After weird: places: - a' - é! - b\"(\"

    supports: AppBundle\Entity\Project transitions: - from: a' name: "{}" to: é! type: workflow Exemple par Grégoire Pineau.
  76. Les-Tilleuls.coop Un store de metadata 4.1: https://github.com/symfony/symfony/pull/26079

  77. Les-Tilleuls.coop Un store de metadata framework: workflows: project: supports: -

    App\Entity\Project metadata: description: 'This is a project' # ... places: created: metadata: some_key: 'some_value' # ... transitions: to_validate: metadata: some_key: 'some_value' Exemple par Javiere Eguiluz.
  78. Les-Tilleuls.coop Un store de metadata public function onReview(Event $event) {

    $metadataStore = $event->getWorkflow()->getMetadataStore(); foreach ($event->getTransition()->getTos() as $place) { $this->flashbag->add('info', $metadataStore->getPlaceMetadata($place)->get(‘description')); } } Exemple par Javier Eguiluz.
  79. Les-Tilleuls.coop Un store de metadata <strong>Current place(s)</strong> <ul> {% for

    place in workflow_marked_places(article) %} <li> {{ place }}: <code>{{ workflow_metadata(article, 'title', place) ?: 'n-a'}}</code> </li> {% endfor %} </ul> Exemple par Javier Eguiluz.
  80. Les-Tilleuls.coop Un store de metadata <strong>Enabled transition(s)</strong> <ul> {% for

    transition in workflow_transitions(article) %} <li> {{ transition.name }}: <code>{{ workflow_metadata(article, 'title', transition) ?: 'n-a'}}</code> </li> {% endfor %} </ul> Exemple par Javier Eguiluz.
  81. Les-Tilleuls.coop Un nouveau dumper

  82. Les-Tilleuls.coop PlantUML php bin/console workflow:dump project --dump-format=puml | java -jar

    plantuml.jar -p > workflow.png http://plantuml.com/
  83. Les-Tilleuls.coop

  84. Les-Tilleuls.coop Une nouvelle interface… 
 Pour les gouverner tous !

  85. Les-Tilleuls.coop

  86. Les-Tilleuls.coop

  87. Les-Tilleuls.coop interface WorkflowInterface { public function getMarking($subject); public function can($subject,

    $transitionName); public function buildTransitionBlockerList($subject, string $transitionName): TransitionBlockerList; public function apply($subject, $transitionName); public function getEnabledTransitions($subject); public function getName(); public function getDefinition(); public function getMarkingStore(); public function getMetadataStore(): MetadataStoreInterface; } 4.1: https://github.com/symfony/symfony/pull/24751
  88. Les-Tilleuls.coop À quoi ça sert ?

  89. Les-Tilleuls.coop Merci ! Des questions ? @cDaed Simperfit http://simperfit.fr