feat: mailing to filtered teamer list
addresses #869dv9bur
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\Teamer;
|
||||
|
||||
use App\Controller\Traits\ReturnUrlTrait;
|
||||
use App\Form\TeamerMailingType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use App\Service\Common\TeamerFilterHandler;
|
||||
use App\Service\Teamer\TeamerMailingDraftHandler;
|
||||
use App\Service\Teamer\TeamerMailingService;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class MailingController extends AbstractController
|
||||
{
|
||||
use ReturnUrlTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly TeamerFilterHandler $filterHandler,
|
||||
private readonly TeamerMailingService $mailingService,
|
||||
private readonly TeamerMailingDraftHandler $draftHandler,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose the mailing. A submit of this form sends the preview to the composing admin,
|
||||
* the real send goes through the confirmation modal below.
|
||||
*/
|
||||
#[Route('/admin/teamer/mailing', name: 'app_admin_teamer_mailing')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$form = $this->createMailingForm($request);
|
||||
|
||||
if ($form->isSubmitted()) {
|
||||
$this->draftHandler->saveDraft($form->getData());
|
||||
}
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->mailingService->sendPreview($form->getData(), $this->getUser());
|
||||
|
||||
$this->addFlash('success', sprintf(
|
||||
'Die Vorschau wurde an %s gesendet',
|
||||
$this->getUser()->getUserIdentifier()
|
||||
));
|
||||
}
|
||||
|
||||
$filterDto = $this->filterHandler->getFilterSettings();
|
||||
|
||||
// no redirect after the preview, the composed mail has to survive it
|
||||
return $this->render('admin/teamer/mailing.html.twig', [
|
||||
'form' => $form->createView(),
|
||||
'filterDto' => $filterDto,
|
||||
'recipients' => $this->mailingService->resolveRecipients($filterDto),
|
||||
'placeholders' => TeamerMailingService::PLACEHOLDERS,
|
||||
'hasDraft' => $this->draftHandler->hasDraft(),
|
||||
'returnUrl' => $this->getReturnUrl($request, 'app_administrative_teamer_index'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Park what has been typed so far, so that a trip to the filter and back does not
|
||||
* throw the composed mail away. Answers nothing, the page stays as it is.
|
||||
*/
|
||||
#[Route('/admin/teamer/mailing/draft', name: 'app_admin_teamer_mailing_draft', methods: ['POST'])]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function draft(Request $request): Response
|
||||
{
|
||||
$this->draftHandler->saveDraft($this->createMailingForm($request)->getData());
|
||||
|
||||
return new Response(null, Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
#[Route('/admin/teamer/mailing/discard', name: 'app_admin_teamer_mailing_discard')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function discard(): Response
|
||||
{
|
||||
$this->draftHandler->resetDraft();
|
||||
|
||||
return $this->redirectToRoute('app_admin_teamer_mailing');
|
||||
}
|
||||
|
||||
#[Route('/admin/teamer/mailing/confirm', name: 'app_admin_teamer_mailing_confirm', methods: ['POST'])]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function confirm(Request $request): Response
|
||||
{
|
||||
$form = $this->createMailingForm($request);
|
||||
$filterDto = $this->filterHandler->getFilterSettings();
|
||||
|
||||
// the composed mail is carried on in hidden fields so no half written mailing has
|
||||
// to be parked in the session between the confirmation and the send
|
||||
return $this->render('admin/teamer/modal_mailing_confirm.html.twig', [
|
||||
'form' => $form->createView(),
|
||||
'mailingDto' => $form->getData(),
|
||||
'valid' => $form->isSubmitted() && $form->isValid(),
|
||||
'recipients' => $this->mailingService->resolveRecipients($filterDto),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/teamer/mailing/send', name: 'app_admin_teamer_mailing_send', methods: ['POST'])]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function send(Request $request): Response
|
||||
{
|
||||
$form = $this->createMailingForm($request);
|
||||
|
||||
if (false === $form->isSubmitted() || false === $form->isValid()) {
|
||||
$this->addFlash('error', 'Die Mail konnte nicht gesendet werden, Betreff oder Nachricht fehlen');
|
||||
|
||||
return new HxRedirectResponse($this->generateUrl('app_admin_teamer_mailing'));
|
||||
}
|
||||
|
||||
$recipients = $this->mailingService->resolveRecipients($this->filterHandler->getFilterSettings());
|
||||
$count = $this->mailingService->send($form->getData(), $recipients);
|
||||
|
||||
// it went out, the next mailing starts on a blank page
|
||||
$this->draftHandler->resetDraft();
|
||||
|
||||
$this->addFlash('success', sprintf('Die Mail wurde an %d Teamer:innen gesendet', $count));
|
||||
|
||||
return new HxRedirectResponse($this->generateUrl('app_administrative_teamer_index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* A GET starts from the parked draft, a POST always carries the current one itself.
|
||||
*/
|
||||
private function createMailingForm(Request $request): FormInterface
|
||||
{
|
||||
$form = $this->createForm(TeamerMailingType::class, $this->draftHandler->getDraft());
|
||||
$form->handleRequest($request);
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Controller\Common;
|
||||
|
||||
use App\Controller\Traits\ReturnUrlTrait;
|
||||
use App\Form\TeamerFilterType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use App\Service\Common\TeamerFilterHandler;
|
||||
@@ -13,6 +14,8 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class TeamerFilterController extends AbstractController
|
||||
{
|
||||
use ReturnUrlTrait;
|
||||
|
||||
public function __construct(private readonly TeamerFilterHandler $filterHandler)
|
||||
{
|
||||
}
|
||||
@@ -27,7 +30,7 @@ class TeamerFilterController extends AbstractController
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->filterHandler->handleRequest($form);
|
||||
$returnUrl = $this->generateUrl('app_administrative_teamer_index');
|
||||
$returnUrl = $this->getReturnUrl($request, 'app_administrative_teamer_index');
|
||||
|
||||
return new HxRedirectResponse($returnUrl);
|
||||
}
|
||||
@@ -42,7 +45,7 @@ class TeamerFilterController extends AbstractController
|
||||
public function reset(Request $request): Response
|
||||
{
|
||||
$this->filterHandler->resetFilterSettings();
|
||||
$returnUrl = $this->generateUrl('app_administrative_teamer_index');
|
||||
$returnUrl = $this->getReturnUrl($request, 'app_administrative_teamer_index');
|
||||
|
||||
return $this->redirect($returnUrl);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user