feat: admin editable email templates
addresses #869eg7ptr
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\EmailText;
|
||||
|
||||
use App\Config\EmailTextCatalog;
|
||||
use App\Config\EmailTextKey;
|
||||
use App\Entity\EmailText;
|
||||
use App\Form\EmailTextType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use App\Repository\EmailTextRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class EditController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EmailTextCatalog $catalog,
|
||||
private readonly EmailTextRepository $emailTextRepository,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/email-text/edit/{key}', name: 'app_admin_system_email_text_edit')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(EmailTextKey $key, Request $request): Response
|
||||
{
|
||||
$definition = $this->catalog->get($key);
|
||||
$emailText = $this->emailTextRepository->findByKey($key);
|
||||
$isNew = null === $emailText;
|
||||
|
||||
// Editing a mail for the first time starts from the delivered wording rather than
|
||||
// from an empty form, so an admin adjusts a sentence instead of rewriting the mail.
|
||||
if (true === $isNew) {
|
||||
$emailText = (new EmailText($key))
|
||||
->setSubject($definition->defaultSubject)
|
||||
->setHeadline($definition->defaultHeadline)
|
||||
->setBody($definition->defaultBody)
|
||||
;
|
||||
}
|
||||
|
||||
$form = $this->createForm(EmailTextType::class, $emailText, [
|
||||
'definition' => $definition,
|
||||
'hx_post' => $request->getUri(),
|
||||
]);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
if (true === $isNew) {
|
||||
$this->entityManager->persist($emailText);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der E-Mail-Text wurde aktualisiert');
|
||||
$this->logger->info('Edit email text', [
|
||||
'email_text_id' => $emailText->getId(),
|
||||
'email_text_key' => $key->value,
|
||||
]);
|
||||
|
||||
return new HxRedirectResponse($this->generateUrl('app_admin_system_email_text_index'));
|
||||
}
|
||||
|
||||
return $this->render('admin/system/email_text/modal_edit.html.twig', [
|
||||
'form' => $form->createView(),
|
||||
'definition' => $definition,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\EmailText;
|
||||
|
||||
use App\Config\EmailTextCatalog;
|
||||
use App\Repository\EmailTextRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EmailTextCatalog $catalog,
|
||||
private readonly EmailTextRepository $emailTextRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/email-text', name: 'app_admin_system_email_text_index')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(): Response
|
||||
{
|
||||
// The list is driven by the catalogue, not by the table: a mail that has never
|
||||
// been edited has no row and still has to show up here.
|
||||
return $this->render('admin/system/email_text/index.html.twig', [
|
||||
'definitions' => $this->catalog->all(),
|
||||
'emailTexts' => $this->emailTextRepository->findAllIndexedByKey(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\EmailText;
|
||||
|
||||
use App\Config\EmailTextCatalog;
|
||||
use App\Config\EmailTextKey;
|
||||
use App\Email\EmailTextRenderer;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class PreviewController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EmailTextCatalog $catalog,
|
||||
private readonly EmailTextRenderer $emailTextRenderer,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the editable part of the mail - subject, headline, text, button - so an admin
|
||||
* can check their wording without triggering the event behind it. The surrounding
|
||||
* layout is left out on purpose: it is not editable, and its logo only resolves while
|
||||
* a real mail is being assembled.
|
||||
*/
|
||||
#[Route('/admin/system/email-text/preview/{key}', name: 'app_admin_system_email_text_preview')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(EmailTextKey $key): Response
|
||||
{
|
||||
$definition = $this->catalog->get($key);
|
||||
|
||||
// The placeholders stand in for themselves: no disposition is at hand here, and a
|
||||
// visible [destination] tells an admin where a real value lands better than an
|
||||
// invented one would.
|
||||
$placeholders = [];
|
||||
|
||||
foreach ($definition->getPlaceholderNames() as $name) {
|
||||
$placeholders[$name] = '['.$name.']';
|
||||
}
|
||||
|
||||
return $this->render('admin/system/email_text/modal_preview.html.twig', [
|
||||
'definition' => $definition,
|
||||
'text' => $this->emailTextRenderer->render($key, $placeholders),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\EmailText;
|
||||
|
||||
use App\Config\EmailTextCatalog;
|
||||
use App\Config\EmailTextKey;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use App\Repository\EmailTextRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class ResetController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EmailTextCatalog $catalog,
|
||||
private readonly EmailTextRepository $emailTextRepository,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/email-text/reset/{key}', name: 'app_admin_system_email_text_reset')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(EmailTextKey $key, Request $request): Response
|
||||
{
|
||||
$emailText = $this->emailTextRepository->findByKey($key);
|
||||
|
||||
if (true === $request->isMethod('POST')) {
|
||||
// Removing the override is the reset: without a row the mail falls back to
|
||||
// the wording in EmailTextCatalog.
|
||||
if (null !== $emailText) {
|
||||
$this->entityManager->remove($emailText);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
$this->addFlash('success', 'Der E-Mail-Text wurde zurückgesetzt');
|
||||
$this->logger->info('Reset email text', [
|
||||
'email_text_key' => $key->value,
|
||||
]);
|
||||
|
||||
return new HxRedirectResponse($this->generateUrl('app_admin_system_email_text_index'));
|
||||
}
|
||||
|
||||
return $this->render('admin/system/email_text/modal_reset.html.twig', [
|
||||
'definition' => $this->catalog->get($key),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user