Add Flow Builder action
This functionality is available starting with Shopware 6.4.6.0

Overview

In this guide, you'll learn how to create custom flow action in Shopware. The flow builder uses actions to perform business tasks. This example will introduce a new custom action called create tags.

Prerequisites

In order to add your own custom flow action for your plugin, you first need a plugin as base. Therefore, you can refer to the Plugin Base Guide.
You also should be familiar with the Dependency Injection container as this is used to register your custom flow action and Listening to events to create a subscriber class.
It might be helpful to gather some general understanding about the concept of Flow Builder as well.

Existing triggers and actions

You can refer to the Flow reference to read triggers and actions detail.

Create custom flow action

To create a custom flow action, firstly you have to make a plugin and install it, you can refer to the Plugin Base Guide to do it. I will create a plugin named ExamplePlugin. We have to implement both backend (PHP) code and a user interface in the Administration to manage it. Let's start with the PHP part first, which handles the main logic of our action. After that, there will be an example to show your new actions in the Administration.

Creating flow action in PHP

Create new Aware interface

First of all, we need to define an aware interface for your own action. I intended to create the CreateTagAction, so I need to create a related aware named TagAware, will be placed in directory <plugin root>/src/Core/Framework/Event. Our new interface has to extend from interfaces Shopware\Core\Framework\Event\FLowEventAware:
<plugin root>/src/Core/Framework/Event/TagAware.php
1
<?php declare(strict_types=1);
2
namespace Swag\ExamplePlugin\Core\Framework\Event;
3
use Shopware\Core\Framework\Event\FlowEventAware;
4
5
interface TagAware extends FlowEventAware
6
{
7
}
Copied!

Create new action

In this example, we will name it CreateTagAction. It will be placed in the directory <plugin root>/src/Core/Content/Flow/Dispatching/Action. Our new class has to extend from the abstract class Shopware\Core\Framework\Event\FLowEvent. Below you can find an example implementation:
<plugin root>/src/Core/Content/Flow/Dispatching/Action/CreateTagAction.php
1
<?php declare(strict_types=1);
2
3
namespace Swag\ExamplePlugin\Core\Content\Flow\Dispatching\Action;
4
5
use Shopware\Core\Content\Flow\Dispatching\Action\FlowAction;
6
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
7
use Shopware\Core\Framework\Uuid\Uuid;
8
use Swag\ExamplePlugin\Core\Framework\Event\TagAware;
9
use Shopware\Core\Framework\Event\FlowEvent;
10
11
class CreateTagAction extends FlowAction
12
{
13
private EntityRepositoryInterface $tagRepository;
14
15
public function __construct(EntityRepositoryInterface $tagRepository)
16
{
17
// you would need this repository to create a tag
18
$this->tagRepository = $tagRepository;
19
}
20
21
public static function getName(): string
22
{
23
// your own action name
24
return 'action.create.tag';
25
}
26
27
public static function getSubscribedEvents(): array
28
{
29
return [
30
self::getName() => 'handle',
31
];
32
}
33
34
public function requirements(): array
35
{
36
return [TagAware::class];
37
}
38
39
public function handle(FlowEvent $event): void
40
{
41
// config is the config data when created a flow sequence
42
$config = $event->getConfig();
43
44
// make sure your tags data is exist
45
if (!\array_key_exists('tags', $config)) {
46
return;
47
}
48
49
$baseEvent = $event->getEvent();
50
51
$tags = $config['tags'];
52
53
// just a step to make sure you're dispatching correct action
54
if (!$baseEvent instanceof TagAware || empty($tags)) {
55
return;
56
}
57
58
$tagData = [];
59
foreach ($tags as $tag) {
60
$tagData[] = [
61
'id' => Uuid::randomHex(),
62
'name' => $tag,
63
];
64
}
65
66
// simply create tags
67
$this->tagRepository->create($tagData, $baseEvent->getContext());
68
}
69
}
Copied!
As you can see, several methods are already implemented:
  • __constructor: This only defines the default expected value. This is overwritten at runtime with the actual value, that the shop owner set in the Administration.
  • getName: Returns a unique technical name for your action.
  • requirements: This defines which interfaces that the action belongs to.
  • handle: Use this method to handle your action stuff.
And we also need to register this action in the container as a service, make sure you have defined a tag <tag name="flow.action" priority="600"> at <plugin root>/src/Resources/config/services.xml, that your action would be added to response of /api/_info/flow-actions.json API and priority will decide the order of action of API response:
<plugin root>/src/Resources/config/services.xml
1
<service id="Swag\ExamplePlugin\Core\Content\Flow\Dispatching\Action\CreateTagAction">
2
<argument type="service" id="tag.repository" />
3
<tag name="kernel.event_subscriber"/>
4
<tag name="flow.action" priority="600"/>
5
</service>
Copied!
Great, your own action is created completely. Let's go to the next step.

Define action scope

At this step, you will know how to define your action scope, for CreateTagAction, I intended it would be available for all events. Let's see the code below:
<plugin root>/src/Core/Content/Flow/Subscriber/BusinessEventCollectorSubscriber.php
1
<?php declare(strict_types=1);
2
3
namespace Swag\ExamplePlugin\Core\Content\Flow\Subscriber;
4
5
use Shopware\Core\Framework\Event\BusinessEventCollectorEvent;
6
use Swag\ExamplePlugin\Core\Framework\Event\TagAware;
7
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
8
9
class BusinessEventCollectorSubscriber implements EventSubscriberInterface
10
{
11
public static function getSubscribedEvents()
12
{
13
return [
14
BusinessEventCollectorEvent::NAME => 'addTagAware',
15
];
16
}
17
18
public function addTagAware(BusinessEventCollectorEvent $event): void
19
{
20
foreach ($event->getCollection()->getElements() as $definition) {
21
$definition->addAware(TagAware::class);
22
}
23
}
24
}
Copied!
And don't forget to register your subscriber to the container at <plugin root>/src/Resources/config/services.xml.
<plugin root>/src/Resources/config/services.xml
1
<service id="Swag\ExamplePlugin\Core\Content\Flow\Subscriber\BusinessEventCollectorSubscriber">
2
<tag name="kernel.event_subscriber"/>
3
</service>
Copied!
Well done, you are successfully created your custom action in Backend in PHP.
This functionality is available starting with Shopware 6.4.6.0

Add custom action in Administration

After we are done with the PHP code, action.create.tag is received from the response of /api/_info/flow-actions.json. However, the custom action displays in the action list without label. These further steps in Administration will help you show the action label and add configuration for it.
To see action list, we select a Trigger, for example [Example\Event] from the Trigger drop-down in the Flow tab. After that, we choose option ACTION (THEN). A action component appears with action list.
Flow Builder trigger
Flow Builder action then
Flow Builder trigger

Step 1: Show action label in action list

First, we need to define an action name in example-plugin.constant.js. To be consistent with the custom action defined in our PHP code, we also create a constant called CREATE_TAG to represent action.create.tag which get from the response of /api/_info/flow-actions.json.
Flow Builder action services list
<plugin root>/src/Resources/app/administration/src/constant/swag-example-plugin.constant.js
1
export const ACTION = Object.freeze({
2
CREATE_TAG: 'action.create.tag',
3
});
4
5
export default {
6
ACTION,
7
};
Copied!
Next, we override sw-flow-sequence-action component to show CREATE_TAG label in action list. For example, we override getActionTitle method to add icon, label for CREATE_TAG action.
<plugin root>/src/Resources/app/administration/src/extension/sw-flow-sequence-action/index.js
1
import { ACTION } from '../../constant/swag-example-plugin.constant';
2
3
const { Component } = Shopware;
4
5
Component.override('sw-flow-sequence-action', {
6
methods: {
7
getActionTitle(actionName) {
8
if (actionName === ACTION.CREATE_TAG) {
9
return {
10
value: actionName,
11
icon: 'default-badge-help',
12
label: this.$tc('swag-example-plugin.titleCreateTag'),
13
}
14
}
15
16
return this.$super('getActionTitle', actionName);
17
},
18
},
19
});
Copied!
Here is the result for the after the Step 1.
Choose a Flow Builder Action

Step 2: Add configuration for action

First, we customise modalName for the configuration modal, add an actionDescription computed property and create the getCreateTagDescription method to show action the configuration description.
<plugin root>/src/Resources/app/administration/src/extension/sw-flow-sequence-action/index.js
1
import { ACTION } from '../../constant/swag-example-plugin.constant';
2
3
const { Component } = Shopware;
4
5
Component.override('sw-flow-sequence-action', {
6
computed: {
7
modalName() {
8
if (this.selectedAction === ACTION.CREATE_TAG) {
9
return 'swag-example-plugin-modal';
10
}
11
12
return this.$super('modalName');
13
},
14
15
actionDescription() {
16
const actionDescriptionList = this.$super('actionDescription');
17
18
return {
19
...actionDescriptionList,
20
[ACTION.CREATE_TAG] : (config) => this.getCreateTagDescription(config),
21
};
22
},
23
},
24
25
methods: {
26
getCreateTagDescription(config) {
27
const tags = config.tags.join(', ');
28
29
return this.$tc('swag-example-plugin.descriptionTags', 0, {
30
tags
31
});
32
},
33
34
getActionTitle(actionName) {
35
if (actionName === ACTION.CREATE_TAG) {
36
return {
37
value: actionName,
38
icon: 'default-badge-help',
39
label: this.$tc('swag-example-plugin.titleCreateTag'),
40
}
41
}
42
43
return this.$super('getActionTitle', actionName);
44
},
45
},
46
});
Copied!
Then, we need a modal to save your action config. For example, we create a component swag-example-plugin-modal.

JavaScript file

<plugin root>/src/Resources/app/administration/src/component/swag-example-plugin-modal/index.js
1
import template from './swag-example-plugin-modal.html.twig';
2
const { Component } = Shopware;
3
4
Component.register('swag-example-plugin-modal', {
5
template,
6
7
props: {
8
sequence: {
9
type: Object,
10
required: true,
11
},
12
},
13
14
data() {
15
return {
16
tags: [],
17
};
18
},
19
20
created() {
21
this.createdComponent();
22
},
23
24
methods: {
25
createdComponent() {
26
this.tags = this.sequence?.config?.tags || [];
27
},
28
29
onClose() {
30
this.$emit('modal-close');
31
},
32
33
onAddAction() {
34
const sequence = {
35
...this.sequence,
36
config: {
37
...this.config,
38
tags: this.tags
39
},
40
};
41
42
this.$emit('process-finish', sequence);
43
},
44
},
45
});
Copied!

Twig template file

<plugin root>/src/Resources/app/administration/src/component/swag-example-plugin-modal/swag-example-plugin-modal.html.twig
1
{% block swag_example_plugin_modal %}
2
<sw-modal
3
class="swag-example-plugin-modal"
4
:title="$tc('swag-example-plugin.titleCreateTag')"
5
@modal-close="onClose"
6
>
7
{% block swag_example_plugin_modal_content %}
8
<sw-multi-tag-select
9
v-model="tags"
10
:label="$tc('swag-example-plugin.labelTags')"
11
/>
12
{% endblock %}
13
14
{% block swag_example_plugin_modal_footer %}
15
<template #modal-footer>
16
{% block swag_example_plugin_modal_footer_cancel_button %}
17
<sw-button
18
class="swag-example-plugin-modal__cancel-button"
19
size="small"
20
@click="onClose"
21
>
22
{{ $tc('global.default.cancel') }}
23
</sw-button>
24
{% endblock %}
25
26
{% block swag_example_plugin_modal_footer_save_button %}
27
<sw-button
28
class="swag-example-plugin-modal__save-button"
29
variant="primary"
30
size="small"
31
@click="onAddAction"
32
>
33
{{ sequence.id
34
? $tc('swag-example-plugin.buttonSaveAction')
35
: $tc('swag-example-plugin.buttonAddAction') }}
36
</sw-button>
37
{% endblock %}
38
</template>
39
{% endblock %}
40
</sw-modal>
41
{% endblock %}
Copied!
Here is the final result
Flow Builder create tag
Click on [Save action] and we will get the result as below screenshot.
Flow Builder create tag result

Demo

Now you can view the whole demo for this custom Flow builder trigger and action as below.
Flow Builder demo
The source code for this demo you could find it at Flow Builder ExamplePlugin.