Новое в Symfony 4.3: Улучшения Workflow

В Symfony 4.3 улучшили компонент Workflow с множеством основных и второстепенных функций. В этом блоге кратко изложены наиболее важные из них.

Добавлен контекст для Workflow::apply()

При применении перехода теперь можно передать пользовательский $context (например, пользователь, который выполнил переход, или текущую дату):

$workflow->apply($article, $request->request->get('transition'), [
    'time' => date('y-m-d H:i:s'),
]);

Перед использованием этой функции обновите свою сущность или любой другой объект, поддерживаемый рабочим процессом, следующим образом:

 class Article
 {
-    public function setMarking($marking)
+    public function setMarking($marking, $context = [])

Затем обновите конфигурацию рабочего процесса, чтобы использовать MethodMarkingStore:

framework:
     workflows:
         article:
             type: workflow
             marking_store:
-                 type: multiple_state
+                 type: method

Возможность изменять контекст в слушателе

Передача контекста при каждом вызове ->apply() может раздражать и приводить к дублированию кода.

Теперь вы можете создать слушателя, который сделает это за вас:

class TransitionEventSubscriber implements EventSubscriberInterface
{
    private $tokenStorage;

    public function __construct(TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    public function onWorkflowArticleTransition(TransitionEvent $event)
    {
        $context = $event->getContext();

        $token = $this->tokenStorage->getToken();
        if ($token instanceof TokenInterface) {
            $user = $token->getUser();
            if ($user instanceof UserInterface) {
                $context['user'] = $user->getUsername();
            }
        }

        $event->setContext($context);
    }

    public static function getSubscribedEvents()
    {
        return [
           TransitionEvent::class => 'onWorkflowArticleTransition',
        ];
    }
}

Выбор цвета в рабочий процесс

Теперь можно настроить способ отображения рабочего процесса благодаря параметру конфигурации метаданных dump_style:

transitions:
    submit:
        from: start
        to: travis
        metadata:
            title: transition submit title
            dump_style:
                label: 'My custom label'
                arrow_color: '#0088FF'
                label_color: 'Red'

И вот как будет выглядеть пользовательский стиль:

Symfony Workflow

Возможность настроить множество начальных мест

В отличие от конечных автоматов, при использовании рабочего процесса можно иметь тему во многих местах. Вот почему компонент теперь позволяет настроить несколько начальных мест:

workflows:
    article:
        type: workflow
        initial_marking: [foo, bar]
        places: [foo, bar, a, b, c, d]

Более простая конфигурация

Как упоминалось выше, субъекты могут находиться только в одном месте в конечных автоматах, но они могут находиться в одном или нескольких состояниях при использовании рабочего процесса. Однако первоначальный дизайн компонента Workflow позволял использовать рабочий процесс с хранилищем разметки единого состояния. Это было не лучшее решение, и оно добавило ненужной сложности.

Начиная с Symfony 4.3, если ваш субъект может находиться только в одном состоянии, используйте конечный автомат. В этом случае свойство (по умолчанию называемое маркировкой) будет строкой. Если тема может быть во многих местах, используйте рабочий процесс. В этом случае свойство будет массивом.

Благодаря этому упрощению улучшили DX (опыт разработчика):

framework:
    workflows:
        article:
            type: workflow
            marking_store:
                type: method # This will be the default value in Symfony 5.0
                property: marking # This is the default value, it could be omitted
        task:
            type: state_machine
            marking_store:
                type: method # This will be the default value in Symfony 5.0
                property: state

Добавлена функция workflow_transition_blockers() для Twig

В Symfony 4.1 добавили функцию, чтобы узнать, почему переход заблокирован.

В Symfony 4.3 добавляем функцию Twig для создания списка блокировщиков:

<h2>Publication was blocked because:</h2>
<ul>
    {% for blocker in workflow_transition_blockers(article, 'publish') %}
        <li>
            {{ blocker.message }}
            {# Display the guard expression #}
            {% if blocker.parameters.expression is defined %}
                <code>{{ blocker.parameters.expression }}</code>
            {% endif %}
        </li>
    {% endfor %}
<ul>