Skip to content

Instantly share code, notes, and snippets.

@ducho
Created August 24, 2022 16:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ducho/16db38921127bc259d09469cea0815e6 to your computer and use it in GitHub Desktop.
Save ducho/16db38921127bc259d09469cea0815e6 to your computer and use it in GitHub Desktop.
EmailVirtualType - Email Forwarding
<?php
namespace App\Form;
use App\Entity\Domain;
use App\Entity\EmailVirtual;
use App\Entity\EmailVirtualDestination;
use App\Repository\EmailVirtualRepository;
use App\Service\CurrentDomainService;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Event\PreSubmitEvent;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* @package App\Form
*/
class EmailVirtualType extends AbstractType
{
/**
* @var EmailVirtualRepository
*/
private $emailVirtualRepository;
/**
* @var CurrentDomainService
*/
private $currentDomainService;
public function __construct(
EmailVirtualRepository $emailVirtualRepository,
CurrentDomainService $currentDomainService
) {
$this->emailVirtualRepository = $emailVirtualRepository;
$this->currentDomainService = $currentDomainService;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$emailVirtual = $options['data'];
/** @var Domain $domain */
$domain = $this->currentDomainService->getCurrentDomain();
$builder
->add('email', TextType::class, [
'label' => 'email.forward.form.email',
'constraints' => [
new NotBlank(),
new Callback(array($this, 'validateEmail')),
],
])
->add(
'destinations',
ChoiceType::class,
[
'label' => 'email.forward.form.destination',
'choices' => $this->getChoices($emailVirtual),
'mapped' => false,
'data' => $this->getData($emailVirtual),
'multiple' => true,
'required' => true,
'constraints' => [
new NotBlank(),
],
]
);
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (PreSubmitEvent $event) {
/** @var EmailVirtual $emailVirtual */
$emailVirtual = $event->getForm()->getData();
$emailVirtual->getDestinations()->clear();
foreach ($event->getData()['destinations'] as $destinationEmail) {
$newDestination = (new EmailVirtualDestination())->setEmail($destinationEmail)->setParent(
$emailVirtual
);
$emailVirtual->getDestinations()->add($newDestination);
}
}
);
$builder->get('destinations')->resetViewTransformers();
}
public function validateEmail($value, ExecutionContextInterface $context)
{
/** @var Domain $domain */
$domain = $this->currentDomainService->getCurrentDomain();
$email = $value . '@' . $domain->getDomain();
$result = true;
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$result = false;
$message = 'Neplatná emailová adresa.';
} else {
/** @var EmailVirtual $data */
$data = $this->emailVirtualRepository->findOneBy(['email' => $email, 'basket' => 0, 'autoreply' => 0]);
if ($data) {
$result = false;
$message = 'Takáto počiatočná adresa pre presmerovanie už existuje.';
}
}
if (!$result) {
$context->buildViolation($message)
->atPath('email')
->addViolation();
}
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'App\Entity\EmailVirtual',
]);
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'app_email_virtual';
}
private function getChoices(EmailVirtual $emailVirtual)
{
$choices = [];
/** @var EmailVirtualDestination $destination */
foreach ($emailVirtual->getDestinations() as $destination) {
$choices[$destination->getEmail()] = $destination->getEmail();
}
return $choices;
}
private function getData(EmailVirtual $emailVirtual)
{
$choices = [];
/** @var EmailVirtualDestination $destination */
foreach ($emailVirtual->getDestinations() as $destination) {
$choices[] = $destination->getEmail();
}
return $choices;
}
}
<?php declare(strict_types=1);
namespace App\Controller;
use App\Entity\Domain;
use App\Entity\EmailUser;
use App\Entity\EmailVirtual;
use App\Entity\EmailVirtualDestination;
use App\Manager\PasswordManager;
use App\Repository\EmailMigrationRepository;
use App\Repository\EmailRepository;
use App\Repository\EmailUserRepository;
use App\Repository\EmailVirtualDestinationRepository;
use App\Repository\EmailVirtualRepository;
use App\Service\CurrentDomainService;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
/**
* Emailuser controller.
*
* @Route("email")
*/
class EmailForwardController extends CoreController
{
/**
* @var CurrentDomainService
*/
private $currentDomainService;
/**
* @var EmailUserRepository
*/
private $emailRepository;
/**
* @var EmailVirtualRepository
*/
private $emailVirtualRepository;
/**
* @var EmailVirtualDestinationRepository
*/
private $emailVirtualDestinationRepository;
/**
* EmailController constructor.
* @param CurrentDomainService $currentDomainService
* @param EmailUserRepository $emailRepository
* @param EmailVirtualRepository $emailVirtualRepository
*/
public function __construct(
CurrentDomainService $currentDomainService,
EmailUserRepository $emailRepository,
EmailVirtualRepository $emailVirtualRepository,
EmailVirtualDestinationRepository $emailVirtualDestinationRepository
)
{
$this->currentDomainService = $currentDomainService;
$this->emailRepository = $emailRepository;
$this->emailVirtualRepository = $emailVirtualRepository;
$this->emailVirtualDestinationRepository = $emailVirtualDestinationRepository;
}
/**
* Lists all forwarded emails.
*
* @Route("/forwards", name="email_forward_index", methods={"GET"})
*/
public function index()
{
/** @var Domain $domain */
$domain = $this->currentDomainService->getCurrentDomain();
return $this->render('email/forward/index.html.twig', array(
'emails' => $this->emailVirtualRepository->getEmailForwarders($domain),
'domain' => $domain,
));
}
/**
* Edit forwarded email.
*
* @Route("/forwards/{id}/edit", name="email_forward_edit", methods={"GET", "POST"})
* @throws \Doctrine\ORM\ORMException
*/
public function edit(Request $request, EmailVirtual $emailVirtual)
{
/** @var Domain $domain */
$domain = $this->currentDomainService->getCurrentDomain();
$form = $this->createForm('App\Form\EmailVirtualEditType', $emailVirtual);
$form->handleRequest($request);
if (!$form->isSubmitted()) {
$form->get('email')->setData(substr($emailVirtual->getEmail(),0, strrpos($emailVirtual->getEmail(), "@")));
}
if ($form->isSubmitted() && $form->isValid()) {
$de = $this->emailVirtualDestinationRepository->findBy([
'parent' => $emailVirtual
]);
foreach ($de as $d) {
$this->emailVirtualDestinationRepository->remove($d);
$this->emailVirtualDestinationRepository->flush();
}
$this->emailVirtualRepository->persist($emailVirtual);
$this->emailVirtualRepository->flush();
return $this->redirectToRoute('email_forward_index');
}
return $this->render('email/forward/edit.html.twig', array(
'domain' => $domain,
'form' => $form->createView(),
));
}
/**
* Creates a new emailUser entity.
* Takze ak vytvaram domenovy kos, tak musim pridat destination email do email_virtual
* pokial sa nachadza v tabulke email_user a nechanachdza sa uz v email_virtual
*
* @Route("/forwards/new", name="email_forward_new", methods={"GET", "POST"})
*/
public function new(Request $request)
{
/** @var Domain $domain */
$domain = $this->currentDomainService->getCurrentDomain();
$emailVirtual = new EmailVirtual();
$form = $this->createForm('App\Form\EmailVirtualType', $emailVirtual);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$emailVirtual->setEmail($emailVirtual->getEmail() . '@' . $domain->getDomain());
$emailVirtual->setDomain($domain);
$this->emailVirtualRepository->persist($emailVirtual);
$this->emailVirtualRepository->flush();
return $this->redirectToRoute('email_forward_index');
}
return $this->render('email/forward/edit.html.twig', array(
'domain' => $domain,
'form' => $form->createView(),
));
}
/**
* @Route("/forwards/delete", name="email_forward_index_ajax_delete", methods={"POST"}, options={"expose"=true})
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\JsonResponse
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function ajaxDelete(Request $request)
{
$status = Response::HTTP_FORBIDDEN;
if ($request->isXmlHttpRequest()) {
$ids = $request->get('id');
$ids = (is_array($ids)) ? $request->get('id') : array($request->get('id'));
foreach ($ids as $id) {
/** @var EmailVirtual $emailVirtual */
$emailVirtual = $this->emailVirtualRepository->find($id);
$this->denyAccessUnlessGranted(self::DELETE, $emailVirtual);
$this->emailVirtualRepository->remove($emailVirtual);
$this->emailVirtualRepository->flush();
$result = [
'status' => true,
];
$status = Response::HTTP_OK;
}
}
return $this->json($result, $status);
}
/**
* @Route("/forwards/email/load", name="email_forward_ajax_load", methods={"GET"}, options={"expose"=true})
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\JsonResponse
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function ajaxEmailLoad(Request $request)
{
$status = Response::HTTP_OK;
$result = [];
if ($request->isXmlHttpRequest()) {
/** @var Domain $domain */
$domain = $this->currentDomainService->getCurrentDomain();
$emails = $domain->getEmails()->filter(
function (EmailUser $emailUser) use ($request) {
return strstr($emailUser->getEmail(), $request->query->get('q'));
}
);
foreach ($emails as $email) {
$result[] = [
'id' => $email->getEmail(),
'text' => $email->getEmail(),
];
}
}
return $this->json($result, $status);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment