mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Add notification to user groups on workflow transition
Implemented NotificationToUserGroupsOnTransition to send group emails upon workflow completion. Also updated NotificationOnTransition to prevent double notifications and created a unit test for the new functionality.
This commit is contained in:
parent
29fa086fde
commit
91a4b45607
@ -0,0 +1,9 @@
|
|||||||
|
Chers membres du groupe {{ user_group.label|localize_translatable_string }},
|
||||||
|
|
||||||
|
Un suivi "{{ workflow.text }}" a atteint une nouvelle étape: {{ place.text }}
|
||||||
|
|
||||||
|
Vous pouvez visualiser le workflow sur cette page:
|
||||||
|
|
||||||
|
{{ absolute_url(path('chill_main_workflow_show', {'id': entity_workflow.id, '_locale': 'fr'})) }}
|
||||||
|
|
||||||
|
Cordialement,
|
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Tests\Workflow\EventSubscriber;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\MainBundle\Entity\UserGroup;
|
||||||
|
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||||
|
use Chill\MainBundle\Workflow\EntityWorkflowMarkingStore;
|
||||||
|
use Chill\MainBundle\Workflow\EventSubscriber\NotificationToUserGroupsOnTransition;
|
||||||
|
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
|
||||||
|
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
|
||||||
|
use Prophecy\Argument;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
|
use Symfony\Component\Mailer\MailerInterface;
|
||||||
|
use Symfony\Component\Mime\BodyRendererInterface;
|
||||||
|
use Symfony\Component\Mime\RawMessage;
|
||||||
|
use Symfony\Component\Workflow\DefinitionBuilder;
|
||||||
|
use Symfony\Component\Workflow\Metadata\InMemoryMetadataStore;
|
||||||
|
use Symfony\Component\Workflow\Registry;
|
||||||
|
use Symfony\Component\Workflow\SupportStrategy\WorkflowSupportStrategyInterface;
|
||||||
|
use Symfony\Component\Workflow\Transition;
|
||||||
|
use Symfony\Component\Workflow\Workflow;
|
||||||
|
use Symfony\Component\Workflow\WorkflowInterface;
|
||||||
|
use Twig\Environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class NotificationToUserGroupsOnTransitionTest extends KernelTestCase
|
||||||
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
private Environment $twig;
|
||||||
|
private BodyRendererInterface $bodyRenderer;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$this->twig = self::getContainer()->get('twig');
|
||||||
|
$this->bodyRenderer = self::getContainer()->get(BodyRendererInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOnCompletedSendNotificationToUserGroupWithEmailAddress(): void
|
||||||
|
{
|
||||||
|
$entityWorkflow = new EntityWorkflow();
|
||||||
|
$reflection = new \ReflectionClass($entityWorkflow);
|
||||||
|
$idProperty = $reflection->getProperty('id');
|
||||||
|
$idProperty->setValue($entityWorkflow, 1);
|
||||||
|
|
||||||
|
$entityWorkflow->setWorkflowName('dummy');
|
||||||
|
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||||
|
$dto->futureDestUsers = [$ug = new UserGroup()];
|
||||||
|
$ug->setEmail('test@email.com')->setLabel(['fr' => 'test group']);
|
||||||
|
|
||||||
|
$mailer = $this->prophesize(MailerInterface::class);
|
||||||
|
$sendMethod = $mailer->send(Argument::that(function (RawMessage $message): bool {
|
||||||
|
if (!$message instanceof TemplatedEmail) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->bodyRenderer->render($message);
|
||||||
|
|
||||||
|
return 'test@email.com' === $message->getTo()[0]->getAddress();
|
||||||
|
}));
|
||||||
|
$sendMethod->shouldBeCalledOnce();
|
||||||
|
|
||||||
|
$metadataExtractor = $this->prophesize(MetadataExtractor::class);
|
||||||
|
$metadataExtractor->buildArrayPresentationForWorkflow(Argument::type(Workflow::class))->willReturn(['name' => 'dummy', 'text' => 'Dummy Workflow']);
|
||||||
|
$metadataExtractor->buildArrayPresentationForPlace($entityWorkflow)->willReturn(['name' => 'to_one', 'text' => 'Dummy Place']);
|
||||||
|
|
||||||
|
$registry = $this->buildRegistryWithEventSubscriber($mailer->reveal(), $metadataExtractor->reveal());
|
||||||
|
$workflow = $registry->get($entityWorkflow, 'dummy');
|
||||||
|
|
||||||
|
$workflow->apply($entityWorkflow, 'to_one', ['context' => $dto, 'transition' => 'to_one', 'transitionAt' => new \DateTimeImmutable(), 'byUser' => new User()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOnCompletedSendNotificationToUserGroupWithoutAnyEmailAddress(): void
|
||||||
|
{
|
||||||
|
$entityWorkflow = new EntityWorkflow();
|
||||||
|
$reflection = new \ReflectionClass($entityWorkflow);
|
||||||
|
$idProperty = $reflection->getProperty('id');
|
||||||
|
$idProperty->setValue($entityWorkflow, 1);
|
||||||
|
|
||||||
|
$entityWorkflow->setWorkflowName('dummy');
|
||||||
|
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||||
|
$dto->futureDestUsers = [$ug = new UserGroup()];
|
||||||
|
|
||||||
|
$mailer = $this->prophesize(MailerInterface::class);
|
||||||
|
$mailer->send(Argument::any())->shouldNotBeCalled();
|
||||||
|
|
||||||
|
$metadataExtractor = $this->prophesize(MetadataExtractor::class);
|
||||||
|
$metadataExtractor->buildArrayPresentationForWorkflow(Argument::type(Workflow::class))->willReturn(['name' => 'dummy', 'text' => 'Dummy Workflow']);
|
||||||
|
$metadataExtractor->buildArrayPresentationForPlace($entityWorkflow)->willReturn(['name' => 'to_one', 'text' => 'Dummy Place']);
|
||||||
|
|
||||||
|
$registry = $this->buildRegistryWithEventSubscriber($mailer->reveal(), $metadataExtractor->reveal());
|
||||||
|
$workflow = $registry->get($entityWorkflow, 'dummy');
|
||||||
|
|
||||||
|
$workflow->apply($entityWorkflow, 'to_one', ['context' => $dto, 'transition' => 'to_one', 'transitionAt' => new \DateTimeImmutable(), 'byUser' => new User()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildRegistryWithEventSubscriber(MailerInterface $mailer, MetadataExtractor $metadataExtractor): Registry
|
||||||
|
{
|
||||||
|
$builder = new DefinitionBuilder();
|
||||||
|
$builder
|
||||||
|
->setInitialPlaces('initial')
|
||||||
|
->addPlaces(['initial', 'to_one'])
|
||||||
|
->addTransition(new Transition('to_one', 'initial', 'to_one'));
|
||||||
|
|
||||||
|
$metadata = new InMemoryMetadataStore(
|
||||||
|
['label' => ['fr' => 'dummy workflow']],
|
||||||
|
);
|
||||||
|
$builder->setMetadataStore($metadata);
|
||||||
|
|
||||||
|
$workflow = new Workflow($builder->build(), new EntityWorkflowMarkingStore(), $eventDispatcher = new EventDispatcher(), 'dummy');
|
||||||
|
$registry = new Registry();
|
||||||
|
$registry->addWorkflow($workflow, new class () implements WorkflowSupportStrategyInterface {
|
||||||
|
public function supports(WorkflowInterface $workflow, object $subject): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$notificationEventSubscriber = new NotificationToUserGroupsOnTransition($this->twig, $metadataExtractor, $registry, $mailer);
|
||||||
|
$eventDispatcher->addSubscriber($notificationEventSubscriber);
|
||||||
|
|
||||||
|
return $registry;
|
||||||
|
}
|
||||||
|
}
|
@ -42,8 +42,8 @@ class NotificationOnTransition implements EventSubscriberInterface
|
|||||||
/**
|
/**
|
||||||
* Send a notification to:.
|
* Send a notification to:.
|
||||||
*
|
*
|
||||||
* * the dests of the new step;
|
* * the dests of the new step, or the members of a user group if the user group has no email;
|
||||||
* * the users which subscribed to workflow, on each step, or on final
|
* * the users which subscribed to workflow, on each step, or on final;
|
||||||
*
|
*
|
||||||
* **Warning** take care that this method must be executed **after** the dest users are added to
|
* **Warning** take care that this method must be executed **after** the dest users are added to
|
||||||
* the step (@see{EntityWorkflowStep::addDestUser}). Currently, this is done during
|
* the step (@see{EntityWorkflowStep::addDestUser}). Currently, this is done during
|
||||||
@ -74,6 +74,11 @@ class NotificationOnTransition implements EventSubscriberInterface
|
|||||||
// the users within groups
|
// the users within groups
|
||||||
$entityWorkflow->getCurrentStep()->getDestUserGroups()->reduce(
|
$entityWorkflow->getCurrentStep()->getDestUserGroups()->reduce(
|
||||||
function (array $accumulator, UserGroup $userGroup) {
|
function (array $accumulator, UserGroup $userGroup) {
|
||||||
|
if ($userGroup->hasEmail()) {
|
||||||
|
// this prevent users to be notified twice if they will already be notiied by the group
|
||||||
|
return $accumulator;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($userGroup->getUsers() as $user) {
|
foreach ($userGroup->getUsers() as $user) {
|
||||||
$accumulator[] = $user;
|
$accumulator[] = $user;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Workflow\EventSubscriber;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Notification;
|
||||||
|
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||||
|
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
|
||||||
|
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\Mailer\MailerInterface;
|
||||||
|
use Symfony\Component\Workflow\Event\Event;
|
||||||
|
use Symfony\Component\Workflow\Registry;
|
||||||
|
|
||||||
|
final readonly class NotificationToUserGroupsOnTransition implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private \Twig\Environment $engine,
|
||||||
|
private MetadataExtractor $metadataExtractor,
|
||||||
|
private Registry $registry,
|
||||||
|
private MailerInterface $mailer,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public static function getSubscribedEvents(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'workflow.completed' => ['onCompletedSendNotification', 2048],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a notification to:.
|
||||||
|
*
|
||||||
|
* * the dests of the new step;
|
||||||
|
* * the users which subscribed to workflow, on each step, or on final
|
||||||
|
*
|
||||||
|
* **Warning** take care that this method must be executed **after** the dest users are added to
|
||||||
|
* the step (@see{EntityWorkflowStep::addDestUser}). Currently, this is done during
|
||||||
|
*
|
||||||
|
* @see{EntityWorkflowTransitionEventSubscriber::addDests}.
|
||||||
|
*/
|
||||||
|
public function onCompletedSendNotification(Event $event): void
|
||||||
|
{
|
||||||
|
if (!$event->getSubject() instanceof EntityWorkflow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var EntityWorkflow $entityWorkflow */
|
||||||
|
$entityWorkflow = $event->getSubject();
|
||||||
|
|
||||||
|
$place = $this->metadataExtractor->buildArrayPresentationForPlace($entityWorkflow);
|
||||||
|
$workflow = $this->metadataExtractor->buildArrayPresentationForWorkflow(
|
||||||
|
$this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName())
|
||||||
|
);
|
||||||
|
|
||||||
|
// send to groups
|
||||||
|
foreach ($entityWorkflow->getCurrentStep()->getDestUserGroups() as $userGroup) {
|
||||||
|
if (!$userGroup->hasEmail()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$context = [
|
||||||
|
'entity_workflow' => $entityWorkflow,
|
||||||
|
'user_group' => $userGroup,
|
||||||
|
'place' => $place,
|
||||||
|
'workflow' => $workflow,
|
||||||
|
'is_dest' => true,
|
||||||
|
];
|
||||||
|
|
||||||
|
$email = new TemplatedEmail();
|
||||||
|
$email
|
||||||
|
->htmlTemplate('@ChillMain/Workflow/workflow_notification_on_transition_completed_content_to_user_group.fr.txt.twig')
|
||||||
|
->context($context)
|
||||||
|
->subject(
|
||||||
|
$this->engine->render('@ChillMain/Workflow/workflow_notification_on_transition_completed_title.fr.txt.twig', $context)
|
||||||
|
)
|
||||||
|
->to($userGroup->getEmail());
|
||||||
|
|
||||||
|
$this->mailer->send($email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user