Skip to content

Added docs for Workflow component #6871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d0701f0
Added docs for Workflow component
Nyholm Aug 12, 2016
91867c2
Moved images
Nyholm Aug 12, 2016
69bca59
Fixes
Nyholm Aug 12, 2016
f99fbb2
Fixes
Nyholm Aug 12, 2016
e797f0c
Syntax error
Nyholm Aug 12, 2016
5b2a029
Cleanup and minor fixes
Nyholm Aug 16, 2016
196baf9
Separated docs for component
Nyholm Aug 16, 2016
763950d
Updating docs to using symfony services
Nyholm Aug 16, 2016
cead2f7
Added docs about registry
Nyholm Aug 16, 2016
e0089c5
Added placeholders
Nyholm Aug 16, 2016
48de43d
Added note about state machines
Nyholm Aug 16, 2016
805b237
Added example with twig
Nyholm Aug 16, 2016
f57ec14
Show Twig function workflow_transitions
Nyholm Aug 16, 2016
03925ff
syntax fix
Nyholm Aug 16, 2016
e6bdee6
Some syntax fixes and a better "why do we need this"
Nyholm Nov 7, 2016
c7464c7
typos
Nyholm Nov 7, 2016
83d26c1
toctree fix
Nyholm Nov 7, 2016
6e7a35f
Fixed typos and comments
Nyholm Nov 8, 2016
4415466
Added usage example on the component
Nyholm Nov 8, 2016
866b25a
Added example how to dump with Symfony
Nyholm Nov 8, 2016
dceebec
Added examples of workflows
Nyholm Nov 8, 2016
b959f8a
Updated state machine with an example
Nyholm Nov 8, 2016
b45edf2
simplify job_application
Nyholm Nov 8, 2016
fefdb5f
syntax
Nyholm Nov 9, 2016
7f0f5b0
Added comment about the service name
Nyholm Nov 9, 2016
c681283
Updated accoding to feedback
Nyholm Nov 9, 2016
86ecf0a
Added PHP config
Nyholm Nov 9, 2016
d002a8b
Added xml and PHP config
Nyholm Nov 9, 2016
b0a8855
Added workflow under guides
Nyholm Nov 9, 2016
4e7cf11
Removed the *why workflows* from the usage page.
Nyholm Nov 9, 2016
3aa433d
Documented support for DefinitionBuilder
Nyholm Nov 9, 2016
4f277dc
fixed typo
Nyholm Nov 9, 2016
2511c21
Merge pull request #1 from Nyholm/workflow-definition-builder
Nyholm Nov 9, 2016
c9b1656
Updated to support changes in https://github.com/symfony/symfony/pull…
Nyholm Nov 9, 2016
2cc2934
Updated twig example
Nyholm Nov 9, 2016
47dc11d
show how to configure the DI extension config
Nyholm Nov 11, 2016
3250621
Fixed typos
Nyholm Nov 11, 2016
c0bd6da
Use imperative instead of past tense.
Nyholm Nov 11, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Added docs for Workflow component
  • Loading branch information
Nyholm committed Nov 7, 2016
commit d0701f04d48af12e0ce485609eab84bb4646e9a2
Binary file added _images/workflow/blogpost.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _images/workflow/states_transactions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
105 changes: 105 additions & 0 deletions components/workflow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,109 @@ You can install the component in 2 different ways:

For more information, see the code in the Git Repository.

Usage
-----

The workflow component gives you an object oriented way to work with state machines. A state machine lets you
define *places* (or *states*) and *transactions*. A transaction describes the action to get from one place to another.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should replace "transaction" with "transition" everywhere.


.. image:: /_images/components/workflow/states_transactions.png

A set of places and ``Transaction``s form a ``Definition``. A ``Workflow`` needs a ``Definition`` and a way to write
the states to the objects, ie a ``MarkingStoreInterface``.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also the initial place with something like: If a definition has no explicit initial place, it uses the first place defined.

Consider the following example for a blog post. A post can have places: 'draft', 'review', 'rejected', 'published'. You
can define the workflow like this:

$states = ['draft', 'review', 'rejected', 'published'];
$transactions[] = new Transition('to_review', ['draft', 'rejected'], 'review');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not work. See symfony/symfony#19605

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add use statements for classes in the first code example you're using them.

$transactions[] = new Transition('publish', 'review', 'published');
$transactions[] = new Transition('reject', 'review', 'rejected');

$definition = new Definition($states, $transactions);
$definition->setInitialPlace('draft');

$marking = new ScalarMarkingStore('currentState');
$workflow = new Workflow($definition, $marking);

The ``Workflow`` can now help you do decide what actions that are allowed on a blog post.


$post = new \stdClass();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use an imaginary BlogPost class here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please prepend this example with // ..., to indicate that this code should be added to the previous code example.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather show the definition of the BlogPost class since it is important that there is a field called currentState.

$post->currentState = null;
$workflow->can($post, 'publish'); // False
$workflow->can($post, 'to_draft'); // True

// Update the currentState on the post
try {
$workflow->apply($post, 'to_review');
} catch (LogicException $e) {
// ...
}

// See all the available transaction for the post in the current state
$transactions = $workflow->getEnabledTransitions($post);



Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the empty lines (except from one)

Using events
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Using Events" (in our title case, all words are capitialized except from closed-class words)

------------

To make your workflows even more powerful you could construct the ``Workflow`` object with an ``EventDispatcher``. You
can now create event listeners to block transactions ie depending on the data in the blog post. The following events
are dispatched:

* workflow.guard
* workflow.[workflow name].guard
* workflow.[workflow name].guard.[transaction name]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please put these event names in literal blocks? (double backticks)


See example to make sure no blog post without title is moved to "review"::

class BlogPostReviewListener implements EventSubscriberInterface
{
public function guardReview(GuardEvent $event)
{
$post = $event->getSubject();
$title = $post->getTitle();

if (empty($title)) {
// Posts with no title should not be allowed
$event->setBlocked(true);
}
}

public static function getSubscribedEvents()
{
return array(
'workflow.blogpost.guad.to_review' => array('guardReview'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess there is a typo here, isn't it ?

-  'workflow.blogpost.guad.to_review'
+ 'workflow.blogpost.guard.to_review'

Is it related to the Guard component ? I don't see any security stuff here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you.

No it is not related to the guard component. It is just named that way. I was also confused in the beginning.

);
}
}

With help from the ``EventDispatcher`` and the ``AuditTrailListener`` you could easily enable logging::

$logger = new PSR3Logger()
$subscriber = new AuditTrailListener($logger);
$dispatcher->addSubscriber($subscriber);

Dumper
------

To help you debug you could dump a representation of your workflow with the use of a ``DumperInterface``. Use the
``GraphvizDumper`` to create a PNG image of the workflow defined above::

// dump-graph.php
$dumper = new GraphvizDumper();
echo $dumper->dump($definition);

.. code-block:: bash

$ php dump-graph-php > out.dot
$ dot -Tpng out.dot -o graph.png
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should explain what is dot as it is an external dependency. Is it available on Windows & macOS ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are very correct. I added a note about graphviz. Yes, is available for Linux, Solaris, Windows and Mac.


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the double empty line

The result will look like this:

.. image:: /_images/components/workflow/blogpost.png


.. _Packagist: https://packagist.org/packages/symfony/workflow