<?php
namespace App\Event;
use App\Entity\BookingRoom;
use App\Entity\BuildingOption;
use App\Entity\Company;
use App\Entity\Country;
use App\Entity\Logs;
use App\Entity\NotificationPush;
use App\Entity\Payment;
use App\Entity\Room;
use App\Entity\RoomOption;
use App\Entity\Town;
use App\Entity\User;
use App\Security\EmailVerifier;
use App\Service\Notification;
use Doctrine\ORM\EntityManagerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityBuiltEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityDeletedEvent;
use Exception;
use GuzzleHttp\Exception\RequestException;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\HttpKernel\Log\Logger;
use Symfony\Component\Mime\Address;
use Symfony\Component\Notifier\Bridge\Firebase\FirebaseTransport;
use Symfony\Component\Notifier\Bridge\Firebase\Notification\AndroidNotification;
use Symfony\Component\Notifier\Chatter;
use Symfony\Component\Notifier\ChatterInterface;
use Symfony\Component\Notifier\Event\MessageEvent;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Translation\TranslatableMessage;
use Symfony\Contracts\Translation\TranslatorInterface;
class EasyAdminSubscriber implements EventSubscriberInterface
{
private $environment;
const RESEND_MAIL = "app_resend_email";
const GENERATE_PAYMENT = "app_payment";
const NOTIFY_PAYMENT = "app_payment_notify";
private $emailVerifier;
private $token;
private $requestStack;
private $tokenStorage;
private $eventDispatcher;
private $session;
private $entityManager;
private $chatter;
private $logger;
private $encoder;
private $urlGenerator;
public function __construct(EmailVerifier $emailVerifier,
UserPasswordHasherInterface $encoder,
EventDispatcherInterface $eventDispatcher,
TokenStorageInterface $tokenStorage,
SessionInterface $session,
ChatterInterface $chatter,
LoggerInterface $logger,
KernelInterface $kernel,
UrlGeneratorInterface $urlGenerator,
EntityManagerInterface $entityManager,
RequestStack $requestStack)
{
$this->emailVerifier = $emailVerifier;
$this->session = $session;
$this->chatter = $chatter;
$this->logger = $logger;
$this->encoder = $encoder;
$this->urlGenerator = $urlGenerator;
$this->environment = $kernel->getEnvironment();
$this->requestStack=$requestStack;
$this->entityManager=$entityManager;
$this->tokenStorage = $tokenStorage;
$this->eventDispatcher = $eventDispatcher;
}
public static function getSubscribedEvents()
{
return [
BeforeCrudActionEvent::class => ['setUserApp'],
AfterEntityBuiltEvent::class => ['onAfterBuiltEntity'],
AfterCrudActionEvent::class => ['afterCrudLaunch'],
AfterEntityPersistedEvent::class => ['onCreateEntity'],
BeforeEntityUpdatedEvent::class => ['onUpdateEntity'],
BeforeEntityDeletedEvent::class => ['onDeleteEntity'],
BeforeEntityPersistedEvent::class => ['onBeforeCreateEntity'],
];
}
public function afterCrudLaunch(AfterCrudActionEvent $event){
}
public function setUserApp(BeforeCrudActionEvent $event)
{
$context = $event->getAdminContext();
}
public function onCreateEntity(AfterEntityPersistedEvent $event){
$error=false;
$entity = $event->getEntityInstance();
if($entity instanceof BookingRoom) {
if ($entity->getPayment()->getAmount() != $entity->getRoom()->getCost()) {
$this->session->getFlashBag()->add("warning", "Payment amount did'nt match with the room cost");
$error = true;
}
if ($entity->getArrivalDate() > $entity->getDepartureDate()) {
$this->session->getFlashBag()->add("warning", "Invalid departure date " . $entity->getDepartureDate()->format("Y-m-d") . ". It's supposed to be greater than arrival date " . $entity->getArrivalDate()->format("Y-m-d"));
$error = true;
}
$bookings=$this->entityManager->getRepository(BookingRoom::class)->findByPeriodRoomBook($entity->getArrivalDate()->format("Y-m-d"),$entity->getDepartureDate()->format("Y-m-d"), $entity->getRoom()->getId());
if(!empty($bookings)){
$this->session->getFlashBag()->add("warning", "Room " . $entity->getRoom() . " is not available on this period " . $entity->getArrivalDate()->format("Y-m-d")." - ".$entity->getDepartureDate()->format("Y-m-d").". Total bookings: ".sizeof($bookings));
$error = true;
}
if ($error) {
$this->entityManager->remove($entity);
}else{
$transactionRef= new TransactionRef();
$transactionRef->amount=$entity->getPayment()->getAmount();
$transactionRef->userId=$entity->getUser()->getId();
$transactionRef->roomId=$entity->getRoom()->getId();
$transactionRef->createdDate=$entity->getCreatedAt()->format("Y-m-d H:i:s");
$entity->getPayment()->setTransactionRef(
sha1(json_encode($transactionRef))
);
$token= new Token();
$token->amount=$entity->getPayment()->getAmount();
$token->booking=$entity->getId();
$token->ref= $entity->getPayment()->getTransactionRef();
$entity->getPayment()->setPaymentToken(
base64_encode(json_encode( $token))
);
$entity->setPaymentLink($this->getGeneratePaymentUrl($entity));
$entity->setPaymentNotificationLink($this->getNotifyPaymentLink());
$this->entityManager->persist($entity);
$this->entityManager->flush();
}
}
if(!$error)
$this->session->getFlashBag()->add('success', new TranslatableMessage('content_admin.flash_message.create', [
'%name%' => (string) $event->getEntityInstance(),
], 'admin'));
$log= new Logs();
$log->setActivity("create new entity ".$entity);
$log->setIpAddress($this->requestStack->getCurrentRequest()->getClientIp());
$user = $this->entityManager->getRepository(User::class)->findOneBy(
['id' => $_SESSION["userId"]]
);
$log->setUser($user);
$this->entityManager->persist($log);
$this->entityManager->flush();
if($entity instanceof User){
$entity->setResendMail($this->getResendEmailUrl($entity));
$this->entityManager->persist($entity);
$this->entityManager->flush();
}
if($entity instanceof Room){
$serverKey="AAAAOSFzLyc:APA91bEBmPSN8xq2h4vYDs4wW5UfhoMTdy-Y3VclpUqIVkoe4svv5tsBLFxczyqdePX4YoIZ4gKuZxKBwM5MrrjdDG98oi5YwM00roWfuOTio_sc83TC1l5D8zyjfBgaschvw22o8EiK";
$host=$this->requestStack->getCurrentRequest()->getBaseUrl();
$client = new \GuzzleHttp\Client([
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer '.$serverKey
]
]);
$notification= new Notification();
$notification->setTitle("New Added in ".$entity->getBuilding());
$notification->setImage($entity->getPicture());
$notification->setData("Room ".$entity);
$notification->setMessage("Room ".$entity);
$notification->setAction("");
$response = $client->post('https://fcm.googleapis.com/fcm/send', [
"json" => [
'to' => '/topics/loger',
'data' => [
"title"=>$notification->getTitle(),
"image"=>$notification->getImage(),
"data"=>$notification->getData(),
"message"=>$notification->getMessage(),
"action"=>$notification->getAction(),
"action_destination"=>$notification->getActionDestination(),
]
]
]);
$responseBodies=json_decode($response->getBody()->getContents());
}
if($entity instanceof NotificationPush){
$serverKey="AAAAOSFzLyc:APA91bEBmPSN8xq2h4vYDs4wW5UfhoMTdy-Y3VclpUqIVkoe4svv5tsBLFxczyqdePX4YoIZ4gKuZxKBwM5MrrjdDG98oi5YwM00roWfuOTio_sc83TC1l5D8zyjfBgaschvw22o8EiK";
$host=$this->requestStack->getCurrentRequest()->getBaseUrl();
$client = new \GuzzleHttp\Client([
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer '.$serverKey
], 'verify'=>false
]);
$notification= new Notification();
$notification->setTitle($entity->getTitle());
$notification->setImage($entity->getImage());
$notification->setData($entity->getMessage());
$notification->setMessage($entity->getMessage());
$notification->setAction("");
foreach ($entity->getFirebaseToken() as $token) {
$response = $client->post('https://fcm.googleapis.com/fcm/send', [
"json" => [
'to' => $token->getDeviseId(),
'data' => [
"title"=>$notification->getTitle(),
"image"=>$notification->getImage(),
"data"=>$notification->getData(),
"message"=>$notification->getMessage(),
"action"=>$notification->getAction(),
"action_destination"=>$notification->getActionDestination(),
]
]
]);
$responseBodies=json_decode($response->getBody()->getContents());
try {
if(($responseBodies->success)){
$this->session->getFlashBag()->add('info', "Notification broacasted with id: ".$responseBodies->multicast_id);
$entity->setHasBeenSent(true);
}else{
$entity->setHasBeenSent(false);
}
}catch (Exception $exception){
}
}
}
}
public function onBeforeCreateEntity(BeforeEntityPersistedEvent $event){
$entity = $event->getEntityInstance();
if($entity instanceof User) {
$encoded = $this->encoder->hashPassword($entity, $entity->getPlainPassword());
$entity->setPassword($encoded);
$entity->setUsername($entity->getEmail());
$this->entityManager->persist($entity);
$this->entityManager->flush();
// generate a signed url and email it to the user
$this->emailVerifier->sendEmailConfirmation('app_verify_email', $entity,
(new TemplatedEmail())
->from(new Address('noreply@loger.cm', 'LOGER CM - NO REPLY'))
->to($entity->getEmail())
->subject('Please Confirm your Email')
->htmlTemplate('registration/confirmation_email.html.twig')
);
// do anything else you need here, like send an email
// @TODO Change the redirect on success and handle or remove the flash message in your templates
$this->session-> getFlashBag()->add('success', 'Email send to verify the mail address.');
}
}
public function onAfterBuiltEntity(AfterEntityBuiltEvent $event){
$entity = $event->getEntity();
}
public function onUpdateEntity(BeforeEntityUpdatedEvent $event){
$entity = $event->getEntityInstance();
$this->session->getFlashBag()->add('success', new TranslatableMessage('content_admin.flash_message.update', [
'%name%' => (string) $entity,
], 'admin'));
$log= new Logs();
$log->setActivity("update entity ".$entity);
$log->setIpAddress($this->requestStack->getCurrentRequest()->getClientIp());
$user = $this->entityManager->getRepository(User::class)->findOneBy(
['id' => $_SESSION["userId"]]
);
$log->setUser($user);
$this->entityManager->persist($log);
$this->entityManager->flush();
if($entity instanceof Country){
$this->session->getFlashBag()->add('info', "searching towns in progress...");
$this->getTowns($entity);
}
if($entity instanceof User){
$entity->setResendMail($this->getResendEmailUrl($entity));
$entity->setUpdateAt(new \DateTimeImmutable());
$this->entityManager->persist($entity);
$this->entityManager->flush();
}
if($entity instanceof BookingRoom){
$transactionRef= new TransactionRef();
$transactionRef->amount=$entity->getPayment()->getAmount();
$transactionRef->userId=$entity->getUser()->getId();
$transactionRef->roomId=$entity->getRoom()->getId();
$transactionRef->createdDate=$entity->getCreatedAt()->format("Y-m-d H:i:s");
$entity->getPayment()->setTransactionRef(
sha1(json_encode($transactionRef))
);
$token= new Token();
$token->amount=$entity->getPayment()->getAmount();
$token->booking=$entity->getId();
$token->ref= $entity->getPayment()->getTransactionRef();
$entity->getPayment()->setPaymentToken(
base64_encode(json_encode( $token))
);
$entity->setPaymentLink($this->getGeneratePaymentUrl($entity));
$entity->setPaymentNotificationLink($this->getNotifyPaymentLink());
$this->entityManager->persist($entity);
$this->entityManager->flush();
}
if($entity instanceof Room){
$serverKey="AAAAOSFzLyc:APA91bEBmPSN8xq2h4vYDs4wW5UfhoMTdy-Y3VclpUqIVkoe4svv5tsBLFxczyqdePX4YoIZ4gKuZxKBwM5MrrjdDG98oi5YwM00roWfuOTio_sc83TC1l5D8zyjfBgaschvw22o8EiK";
$host=$this->requestStack->getCurrentRequest()->getBaseUrl();
$client = new \GuzzleHttp\Client([
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer '.$serverKey
], 'verify'=>false
]);
$notification= new Notification();
$notification->setTitle("New update in ".$entity->getBuilding());
$notification->setImage($entity->getPicture());
$notification->setData("Room ".$entity);
$notification->setMessage("Room ".$entity);
$notification->setAction("");
$response = $client->post('https://fcm.googleapis.com/fcm/send', [
"json" => [
'to' => '/topics/loger',
'data' => [
"title"=>$notification->getTitle(),
"image"=>$notification->getImage(),
"data"=>$notification->getData(),
"message"=>$notification->getMessage(),
"action"=>$notification->getAction(),
"action_destination"=>$notification->getActionDestination(),
]
]
]);
$responseBodies=json_decode($response->getBody()->getContents());
$this->session->getFlashBag()->add('info', "Notification broacasted with id: ".$responseBodies->message_id);
}
}
public function onDeleteEntity(BeforeEntityDeletedEvent $event){
$entity=$event->getEntityInstance();
$this->session->getFlashBag()->add('success', new TranslatableMessage('content_admin.flash_message.delete', [
'%name%' => (string) $entity,
], 'admin'));
$log= new Logs();
$log->setActivity("delete entity ".$entity);
$log->setIpAddress($this->requestStack->getCurrentRequest()->getClientIp());
$user = $this->entityManager->getRepository(User::class)->findOneBy(
['id' => $_SESSION["userId"]]
);
$log->setUser($user);
$this->entityManager->persist($log);
$this->entityManager->flush();
if($entity instanceof BookingRoom){
$entity->getRoom()->setIsFree(true);
$this->entityManager->persist($entity);
$this->entityManager->flush();
}
}
public function getTowns(Country $country){
$client = new \GuzzleHttp\Client();
try {
$response = $client->request('GET', 'https://wft-geo-db.p.rapidapi.com/v1/geo/cities?countryIds='.$country->getCode()."&offset=".$country->getOffset()."&limit=5", [
'headers' => [
'X-RapidAPI-Host' => 'wft-geo-db.p.rapidapi.com',
'X-RapidAPI-Key' => 'd01923dc5amsh8cc5a1094d152c2p117a73jsneebdb0db3f67',
],
'verify' => false
]);
$responseBodies=json_decode($response->getBody()->getContents());
$offset=$country->getOffset()+sizeof($responseBodies->data);
foreach ($responseBodies->data as $responseTown){
$town=new Town();
$town->setCountry($country);
$town->setTownName($responseTown-> name);
$town->setLatitude($responseTown-> latitude);
$town->setLongitude($responseTown-> longitude);
$town->setRegion($responseTown-> longitude);
$town->setPopulation($responseTown-> population);
$town->setIsCapital(false);
$dbTown=$this->entityManager->getRepository(Town::class)->findOneByName($responseTown-> name);
if (empty($dbTown)) {
$this->entityManager->persist($town);
$this->entityManager->flush();
$this->session->getFlashBag()->add('success', $town." added");
}else{
$dbTown->setLatitude($responseTown-> latitude);
$dbTown->setLongitude($responseTown-> longitude);
$dbTown->setPopulation($responseTown-> population);
$dbTown->setRegion($responseTown-> region);
$this->entityManager->persist($dbTown);
$this->entityManager->flush();
$offset--;
$this->session->getFlashBag()->add('success', $town." updated");
}
}
$country->setOffset( $offset);
$this->entityManager->persist($country);
if($offset<$responseBodies->metadata->totalCount){
$this->getTowns($country);
}
}catch (RequestException $exception){
}
}
public function getResendEmailUrl(User $user): string
{
return $this->urlGenerator->generate(self::RESEND_MAIL,["user"=>$user->id]);
}
public function getGeneratePaymentUrl(BookingRoom $bookingRoom): string
{
return $this->urlGenerator->generate(self::GENERATE_PAYMENT,["token"=>$bookingRoom->getPayment()->getPaymentToken()]);
}
public function getNotifyPaymentLink(): string
{
return $this->urlGenerator->generate(self::NOTIFY_PAYMENT);
}
}