<?php
namespace App\EventSubscriber;
use ApiPlatform\Core\EventListener\EventPriorities;
use App\Entity\AbstractPeople;
use App\Entity\Property;
use App\Entity\Reference\ReferencePropertyDomain;
use App\Entity\Reference\ReferencePropertyServiceType;
use App\Entity\Reference\ReferencePropertyStatus;
use App\Manager\Property\AssignPropertyRecommendationInterface;
use App\Manager\Property\PropertyReferenceGeneratorInterface;
use App\Message\GenerateBusinessIndicationMandateMessage;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\TerminateEvent;
use Symfony\Component\Messenger\MessageBusInterface;
use Psr\Log\LoggerInterface;
class PropertySubscriber implements EventSubscriberInterface
{
public const BUSINESS_INDICATION_ALLOWED_METHODS = [
Request::METHOD_POST,
Request::METHOD_PUT,
Request::METHOD_PATCH
];
public const BUSINESS_INDICATION_ALLOWED_STATUS_CODE = [
Response::HTTP_CREATED
];
private EntityManagerInterface $entityManager;
private PropertyReferenceGeneratorInterface $referenceGenerator;
private AssignPropertyRecommendationInterface $assignPropertyRecommendation;
private MessageBusInterface $bus;
private LoggerInterface $logger;
public function __construct(
EntityManagerInterface $entityManager,
PropertyReferenceGeneratorInterface $referenceGenerator,
AssignPropertyRecommendationInterface $assignPropertyRecommendation,
MessageBusInterface $bus,
LoggerInterface $logger
) {
$this->entityManager = $entityManager;
$this->referenceGenerator = $referenceGenerator;
$this->assignPropertyRecommendation = $assignPropertyRecommendation;
$this->bus = $bus;
$this->logger = $logger;
}
/**
* @param ViewEvent $event
*/
public function postUpdate(ViewEvent $event): void
{
$property = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$property instanceof Property || Request::METHOD_PUT !== $method) {
return;
} elseif (
$property->getReferencePropertyStatus()->getName() ===
ReferencePropertyStatus::REFERENCE_PROPERTY_STATUS_INVALIDE
) {
$this->assignPropertyRecommendation->assignRecommendation($property);
$this->entityManager->flush();
}
if ($property->getVMandate()) {
$mandate = $property->getVMandate()[0];
$mandate->setMaximumPrice($property->getMinimalPrice());
$this->entityManager->flush();
}
$hasUpdatedArea = false;
foreach ($property->getMandates() as $mandate) {
if ($mandate->getMinimalArea() !== $property->getMinimalArea()) {
$hasUpdatedArea = true;
$mandate->setMinimalArea($property->getMinimalArea());
$this->entityManager->persist($mandate);
}
if ($mandate->getMaximalArea() !== $property->getMaximalArea()) {
$hasUpdatedArea = true;
$mandate->setMaximalArea($property->getMaximalArea());
$this->entityManager->persist($mandate);
}
}
if ($hasUpdatedArea) {
$this->entityManager->flush();
}
}
public function generateKey($event): void
{
$property = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$property instanceof Property || Request::METHOD_POST !== $method) {
return;
}
$this->referenceGenerator->generate($property);
}
public function handleBusinessIndicationProcess(TerminateEvent $event): void
{
$entity = $event->getRequest()->attributes->get('_api_resource_class');
$method = $event->getRequest()->getMethod();
$responseStatus = $event->getResponse()->getStatusCode();
if (
$entity === Property::class
&& in_array($method, self::BUSINESS_INDICATION_ALLOWED_METHODS, true)
&& in_array($responseStatus, self::BUSINESS_INDICATION_ALLOWED_STATUS_CODE, true)
) {
$responseContent = json_decode($event->getResponse()->getContent(), true);
if ($this->isBusinessIndicationProcess($responseContent)) {
try {
$message = new GenerateBusinessIndicationMandateMessage((int) $responseContent['id']);
$this->bus->dispatch($message);
} catch (\Throwable $exception) {
$this->logger->error(
'Failed to publish GeneratBusinessIndicationMandateMessage !',
[
'trace' => $exception->getTrace(),
'line' => $exception->getLine(),
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
]
);
}
}
}
}
/**
* @param array $propertyResponse
*
* @return bool
*/
private function isBusinessIndicationProcess(array $propertyResponse): bool
{
return
$propertyResponse['referencePropertyDomain']['code'] ===
ReferencePropertyDomain::REFERENCE_CODE_PROPERTY_DOMAIN_NEW
&& $propertyResponse['referenceServiceType']['code'] ===
ReferencePropertyServiceType::REFERENCE_CODE_PROPERTY_SERVICE_TYPE_SELL
&& $propertyResponse['contact']['personType'] === AbstractPeople::PERSON_TYPE_MORAL
&& $propertyResponse['contact']['isBusinessIndication'];
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::VIEW => [
['postUpdate', EventPriorities::POST_WRITE],
['generateKey', EventPriorities::POST_WRITE],
],
KernelEvents::TERMINATE => [['handleBusinessIndicationProcess', 0]]
];
}
}