Skip to content

Commit 215dbee

Browse files
jheimbachJohannes Heimbachsolverat
authored
Use name instead of ID in switchOutputWorkflow Action (#408)
* use workflowname instead of workflowId in switchOutputWorkflow ConditionalLogic action * also migrate condition workflow to name * check if workflow is available before migrating * improve dependency checks in ow conditions --------- Co-authored-by: Johannes Heimbach <j.heimbach@anymotion.de> Co-authored-by: Stefan Hagspiel <info@solverat.com>
1 parent 57c62e8 commit 215dbee

File tree

12 files changed

+199
-24
lines changed

12 files changed

+199
-24
lines changed

UPGRADE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- [DEPRECATION REMOVED] removed `FormDefinition::setMailLayout`. Please migrate to output workflows before updating
88
- [IMPROVEMENT] Recommended folder structure by symfony adopted
99
- [IMPROVEMENT] Make success flash message optional [#403](https://github.com/dachcom-digital/pimcore-formbuilder/issues/403)
10+
- [IMPROVEMENT] Use name instead of ID in output workflow actions [#408](https://github.com/dachcom-digital/pimcore-formbuilder/pull/408)
1011
- [FUNNEL] Route include changed from `@FormBuilderBundle/Resources/config/pimcore/routing_funnels.yml` to `@FormBuilderBundle/config/pimcore/routing_funnels.yaml`
1112
- [BC BREAK] Mail Layout Editor: While there is a migration, we're not able to migrate container (fieldset, repeater) fields. Please adjust your output workflow channels manually.
1213
- [BC BREAK] All views are lowercase/underscore now (`email/form_data.html.twig`, `form/elements/dynamic_multi_file/*`)

public/js/extjs/conditional-logic/action/switchOutputWorkflow.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ Formbuilder.extjs.conditionalLogic.action.switchOutputWorkflow = Class.create(Fo
2222
},
2323
{
2424
xtype: 'combo',
25-
name: _.generateFieldName(this.sectionId, this.index, 'workflowId'),
25+
name: _.generateFieldName(this.sectionId, this.index, 'workflowName'),
2626
fieldLabel: t('form_builder_switch_output_workflow_identifier'),
2727
anchor: '100%',
2828
queryDelay: 0,
2929
displayField: 'name',
30-
valueField: 'id',
30+
valueField: 'name',
3131
mode: 'local',
3232
labelAlign: 'top',
3333
allowBlank: false,
@@ -50,13 +50,13 @@ Formbuilder.extjs.conditionalLogic.action.switchOutputWorkflow = Class.create(Fo
5050
afterrender: function (cb) {
5151
cb.store.load({
5252
callback: function () {
53-
var value = this.data ? this.checkFieldAvailability([this.data.workflowId], cb.store, 'id') : null;
53+
var value = this.data ? this.checkFieldAvailability([this.data.workflowName], cb.store, 'name') : null;
5454
cb.setValue(value !== null && value.length > 0 ? value[0] : null);
5555
}.bind(this)
5656
});
5757
}.bind(this),
5858
updateIndexName: function (sectionId, index) {
59-
this.name = _.generateFieldName(sectionId, index, 'outputWorkflows');
59+
this.name = _.generateFieldName(sectionId, index, 'workflowName');
6060
}
6161
}
6262
}

public/js/extjs/conditional-logic/condition/outputWorkflow.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Formbuilder.extjs.conditionalLogic.condition.outputWorkflow = Class.create(Formb
2525
anchor: '100%',
2626
stacked: true,
2727
displayField: 'name',
28-
valueField: 'id',
28+
valueField: 'name',
2929
allowBlank: false,
3030
flex: 1,
3131
queryMode: 'local',
@@ -49,7 +49,7 @@ Formbuilder.extjs.conditionalLogic.condition.outputWorkflow = Class.create(Formb
4949
afterrender: function (cb) {
5050
cb.store.load({
5151
callback: function () {
52-
var value = this.data ? this.checkFieldAvailability(this.data.outputWorkflows, cb.store, 'id') : null;
52+
var value = this.data ? this.checkFieldAvailability(this.data.outputWorkflows, cb.store, 'name') : null;
5353
cb.setValue(value);
5454
}.bind(this)
5555
});

src/Controller/Admin/OutputWorkflowController.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,13 @@ public function saveOutputWorkflowAction(Request $request, int $outputWorkflowId
184184
'message' => sprintf('Output Workflow with name "%s" already exists in this form!', $outputWorkflowName)
185185
]);
186186
}
187+
188+
if ($this->outputWorkflowManager->outputWorkflowIsRequiredByConditionalLogic($outputWorkflow)) {
189+
return $this->json([
190+
'success' => false,
191+
'message' => sprintf('Output Workflow with name "%s" is required in conditional logic section. Please remove those dependencies first!', $outputWorkflowName)
192+
]);
193+
}
187194
}
188195

189196
$form = $this->formFactory->createNamed('', OutputWorkflowType::class, $outputWorkflow);
@@ -203,7 +210,7 @@ public function saveOutputWorkflowAction(Request $request, int $outputWorkflowId
203210
}
204211

205212
$success = false;
206-
$message = join('<br>', $errors);
213+
$message = implode('<br>', $errors);
207214
}
208215

209216
return $this->adminJson([

src/Manager/OutputWorkflowManager.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,32 @@ public function getFormOutputWorkflowByName(string $name, int $formId): ?OutputW
7979
{
8080
return $this->outputWorkflowRepository->findByNameAndFormId($name, $formId);
8181
}
82+
83+
public function outputWorkflowIsRequiredByConditionalLogic(OutputWorkflowInterface $outputWorkflow): bool
84+
{
85+
$cl = $outputWorkflow->getFormDefinition()->getConditionalLogic();
86+
87+
foreach ($cl as $block) {
88+
89+
if (count(
90+
array_filter(
91+
$block['condition'] ?? [],
92+
static function (array $condition) use ($outputWorkflow) {
93+
return $condition['type'] === 'outputWorkflow' && in_array($outputWorkflow->getName(), $condition['outputWorkflows'], true);
94+
})) > 0) {
95+
return true;
96+
}
97+
98+
if (count(
99+
array_filter(
100+
$block['action'] ?? [],
101+
static function (array $action) use ($outputWorkflow) {
102+
return $action['type'] === 'switchOutputWorkflow' && $action['workflowName'] === $outputWorkflow->getName();
103+
})) > 0) {
104+
return true;
105+
}
106+
}
107+
108+
return false;
109+
}
82110
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FormBuilderBundle\Migrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
final class Version20230908101855 extends AbstractMigration
11+
{
12+
public function getDescription(): string
13+
{
14+
return 'Replace all workflowId fields with workflowName in switchWorkflow action';
15+
}
16+
17+
public function up(Schema $schema): void
18+
{
19+
$workflowIdMapData = $this->connection->fetchAllAssociative('SELECT id, name FROM formbuilder_output_workflow');
20+
21+
$workflowIdMap = array_reduce($workflowIdMapData, static function ($carry, $data) {
22+
$carry[$data['id']] = $data['name'];
23+
return $carry;
24+
}, []);
25+
26+
$forms = $this->connection->fetchAllAssociative("SELECT id, conditionalLogic FROM formbuilder_forms WHERE conditionalLogic LIKE '%switchOutputWorkflow%'");
27+
28+
foreach ($forms as $form) {
29+
30+
$conditionalLogic = array_map(static function ($logic) use ($workflowIdMap) {
31+
return [
32+
'condition' => array_filter(
33+
array_map(static function ($condition) use ($workflowIdMap) {
34+
if ($condition['type'] !== 'outputWorkflow') {
35+
return $condition;
36+
}
37+
38+
foreach ($condition['outputWorkflows'] as $index => $outputWorkflowId) {
39+
40+
if (!isset($workflowIdMap[$outputWorkflowId])) {
41+
unset($condition['outputWorkflows'][$index]);
42+
continue;
43+
}
44+
45+
$condition['outputWorkflows'][$index] = $workflowIdMap[$outputWorkflowId];
46+
}
47+
48+
if (count($condition['outputWorkflows']) === 0) {
49+
return null;
50+
}
51+
52+
$condition['outputWorkflows'] = array_values($condition['outputWorkflows']);
53+
54+
return $condition;
55+
56+
}, $logic['condition'] ?? [])
57+
),
58+
'action' => array_filter(
59+
array_map(static function ($action) use ($workflowIdMap) {
60+
if ($action['type'] !== 'switchOutputWorkflow') {
61+
return $action;
62+
}
63+
64+
if (!isset($workflowIdMap[$action['workflowId']])) {
65+
return null;
66+
}
67+
68+
$action['workflowName'] = $workflowIdMap[$action['workflowId']];
69+
unset($action['workflowId']);
70+
71+
return $action;
72+
73+
}, $logic['action'] ?? [])
74+
)
75+
];
76+
}, unserialize($form['conditionalLogic']));
77+
78+
$this->addSql('UPDATE formbuilder_forms SET conditionalLogic = ? WHERE id = ?', [serialize($conditionalLogic), $form['id']]);
79+
}
80+
}
81+
82+
public function down(Schema $schema): void
83+
{
84+
$workflowIdMapData = $this->connection->fetchAllAssociative('SELECT id, name FROM formbuilder_output_workflow');
85+
86+
$workflowIdMap = array_reduce($workflowIdMapData, static function ($carry, $data) {
87+
$carry[$data['name']] = $data['id'];
88+
return $carry;
89+
}, []);
90+
91+
$forms = $this->connection->fetchAllAssociative("SELECT id, conditionalLogic FROM formbuilder_forms WHERE conditionalLogic LIKE '%switchOutputWorkflow%'");
92+
93+
foreach ($forms as $form) {
94+
95+
$conditionalLogic = array_map(static function ($logic) use ($workflowIdMap) {
96+
return [
97+
'condition' => array_map(static function ($condition) use ($workflowIdMap) {
98+
if ($condition['type'] !== 'outputWorkflow') {
99+
return $condition;
100+
}
101+
102+
foreach ($condition['outputWorkflows'] as $index => $outputWorkflowId) {
103+
$condition['outputWorkflows'][$index] = $workflowIdMap[$outputWorkflowId];
104+
}
105+
106+
return $condition;
107+
108+
}, $logic['condition'] ?? []),
109+
'action' => array_map(static function ($action) use ($workflowIdMap) {
110+
if ($action['type'] !== 'switchOutputWorkflow') {
111+
return $action;
112+
}
113+
114+
$action['workflowId'] = $workflowIdMap[$action['workflowName']];
115+
unset($action['workflowName']);
116+
117+
return $action;
118+
119+
}, $logic['action'] ?? [])
120+
];
121+
}, unserialize($form['conditionalLogic']));
122+
123+
$this->addSql('UPDATE formbuilder_forms SET conditionalLogic = ? WHERE id = ?', [serialize($conditionalLogic), $form['id']]);
124+
}
125+
}
126+
}

src/OutputWorkflow/OutputWorkflowResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ public function resolve(SubmissionEvent $submissionEvent): ?OutputWorkflowInterf
2929
/** @var SwitchOutputWorkflowData $switchOutputWorkflowData */
3030
$switchOutputWorkflowData = $this->checkOutputWorkflowCondition('switch_output_workflow', $data, $formRuntimeData, []);
3131

32-
if ($switchOutputWorkflowData->hasOutputWorkflowId()) {
33-
$userSelectedOutputWorkflow = $switchOutputWorkflowData->getOutputWorkflowId();
32+
if ($switchOutputWorkflowData->hasOutputWorkflowName()) {
33+
$userSelectedOutputWorkflow = $switchOutputWorkflowData->getOutputWorkflowName();
3434
}
3535

3636
$outputWorkflows = $formDefinition->getOutputWorkflows();

src/Validation/ConditionalLogic/Dispatcher/Module/Data/SwitchOutputWorkflowData.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
class SwitchOutputWorkflowData implements DataInterface
66
{
7-
public const IDENTIFIER = 'workflowId';
7+
public const IDENTIFIER = 'workflowName';
88

99
private array $data = [];
1010

@@ -23,14 +23,14 @@ public function getData(): mixed
2323
return $this->data;
2424
}
2525

26-
public function hasOutputWorkflowId(): bool
26+
public function hasOutputWorkflowName(): bool
2727
{
28-
return isset($this->data[self::IDENTIFIER]) && is_int($this->data[self::IDENTIFIER]);
28+
return !empty($this->data[self::IDENTIFIER]);
2929
}
3030

31-
public function getOutputWorkflowId(): ?int
31+
public function getOutputWorkflowName(): ?string
3232
{
33-
if (!$this->hasOutputWorkflowId()) {
33+
if (!$this->hasOutputWorkflowName()) {
3434
return null;
3535
}
3636

src/Validation/ConditionalLogic/Dispatcher/Module/SwitchOutputWorkflow.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ public function apply(array $options): DataInterface
6565
continue;
6666
}
6767

68-
if (!isset($returnStackData['workflowId']) || !is_numeric($returnStackData['workflowId'])) {
68+
if (empty($returnStackData['workflowName'])) {
6969
continue;
7070
}
7171

72-
$switchWorkflowConfig['workflowId'] = (int) $returnStackData['workflowId'];
72+
$switchWorkflowConfig['workflowName'] = $returnStackData['workflowName'];
7373
}
7474

7575
$returnContainer->setData($switchWorkflowConfig);

src/Validation/ConditionalLogic/Rule/Action/SwitchOutputWorkflowAction.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,25 @@ class SwitchOutputWorkflowAction implements ActionInterface
1010
{
1111
use ActionTrait;
1212

13-
protected ?string $workflowId = null;
13+
protected ?string $workflowName = null;
1414

1515
public function apply(bool $validationState, array $formData, int $ruleId): ReturnStackInterface
1616
{
1717
$data = [];
1818
if ($validationState === true) {
19-
$data['workflowId'] = $this->getWorkflowId();
19+
$data['workflowName'] = $this->getWorkflowName();
2020
}
2121

2222
return new SimpleReturnStack('switchOutputWorkflow', $data);
2323
}
2424

25-
public function getWorkflowId(): ?string
25+
public function getWorkflowName(): ?string
2626
{
27-
return $this->workflowId;
27+
return $this->workflowName;
2828
}
2929

30-
public function setWorkflowId(string $workflowId): void
30+
public function setWorkflowName(string $workflowName): void
3131
{
32-
$this->workflowId = $workflowId;
32+
$this->workflowName = $workflowName;
3333
}
3434
}

0 commit comments

Comments
 (0)