<?php
namespace App\Controller\Shop;
use App\Security\Guard\ShopUserProxyAuthenticator;
use App\Service\ApiBridge;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
use Sylius\Component\Resource\Exception\UpdateHandlingException;
use Sylius\Component\Resource\ResourceActions;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
class CustomerController extends ResourceController
{
public const REGISTRATION_TYPE_INDIVIDUAL = 'individual';
public const REGISTRATION_TYPE_ESTABLISHMENT = 'establishment';
/**
* Override Shop registration form
*
* @param Request $request
* @return Response
* @throws \JsonException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws ClientExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
*/
public function createAction(Request $request): Response
{
// Get registration type
$registrationType = $request->query->get('t');
// Create config
$configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
// Check isGranted
$this->isGrantedOr403($configuration, ResourceActions::CREATE);
// Create resource by config
$newResource = $this->newResourceFactory->create($configuration, $this->factory);
// Create form from config & resource
$form = $this->resourceFormFactory->create($configuration, $newResource);
$form->add('id', TextType::class);
$form->handleRequest($request);
// POST form
if ($request->isMethod(Request::METHOD_POST) && $form->isSubmitted() && $form->isValid()) {
$apiBridge = $this->container->get('app.api_bridge');
// Create User in CRM
/// Handle CRM StructureContact creation
if ($registrationType === self::REGISTRATION_TYPE_INDIVIDUAL) {
$this->handleContactCreation($apiBridge, $form);
}
/// Handle CRM StructureEstablishment && StructureContact creation
if ($registrationType === self::REGISTRATION_TYPE_ESTABLISHMENT) {
$this->handleEstablishmentAndContactCreation($apiBridge, $form);
}
$newResource = $form->getData();
// Add VEL_OTHER role to newly created ShopUser
$newResource->getUser()->addRole(ShopUserProxyAuthenticator::ROLE_VEL_OTHER);
// Force add Newsletter
$newResource->setSubscribedToNewsletter($form->get('newsletterFntvServices')->getData());
$event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::CREATE, $configuration, $newResource);
if ($event->isStopped() && !$configuration->isHtmlRequest()) {
throw new HttpException($event->getErrorCode(), $event->getMessage());
}
if ($event->isStopped()) {
$this->flashHelper->addFlashFromEvent($configuration, $event);
$eventResponse = $event->getResponse();
return $eventResponse ?? $this->redirectHandler->redirectToIndex($configuration, $newResource);
}
if ($configuration->hasStateMachine()) {
$stateMachine = $this->getStateMachine();
$stateMachine->apply($configuration, $newResource);
}
$this->repository->add($newResource);
if ($configuration->isHtmlRequest()) {
$this->flashHelper->addSuccessFlash($configuration, ResourceActions::CREATE, $newResource);
}
$postEvent = $this->eventDispatcher->dispatchPostEvent(ResourceActions::CREATE, $configuration, $newResource);
if (!$configuration->isHtmlRequest()) {
return $this->createRestView($configuration, $newResource, Response::HTTP_CREATED);
}
$postEventResponse = $postEvent->getResponse();
return $postEventResponse ?? $this->redirectHandler->redirectToResource($configuration, $newResource);
}
if (!$configuration->isHtmlRequest()) {
return $this->createRestView($configuration, $form, Response::HTTP_BAD_REQUEST);
}
$initializeEvent = $this->eventDispatcher->dispatchInitializeEvent(ResourceActions::CREATE, $configuration, $newResource);
$initializeEventResponse = $initializeEvent->getResponse();
return $initializeEventResponse ?? $this->render($configuration->getTemplate(ResourceActions::CREATE . '.html'), [
'configuration' => $configuration,
'metadata' => $this->metadata,
'resource' => $newResource,
$this->metadata->getName() => $newResource,
'form' => $form->createView()
]);
}
/**
* @param ApiBridge $apiBridge
* @param $newResource
* @return void
* @throws ClientExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
* @throws \JsonException
*/
private function handleEstablishmentAndContactCreation(ApiBridge $apiBridge, $form): void
{
// Create Establishment
$establishment = $apiBridge->createEstablishment([
'structureName' => $form->get('structureName')->getData(),
'activity' => $form->get('activity')->getData(),
'address' => $form->get('address')->getData(),
'zipCode' => $form->get('zipCode')->getData(),
'city' => $form->get('city')->getData(),
'country' => $form->get('country')->getData(),
'structurePhoneNumber' => $form->get('structurePhoneNumber')->getData(),
'structureSubType' => 'Client'
]);
$establishment = json_decode($establishment->getContent(), true, 512, JSON_THROW_ON_ERROR)['data'];
$establishmentId = $establishment['data']['establishment_id'];
// Create Contact
// If Structure Contact doesn't already exist in CRM
if (false === $apiBridge->structureContactExists($form->get('email')->getData())) {
$apiBridge->createStructureContact([
'email' => $form->get('email')->getData(),
'firstname' => $form->get('firstName')->getData(),
'lastname' => $form->get('lastName')->getData(),
'phone' => $form->get('phoneNumber')->getData(),
'newsletterFntvServices' => $form->get('newsletterFntvServices')->getData(),
'subProfession' => 'GĂ©rant'
], $establishmentId);
}
}
/**
* @param ApiBridge $apiBridge
* @param $form
* @return void
* @throws ClientExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
* @throws \JsonException
*/
private function handleContactCreation(ApiBridge $apiBridge, $form): void
{
// If Structure Contact doesn't already exist in CRM
if (false === $apiBridge->structureContactExists($form->get('email')->getData())) {
$apiBridge->createStructureContact([
'email' => $form->get('email')->getData(),
'firstname' => $form->get('firstName')->getData(),
'lastname' => $form->get('lastName')->getData(),
'phone' => $form->get('phoneNumber')->getData(),
'newsletterFntvServices' => $form->get('newsletterFntvServices')->getData(),
'subProfession' => $this->getParameter('default_vel_sub_profession_id'),
], $this->getParameter('default_vel_structure_id'));
}
}
/**
* Override Shop edit account form
*
* @param Request $request
* @return Response
* @throws ClientExceptionInterface
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
* @throws \JsonException
*/
public function updateAction(Request $request): Response
{
$configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
$this->isGrantedOr403($configuration, ResourceActions::UPDATE);
$resource = $this->findOr404($configuration);
$form = $this->resourceFormFactory->create($configuration, $resource);
$form->handleRequest($request);
if (
\in_array($request->getMethod(), ['POST', 'PUT', 'PATCH'], true)
&& $form->isSubmitted()
&& $form->isValid()
) {
$resource = $form->getData();
$event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::UPDATE, $configuration, $resource);
if ($event->isStopped() && !$configuration->isHtmlRequest()) {
throw new HttpException($event->getErrorCode(), $event->getMessage());
}
if ($event->isStopped()) {
$this->flashHelper->addFlashFromEvent($configuration, $event);
$eventResponse = $event->getResponse();
return $eventResponse ?? $this->redirectHandler->redirectToResource($configuration, $resource);
}
try {
$this->resourceUpdateHandler->handle($resource, $configuration, $this->manager);
// Update User in CRM
/** @var ApiBridge $apiBridge */
$apiBridge = $this->container->get('app.api_bridge');
if (true === $apiBridge->structureContactExists($resource->getEmail())) {
$apiBridge->updateStructureContact([
'email' => $resource->getEmail(),
'firstname' => $resource->getFirstName(),
'lastname' => $resource->getLastName(),
'phone' => $resource->getPhoneNumber(),
'birthday' => $resource->getBirthday(),
'newsletterFntvServices' => $resource->isSubscribedToNewsletter()
]);
}
} catch (UpdateHandlingException $exception) {
if (!$configuration->isHtmlRequest()) {
return $this->createRestView($configuration, $form, $exception->getApiResponseCode());
}
$this->flashHelper->addErrorFlash($configuration, $exception->getFlash());
return $this->redirectHandler->redirectToReferer($configuration);
}
if ($configuration->isHtmlRequest()) {
$this->flashHelper->addSuccessFlash($configuration, ResourceActions::UPDATE, $resource);
}
$postEvent = $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE, $configuration, $resource);
if (!$configuration->isHtmlRequest()) {
if ($configuration->getParameters()->get('return_content', false)) {
return $this->createRestView($configuration, $resource, Response::HTTP_OK);
}
return $this->createRestView($configuration, null, Response::HTTP_NO_CONTENT);
}
$postEventResponse = $postEvent->getResponse();
return $postEventResponse ?? $this->redirectHandler->redirectToResource($configuration, $resource);
}
if (!$configuration->isHtmlRequest()) {
return $this->createRestView($configuration, $form, Response::HTTP_BAD_REQUEST);
}
$initializeEvent = $this->eventDispatcher->dispatchInitializeEvent(ResourceActions::UPDATE, $configuration, $resource);
$initializeEventResponse = $initializeEvent->getResponse();
return $initializeEventResponse ?? $this->render($configuration->getTemplate(ResourceActions::UPDATE . '.html'), [
'configuration' => $configuration,
'metadata' => $this->metadata,
'resource' => $resource,
$this->metadata->getName() => $resource,
'form' => $form->createView()
]);
}
}