<?php
namespace App\EventSubscriber;
use App\Entity\Organization;
use App\Helper\CustomFieldHelper;
use App\Model\Builder\InspectionFormBuilder;
use App\Model\Builder\RegistrationFormBuilder;
use App\Event\AppEvents;
use App\Event\FormCreatedEvent;
use App\Event\FormEvent;
use App\Event\Municipality\FeeEvent;
use App\Event\Review\FeeEvent as ReviewFeeEvent;
use App\Event\Review\FormEvent as ReviewFormEvent;
use App\Event\Municipality\MunicipalityEvent;
use App\Event\OrganizationEvent;
use App\Event\Review\NotifyReviewEvent;
use App\Event\Review\UserEvent;
use App\Event\ReviewEvent;
use App\Entity\RegistrationForm as EntityRegistrationForm;
use App\Helper\PropertyHelper;
use App\Model\Parser\ReviewDeregistrationForm;
use App\Model\Parser\ReviewInspection;
use App\Model\Parser\ReviewInvoice;
use App\Model\Parser\ReviewMunicipality;
use App\Model\Parser\ReviewMunicipalityFee;
use App\Model\Parser\ReviewOrganization;
use App\Model\Parser\ReviewProperty;
use App\Model\Parser\ReviewRegistrationForm;
use App\Model\Parser\ReviewRenewalForm;
use App\Model\Parser\ReviewUser;
use App\ValueObject\UserRoles;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\DeregistrationForm;
use App\Entity\DeregistrationFormReview;
use App\Entity\InspectionForm;
use App\Entity\InspectionFormReview;
use App\Entity\InvoiceReview;
use App\Entity\MunicipalityFeeReview;
use App\Entity\MunicipalityReview;
use App\Entity\OrganizationReview;
use App\Entity\PropertyReview;
use App\Entity\RegistrationForm;
use App\Entity\RegistrationFormReview;
use App\Entity\RenewalForm;
use App\Entity\RenewalFormReview;
use App\Entity\User;
use App\Entity\UserReview;
use App\ValueObject\InvoiceTypes;
use App\ValueObject\ReviewStatuses;
use App\ValueObject\UserTypes;
use App\ValueObject\FormTypes;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/**
* Class ReviewListener
*/
class ReviewSubscriber implements EventSubscriberInterface
{
const ADMIN_REVIEW = true;
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var CustomFieldHelper
*/
protected $customFieldHelper;
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* @var PropertyHelper
*/
private $propertyHelper;
/**
* ReviewListener constructor.
*
* @param EntityManagerInterface $em
* @param CustomFieldHelper $customFieldHelper
* @param TokenStorageInterface $tokenStorage
* @param EventDispatcherInterface $eventDispatcher
* @param PropertyHelper $propertyHelper
*/
public function __construct(
EntityManagerInterface $em,
CustomFieldHelper $customFieldHelper,
TokenStorageInterface $tokenStorage,
EventDispatcherInterface $eventDispatcher,
PropertyHelper $propertyHelper
) {
$this->em = $em;
$this->customFieldHelper = $customFieldHelper;
$this->tokenStorage = $tokenStorage;
$this->eventDispatcher = $eventDispatcher;
$this->propertyHelper = $propertyHelper;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
AppEvents::REVIEW_USER_CREATED => ['onUserCreated'],
AppEvents::REVIEW_APPROVED => ['onReviewApproved'],
AppEvents::REVIEW_DENIED => ['onReviewDenied'],
AppEvents::REVIEW_INSPECTION_CREATED => ['onInspectionCreated'],
AppEvents::REVIEW_MUNICIPALITY_CREATED => ['onMunicipalityCreated'],
AppEvents::REVIEW_MUNICIPALITY_FEE_CREATED => ['onMunicipalityFeeCreated'],
AppEvents::REVIEW_ORGANIZATION_CREATED => ['onOrganizationCreated'],
AppEvents::REVIEW_REGISTRATION_FORM_CREATED => ['onRegistrationFormCreated'],
AppEvents::REVIEW_RENEWAL_FORM_CREATED => ['onRenewalFormCreated'],
AppEvents::REVIEW_DEREGISTRATION_FORM_CREATED => ['onDeregistrationFormCreated']
];
}
/**
* @param UserEvent $event
*/
public function onUserCreated(UserEvent $event)
{
$currentUser = $this->getCurrentUser();
$user = $event->getUser();
if ($user->getType() === UserTypes::REGISTER_PARTY) {
$userReview = new UserReview($user, $currentUser, [], ReviewStatuses::PENDING);
$this->em->persist($userReview);
$this->em->flush();
}
}
/**
* @param OrganizationEvent $event
*/
public function onOrganizationCreated(OrganizationEvent $event)
{
$currentUser = $this->getCurrentUser();
$organization = $event->getOrganization();
$organizationReview = new OrganizationReview($organization, $currentUser, [], ReviewStatuses::PENDING, self::ADMIN_REVIEW);
$this->em->persist($organizationReview);
$this->em->flush();
}
/**
* @param ReviewFormEvent $event
*/
public function onInspectionCreated(ReviewFormEvent $event)
{
$currentUser = $this->getCurrentUser();
/** @var InspectionForm $inspection */
$inspection = $event->getForm();
if ($currentUser->hasRole($currentUser, UserRoles::ROLE_ADMIN_MUNICIPAL) || $currentUser->hasRole($currentUser, UserRoles::ROLE_MUNICIPAL)) {
$defaultOrg = $this->em->getRepository(Organization::class)->findOneBy(['name' => 'A -- PLEASE SELECT IF NON-REGISTERING ORGANIZATION']);
$inspection->setRegistrant($defaultOrg);
}
$this->em->persist($inspection);
$this->em->flush();
$inspection->setStatus(ReviewStatuses::PENDING);
$needAdmin = $event->getNeedAdmin();
$inspectionReview = new InspectionFormReview($inspection, $currentUser, [], ReviewStatuses::PENDING, $needAdmin);
$this->em->persist($inspectionReview);
$this->em->persist($inspection);
$this->em->flush();
}
/**
* @param ReviewFormEvent $event
*/
public function onRegistrationFormCreated(ReviewFormEvent $event)
{
$currentUser = $this->getCurrentUser();
/** @var RegistrationForm $form */
$form = $event->getForm();
$form->setStatus(ReviewStatuses::PENDING);
$builder = $event->getBuilder();
$customFields = json_encode($builder->customFields);
$needAdmin = $event->getNeedAdmin();
$formReview = new RegistrationFormReview($form, $customFields, $currentUser, [], ReviewStatuses::PENDING, $needAdmin);
if ($event->getPayByCheck()) {
$this->addPayByCheckToFormReview($formReview);
}
$formReview->setForm($form);
$this->em->persist($form);
$this->em->persist($formReview);
$this->em->flush();
}
/**
* @param ReviewFormEvent $event
*/
public function onDeregistrationFormCreated(ReviewFormEvent $event)
{
$currentUser = $this->getCurrentUser();
/** @var DeregistrationForm $form */
$form = $event->getForm();
$form->setStatus(ReviewStatuses::PENDING);
$builder = $event->getBuilder();
$customFields = json_encode($builder->customFields);
$needAdmin = $event->getNeedAdmin();
$formReview = new DeregistrationFormReview($form, $customFields, $currentUser, [], ReviewStatuses::PENDING, $needAdmin);
$formReview->setForm($form);
$this->em->persist($formReview);
$this->em->persist($form);
$this->em->flush();
}
/**
* @param ReviewFormEvent $event
*/
public function onRenewalFormCreated(ReviewFormEvent $event)
{
$currentUser = $this->getCurrentUser();
/** @var RenewalForm $form */
$form = $event->getForm();
$form->setStatus(ReviewStatuses::PENDING);
$needAdmin = $event->getNeedAdmin();
$builder = $event->getBuilder();
$customFields = json_encode($builder->customFields);
$formReview = new RenewalFormReview($form, $currentUser, [], ReviewStatuses::PENDING, $needAdmin, $customFields);
if ($event->getPayByCheck()) {
$this->addPayByCheckToFormReview($formReview);
}
$formReview->setForm($form);
$this->em->persist($formReview);
$this->em->persist($form);
$this->em->flush();
}
public function addPayByCheckToFormReview($formReview): void
{
$customFields = $formReview->getCustomFields();
$customFieldsData = json_decode($customFields, true);
$customFieldsData['pay_by_check'] = true;
$customFieldsData = json_encode($customFieldsData);
$formReview->setCustomFields($customFieldsData);
}
/**
* @param MunicipalityEvent $event
*/
public function onMunicipalityCreated(MunicipalityEvent $event)
{
$currentUser = $this->getCurrentUser();
$municipality = $event->getMunicipality();
$municipalityReview = new MunicipalityReview($municipality, $currentUser, [], ReviewStatuses::PENDING, self::ADMIN_REVIEW);
$this->em->persist($municipalityReview);
$this->em->flush();
}
/**
* @param ReviewFeeEvent $event
*/
public function onMunicipalityFeeCreated(ReviewFeeEvent $event)
{
$currentUser = $this->getCurrentUser();
$fee = $event->getFee();
$feeReview = new MunicipalityFeeReview($fee, $currentUser, [], ReviewStatuses::PENDING, self::ADMIN_REVIEW);
$this->em->persist($feeReview);
$this->em->flush();
}
/**
* @param ReviewEvent $event
*/
public function onReviewApproved(ReviewEvent $event)
{
$entity = null;
$eventType = null;
$newEntityEvent = null;
$review = $event->getReview();
$usedPayByCheckInRegistrationAndRenewal = false;
if ($review instanceof UserReview) {
$entity = ReviewUser::parse($review, $review->getUser());
if ($review->getType() == UserTypes::REGISTER_PARTY
&& $review->getReviewCreator() == null
) {
//registered user.
$eventType = AppEvents::USER_REGISTRATION_APPROVED;
$newEntityEvent = new UserEvent($entity);
}
}
if ($review instanceof MunicipalityReview) {
$entity = ReviewMunicipality::parse($review, $review->getMunicipality());
if ($review->getMunicipality() == null) {
//Is a new Municipality.
$eventType = AppEvents::MUNICIPALITY_CREATED;
$newEntityEvent = new MunicipalityEvent($entity);
}
}
if ($review instanceof OrganizationReview) {
$entity = ReviewOrganization::parse($review, $review->getOrganization());
}
if ($review instanceof InspectionFormReview) {
$entity = ReviewInspection::parse($review, $review->getForm());
$entity->setStatus(ReviewStatuses::APPROVED);
$eventType = AppEvents::INSPECTION_FORM_CREATED;
$newEntityEvent = new FormEvent($entity);
// if ($review->getForm() !== null) $review->setForm(null);
//
// if ($review->getForm() == null) {
// //Is a new Inspection
// $eventType = AppEvents::INSPECTION_FORM_CREATED;
// $newEntityEvent = new FormEvent($entity);
// }
}
if ($review instanceof PropertyReview) {
$entity = ReviewProperty::parse($review, $review->getProperty());
}
if ($review instanceof MunicipalityFeeReview) {
$entity = ReviewMunicipalityFee::parse($review, $review->getMunicipalityFee());
if ($review->getMunicipalityFee() == null) {
//Is a new MunicipalityFee.
$eventType = AppEvents::MUNICIPALITY_FEE_CREATED;
} else {
$eventType = AppEvents::MUNICIPALITY_FEE_UPDATED;
}
$newEntityEvent = new FeeEvent($entity);
}
if ($review instanceof InvoiceReview) {
$entity = ReviewInvoice::parse($review, $review->getInvoice());
}
if ($review instanceof RegistrationFormReview) {
$entity = ReviewRegistrationForm::parse($review, $review->getForm(), true);
if ($review->getForm() !== null) $review->setForm(null);
$reviewCustomFields = json_decode($review->getCustomFields(), true);
$usedPayByCheckInRegistrationAndRenewal = array_key_exists('pay_by_check', $reviewCustomFields) ? $reviewCustomFields['pay_by_check'] : false;
$property = $entity->getProperty();
$registrationForm = new EntityRegistrationForm($property, $property->getRegistrant());
$customFields = $this->customFieldHelper->getCustomFields($property->getMunicipality(), FormTypes::REGISTRATION);
$builder = RegistrationFormBuilder::fromEntity($registrationForm, $customFields);
$builder->customFields = json_decode($review->getCustomFields(), true);
$entity->setStartDate(new \DateTime(PropertyHelper::DELAY_FOR_INVOICE));
if ($this->propertyHelper->getNextRenewalDate($entity->getProperty()))
$entity->setEndDate($this->propertyHelper->getNextRenewalDate($entity->getProperty()));
if ($review->getForm() == null) {
$eventType = AppEvents::REGISTRATION_FORM_CREATED;
$invoiceEvent = new FormCreatedEvent($entity, InvoiceTypes::VPR_REGISTRATION, null, $usedPayByCheckInRegistrationAndRenewal);
} else {
$eventType = AppEvents::REGISTRATION_FORM_UPDATED;
}
$newEntityEvent = new FormEvent($entity);
}
if ($review instanceof RenewalFormReview) {
$entity = ReviewRenewalForm::parse($review, $review->getForm(), true);
$reviewCustomFields = json_decode($review->getCustomFields(), true);
$usedPayByCheckInRegistrationAndRenewal = array_key_exists('pay_by_check', $reviewCustomFields) ? $reviewCustomFields['pay_by_check'] : false;
if ($review->getForm() !== null) $review->setForm(null);
$entity->setStartDate(new \DateTime(PropertyHelper::DELAY_FOR_INVOICE));
$entity->setEndDate($this->propertyHelper->getNextRenewalDate($entity->getProperty()));
if ($review->getForm() == null) {
$eventType = AppEvents::RENEWAL_FORM_CREATED;
$invoiceEvent = new FormCreatedEvent($entity, InvoiceTypes::VPR_RENEWAL, null, $usedPayByCheckInRegistrationAndRenewal);
} else {
$eventType = AppEvents::RENEWAL_FORM_UPDATED;
}
//TODO handle custom fields.
$newEntityEvent = new FormEvent($entity);
}
if ($review instanceof DeregistrationFormReview) {
$entity = ReviewDeregistrationForm::parse($review, $review->getForm(), true);
if ($review->getForm() !== null) $review->setForm(null);
if ($review->getForm() == null) {
$eventType = AppEvents::DEREGISTRATION_FORM_CREATED;
} else {
$eventType = AppEvents::DEREGISTRATION_FORM_UPDATED;
}
//TODO handle custom fields.
$newEntityEvent = new FormEvent($entity);
}
if ($entity) {
$this->em->persist($entity);
$this->em->flush();
if ($review instanceof RegistrationFormReview) {
$this->customFieldHelper->saveFormCustomFields($entity, FormTypes::REGISTRATION, $builder);
}
if ($newEntityEvent) {
$this->eventDispatcher->dispatch($newEntityEvent, $eventType);
}
}
if(isset($invoiceEvent)) {
$this->eventDispatcher->dispatch($invoiceEvent, AppEvents::FORM_CREATED);
//TODO PAYMENT
}
}
/**
* @param ReviewEvent $event
*/
public function onReviewDenied(ReviewEvent $event)
{
$review = $event->getReview();
if (!empty($event->getReview()->getForm())) {
$form = $event->getReview()->getForm();
$form->setStatus(ReviewStatuses::DECLINED);
$this->em->persist($form);
$this->em->flush();
}
// if ($review->notifyUser()) {
$event = new NotifyReviewEvent($review);
$this->eventDispatcher->dispatch($event, AppEvents::REVIEW_NOTIFY_DENIED);
// }
}
/**
* @return User|null
*/
protected function getCurrentUser()
{
$currentUser = null;
if ($this->tokenStorage->getToken()
&& $this->tokenStorage->getToken()->getUser() instanceof User
) {
$currentUser = $this->tokenStorage->getToken()->getUser();
}
return $currentUser;
}
}