<?php
namespace App\Controller;
use App\Entity\Event;
use App\Entity\Invitee;
use App\Entity\Lineup;
use App\Entity\News;
use App\Entity\Purchase;
use App\Entity\Sponsor;
use App\Entity\Stage;
use App\Form\InviteeType;
use App\Form\PurchaseEmailType;
use App\Form\PurchaseLoginType;
use App\Repository\ArtistRepository;
use App\Repository\ContentRepository;
use App\Repository\FaqRepository;
use App\Repository\FoodRepository;
use App\Repository\InviteeRepository;
use App\Repository\LineupRepository;
use App\Repository\NewsRepository;
use App\Repository\PurchaseRepository;
use App\Repository\SponsorRepository;
use App\Repository\StageRepository;
use App\Service\PurchaseHelper;
use App\Service\TicketTailorApi;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class ApplicationController extends AbstractController
{
private array $orders = [];
private ManagerRegistry $doctrine;
private ?Event $currentEvantevent;
private ?FormInterface $shareForm = null;
private PurchaseHelper $purchaseHelper;
public function __construct(ManagerRegistry $doctrine, PurchaseHelper $purchaseHelper)
{
$this->doctrine = $doctrine;
$this->purchaseHelper = $purchaseHelper;
$this->currentEvantevent = $this->doctrine->getRepository(Event::class)->findOneBy(['state'=>Event::STATE_ACTIVE]);
}
/**
* @Route("/", name="feapp_landing")
* @Route("/ticket_login", name="feapp_landing_login")
*/
public function landing(
Request $request,
PurchaseHelper $helper,
PurchaseRepository $repository,
InviteeRepository $inviteeRepository,
TicketTailorApi $api,
Purchase $purchase=null
): Response
{
if ($request->get('_route')=='feapp_landing_login') {
$request->getSession()->set('login_session',true);
$request->cookies->remove('no_ticket');
} else {
if ($this->validSession($request, true)) {
return $this->redirectToRouteClearNoTicket($request, 'feapp_home');
} else {
return $this->anonymousLogin($request);
}
}
$new = false;
if (!$purchase) {
$purchase = new Purchase();
$new = true;
} elseif ($request->get('_route')=='upgrade_landing_email') {
$purchase->setCampaignClickedAt(new \DateTimeImmutable());
$this->doctrine->getManager()->persist($purchase);
$this->doctrine->getManager()->flush();
}
$form = $this->createForm(PurchaseEmailType::class, $purchase);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$_email = $purchase->getEmail();
if (!$new) {
$this->doctrine->getManager()->refresh($purchase);
}
unset($purchase);
$_purchase = $repository->findOneBy([
'email'=>$_email,
'event'=>$this->currentEvantevent
]);
if (!$_purchase) {
$_purchase = $api->getOrderByEmail($form->get('email')->getData());
}
if ($_purchase) {
$helper->generateLoginCode($_purchase);
$this->doctrine->getManager()->persist($_purchase);
$this->doctrine->getManager()->flush();
$helper->sendAppLoginCode($_purchase);
$this->addFlash('info', 'Please check your '.$_purchase->getEmail().' email for security code.');
return $this->redirectToRouteClearNoTicket($request, 'feapp_login',['id'=>$_purchase->getId()]);
}
// No purchases. Look for invitations
$_invitation = $inviteeRepository->findOneBy(['email'=>$form->get('email')->getData()]);
if ($_invitation) {
$helper->generateLoginCode($_invitation);
$this->doctrine->getManager()->persist($_invitation);
$this->doctrine->getManager()->flush();
$helper->sendAppLoginCode($_invitation);
$this->addFlash('info', 'Please check your '.$form->get('email')->getData().' email for security code.');
return $this->redirectToRouteClearNoTicket($request, 'feapp_login',['id'=>$_invitation->getPurchase()->getId()]);
}
$this->addFlash('warning', 'We were not able to find your order. Please check information you provided.');
}
if (!$request->cookies->has('no_ticket')) {
$response = new Response();
$response->headers->clearCookie('no_ticket');
} else {
$response = null;
}
return $this->render(
'feSecurity/landing.html.twig',
[
'form'=>$form->createView(),
],
$response
);
}
/**
* @Route("/app/anonymous-login", name="feapp_login_anonymously", methods={"POST"})
*/
public function anonymousLogin(Request $request): Response
{
$request->getSession()->remove('order');
$request->getSession()->remove('login_session');
$request->cookies->remove('anonymos-visitor');
$cookie = Cookie::create('no_ticket')
->withValue('lowdefest')
->withExpires(new \DateTime('+3 hours'))
->withSecure(true);
$response = new RedirectResponse($this->generateUrl('feapp_home', [],Response::HTTP_SEE_OTHER));
$response->headers->setCookie($cookie);
return $response;
}
/**
* @Route("/app/{id}/login", name="feapp_login")
* @Route("/app/{id}/login/{code}", name="feapp_login_code")
*/
public function login(Request $request, Purchase $purchase, $code = ''): Response
{
if ( !$purchase->isValidInviteeLoginCode() ) {
$this->addFlash('warning', 'You login request has been expired. Please request the new login code.');
return $this->redirectToRoute('feapp_landing_login');
}
$formPurchase = clone $purchase;
$formPurchase->setLoginCode($code);
$form = $this->createForm(PurchaseLoginType::class, $formPurchase);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ( $loginObject = $purchase->checkLoginCode($formPurchase->getLoginCode()) ) {
$request->getSession()->set('order', [
'email'=>$loginObject->getEmail(),
'event'=>($loginObject instanceof Purchase)?$loginObject->getEvent()->getId():$loginObject->getPurchase()->getEvent()->getId()
]);
$request->getSession()->remove('login_session');
$loginObject->setLoginCodeExpireAt(null);
$this->doctrine->getManager()->persist($loginObject);
$this->doctrine->getManager()->flush();
return $this->redirectToRoute('feapp_home');
} else {
$this->addFlash('danger', 'Invalid login code. Please check your email for a valid login code.');
}
}
return $this->render('feSecurity/login.html.twig', [
'form'=>$form->createView(),
]);
}
/**
* @Route("/app", name="feapp_home")
*/
public function home(
Request $request,
ArtistRepository $repository
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('feHome.html.twig', [
//'artists' => $repository->getRandom(3),
'artists' => $repository->getRandom(25, $this->currentEvantevent),
]);
}
/**
* @Route("/app/news", name="feapp_news")
*/
public function news(Request $request, NewsRepository $newsRepository): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('news.html.twig', [
'news' => $newsRepository->findCurrentNews(new \DateTimeImmutable(), $this->currentEvantevent),
]);
}
/**
* @Route("/app/news/{id}", name="feapp_news_details")
*/
public function newsDetails(Request $request, News $article): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('newsDetails.html.twig', [
'article' => $article,
]);
}
/**
* @Route("/app/artists", name="feapp_artists")
*/
public function artists(Request $request, ArtistRepository $repository): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('artists.html.twig', [
'artists' => $repository->findByEvent($this->currentEvantevent),
]);
}
/**
* @Route("/app/stages", name="feapp_stages")
*/
public function stages(Request $request, StageRepository $repository): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('stages.html.twig', [
'stages' => $repository->findByEvent($this->currentEvantevent),
]);
}
/**
* @Route("/app/lineup", name="feapp_lineup")
* @Route("/app/lineup/{id}", name="feapp_lineup_stage")
*/
public function lineup(
Request $request,
StageRepository $repository,
LineupRepository $luRepository,
Stage $stage=null
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('lineup.html.twig', [
'stages' => $repository->findByEvent($this->currentEvantevent),
'stage' => $stage,
'lineups' => $luRepository->getRecordsByStage($stage, $this->currentEvantevent),
]);
}
/**
* @Route("/app/faqs", name="feapp_faqs")
*/
public function faqs(
Request $request,
FaqRepository $repository
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('faqs.html.twig', [
'faqs'=>$repository->findAll(),
]);
}
/**
* @Route("/app/sponsors", name="feapp_sponsors")
*/
public function sponsors(
Request $request,
SponsorRepository $repository
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('sponsors.html.twig', [
'sponsors'=>$repository->findAllSponsors($this->currentEvantevent),
]);
}
/**
* @Route("/app/local_busines_partners", name="feapp_partners")
*/
public function businessPartners(
Request $request,
SponsorRepository $repository
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('partners.html.twig', [
'sponsors'=>$repository->findAllPartners($this->currentEvantevent),
]);
}
/**
* @Route("/app/sponsors/{id}", name="feapp_sponsors_details")
*/
public function sponsorDetails(
Request $request,
Sponsor $sponsor
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('sponsorDetails.html.twig', [
'sponsor' => $sponsor,
]);
}
protected function getUpcoming()
{
if ((new \DateTimeImmutable())>$this->currentEvantevent->getStartAt()) {
return $this->getDoctrine()->getRepository(Lineup::class)->getGlobalUpcoming(new \DateTimeImmutable('+1 hour'));
}
return [];
}
protected function getOnAir()
{
if ((new \DateTimeImmutable())>$this->currentEvantevent->getStartAt()) {
return $this->getDoctrine()->getRepository(Lineup::class)->getGlobalOnAir();
}
return [];
}
protected function validSession(Request $request, bool $noGuests = false): bool
{
$template = [
'purchased'=>[],
'invited'=>[],
];
if (
$request->getSession()->has('order')
) {
$s = $request->getSession()->get('order');
if (isset($s['email']) && isset($s['event'])) {
$event = $this->doctrine->getRepository(Event::class)->find($s['event']);
$this->orders = $this->purchaseHelper->getAllAvailablePurchases($s['email'], $event);
if (count($this->orders['purchased']) || count($this->orders['invited'])) {
return true;
}
}
} elseif ($request->cookies->has('no_ticket') && !$noGuests) {
$this->orders = $template;
return true;
}
$this->orders = $template;
return false;
}
/**
* @Route("/app/directions", name="feapp_directions")
*/
public function directionsMap(
Request $request
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('sponsors.html.twig', []);
}
/**
* @Route("/app/taxi", name="feapp_taxi")
*/
public function bookTaxi(
Request $request,
ContentRepository $repository
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('taxi.html.twig', [
'content'=>$repository->get('taxi'),
]);
}
/**
* @Route("/app/directions", name="feapp_directions")
*/
public function directions(
Request $request,
ContentRepository $repository
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('directions.html.twig', [
'content'=>$repository->get('directions'),
]);
}
/**
* @Route("/app/about-lowdefest", name="feapp_about")
*/
public function adout(
Request $request,
ContentRepository $repository
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('cms.html.twig', [
'content'=>$repository->get('about'),
]);
}
/**
* @Route("/app/about-lowde-music-trust", name="feapp_about_trust")
*/
public function aboutTrust(
Request $request,
ContentRepository $repository
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('cms.html.twig', [
'content'=>$repository->get('about-trust'),
]);
}
/**
* @Route("/app/food-and-bars", name="feapp_food")
*/
public function foodAndBars(
Request $request,
FoodRepository $repository
): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
return $this->render('food.html.twig', [
'content'=>$repository->findByEvent($this->currentEvantevent),
]);
}
protected function render(string $view, array $parameters = [], Response $response = null): Response
{
if (!$this->shareForm) {
$invitee = new Invitee();
$this->shareForm = $this->createForm(InviteeType::class, $invitee);
}
$shared = [
'orders'=>$this->orders,
'upcoming' => $this->getUpcoming(),
'onAir' => $this->getOnAir(),
'shareForm' => $this->shareForm->createView(),
'currentEvent' => $this->currentEvantevent,
];
return parent::render($view, array_merge($shared, $parameters), $response);
}
/**
* @Route("/app/share/{id}", name="feapp_share_ticket", methods={"POST"})
*/
public function addInvitation(Request $request, Purchase $purchase, ManagerRegistry $doctrine): Response
{
if (!$this->validSession($request)) {
$this->addFlash('warning','You session expired. Please login once more.');
return $this->redirectToRoute('feapp_landing');
}
foreach ($this->orders['invited'] as $order) {
if ($order->getId()==$purchase->getId()) {
$this->addFlash(
'danger',
'You can share only your own tickets',
);
return $this->redirectToRoute('feapp_home');
}
}
$invitee = new Invitee();
$this->shareForm = $this->createForm(InviteeType::class, $invitee);
$this->shareForm->handleRequest($request);
if ($this->shareForm->isSubmitted() && $this->shareForm->isValid()) {
$purchase->addInvitee($invitee);
$doctrine->getManager()
->persist($purchase);
$doctrine->getManager()->flush();
$this->addFlash(
'success',
'You shared your ticket with '.$invitee->getEmail()
);
$this->purchaseHelper->sendSharedTickets($invitee);
}
return $this->redirectToRoute('feapp_home');
}
/**
* Returns a RedirectResponse to the given route with the given parameters.
*/
protected function redirectToRouteClearNoTicket(Request $request, string $route, array $parameters = [], int $status = 302): RedirectResponse
{
$response = new RedirectResponse($this->generateUrl($route, $parameters), $status);
if (!$request->cookies->has('no_ticket')) {
$response->headers->clearCookie('no_ticket');
}
return $response;
}
}