Skip to content

Commit 7a791b9

Browse files
authored
Introduce Output Workflow Signal Event (#321)
* implement output workflow signal event, keep attachment in multiple channels, fixes #311
1 parent e89a671 commit 7a791b9

File tree

15 files changed

+309
-59
lines changed

15 files changed

+309
-59
lines changed

UPGRADE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- **[NEW FEATURE]**: API Output channel [#290](https://github.com/dachcom-digital/pimcore-formbuilder/issues/301)
55
- **[NEW FEATURE]**: API Output channel field transformer
66
- **[BUGFIX]**: ensure migration of form configs will be symfony5 compatible [@grizzlydotweb](https://github.com/dachcom-digital/pimcore-formbuilder/pull/310)
7+
- **[BUGFIX]**: introduce output workflow signals: attachments not working with multiple channels [#311](https://github.com/dachcom-digital/pimcore-formbuilder/issues/311)
78
- **[BUGFIX]**: fix typo in translation [#312](https://github.com/dachcom-digital/pimcore-formbuilder/issues/312)
89
- **[BUGFIX]**: disable `selectOnFocus` [#315](https://github.com/dachcom-digital/pimcore-formbuilder/issues/315)
910
- **[BUGFIX]**: ⚠️ multi file upload: hidden type `_data` not in form row. touched view: `form/theme/type/dynamic_multi_file.html.twig` [#316](https://github.com/dachcom-digital/pimcore-formbuilder/issues/316)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace FormBuilderBundle\Event\OutputWorkflow;
4+
5+
use Symfony\Contracts\EventDispatcher\Event;
6+
7+
class OutputWorkflowSignalEvent extends Event
8+
{
9+
public const NAME = 'form_builder.output_workflow.signal';
10+
11+
protected string $name;
12+
protected mixed $data;
13+
14+
public function __construct(string $name, mixed $data)
15+
{
16+
$this->name = $name;
17+
$this->data = $data;
18+
}
19+
20+
public function getName(): string
21+
{
22+
return $this->name;
23+
}
24+
25+
public function getData(): mixed
26+
{
27+
return $this->data;
28+
}
29+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace FormBuilderBundle\Event\OutputWorkflow;
4+
5+
use FormBuilderBundle\Exception\OutputWorkflow;
6+
use Symfony\Contracts\EventDispatcher\Event;
7+
8+
class OutputWorkflowSignalsEvent extends Event
9+
{
10+
protected array $signals;
11+
protected ?\Exception $exception;
12+
13+
public function __construct(array $signals, ?\Exception $exception)
14+
{
15+
$this->signals = $signals;
16+
$this->exception = $exception;
17+
}
18+
19+
public function hasException(): bool
20+
{
21+
return $this->exception instanceof \Exception;
22+
}
23+
24+
public function hasGuardException(): bool
25+
{
26+
return $this->exception instanceof OutputWorkflow\GuardChannelException ||
27+
$this->exception instanceof OutputWorkflow\GuardOutputWorkflowException ||
28+
$this->exception instanceof OutputWorkflow\GuardStackedException;
29+
}
30+
31+
public function getException(): ?\Exception
32+
{
33+
return $this->exception;
34+
}
35+
36+
/**
37+
* @return array<int, OutputWorkflowSignalEvent>
38+
*/
39+
public function getAllSignals(): array
40+
{
41+
return $this->signals;
42+
}
43+
44+
/**
45+
* @return array<int, OutputWorkflowSignalEvent>
46+
*/
47+
public function getSignalsByName(string $name): array
48+
{
49+
return array_values(
50+
array_filter($this->signals, static function (OutputWorkflowSignalEvent $signal) use ($name) {
51+
return $signal->getName() === $name;
52+
})
53+
);
54+
}
55+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace FormBuilderBundle\EventSubscriber;
4+
5+
use FormBuilderBundle\Event\OutputWorkflow\OutputWorkflowSignalEvent;
6+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
7+
8+
class OutputWorkflowSignalSubscriber implements EventSubscriberInterface
9+
{
10+
protected array $signals = [];
11+
12+
public static function getSubscribedEvents(): array
13+
{
14+
return [
15+
OutputWorkflowSignalEvent::NAME => 'addSignal',
16+
];
17+
}
18+
19+
public function addSignal(OutputWorkflowSignalEvent $signalEvent): void
20+
{
21+
$this->signals[] = $signalEvent;
22+
}
23+
24+
public function getSignals(): array
25+
{
26+
return $this->signals;
27+
}
28+
}

src/FormBuilderBundle/Form/Data/FormData.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace FormBuilderBundle\Form\Data;
44

55
use FormBuilderBundle\Model\FormDefinitionInterface;
6+
use FormBuilderBundle\Stream\File;
67

78
class FormData implements FormDataInterface
89
{
@@ -32,12 +33,16 @@ public function hasAttachments(): bool
3233

3334
public function getAttachments(): array
3435
{
35-
return $this->attachments;
36+
return array_values($this->attachments);
3637
}
3738

38-
public function addAttachment(array $attachmentFileInfo): void
39+
public function addAttachment(File $attachmentFile): void
3940
{
40-
$this->attachments[] = $attachmentFileInfo;
41+
if (array_key_exists($attachmentFile->getId(), $this->attachments)) {
42+
return;
43+
}
44+
45+
$this->attachments[$attachmentFile->getId()] = $attachmentFile;
4146
}
4247

4348
public function getFieldValue(string $name): mixed

src/FormBuilderBundle/Form/Data/FormDataInterface.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace FormBuilderBundle\Form\Data;
44

55
use FormBuilderBundle\Model\FormDefinitionInterface;
6+
use FormBuilderBundle\Stream\File;
67

78
interface FormDataInterface
89
{
@@ -16,7 +17,10 @@ public function setFieldValue(string $name, mixed $value);
1617

1718
public function hasAttachments(): bool;
1819

20+
/**
21+
* @return array<int, File>
22+
*/
1923
public function getAttachments(): array;
2024

21-
public function addAttachment(array $attachmentFileInfo): void;
25+
public function addAttachment(File $attachmentFile): void;
2226
}

src/FormBuilderBundle/FormBuilderEvents.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,9 @@ final class FormBuilderEvents
5252
* @see \FormBuilderBundle\Event\OutputWorkflow\ChannelSubjectGuardEvent
5353
*/
5454
public const OUTPUT_WORKFLOW_GUARD_SUBJECT_PRE_DISPATCH = 'form_builder.output_workflow.guard.subject.pre_dispatch';
55+
56+
/**
57+
* @see \FormBuilderBundle\Event\OutputWorkflow\OutputWorkflowSignalsEvent
58+
*/
59+
public const OUTPUT_WORKFLOW_SIGNALS = 'form_builder.output_workflow.signals';
5560
}

src/FormBuilderBundle/OutputWorkflow/Channel/Email/EmailOutputChannel.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ public function isLocalizedConfiguration(): bool
2828
return true;
2929
}
3030

31-
/**
32-
* Currently unsupported for EmailOutputChanel.
33-
*/
3431
public function getUsedFormFieldNames(array $channelConfiguration): array
3532
{
33+
// Unsupported for EmailOutputChanel
34+
3635
return [];
3736
}
3837

src/FormBuilderBundle/OutputWorkflow/Channel/Email/Parser/MailParser.php

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,30 @@
22

33
namespace FormBuilderBundle\OutputWorkflow\Channel\Email\Parser;
44

5+
use FormBuilderBundle\Stream\File;
56
use Pimcore\Mail;
67
use Pimcore\Model\Document\Email;
78
use Symfony\Component\Form\FormInterface;
89
use Symfony\Component\Templating\EngineInterface;
910
use FormBuilderBundle\Form\Data\FormDataInterface;
1011
use FormBuilderBundle\Form\FormValuesOutputApplierInterface;
1112
use FormBuilderBundle\MailEditor\Parser\PlaceholderParserInterface;
12-
use FormBuilderBundle\Stream\AttachmentStreamInterface;
1313

1414
class MailParser
1515
{
1616
protected EngineInterface $templating;
1717
protected Email $mailTemplate;
1818
protected FormValuesOutputApplierInterface $formValuesOutputApplier;
1919
protected PlaceholderParserInterface $placeholderParser;
20-
protected AttachmentStreamInterface $attachmentStream;
2120

2221
public function __construct(
2322
EngineInterface $templating,
2423
FormValuesOutputApplierInterface $formValuesOutputApplier,
25-
PlaceholderParserInterface $placeholderParser,
26-
AttachmentStreamInterface $attachmentStream
24+
PlaceholderParserInterface $placeholderParser
2725
) {
2826
$this->templating = $templating;
2927
$this->formValuesOutputApplier = $formValuesOutputApplier;
3028
$this->placeholderParser = $placeholderParser;
31-
$this->attachmentStream = $attachmentStream;
3229
}
3330

3431
/**
@@ -154,14 +151,13 @@ protected function setMailBodyPlaceholder(Mail $mail, FormInterface $form, array
154151

155152
protected function parseMailAttachment(Mail $mail, array $attachments): void
156153
{
157-
foreach ($attachments as $attachmentFileInfo) {
154+
/** @var File $attachmentFile */
155+
foreach ($attachments as $attachmentFile) {
158156
try {
159-
$mail->attach(file_get_contents($attachmentFileInfo['path']), $attachmentFileInfo['name']);
157+
$mail->attach(file_get_contents($attachmentFile->getPath()), $attachmentFile->getName());
160158
} catch (\Exception $e) {
161159
// fail silently.
162160
}
163-
164-
$this->attachmentStream->removeAttachmentByFileInfo($attachmentFileInfo);
165161
}
166162
}
167163

src/FormBuilderBundle/OutputWorkflow/OutputWorkflowDispatcher.php

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,33 @@
33
namespace FormBuilderBundle\OutputWorkflow;
44

55
use FormBuilderBundle\Event\SubmissionEvent;
6+
use FormBuilderBundle\Event\OutputWorkflow\OutputWorkflowSignalsEvent;
7+
use FormBuilderBundle\EventSubscriber\OutputWorkflowSignalSubscriber;
68
use FormBuilderBundle\Exception\OutputWorkflow\GuardChannelException;
79
use FormBuilderBundle\Exception\OutputWorkflow\GuardOutputWorkflowException;
810
use FormBuilderBundle\Exception\OutputWorkflow\GuardStackedException;
11+
use FormBuilderBundle\FormBuilderEvents;
912
use FormBuilderBundle\Model\OutputWorkflowInterface;
1013
use FormBuilderBundle\Registry\OutputWorkflowChannelRegistry;
14+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1115

1216
class OutputWorkflowDispatcher implements OutputWorkflowDispatcherInterface
1317
{
18+
protected EventDispatcherInterface $eventDispatcher;
1419
protected OutputWorkflowChannelRegistry $channelRegistry;
20+
protected OutputWorkflowSignalSubscriber $subscriber;
1521

16-
public function __construct(OutputWorkflowChannelRegistry $channelRegistry)
22+
public function __construct(EventDispatcherInterface $eventDispatcher, OutputWorkflowChannelRegistry $channelRegistry)
1723
{
24+
$this->eventDispatcher = $eventDispatcher;
1825
$this->channelRegistry = $channelRegistry;
1926
}
2027

2128
public function dispatch(OutputWorkflowInterface $outputWorkflow, SubmissionEvent $submissionEvent): void
2229
{
30+
$this->subscriber = new OutputWorkflowSignalSubscriber();
31+
$this->eventDispatcher->addSubscriber($this->subscriber);
32+
2333
$exceptionStack = [];
2434
foreach ($outputWorkflow->getChannels() as $index => $channel) {
2535
try {
@@ -28,8 +38,15 @@ public function dispatch(OutputWorkflowInterface $outputWorkflow, SubmissionEven
2838
} catch (GuardChannelException $e) {
2939
$exceptionStack[] = $e;
3040
} catch (GuardOutputWorkflowException $e) {
41+
42+
$this->dispatchSignalsEvent($e);
43+
3144
throw $e;
45+
3246
} catch (\Throwable $e) {
47+
48+
$this->dispatchSignalsEvent($e);
49+
3350
throw new \Exception(
3451
sprintf(
3552
'"%s" workflow channel "%s" errored at step %d: %s',
@@ -43,7 +60,20 @@ public function dispatch(OutputWorkflowInterface $outputWorkflow, SubmissionEven
4360
}
4461

4562
if (count($exceptionStack) > 0) {
46-
throw new GuardStackedException($exceptionStack);
63+
64+
$exception = new GuardStackedException($exceptionStack);
65+
$this->dispatchSignalsEvent($exception);
66+
67+
throw $exception;
4768
}
69+
70+
$this->dispatchSignalsEvent();
71+
}
72+
73+
protected function dispatchSignalsEvent(?\Exception $exception = null): void
74+
{
75+
$signals = $this->subscriber->getSignals();
76+
$this->eventDispatcher->removeSubscriber($this->subscriber);
77+
$this->eventDispatcher->dispatch(new OutputWorkflowSignalsEvent($signals, $exception), FormBuilderEvents::OUTPUT_WORKFLOW_SIGNALS);
4878
}
4979
}

0 commit comments

Comments
 (0)