<?php
namespace App\V4\EventSubscriber\CustomEventTrigger;
use App\Form\Type\AbstractViewOrderAwareType;
use App\Service\Serializer\NoNullObjectNormalizer;
use App\V4\Builder\CustomEventTrigger\CustomEventTriggerBuilder;
use App\V4\Entity\CustomEventTrigger;
use App\V4\Model\ChildrenAwareInterface;
use App\V4\Model\Prospect\Prospect;
use App\V4\Model\Quote\Quote;
use App\V4\Repository\CustomEventTriggerRepository;
use App\V4\Transformer\FQCNToShortNameTransformer;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class CustomEventTriggerPostSetDataOnCreationSubscriber implements EventSubscriberInterface
{
/**
* @var CustomEventTriggerRepository
*/
private $customEventTriggerRepository;
/**
* @var CustomEventTriggerBuilder
*/
private $customEventTriggerBuilder;
/**
* @var NormalizerInterface
*/
private $normalizer;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @param CustomEventTriggerRepository $customEventTriggerRepository
* @param CustomEventTriggerBuilder $customEventTriggerBuilder
* @param NormalizerInterface $normalizer
* @param RequestStack $requestStack
*/
public function __construct(
CustomEventTriggerRepository $customEventTriggerRepository,
CustomEventTriggerBuilder $customEventTriggerBuilder,
NormalizerInterface $normalizer,
RequestStack $requestStack
) {
$this->customEventTriggerRepository = $customEventTriggerRepository;
$this->customEventTriggerBuilder = $customEventTriggerBuilder;
$this->normalizer = $normalizer;
$this->requestStack = $requestStack;
}
public static function getSubscribedEvents(): array
{
return [
FormEvents::POST_SET_DATA => 'onPostSetData',
];
}
/**
* @param FormEvent $event
*
* @return bool
*/
public function supports(FormEvent $event): bool
{
$entity = $event->getData();
if (!$entity instanceof Quote && !$entity instanceof Prospect) {
return false;
}
if ($entity instanceof ChildrenAwareInterface && $entity->isSplit()) {
return false;
}
$request = $this->requestStack->getCurrentRequest();
if ($request instanceof Request
&& $request->query->get('context')
&& AbstractViewOrderAwareType::CONTEXT_SHOW === $request->query->get('context')
) {
return false;
}
return true;
}
/**
* @param FormEvent $event
*
* @return void
*
* @throws ExceptionInterface
*/
public function onPostSetData(FormEvent $event): void
{
if (!$this->supports($event)) {
return;
}
$customEventTriggers = $this
->customEventTriggerRepository
->searchByEntityAndWhenApply(
(new FQCNToShortNameTransformer())->transform($event->getForm()->getConfig()->getDataClass()),
CustomEventTrigger::WHEN_POST_SET_DATA
)
;
if (empty($customEventTriggers)) {
return;
}
$initialNormalizedData = $this
->normalizer
->normalize($event->getData(), null, [NoNullObjectNormalizer::CONTEXT_IS_DISABLED => true])
;
$dataArrayModified = $initialNormalizedData;
foreach ($customEventTriggers as $customEventTrigger) {
$dataArrayModified = $this
->customEventTriggerBuilder
->getBuilder($dataArrayModified, $customEventTrigger)
->apply($dataArrayModified, $customEventTrigger)
;
}
$diff = $this->arrayRecursiveDiff($dataArrayModified, $initialNormalizedData);
foreach ($diff as $fieldName => $value) {
if (!$event->getForm()->has($fieldName)) {
continue;
}
$event
->getForm()
->get($fieldName)
->setData($value)
;
}
}
/**
* @param $aArray1
* @param $aArray2
*
* @return array
*/
private function arrayRecursiveDiff($aArray1, $aArray2): array
{
$aReturn = [];
foreach ($aArray1 as $mKey => $mValue) {
if (array_key_exists($mKey, $aArray2)) {
if (is_array($mValue)) {
$aRecursiveDiff = $this->arrayRecursiveDiff($mValue, $aArray2[$mKey]);
if (count($aRecursiveDiff)) {
$aReturn[$mKey] = $aRecursiveDiff;
}
continue;
}
if ($mValue !== $aArray2[$mKey]) {
$aReturn[$mKey] = $mValue;
}
continue;
}
$aReturn[$mKey] = $mValue;
}
return $aReturn;
}
}