<?php
namespace Bidcoz\Bundle\FrontendBundle\Controller;
use Bidcoz\Bundle\CoreBundle\Controller\CoreController;
use Bidcoz\Bundle\CoreBundle\Entity\Campaign;
use Bidcoz\Bundle\CoreBundle\Entity\Organization;
use Bidcoz\Bundle\CoreBundle\Entity\Proxy\Contact;
use Bidcoz\Bundle\CoreBundle\Entity\Proxy\MultipleTicketPurchaseProxy;
use Bidcoz\Bundle\CoreBundle\Entity\Proxy\TicketPurchaseProxy;
use Bidcoz\Bundle\CoreBundle\Entity\Ticket\TicketType;
use Bidcoz\Bundle\FrontendBundle\Form\Type\MultipleTicketPurchaseType;
use Bidcoz\Bundle\FrontendBundle\Form\Type\TicketPurchaseType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/{orgSlug}/{campaignSlug}/tickets")
* @IsGranted("VIEW", subject="organization")
* @IsGranted("FRONT_END", subject="campaign")
*/
class TicketController extends CoreController
{
/**
* @Route("/{ticketTypeIds}", defaults={"ticketTypeIds"=null}, name="campaign_tickets")
*/
public function ticketsAction(Request $request, Organization $organization, Campaign $campaign, ?string $ticketTypeIds)
{
if ($redirect = $this->ticketAvailibility($campaign)) {
return $redirect;
}
if ($ticketTypeIds && !$this->getUser()) {
$this->addFlash('info', 'Please login or create an account before purchasing a ticket.');
throw $this->createAccessDeniedException('Unable to access this page!');
}
$ticketTypes = $this->getRepository('Ticket\TicketType')->findCampaignTicketTypes($campaign);
$ticketsSold = $this->getTicketManager()->getCampaignTicketsSold($campaign);
$ticketsRemaining = $this->getTicketManager()->getTicketsRemaining($campaign);
$ticketTypeIdsList = $ticketTypeIds ? explode(',', $ticketTypeIds) : [];
$ticketTypesList = [];
$multipleTicketPurchaseProxy = new MultipleTicketPurchaseProxy();
foreach ($ticketTypeIdsList as $idx => $ticketTypeId) {
/** @var TicketType $ticketType */
$ticketType = $this->getRepository('Ticket\TicketType')->find($ticketTypeId);
if (!$ticketType) {
$this->addFlash('danger', sprintf('Ticket Level "%s" does not exist.', $ticketTypeId));
$ticketTypeIdsList = array_diff($ticketTypeIdsList, [$ticketTypeId]);
continue;
} elseif (!in_array($ticketType, $ticketTypes, true)) {
$this->addFlash('danger', sprintf('Ticket Level "%s" is not available for this campaign.', $ticketType->getName()));
$ticketTypeIdsList = array_diff($ticketTypeIdsList, [$ticketTypeId]);
continue;
} elseif ($this->getTicketExtension()->isTicketTypeSoldout($ticketType)) {
$this->addFlash('danger', sprintf('Ticket Level "%s" is already soldout.', $ticketType->getName()));
$ticketTypeIdsList = array_diff($ticketTypeIdsList, [$ticketTypeId]);
continue;
}
$proxy = $this->createTicketProxy($ticketType, $campaign, $idx);
$multipleTicketPurchaseProxy->addTicketPurchase($proxy);
$ticketTypesList[$idx] = $ticketType;
}
$formOptions = $this->getPurchaseTicketFormOptions($campaign);
$form = $this->getMultiplePurchaseTicketForm($multipleTicketPurchaseProxy, $formOptions);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if (!$this->getUser()) {
$this->addFlash('info', 'Please login or create an account before purchasing a ticket.');
throw $this->createAccessDeniedException('Unable to access this page!');
}
$user = $this->getUser();
/** @var MultipleTicketPurchaseProxy $data */
$data = $form->getData();
// Set the campaign on the contacts
foreach ($data->getTicketPurchases() as $ticketPurchase) {
array_map(function ($contact) use ($campaign) {
$contact->setCampaign($campaign);
}, $ticketPurchase->getContacts());
$this->getTicketManager()->createTicketPurchase($campaign, $user, $ticketPurchase);
}
$this->getEntityManager()->flush();
return $this->redirectToRoute('account_campaign_purchases', [
'orgSlug' => $organization->getSlug(),
'campaignSlug' => $campaign->getSlug(),
]);
}
return $this->render('@BidcozFrontend/Campaign/Tickets/index.html.twig', array_merge($formOptions, [
'organization' => $organization,
'campaign' => $campaign,
'ticketTypes' => $ticketTypes,
'ticketsSold' => $ticketsSold,
'ticketsRemaining' => $ticketsRemaining,
'ticketTypeIdsList' => $ticketTypeIdsList,
'ticketTypesList' => $ticketTypesList,
'form' => $form->createView(),
]));
}
/**
* @Route("/tickets/{ticketId}", name="campaign_ticket_view", methods={"GET"})
* @ParamConverter("ticketType", class="Bidcoz\Bundle\CoreBundle\Entity\Ticket\TicketType", options={"id" = "ticketId"})
*/
public function viewTicketAction(Organization $organization, Campaign $campaign, TicketType $ticketType)
{
if ($redirect = $this->ticketAvailibility($campaign)) {
return $redirect;
}
$user = $this->getUser();
if (!$user) {
$this->messageAccessDeniedException('You must login or create an account to purchase tickets.');
}
if ($this->getTicketExtension()->isTicketTypeSoldout($ticketType)) {
$this->addFlash('danger', sprintf('Ticket Level "%s" is already soldout.', $ticketType->getName()));
return $this->redirectToRoute('campaign_tickets', [
'orgSlug' => $organization->getSlug(),
'campaignSlug' => $campaign->getSlug(),
]);
}
$proxy = $this->createTicketProxy($ticketType, $campaign);
$formOptions = $this->getPurchaseTicketFormOptions($campaign);
$form = $this->getPurchaseTicketForm($proxy, $formOptions);
return $this->render('@BidcozFrontend/Campaign/Tickets/buy.html.twig', array_merge($formOptions, [
'organization' => $organization,
'campaign' => $campaign,
'ticketType' => $ticketType,
'form' => $form->createView(),
]));
}
protected function createTicketProxy(TicketType $ticketType, Campaign $campaign, ?int $idx = null)
{
$user = $this->getUser();
$questions = $this->getRepository('Ticket\TicketQuestion')->findCampaignTicketQuestions($campaign, true);
if ($ticketType->getQuestionsDoNotApply()) {
$questions = [];
}
$ticketQuestions = $ticketGroupQuestions = [];
foreach ($questions as $question) {
if ($question->isTicketGroupQuestion()) {
$ticketGroupQuestions[] = $question;
} else {
$ticketQuestions[] = $question;
}
}
$ticketGroupAnswers = array_map(function ($ticketQuestion) use ($user) {
$question = $ticketQuestion->getQuestion();
return $this->getQuestionManager()->createTicketGroupAnswer($question, $user);
}, $ticketGroupQuestions);
$proxy = new TicketPurchaseProxy($ticketType, $idx);
$contacts = [];
for ($x = 0; $x < $ticketType->getNumAdmissions(); ++$x) {
$ticketAnswers = array_map(function ($ticketQuestion) {
$question = $ticketQuestion->getQuestion();
return $this->getQuestionManager()->createTicketAnswerProxy($question);
}, $ticketQuestions);
$contact = new Contact();
$contact->setTicketAnswers($ticketAnswers);
if ($campaign->getOrganization()->isEnableCustomizations()) {
$contact->setEmail($user->getEmail());
$contact->setFirstName($user->getFirstName());
$contact->setLastName($user->getLastName());
}
$contacts[] = $contact;
}
$proxy->setContacts($contacts);
$proxy->setTicketGroupAnswers($ticketGroupAnswers);
return $proxy;
}
protected function getPurchaseTicketFormOptions(Campaign $campaign)
{
$ticketDiscounts = $this->getRepository('Discount\TicketTypeDiscount')->findAllForCampaign($campaign);
$hasActiveDiscountCode = count($ticketDiscounts) > 0;
return [
'campaign' => $campaign,
'show_discount_code' => $hasActiveDiscountCode,
];
}
protected function getPurchaseTicketForm(TicketPurchaseProxy $proxy, array $options)
{
return $this->createForm(TicketPurchaseType::class, $proxy, $options);
}
protected function getMultiplePurchaseTicketForm(MultipleTicketPurchaseProxy $multipleTicketPurchaseProxy, array $options)
{
return $this->createForm(MultipleTicketPurchaseType::class, $multipleTicketPurchaseProxy, $options);
}
protected function ticketAvailibility(Campaign $campaign)
{
if (!$this->getTicketManager()->areTicketsAvailable($campaign)) {
$this->addFlash('warning', 'Tickets are no longer available');
return $this->redirectToRoute('campaign_home', [
'orgSlug' => $campaign->getOrganization()->getSlug(),
'campaignSlug' => $campaign->getSlug(),
]);
}
}
}