<?php
namespace App\EventSubscriber;
use App\Event\OrderEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mime\Address;
use Psr\Log\LoggerInterface;
use App\Entity\ShopOrder;
use App\Entity\ShopOrderProduct;
use App\Entity\User;
use App\Entity\UserEleveCredit;
use App\Event\CreditEvent;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Lock\LockFactory;
class OrderEventSubscriber implements EventSubscriberInterface
{
private $entityManager;
private $logger;
private $mailer;
public function __construct(LockFactory $locker, LoggerInterface $lifecycleLogger, EntityManagerInterface $entityManager, MailerInterface $mailer, \App\Cacher\PreSetCacher $cacher, UserEventSubscriber $UserEventSubscriber)
{
$this->locker = $locker;
$this->dispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
$this->dispatcher->addSubscriber($UserEventSubscriber);
$this->logger = $lifecycleLogger;
$this->entityManager = $entityManager;
$this->mailer = $mailer;
$cacher->setItemName('commande');
$this->order_cacher = clone $cacher;
$cacher->setItemName('eleve');
$this->eleve_cacher = clone $cacher;
$cacher->setItemName('lifecycle');
$this->lifecycle_cacher = clone $cacher;
}
public static function getSubscribedEvents() : array
{
return [
OrderEvent::CONFIRMED => 'onOrderConfirmed',
];
}
public function onOrderConfirmed(OrderEvent $event)
{
#à bug aléatoire, solution aléatoire
sleep(rand(0,3));
$shopOrder = $event->getShopOrder();
// Log the event
$this->logger->info(OrderEvent::CONFIRMED, [
'shopOrder'=>$shopOrder,
]);
$lock = $this->locker->createLock('order:'.$shopOrder->getReference());
$locked = $lock->acquire(true);
// $e = new \Exception;
$trace = '';
// $trace = print_r($e->getTraceAsString(),true);
$trace .= '#locked '.print_r($locked,true);
$trace .= '#_GET '.print_r($_GET,true);
$trace .= '#_POST '.print_r($_POST,true);
$trace .= '#_SERVER '.print_r($_SERVER,true);
// $trace .= '#Request '.print_r(Request::createFromGlobals()->getContent(),true);
// $trace .= '#lock '.print_r($lock,true);
$this->mailer->send((new TemplatedEmail())
->to('gabriel@pyreweb.com')
->subject('Locker')
->textTemplate('maildebug.txt.twig')
->context([
'texte'=>$shopOrder->getReference().' has a locker?'.PHP_EOL.$trace,
])
);
if($shopOrder->getStatus()->getCode() == 'success') {
// $this->mailAdminAboutError($shopOrder, 'La commande n°'.$shopOrder->getReference().' a déjà été payée.');
throw new \Error('La commande n°'.$shopOrder->getReference().' a déjà été payée.');
}
$user = $event->getUser();
// Delete the cache entries
$this->lifecycle_cacher->empty();
$this->eleve_cacher->delete($user);
$this->order_cacher->delete($shopOrder);
$this->order_cacher->delete('count');
$entityManager = $this->entityManager;
$ShopOrderStatus = $entityManager->getRepository(\App\Entity\ShopOrderStatus::class)->findOneBy(['code'=>'success']);
$shopOrder->setStatus($ShopOrderStatus);
//liste des crédits utilisateurs non flushés
$UserEleveCredits = new \Doctrine\Common\Collections\ArrayCollection();
// Traitement des éléments de la commande
foreach($shopOrder->getshopOrderProducts() as $shopOrderProduct) {
//Mise à jour des crédits utilisateur
// La catégorie des crédits utilisateur concernée existe-elle ?
$cat = $entityManager->getRepository(UserEleveCredit::class);
$UserEleveCredit = $cat->findOneWithShopOrderProduct($shopOrderProduct);
if($UserEleveCredit == null) {
// On vérifie s'il y a une catégorie pas encore flushée pour le user
$UserEleveCredit = $UserEleveCredits->filter(function($UserEleveCredit) use ($shopOrderProduct) {
return $UserEleveCredit->getCategorie() == $shopOrderProduct->getCategorie();
})->first();
if(!$UserEleveCredit) {
$UserEleveCredit = null;
}
}
// Elle n'existe pas pour ce User, on la crée
if($UserEleveCredit == null) {
$UserEleveCredit = new UserEleveCredit();
$UserEleveCredit->setUser($user);
$UserEleveCredit->setCategorie($shopOrderProduct->getCategorie());
}
// On ajoute les points
$UserEleveCredit->addPoints($shopOrderProduct->getTotalPoints());
$entityManager->persist($UserEleveCredit);
$UserEleveCredits->add($UserEleveCredit);
$event = new CreditEvent($UserEleveCredit);
$event->setMovedPoints($shopOrderProduct->getTotalPoints());
$this->dispatcher->dispatch($event, CreditEvent::ADDED);
}
$entityManager->persist($shopOrder);
$entityManager->flush();
$lock->release();
$this->mailAdminAboutConfirmation($shopOrder);
$this->mailUserAboutConfirmation($shopOrder);
}
protected function mailAdminAboutError(ShopOrder $shopOrder, string $erreur){
$this->mailer->send((new TemplatedEmail())
->subject('Erreur sur une Commande')
->htmlTemplate('admin/mail/order_error.html.twig')
->context([
'commande'=>$shopOrder,
'erreur'=>$erreur
])
);
}
protected function mailAdminAboutConfirmation(ShopOrder $shopOrder){
$this->mailer->send((new TemplatedEmail())
->subject('Commande confirmée')
->htmlTemplate('admin/mail/order_confirmed.html.twig')
->context([
'commande'=>$shopOrder,
])
);
}
protected function mailUserAboutConfirmation(ShopOrder $shopOrder){
$this->mailer->send((new TemplatedEmail())
->to($shopOrder->getUser()->getEmail())
->subject('Commande confirmée')
->htmlTemplate('eleve/mail/order_confirmed.html.twig')
->context([
'commande'=>$shopOrder,
])
);
}
}