<?php
namespace App\Controller\Page;
use App\Component\Configuration\Util\Config;
use App\Component\FeedbackCompany\Util\FeedbackCompanyUtil;
use App\Entity\Company;
use App\Entity\Contact;
use App\Entity\Option;
use App\Entity\OptionValue;
use App\Event\ContactSubmitEvent;
use App\EventListener\FeatureFlagListener;
use App\Form\ContactType;
use App\Form\Setting\ContactSettingType;
use App\Renderer\Page as PageRenderer;
use App\Service\ContactService;
use Flagception\Manager\FeatureManagerInterface;
use GuzzleHttp\Exception\ClientException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
class ContactController extends AbstractController
{
private EventDispatcherInterface $eventDispatcher;
private PageRenderer $pageRenderer;
private RequestStack $request;
private ContactService $service;
private Config $config;
public function __construct(
EventDispatcherInterface $eventDispatcher,
PageRenderer $pageRenderer,
RequestStack $request,
ContactService $service,
Config $config
) {
$this->eventDispatcher = $eventDispatcher;
$this->pageRenderer = $pageRenderer;
$this->request = $request;
$this->service = $service;
$this->config = $config;
}
/**
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
#[Route(path: '/contact', name: 'contact')]
public function indexAction(Request $request, FeatureManagerInterface $featureManager, FeedbackCompanyUtil $feedbackCompanyUtil, ParameterBagInterface $parameterBag): Response
{
$contact = new Contact();
$contact->setLocale($request->getLocale());
$contactTypeConfig = [];
if ($request->query->count() > 0) {
$contactTypeConfig = [
'action' => $this->generateUrl('contact', $request->query->all()),
];
}
$form = $this->createForm(ContactType::class, $contact, $contactTypeConfig);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$contact->setOrigin($request->getUri());
try {
$this->service->saveContact($contact);
$this->eventDispatcher->dispatch(new ContactSubmitEvent($contact, $form), ContactSubmitEvent::NAME);
return $this->redirectToRoute('contact_thanks');
} catch (ClientException $exception) {
$errors = json_decode($exception->getResponse()?->getBody()->getContents(), true, 512, \JSON_THROW_ON_ERROR);
foreach ($errors as $field => $message) {
$form->get($field)->addError(new FormError($message));
}
}
} catch (\Exception) {
}
}
$overviewVacancyCounts = [];
if ($this->config->get('site_company_overview_option') instanceof Option) {
$companies = $this->getDoctrine()->getRepository(Company::class)->findAll();
$overviewVacancyCounts = $this->getDoctrine()->getRepository(OptionValue::class)
->findOptionsWithVacancyCountForCompanyOption(
array_map(static fn (Company $company) => $company->getId(), $companies),
$this->config->get('site_company_overview_option')
);
}
$reviewSummary = [];
if ($featureManager->isActive(FeatureFlagListener::FEATURE_FEEDBACK_COMPANY)) {
$reviewSummary = $feedbackCompanyUtil->fetchAllById();
}
$response = $this
->pageRenderer
->renderPage(
'{contact_form}',
'@default/pages/contact_form.html.twig',
[
'contact' => $contact,
'form' => $form->createView(),
'show_privacy_statement_text' => (ContactSettingType::PRIVACY_STATEMENT_STRATEGY_TEXT
=== $this->config->get('site_contact_privacy_statement_option')),
'privacy_statement_text' => $parameterBag->get('site_contact_privacy_statement_text'),
'explanatoryText' => $this->config->get('site_contact_explanatory_text'),
'overviewVacancyCounts' => $overviewVacancyCounts,
'reviewSummary' => $reviewSummary,
]
);
$response->setSharedMaxAge(0);
return $response;
}
/**
* @throws \Throwable
*/
#[Route(path: '/contact/thanks', name: 'contact_thanks')]
public function thankAction(): Response
{
return $this
->pageRenderer
->renderPage(
'{contact_thanks}',
'@default/pages/contact_thanks.html.twig',
[]
);
}
#[Route(path: '/contact/block/snippet', name: 'contact_block_snippet')]
public function blockSnippetAction(): Response
{
return $this->render('@default/pages/contact_block.html.twig');
}
#[Route(path: '/contact/block/snippet/custom', name: 'contact_block_snippet_custom')]
public function customBlockSnippetAction(): Response
{
return $this->render('@default/pages/contact_custom_block.html.twig');
}
#[Route(path: '/contact/form', name: 'contact_form')]
public function contactFormAction(Request $request, string $redirectTo = ''): Response
{
if ('' === $redirectTo) {
$redirectTo = $request->get('redirectTo');
}
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact, [
'action' => $this->generateUrl('contact_form', ['redirectTo' => $redirectTo]),
]);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$this->getDoctrine()->getManager()->persist($contact);
$this->getDoctrine()->getManager()->flush();
$this->eventDispatcher->dispatch(
new ContactSubmitEvent($contact, $form),
ContactSubmitEvent::NAME
);
$this->addFlash('success', 'Uw contactaanvraag is verwerkt');
if (!empty($redirectTo)) {
return $this->redirectToRoute($redirectTo);
}
}
$this->addFlash('danger', 'Uw contactaanvraag kon niet worden verwerkt');
if (!empty($redirectTo)) {
return $this->redirectToRoute($redirectTo);
}
}
return $this->render(
'@Contact\Frontend\form.html.twig',
['form' => $form->createView()]
);
}
#[Route(path: '/contact/headless_form', name: 'contact_form_headless')]
public function headless(Request $request): Response
{
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$contact->setOrigin($request->headers->get('referer'));
$this->service->saveContact($contact);
$this->eventDispatcher->dispatch(new ContactSubmitEvent($contact, $form), ContactSubmitEvent::NAME);
$redirectUrl = $this->generateUrl('contact_thanks');
if ($request->isXmlHttpRequest()) {
return new JsonResponse([
'redirect' => $redirectUrl,
]);
}
return new RedirectResponse($redirectUrl);
}
return $this->render('@default/pages/form/contact_form_headless.html.twig', [
'form' => $form->createView(),
]);
}
#[Route(path: '/contact/form/static', name: 'contact_form_static')]
public function staticContactFormAction(Request $request, string $redirectTo = ''): Response
{
$formId = 'form-snippet';
if (!empty($request->get('redirectTo'))) {
$redirectTo = $request->get('redirectTo');
}
if ('' === trim($redirectTo)) {
$redirectTo = sprintf('%s#%s', $request->headers->get('referer'), $formId);
}
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact, [
'action' => $this->generateUrl('contact_form_static', ['redirectTo' => $redirectTo]),
]);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$this->getDoctrine()->getManager()->persist($contact);
$this->getDoctrine()->getManager()->flush();
$this->eventDispatcher
->dispatch(new ContactSubmitEvent($contact, $form), ContactSubmitEvent::NAME);
$this->addFlash('success', 'Uw contactaanvraag is verwerkt');
if (!empty($redirectTo)) {
return $this->redirect($redirectTo);
}
}
$this->addFlash('danger', 'Uw contactaanvraag kon niet worden verwerkt');
if (!empty($redirectTo)) {
return $this->redirect($redirectTo);
}
}
return $this->render(
'@default/pages/contact_form.html.twig',
['form' => $form->createView()]
);
}
#[Route(path: '/contact/form/clean', name: 'contact_form_clean_static')]
public function staticContactFormCleanAction(Request $request, string $redirectTo = ''): Response
{
$formId = 'form-snippet';
if ('' === $redirectTo) {
$redirectTo = sprintf('%s#%s', $request->headers->get('referer'), $formId);
}
$actionQueryParameters = [
'redirectTo' => $redirectTo,
'origin' => $this->request->getMainRequest()?->getPathInfo(),
];
if ($companyId = $request->get('company')) {
$actionQueryParameters['company'] = $companyId;
}
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact, [
'action' => $this->generateUrl('contact_form_clean_static', $actionQueryParameters),
]);
if ($companyId && $form->has('contactedCompany')) {
$form->remove('contactedCompany');
}
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$contact->setOrigin($request->headers->get('referer'));
if ($request->query->has('company')) {
$company = $this->getDoctrine()->getRepository(Company::class)->find(
$request->query->get('company')
);
$contact->setContactedCompany($company);
}
$this->getDoctrine()->getManager()->persist($contact);
$this->getDoctrine()->getManager()->flush();
$this->eventDispatcher
->dispatch(new ContactSubmitEvent($contact, $form), ContactSubmitEvent::NAME);
$this->addFlash('success', 'Uw contactaanvraag is verwerkt');
if (!empty($redirectTo)) {
return $this->redirect($redirectTo);
}
}
$this->addFlash('danger', 'Uw contactaanvraag kon niet worden verwerkt');
if (!empty($redirectTo)) {
return $this->redirect($redirectTo);
}
}
$response = $this->render(
'@default/pages/contact_form_clean.html.twig',
['form' => $form->createView()]
);
$response->setSharedMaxAge(0);
return $response;
}
}