<?php
namespace App\EventListener;
use App\Entity\Activity;
use App\Entity\Order;
use App\Entity\OrderSpecification;
use App\Entity\User;
use App\Enum\NotificationTopic;
use App\Event\OrderEditEvent;
use App\Notification\FindUserNotification;
use App\Notification\MercureNotification;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
class OrderEditEventListener
{
private $activities = [];
/**
* @var MercureNotification
*/
private $mercureNotification;
/**
* @var FindUserNotification
*/
private $findUserNotification;
public function __construct(MercureNotification $mercureNotification, FindUserNotification $findUserNotification)
{
$this->mercureNotification = $mercureNotification;
$this->findUserNotification = $findUserNotification;
}
public function __invoke(OrderEditEvent $orderEditEvent)
{
$activities = $this->getActivities($orderEditEvent);
$encoders = [new XmlEncoder(), new JsonEncoder()];
$dateCallback = function ($innerObject, $outerObject, string $attributeName, string $format = null, array $context = []) {
return $innerObject instanceof \DateTimeInterface ? $innerObject->format('h:i:s a \<\/\b\r\> d-m-Y ') : '';
};
$defaultContext = [
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object, $format, $context) {
return $object->getFullName();
},
AbstractNormalizer::CALLBACKS => [
'createdAt' => $dateCallback,
],
];
$normalizer = new ObjectNormalizer(null, null, null, null, null, null, $defaultContext);
$serializer = new Serializer([$normalizer], $encoders);
$data = [
'activities' => [],
'users' => $this->findUserNotification->findByOrder($orderEditEvent->getNewOrder(), $orderEditEvent->getUser()),
];
foreach ($activities as $activity) {
$data['activities'][] = $serializer->serialize($activity, 'json');
}
$this->mercureNotification->notification(NotificationTopic::ORDER, $data);
}
/**
* @throws \Exception
*/
public function getActivities(OrderEditEvent $orderEditEvent): array
{
$now = new \DateTimeImmutable();
if (\count($this->diffOrder($orderEditEvent)) < 1) {
return [];
}
foreach ($this->diffOrder($orderEditEvent) as $item) {
$activity = new Activity();
$activity->setClassId($orderEditEvent->getOldOrder()->getId());
$activity->setClassName(Order::class);
$activity->setField($item['label']);
$activity->setNewValue($item['newValue']);
$activity->setOldValue($item['oldValue']);
$activity->setCreatedAt($now);
$activity->setCode('order_1_'.$now->format('d-m-Y-h-i-s'));
/** @var User $userCurrent */
$userCurrent = $orderEditEvent->getUser();
$user = new User();
$user->setFirstName($userCurrent->getFirstName());
$user->setLastName($userCurrent->getLastName());
$activity->setUser($user);
$activity->setType($item['type']);
$activity->setView(0);
$this->activities[] = $activity;
}
return $this->activities;
}
private function diffOrder(OrderEditEvent $orderEditEvent): array
{
$items = [];
$oldOrder = $orderEditEvent->getOldOrder();
$newOrder = $orderEditEvent->getNewOrder();
if ($oldOrder->getName() !== $newOrder->getName()) {
$items[] = [
'label' => 'name',
'oldValue' => $oldOrder->getName(),
'newValue' => $newOrder->getName(),
'type' => 'attribute',
];
}
if ($oldOrder->getDeliveredAt() !== $newOrder->getDeliveredAt()) {
$items[] = [
'label' => 'deliveredAt',
'oldValue' => $oldOrder->getDeliveredAt(),
'newValue' => $newOrder->getDeliveredAt(),
'type' => 'attribute',
];
}
if ($oldOrder->getShortNote() !== $newOrder->getShortNote()) {
$items[] = [
'label' => 'shortNote',
'oldValue' => $oldOrder->getShortNote(),
'newValue' => $newOrder->getShortNote(),
'type' => 'attribute',
];
}
if ($oldOrder->getNameNumber() !== $newOrder->getNameNumber()) {
$items[] = [
'label' => 'nameNumber',
'oldValue' => $oldOrder->getNameNumber(),
'newValue' => $newOrder->getNameNumber(),
'type' => 'attribute',
];
}
foreach ($oldOrder->getOrderSpecifications() as $orderSpecification) {
$indexOf = $newOrder->getOrderSpecifications()->indexOf($orderSpecification);
if ($indexOf) {
/** @var OrderSpecification $orderSpecificationNew */
$orderSpecificationNew = $newOrder->getOrderSpecifications()->get($indexOf);
if ($orderSpecificationNew->getQuantity() === $orderSpecificationNew->getQuantity()) {
continue;
}
$items[] = [
'label' => $orderSpecificationNew->getSpecification()->getName(),
'oldValue' => $orderSpecification->getQuantity(),
'newValue' => $orderSpecificationNew->getQuantity(),
'type' => 'specification',
];
} else {
//remove
$items[] = [
'label' => $orderSpecification->getSpecification()->getName(),
'oldValue' => $orderSpecification->getQuantity(),
'newValue' => '',
'type' => 'specification',
];
}
}
//addOrderSpecifications
$list = $newOrder->getOrderSpecifications()->filter(function (OrderSpecification $orderSpecification) use ($oldOrder) {
return !is_numeric($oldOrder->getOrderSpecifications()->indexOf($orderSpecification));
});
/** @var OrderSpecification $orderSpecification */
foreach ($list as $orderSpecification) {
$items[] = [
'label' => $orderSpecification->getSpecification()->getName(),
'oldValue' => $orderSpecification->getQuantity(),
'newValue' => '',
'type' => 'specification',
];
}
return $items;
}
}