<?php
namespace App\V4\Service\Prospect;
use App\ApiFormFactory\ApiFormFactory;
use App\Model\Form\FormSchema;
use App\Normalizer\FormNormalizer;
use App\Normalizer\ViewOrderAwareFormNormalizer;
use App\Service\Form\FormUtils;
use App\V4\DataProvider\CustomAction\ActionBuilder;
use App\V4\Form\Type\Prospect\ProspectBusinessType;
use App\V4\Form\Type\Prospect\ProspectContactSearchType;
use App\V4\Form\Type\Prospect\ProspectIndividualType;
use App\V4\Form\Type\Prospect\ProspectSearchType;
use App\V4\Model\Address\Address;
use App\V4\Model\Company\Company;
use App\V4\Model\Contact\Contact;
use App\V4\Model\Prospect\Prospect;
use App\V4\Model\Prospect\ProspectContactSearch;
use App\V4\Model\Response\Response;
use App\V4\Model\Response\Result;
use Exception;
use Sentry\State\Scope;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response as HttpResponse;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use function Sentry\captureMessage;
use function Sentry\withScope;
class ProspectFormHandler
{
use FormUtils;
/**
* @var FormFactoryInterface
*/
private $formFactory;
/**
* @var ApiFormFactory
*/
private $legacyFormFactory;
/**
* @var ViewOrderAwareFormNormalizer
*/
private $viewOrderAwareFormNormalizer;
/**
* @var NormalizerInterface
*/
private $normalizer;
/**
* @var FormNormalizer
*/
private $formNormalizer;
/**
* @var ActionBuilder
*/
private $actionBuilder;
public function __construct(
FormFactoryInterface $formFactory,
ApiFormFactory $legacyFormFactory,
ViewOrderAwareFormNormalizer $viewOrderAwareFormNormalizer,
NormalizerInterface $normalizer,
FormNormalizer $formNormalizer,
ActionBuilder $actionBuilder
) {
$this->formFactory = $formFactory;
$this->legacyFormFactory = $legacyFormFactory;
$this->viewOrderAwareFormNormalizer = $viewOrderAwareFormNormalizer;
$this->normalizer = $normalizer;
$this->formNormalizer = $formNormalizer;
$this->actionBuilder = $actionBuilder;
}
/**
* @SuppressWarnings(PHPMD.BooleanArgumentFlag)
*
* @param bool $isLegacy
* @param bool $isGeolocationSearch
*
* @return JsonResponse|FormSchema
*
* @throws ExceptionInterface
*/
public function getProspectSearchForm(bool $isLegacy = false, bool $isGeolocationSearch = false)
{
if ($isLegacy) {
return (new FormSchema())
->setSchema($this->legacyFormFactory->createAsJson(ProspectSearchType::class))
;
}
$response = new Response();
$response->setResults(
$this->viewOrderAwareFormNormalizer->normalize(
$this->formFactory->create(ProspectSearchType::class, null, [
'isGeolocationSearch' => $isGeolocationSearch,
])
)
);
return new JsonResponse(['hydra:member' => $this->normalizer->normalize($response)], HttpResponse::HTTP_OK);
}
/**
* @SuppressWarnings(PHPMD.BooleanArgumentFlag)
*
* @param string $searchRequestContent
* @param bool $isGeolocationSearch
*
* @return FormInterface
*/
public function handleProspectSearchForm(string $searchRequestContent, bool $isGeolocationSearch = false): FormInterface
{
$prospectSearchForm = $this->formFactory->create(ProspectSearchType::class, null, [
'isGeolocationSearch' => $isGeolocationSearch,
]);
$prospectSearchForm->submit(json_decode($searchRequestContent, true));
return $prospectSearchForm;
}
/**
* @SuppressWarnings(PHPMD.BooleanArgumentFlag)
*
* @param Prospect $prospect
* @param string $prospectType
* @param bool $isLegacy
*
* @return FormSchema|JsonResponse
*
* @throws ExceptionInterface
*/
public function getProspectForm(Prospect $prospect, string $prospectType, bool $isLegacy = false)
{
if ($isLegacy) {
return (new FormSchema())
->setSchema(
$this->legacyFormFactory->createAsJson(
Prospect::GROUP_TYPE_INDIVIDUAL === $prospectType
? ProspectIndividualType::class
: ProspectBusinessType::class,
$prospect
)
)
;
}
$prospectForm = $this->formFactory->create(
Prospect::GROUP_TYPE_INDIVIDUAL === $prospectType
? ProspectIndividualType::class
: ProspectBusinessType::class,
$prospect
);
$response = new Response();
$response->setResults($this->viewOrderAwareFormNormalizer->normalize($prospectForm));
if (null !== $prospect->getId()) {
$updatedInfos = $this->getLastUpdatedAtUpdatedBy($prospect);
$response->addMetadata('id', $prospect->getId());
$response->addMetadata('name', $prospect->getFullname());
$response->addMetadata('isBusiness', $prospect->isBusiness());
$response->addMetadata('prospectType', $prospect->getType());
$response->addMetadata('fullname', $prospect->getFullname());
$response->addMetadata('createdBy', $prospect->getCreatedBy());
$response->addMetadata('createdAt', $prospect->getCreatedAt());
$response->addMetadata('updatedBy', $updatedInfos['lastUpdatedBy']);
$response->addMetadata('updatedAt', $updatedInfos['lastUpdatedAt']);
$response->addMetadata('prospectSubscription', $prospect->getProspectSubscriptions());
$response->addMetadata('isUnknown', $prospect->isUnknown());
$response->addMetadata('showActions', $this->actionBuilder->getActions($prospect));
$contact = $prospect->getContact();
if ($contact instanceof Contact) {
$response->addMetadata('phone', $contact->getPhone());
}
$prospectAddress = $prospect->getMainAddress();
if ($prospectAddress instanceof Address) {
$addressMetadata = [
'address' => $prospectAddress->getAddress(),
'city' => $prospectAddress->getCity(),
'postalCode' => $prospectAddress->getPostalCode(),
];
$response->addMetadata('address', $addressMetadata);
$response->addMetadata('lat', $prospectAddress->getLat());
$response->addMetadata('lng', $prospectAddress->getLng());
}
}
return new JsonResponse(['hydra:member' => $this->normalizer->normalize($response)], HttpResponse::HTTP_OK);
}
/**
* @param Prospect $prospect
*
* @return array
*/
private function getLastUpdatedAtUpdatedBy(Prospect $prospect): array
{
$lastUpdatedAt = $prospect->getUpdatedAt();
$lastUpdatedBy = $prospect->getUpdatedBy();
if ($prospect->getCompany() instanceof Company && $lastUpdatedAt < $prospect->getCompany()->getUpdatedAt()) {
$lastUpdatedAt = $prospect->getCompany()->getUpdatedAt();
$lastUpdatedBy = $prospect->getCompany()->getUpdatedBy();
}
if ($prospect->getContact() instanceof Contact && $lastUpdatedAt < $prospect->getContact()->getUpdatedAt()) {
$lastUpdatedAt = $prospect->getContact()->getUpdatedAt();
$lastUpdatedBy = $prospect->getContact()->getUpdatedBy();
}
return [
'lastUpdatedAt' => $lastUpdatedAt,
'lastUpdatedBy' => $lastUpdatedBy,
];
}
/**
* @throws ExceptionInterface
*/
public function getProspectContactSearchForm(): JsonResponse
{
$normalized = $this->formNormalizer->normalize($this->formFactory->create(ProspectContactSearchType::class));
$properties = [];
foreach ($normalized as $key => $property) {
$properties[] = array_merge(['key' => $key], $property);
}
$result = new Result();
$result->addMetadata('group', [
'groupName' => null,
'properties' => $properties,
]);
$response = [
'results' => [
'group' => [
'groupName' => null,
'properties' => $properties,
],
],
];
return new JsonResponse(['hydra:member' => $this->normalizer->normalize($response)], HttpResponse::HTTP_OK);
}
/**
* @throws ExceptionInterface
* @throws Exception
*/
public function handleProspectContactSearchForm(array $content): array
{
$prospectContactSearchForm = $this->formFactory->create(ProspectContactSearchType::class);
$prospectContactSearchForm->submit($content);
if ($prospectContactSearchForm->isSubmitted() && $prospectContactSearchForm->isValid()) {
$prospectContactSearch = $prospectContactSearchForm->getData();
return $this->normalizer->normalize($prospectContactSearch ?? new ProspectContactSearch());
}
$errors = $this->convertFormErrorsToArray($prospectContactSearchForm);
withScope(function (Scope $scope) use ($content, $errors) {
$scope
->setExtra('catchOnClass', self::class)
->setExtra('method', 'handleProspectContactSearchForm')
->setExtra('formCalled', 'ProspectContactSearchType')
->setExtra('content', $content)
->setExtra('errors', $errors)
->setTag('PostProspectContactSearchFormAction', 'searchForm');
captureMessage('Invalid prospect contact search form submission');
});
return $errors;
}
}