<?php
namespace App\Controller;
use App\Entity\Person;
use App\Form\EmailType;
use App\Entity\Attachment;
use App\Entity\Newsletter;
use App\Service\PdfService;
use App\Entity\Dto\EmailDto;
use App\Service\MailerService;
use App\Entity\EmailHistoryEntry;
use App\Repository\PersonRepository;
use App\Service\EmailHistoryService;
use App\Repository\InvoiceRepository;
use App\Repository\NewsletterRepository;
use Doctrine\Persistence\ManagerRegistry;
use App\Repository\ClientConfigRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use App\Repository\EmailHistoryEntryRepository;
use Symfony\Component\Routing\Annotation\Route;
use App\Repository\CustomerHistoryEntryRepository;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Menke\UserBundle\Controller\AbstractClientableController;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
/**
* @Route("/email")
* @IsGranted("ROLE_MANAGER")
* @IsGranted("ROLE_ADMIN")
*/
class EmailController extends AbstractClientableController
{
const LISTING_LIMIT = 20;
private $em;
public function __construct(ManagerRegistry $em)
{
$this->em = $em->getManager();
}
/**
* @Route("/", name="email_index", methods="GET")
*/
public function index(EmailHistoryEntryRepository $emailHistoryRepo): Response
{
$emailEntries = $emailHistoryRepo->getHistoryByClientPaged($this->getCurrentClient(), self::LISTING_LIMIT, 'DESC', 'date', 1);
return $this->render('email/index.html.twig', [
'emailEntries' => $emailEntries,
'total' => $emailEntries->count(),
'pages' => ceil($emailEntries->count() / self::LISTING_LIMIT),
'page' => 1,
]);
}
/**
* @Route("/{page}/{orderby}/{order}", name="email_index_listing", methods="GET", requirements={"page"="\d+","order"="asc|desc"})
*/
public function indexListing(EmailHistoryEntryRepository $emailHistoryRepo, $page, $orderby, $order): Response
{
$emailEntries = $emailHistoryRepo->getHistoryByClientPaged($this->getCurrentClient(), self::LISTING_LIMIT, $order, $orderby, $page);
return $this->render('email/_index_listing.html.twig', [
'emailEntries' => $emailEntries,
'total' => $emailEntries->count(),
'pages' => ceil($emailEntries->count() / self::LISTING_LIMIT),
'page' => $page,
]);
}
/**
* @Route("/{id}", name="email_show", methods="GET", requirements={"id"="\d+"})
*/
public function show(Request $request, EmailHistoryEntry $emailEntry): Response
{
$this->denyAccessUnlessGranted('ROLE_MANAGER', $emailEntry);
return $this->render('email/show.html.twig', [
'emailEntry' => $emailEntry,
]);
}
// /**
// * @Route("/{id}/attachment", name="email_attachment", methods="GET", requirements={"id"="\d+"})
// */
// public function attachment(Request $request, EmailHistoryEntry $emailEntry): Response
// {
// $this->denyAccessUnlessGranted('ROLE_MANAGER', $emailEntry);
// if ($emailEntry->getAttachment() && $emailEntry->getAttachmentName()) {
// $file = $this->getParameter('attachment_directory') . '/' . $emailEntry->getAttachment();
// $mimeType = mime_content_type($file);
// $headers = [
// 'Content-Type' => $mimeType,
// 'Content-Disposition' => 'attachment; filename="' . $emailEntry->getAttachmentName() . '"'
// ];
// return new Response(file_get_contents($file), 200, $headers);
// }
// return new Response('Die Datei konnte nicht gefunden werden.', 404);
// }
/**
* @Route("/{id}/attachment", name="email_attachment", methods="GET", requirements={"id"="\d+"})
*/
public function attachment(Request $request, Attachment $attachment): Response
{
if ($attachment->getEmailHistoryEntry()) {
$this->denyAccessUnlessGranted('ROLE_MANAGER', $attachment->getEmailHistoryEntry());
if ($attachment->getName() && $attachment->getPath()) {
$file = $attachment->getPath();
$mimeType = mime_content_type($file);
$headers = [
'Content-Type' => $mimeType,
'Content-Disposition' => 'attachment; filename="' . $attachment->getName() . '"'
];
return new Response(file_get_contents($file), 200, $headers);
}
}
return new Response('Die Datei konnte nicht gefunden werden.', 404);
}
/**
* @Route("/sender/{personId}/{emailAddress}", name="email_sender", methods="GET|POST", requirements={"personId"="\d+"}, defaults={"personId"=0, "email"=""})
*/
public function sender(Request $request, $personId = 0, $emailAddress = '', MailerService $mailer, EmailHistoryService $emailHistoryService, PersonRepository $personRepo)
{
$user = $this->getCurrentUser();
$email = new EmailDto();
if ($emailAddress) {
$email->recipient = $emailAddress;
} elseif ($personId) {
$person = $personRepo->findOneBy(['id' => $personId]);
if ($person && $person->getContactEmail()) {
$email->recipientId = $personId;
$email->recipient = $person->getContactEmail();
}
}
$form = $this->createForm(EmailType::class, $email, [
'action' => $this->generateUrl('email_sender'),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$isTest = false;
if ($email->testRecipient != '') {
$isTest = true;
$recipients = [$email->testRecipient];
} else {
$recipients = [$email->recipient];
}
$attachments = [];
$this->handleAttachmentUpload($form, $attachments);
$success = $mailer->sendCustomMessage(
$user->getClient(),
$email->sender,
$email->subject,
$email->content,
$recipients,
$attachments
);
if ($success) {
$this->addFlash('notice', 'E-Mail wurde versandt.');
if (!$isTest) {
$people = [];
if ($email->recipientId) {
$people = $personRepo->findBy(['id' => $email->recipientId]);
}
$emailHistoryService->saveProtocolEntriesFromEmailDto($email, $attachments, $people, $this->getCurrentUser()->getEmail(), $this->getCurrentClient());
}
} else {
$this->addFlash('error', 'Beim E-Mail-Versand ist ein Fehler aufgetreten.');
}
return $this->redirectToRoute('customer_index');
}
return $this->render('email/sender.html.twig', [
'email' => $email,
'form' => $form->createView(),
]);
}
/**
* @Route("/sender/multiple", name="email_sender_multiple", methods="GET|POST")
*/
public function senderMultiple(
Request $request,
MailerService $mailer,
PersonRepository $personRepo,
EmailHistoryService $emailHistoryService,
ClientConfigRepository $clientConfigRepo
) {
$user = $this->getCurrentUser();
$config = $clientConfigRepo->getSingleByClient($this->getCurrentClient());
$email = new EmailDto();
$items = $request->request->get('item');
if ($items) {
$people = $personRepo->getPeopleByClientAndIds($this->getCurrentClient(), array_keys($items));
$email->recipients = $people;
}
$speakers = $request->request->get('speaker');
if (empty($email->recipients) && $speakers) {
$people = $personRepo->getPeopleByClientAndSpeakerIds($this->getCurrentClient(), array_keys($speakers));
$email->recipients = $people;
}
$form = $this->createForm(EmailType::class, $email, [
'action' => $this->generateUrl('email_sender_multiple'),
'form_mode' => EmailType::FORM_MODE_MULTIPLE,
'client' => $this->getCurrentClient(),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$isTest = false;
if ($email->testRecipient != '') {
$isTest = true;
$recipients = ['email' => $email->testRecipient];
$subject = '[TEST] '.$email->subject;
} else {
$recipients = $this->parseRecipients($email, $config);
$subject = $email->subject;
}
$attachments = [];
$this->handleAttachmentUpload($form, $attachments);
$success = $mailer->sendIndividualMessage(
$user->getClient(),
$email->sender,
$subject,
$email->content,
$recipients,
$attachments
);
if ($success) {
$this->addFlash('notice', 'E-Mail wurde versandt.');
if (!$isTest) {
$emailHistoryService->saveProtocolEntriesFromEmailDto($email, $attachments, $email->recipients, $this->getCurrentUser()->getEmail(), $this->getCurrentClient());
return $this->redirectToRoute('customer_index');
}
$this->addFlash('notice', 'E-Mail wurde versandt.');
} else {
$this->addFlash('error', 'Beim E-Mail-Versand ist ein Fehler aufgetreten.');
}
return $this->redirectToRoute('customer_index');
}
return $this->render('email/sender-multiple.html.twig', [
'email' => $email,
'form' => $form->createView(),
]);
}
/**
* @Route("/sender/all/{type}", name="email_sender_all", methods="GET|POST")
*/
public function senderAll(
Request $request,
MailerService $mailer,
PersonRepository $personRepo,
EmailHistoryService $emailHistoryService,
ClientConfigRepository $clientConfigRepo,
NewsletterRepository $newsletterRepository,
$type
) {
$user = $this->getCurrentUser();
$config = $clientConfigRepo->getSingleByClient($this->getCurrentClient());
$email = new EmailDto();
$recipientEntities = [];
switch ($type) {
case 'customer':
$recipientEntities = $personRepo->getPersonByClient($this->getCurrentClient(), true);
break;
case 'speaker':
$recipientEntities = $personRepo->getPersonByClient($this->getCurrentClient(), false, true);
break;
case 'family':
$recipientEntities = $personRepo->getFamilyByClient($this->getCurrentClient());
break;
case 'newsletter':
$recipientEntities['persons'] = $personRepo->getNewsletterRecipientsByClient($this->getCurrentClient());
$recipientEntities['newsletter_persons'] = $newsletterRepository->getActiveMembers();
break;
}
$email->recipients = count($recipientEntities) . ' Empfänger';
if ($type === 'newsletter') {
$customers = 0;
$speakers = 0;
$newsletterPersons = 0;
foreach ($recipientEntities['persons'] as $recipient) {
if ($recipient->isSpeaker()) {
$speakers++;
} else if ($recipient->isCustomer()) {
$customers++;
}
}
$newsletterPersons = count($recipientEntities['newsletter_persons']);
$email->recipients .= " (davon {$customers} Kunde(n) und {$speakers} Referent(en)) "
. "sowie {$newsletterPersons} Newsletter Abonnenten";
$recipientEntities = array_merge($recipientEntities['persons'], $recipientEntities['newsletter_persons']);
}
$form = $this->createForm(EmailType::class, $email, [
'action' => $this->generateUrl('email_sender_all', ['type' => $type]),
'form_mode' => EmailType::FORM_MODE_ALL,
'client' => $this->getCurrentClient(),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$email->recipients = $recipientEntities;
$isTest = false;
if ($email->action == 'test') {
$isTest = true;
$recipients = [['email' => $email->testRecipient]];
} else {
$recipients = $this->parseRecipients($email, $config);
}
$attachments = [];
$this->handleAttachmentUpload($form, $attachments);
$success = $mailer->sendIndividualMessage(
$user->getClient(),
$email->sender,
$email->subject,
$email->content,
$recipients,
$attachments
);
if ($success) {
$this->addFlash('notice', 'E-Mail wurde versandt.');
if (!$isTest) {
$emailHistoryService->saveProtocolEntriesFromEmailDto($email, $attachments, $email->recipients, $this->getCurrentUser()->getEmail(), $this->getCurrentClient());
return $this->redirectToRoute('customer_index');
}
} else {
$this->addFlash('error', 'Beim E-Mail-Versand ist ein Fehler aufgetreten.');
return $this->redirectToRoute('customer_index');
}
}
return $this->render('email/sender-multiple.html.twig', [
'email' => $email,
'form' => $form->createView(),
]);
}
protected function parseRecipients(EmailDto $email, $config)
{
$recipients = [];
foreach ($email->recipients as $recipient) {
if ($recipient instanceof Person) {
$recipientItem = [];
if ($recipient->getContactEmail()) {
$recipientItem['email'] = $recipient->getContactEmail();
} elseif ($recipient->getUser() && $recipient->getUser()->getEmail()) {
$recipientItem['email'] = $recipient->getUser()->getEmail();
} elseif ($recipient->getFamilyMemberOf()) {
if ($recipient->getFamilyMemberOf()->getContactEmail()) {
$recipientItem['email'] = $recipient->getFamilyMemberOf()->getContactEmail();
} elseif ($recipient->getFamilyMemberOf()->getUser() && $recipient->getFamilyMemberOf()->getUser()->getEmail()) {
$recipientItem['email'] = $recipient->getFamilyMemberOf()->getUser()->getEmail();
}
}
} elseif ($recipient instanceof Newsletter) {
$recipientItem['email'] = $recipient->getEmail();
}
if (count($recipientItem) > 0) {
if ($email->isNewsletter && $recipient->isReceiveNewsletter()) {
$hash = md5($recipient->getId() . '_' . $recipient->getCreated()->format('Y-m-d H:i:s'));
$link = $this->generateUrl('newsletter_unsubscribe', ['hash' => $hash], UrlGeneratorInterface::ABSOLUTE_URL);
$recipientItem['addendum'] = str_ireplace(
'[link]',
'<a href="' . $link . '" target="_blank">Link</a>',
$config->getNewsletterClause()
);
$recipients[] = $recipientItem;
} elseif (!$email->isNewsletter) {
$recipients[] = $recipientItem;
}
}
}
return $recipients;
}
/**
* @Route("/send-again/{id}", name="email_send_again", methods="GET|POST")
*/
public function sendHistoryEntryAgain(
Request $request,
EmailHistoryEntry $emailEntry,
MailerService $mailer,
CustomerHistoryEntryRepository $repo,
EmailHistoryService $emailHistoryService,
InvoiceRepository $invoiceRepository,
PdfService $pdfService
) {
$this->denyAccessUnlessGranted('ROLE_MANAGER', $emailEntry);
try {
if ($request->query->has('invoiceId')) {
$customerHistoryEntry = $repo->findOneBy(['emailHistoryEntry' => $emailEntry]);
$recipients = explode(',', $emailEntry->getRecipients());
if ($customerHistoryEntry && count($recipients) > 0) {
$invoice = $invoiceRepository->find($request->get('invoiceId'));
$pdf = $pdfService->getInvoicePdf($this->getCurrentClient(), $invoice);
$sentMessage = $mailer->sendInvoiceEmail(
$invoice,
'Rechnung-' . $invoice->getNumber() . '.pdf',
$pdf->Output('S', 'Rechnung-' . $invoice->getNumber() . '.pdf')
);
$outputfile = $this->generateUniqueFileName() . '.pdf';
$outputpath = $this->getParameter('attachment_directory') . '/' . $outputfile;
$pdf->Output('F', $outputpath);
$emailHistoryService->saveProtocolEntryFromInvoiceMessage(
$invoice,
$sentMessage['sender'],
$sentMessage['subject'],
$sentMessage['message'],
$outputfile,
'Rechnung-' . $invoice->getNumber() . '.pdf'
);
$this->addFlash('notice', 'E-Mail wurde versandt.');
} else {
$this->addFlash('error', 'Diese E-Mail kann nicht versandt werden, weil der Empfänger ungültig ist.');
}
return $this->redirectToRoute('customer_index');
}
$customerHistoryEntry = $repo->findOneBy(['emailHistoryEntry' => $emailEntry]);
$recipients = explode(',', $emailEntry->getRecipients());
if ($customerHistoryEntry && count($recipients) > 0) {
$recipient = $recipients[0];
$mailer->sendPlainMessage(
$this->getCurrentClient(),
null,
$emailEntry->getSubject(),
$emailEntry->getContent(),
$recipient,
$emailEntry->getAttachments()
);
$emailHistoryService->saveProtocolEntriesFromPerson(
$this->getCurrentClient(),
$customerHistoryEntry->getCustomer(),
$customerHistoryEntry->getType(),
$emailEntry->getSubject(),
$emailEntry->getContent(),
$customerHistoryEntry->getEntry(),
null,
$emailEntry->getAttachments()
);
$this->addFlash('notice', 'E-Mail wurde versandt.');
} else {
$this->addFlash('error', 'Diese E-Mail kann nicht versandt werden, weil der Empfänger ungültig ist.');
}
} catch (\Exception $e) {
$this->addFlash('error', 'Beim E-Mail-Versand ist ein Fehler aufgetreten.');
}
return $this->redirectToRoute('customer_index');
}
protected function handleAttachmentUpload(&$form, &$attachments)
{
if ($attachmentsList = $form->get('attachments')->getData()) {
foreach ($attachmentsList as $attachment) {
/** @var UploadedFile */
$attachmentName = $attachment->getClientOriginalName();
$fileName = $this->generateUniqueFileName() . '.' . $attachment->guessExtension();
try {
$attachment->move(
$this->getParameter('attachment_directory'),
$fileName
);
$attachmentPath = $this->getParameter('attachment_directory') . '/' . $fileName;
$attachmentModel = new Attachment();
$attachmentModel->setName($attachmentName);
$attachmentModel->setPath($attachmentPath);
$attachmentModel->setCreatedAt(new \DateTimeImmutable());
$this->em->persist($attachmentModel);
$this->em->flush();
$attachments[] = $attachmentModel;
} catch (FileException $e) {
// ... handle exception if something happens during file upload
}
}
}
}
private function generateUniqueFileName()
{
return md5(uniqid());
}
}