<?php
declare(strict_types=1);
namespace App\Controller\Action;
use App\Entity\Newsletter\NewsletterSubscribes;
use App\Form\Type\Newsletter\SubscribeToNewsletterType;
use App\Repository\Newsletter\NewsletterSubscribesRepository;
use Doctrine\ORM\EntityManagerInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Environment;
use SendinBlue\Client\Api\ContactsApi;
use SendinBlue\Client\Configuration;
use GuzzleHttp\Client as GuzzleClient;
final class SubscribeToNewsletterAction
{
private $sendinblueApiKey;
/** @var FormFactoryInterface */
private $formFactory;
/** @var Environment */
private $twig;
/** @var TranslatorInterface */
private $translator;
/** @var ChannelContextInterface */
private $channelContext;
private $newsletterSubscribesRepository;
private $localeContext;
private $em;
public function __construct(
string $sendinblueApiKey,
FormFactoryInterface $formFactory,
Environment $twig,
TranslatorInterface $translator,
ChannelContextInterface $channelContext,
NewsletterSubscribesRepository $newsletterSubscribesRepository,
LocaleContextInterface $localeContext,
EntityManagerInterface $em
) {
$this->sendinblueApiKey = $sendinblueApiKey;
$this->formFactory = $formFactory;
$this->twig = $twig;
$this->translator = $translator;
$this->channelContext = $channelContext;
$this->newsletterSubscribesRepository = $newsletterSubscribesRepository;
$this->localeContext = $localeContext;
$this->em = $em;
}
public function __invoke(Request $request): Response
{
$form = $this->formFactory->create(SubscribeToNewsletterType::class);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if (!$form->isValid()) {
$errors = $this->getErrorsFromForm($form);
if (is_string($errors)) {
$errors = [$errors];
}
return $this->json(
$this->translator->trans('setono_sylius_mailchimp.ui.an_error_occurred'),
400,
$errors
);
}
$email = $form->get('email')->getData() ?? '';
if (!filter_var($email, \FILTER_VALIDATE_EMAIL)) {
return $this->json(
$this->translator->trans('setono_sylius_mailchimp.ui.an_error_occurred')
);
}
$subscribe = $this->newsletterSubscribesRepository->findOneBy(['mail' => $email]);
if ($subscribe === null) {
$subscribe = new NewsletterSubscribes();
$subscribe->setMail($email);
$subscribe->setLocaleCode($this->localeContext->getLocaleCode());
$this->em->persist($subscribe);
$this->em->flush();
}
$config = Configuration::getDefaultConfiguration()->setApiKey('api-key', $this->sendinblueApiKey);
$apiInstance = new ContactsApi(new GuzzleClient(), $config);
$contact = [
'email' => $email,
'listIds' => [8],
'updateEnabled' => true,
'attributes' => [
'EMAIL' => $email,
],
];
try {
$apiInstance->createContact($contact);
} catch (\Exception $e) {
return $this->json($this->translator->trans('Erreur lors de l\'inscription à la newsletter'), 500, [$e->getMessage()]);
}
return $this->json($this->translator->trans('setono_sylius_mailchimp.ui.subscribed_successfully'));
}
$template = $request->query->get('template', '@SetonoSyliusMailchimpPlugin/Shop/Subscribe/content.html.twig');
$content = $this->twig->render($template, [
'form' => $form->createView(),
]);
return new Response($content);
}
private function json(string $message, int $status = 200, array $errors = []): JsonResponse
{
return new JsonResponse([
'message' => $message,
'errors' => $errors,
], $status);
}
/**
* Taken from https://symfonycasts.com/screencast/javascript/post-proper-api-endpoint#codeblock-99cf6afd45.
*
* @return array|string
*/
private function getErrorsFromForm(FormInterface $form)
{
/** @var FormError $error */
foreach ($form->getErrors() as $error) {
// only supporting 1 error per field
// and not supporting a "field" with errors, that has more
// fields with errors below it
return $error->getMessage();
}
$errors = [];
foreach ($form->all() as $childForm) {
$childError = $this->getErrorsFromForm($childForm);
if (is_string($childError)) {
$errors[$childForm->getName()] = $childError;
}
}
return $errors;
}
}