Skip to content

Commit

Permalink
minor #11209 Documented the workflow metadata [redux] (javiereguiluz,…
Browse files Browse the repository at this point in the history
… pbowyer, OskarStark)

This PR was merged into the 4.2 branch.

Discussion
----------

Documented the workflow metadata [redux]

With @javiereguiluz's permission I have taken #9476 and incorporated the comments and code examples into it.

This is the start of a push to improve the Workflow documentation. The focus now is on expanding the documentation by merging pull requests; organizing it will come later.

Commits
-------

7f3a0fd Oskar's feedback
a4c23c1 Add blank line between code block and sentence above. Code block was not rendering.
6080aa8 Remove the word 'simple'
3765ddb Change code formatting of PHP snippet per https://github.com/symfony/symfony-docs/pull/11209/files/d57fa38d903175d58d9cfbf63f20e7ced8d2fd01#r268391655
55c9199 Indent PHP block by an additional 4 spaces
225c2fe Apply suggestions from code review
f716e81 Incorporate @OskarStark's feedback
94d17de Simplify the English and turn it into a tip
40fbaf3 Update arrays to use short syntax
ea64992 Incorporate further excellent feedback from @HeahDude
af71c14 Add an introduction as suggested in #11209 (comment)
ca66356 Document how to see all configuration options (see #11209 (comment))
c9ef262 Incorporate @OskarStark's feedback
c595c47 First set of tidy-ups for @HeahDude's feedback.
663639b Incorporate the code examples in #9476 (comment) into the documentation
17eae8c Add missing metadata key, fixing comment by @noniagriconomie on #9476
d68cc99 Documented the workflow metadata
  • Loading branch information
javiereguiluz committed Apr 17, 2019
2 parents 96cb148 + 7f3a0fd commit 3456cc0
Showing 1 changed file with 230 additions and 0 deletions.
230 changes: 230 additions & 0 deletions workflow/usage.rst
Expand Up @@ -14,6 +14,15 @@ install the workflow feature before using it:
$ composer require symfony/workflow
Configuration
-------------

To see all configuration options, if you are using the component inside a Symfony project run this command:

.. code-block:: terminal
$ bin/console config:dump-reference framework workflows
Creating a Workflow
-------------------

Expand Down Expand Up @@ -552,3 +561,224 @@ Don't need a human-readable message? You can also block a transition via a guard
event using::

$event->setBlocked('true');

Storing Metadata
----------------

.. versionadded:: 4.1

The feature to store metadata in workflows was introduced in Symfony 4.1.

In case you need it, you can store arbitrary metadata in workflows, their
places, and their transitions using the ``metadata`` option. This metadata can
be as simple as the title of the workflow or as complex as your own application
requires:

.. configuration-block::

.. code-block:: yaml
# config/packages/workflow.yaml
framework:
workflows:
blog_publishing:
metadata:
title: 'Blog Publishing Workflow'
# ...
places:
draft:
metadata:
max_num_of_words: 500
# ...
transitions:
to_review:
from: draft
to: review
metadata:
priority: 0.5
# ...
.. code-block:: xml
<!-- config/packages/workflow.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"
>
<framework:config>
<framework:workflow name="blog_publishing">
<framework:metadata>
<framework:title>Blog Publishing Workflow</framework:title>
</framework:metadata>
<!-- ... -->
<framework:place name="draft">
<framework:metadata>
<framework:max-num-of-words>500</framework:max-num-of-words>
</framework:metadata>
</framework:place>
<!-- ... -->
<framework:transition name="to_review">
<framework:from>draft</framework:from>
<framework:to>review</framework:to>
<framework:metadata>
<framework:priority>0.5</framework:priority>
</framework:metadata>
</framework:transition>
<!-- ... -->
</framework:workflow>
</framework:config>
</container>
.. code-block:: php
// config/packages/workflow.php
$container->loadFromExtension('framework', [
// ...
'workflows' => [
'blog_publishing' => [
'metadata' => [
'title' => 'Blog Publishing Workflow',
],
// ...
'places' => [
'draft' => [
'metadata' => [
'max_num_of_words' => 500,
],
],
// ...
],
'transitions' => [
'to_review' => [
'from' => 'draft',
'to' => 'review',
'metadata' => [
'priority' => 0.5,
],
],
],
],
],
]);
Then you can access this metadata in your controller as follows::

public function myControllerAction(Registry $registry, Article $article)
{
$workflow = $registry->get($article);

$workflow
->getMetadataStore()
->getWorkflowMetadata()['title'] ?? false
;

// or
$workflow->getMetadataStore()
->getWorkflowMetadata()['title'] ?? false
;

// or
$aTransition = $workflow->getDefinition()->getTransitions()[0];
$workflow
->getMetadataStore()
->getTransitionMetadata($aTransition)['title'] ?? false
;
}

There is a shortcut that works with everything::

$workflow
->getMetadataStore()
->getMetadata('title')
;

In a Flash message in your Controller::

// $transition = ...; (an instance of Transition)

// $workflow is a Workflow instance retrieved from the Registry (see above)
$title = $workflow->getMetadataStore()->getMetadata('title', $transition);
$this->addFlash('info', "You have successfully applied the transition with title: '$title'");

Metadata can also be accessed in a Listener, from the Event object.

Using transition blockers you can
return a user-friendly error message when you stop a transition from happening. In the example we
get this message from the :class:`Symfony\\Component\\Workflow\\Event\\Event`'s metadata, giving
you a central place to manage the text.

.. tip::

This example has been simplified; in production you may prefer to use the :doc:`Translation </components/translation>`
component to manage messages in one place::

namespace App\Listener\Workflow\Task;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\GuardEvent;
use Symfony\Component\Workflow\TransitionBlocker;

class OverdueGuard implements EventSubscriberInterface
{
public function guardPublish(GuardEvent $event)
{
$timeLimit = $event->getMetadata('time_limit', $event->getTransition());

if (date('Hi') <= $timeLimit) {
return;
}

$explanation = $event->getMetadata('explanation', $event->getTransition());
$event->addTransitionBlocker(new TransitionBlocker($explanation , 0));
}

public static function getSubscribedEvents()
{
return [
'workflow.task.guard.done' => 'guardPublish',
];
}
}

.. versionadded:: 4.1

The transition blockers were introduced in Symfony 4.1.

In Twig templates, metadata is available via the ``workflow_metadata()`` function:

.. code-block:: html+twig

<h2>Metadata</h2>
<p>
<strong>Workflow</strong>:<br >
<code>{{ workflow_metadata(article, 'title') }}</code>
</p>
<p>
<strong>Current place(s)</strong>
<ul>
{% for place in workflow_marked_places(article) %}
<li>
{{ place }}:
<code>{{ workflow_metadata(article, 'max_num_of_words', place) ?: 'Unlimited'}}</code>
</li>
{% endfor %}
</ul>
</p>
<p>
<strong>Enabled transition(s)</strong>
<ul>
{% for transition in workflow_transitions(article) %}
<li>
{{ transition.name }}:
<code>{{ workflow_metadata(article, 'priority', transition) ?: '0' }}</code>
</li>
{% endfor %}
</ul>
</p>

0 comments on commit 3456cc0

Please sign in to comment.