<?php
namespace App\Race\Controller;
use App\Profile\Form\Type\ProfileAttendType;
use App\Profile\Model\Profile as ModelProfile;
use App\Profile\Service\ProfileService;
use App\Race\Event\RaceAttendEvent;
use App\Race\Event\RaceEvents;
use App\Race\Form\Type\RaceFilterType;
use App\Race\Manager\RaceManager;
use App\Timeline\Event\TimelinePostDeletedEvent;
use App\Timeline\Event\TimelinePostEvents;
use App\Timeline\Event\TimelinePostPublishedEvent;
use Carbon\Carbon;
use Doctrine\DBAL\Query\QueryBuilder;
use Knp\Component\Pager\PaginatorInterface;
use Pimcore\Controller\FrontendController;
use Pimcore\Model\DataObject\Folder;
use Pimcore\Model\DataObject\Profile;
use Pimcore\Model\DataObject\Race;
use Pimcore\Model\DataObject\Raceday;
use Pimcore\Model\DataObject\TimelinePost;
use Pimcore\Translation\Translator;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Uid\Uuid;
use Symfony\Contracts\Translation\TranslatorInterface;
class RaceController extends FrontendController
{
/**
* List with race and filter...
*/
public function races(Request $request, PaginatorInterface $paginator)
{
$period = $request->get('period', 'future');
$country = $request->get('country', null);
$page = $request->get('page', 1);
$filter = $this->createForm(RaceFilterType::class, [
'period' => $period,
'country' => $country,
], ['method' => 'get']);
$filter->handleRequest($request);
// $raceDays = new \App\Raceday\Model\Listing();
$raceDays = Raceday::getList();
// $sql = $raceDays->addConditionParam('object_race.start >= :now', ['now' => Carbon::now()->format('Y-m-d')]);
$raceDays->addConditionParam('date >= :now', ['now' => Carbon::now()->format('Y-m-d')]);
$raceDays->setOrderKey('date', false);
$maxItemsPerPage = 10;
if ($filter->isSubmitted() && $filter->isValid()) {
$data = (object) $filter->getData();
$raceDays = Raceday::getList();
$raceDays->setOrderKey('date', false);
// if ($data->pricemoney) {
// $raceDays->addConditionParam('pricemoney LIKE :pricemoney', ['pricemoney' => $data->pricemoney]);
// }
$raceDays->onCreateQueryBuilder(
function (QueryBuilder $queryBuilder) use ($data) {
$queryBuilder->rightJoin('object_raceday', 'object_brick_query_RacetrackProfile_profile', 'racingtrack', 'object_raceday.racingtrack__id = racingtrack.o_id');
$queryBuilder->rightJoin('object_raceday', 'object_profile', 'profile', 'object_raceday.racingtrack__id = profile.oo_id');
if ($data->direction) {
$queryBuilder->andWhere('racingtrack.direction = "'.$data->direction.'"');
}
if ($data->surface) {
$queryBuilder->andWhere('racingtrack.surface = "'.$data->surface.'"');
}
if ($data->country) {
$queryBuilder->andWhere('profile.country = "'.$data->country.'"');
}
}
);
// if ($data->surface) {
// $raceDays->addConditionParam('surface = :surface', ['surface' => $data->surface]);
// }
// if ($data->direction) {
// $raceDays->addConditionParam('direction = :direction', ['direction' => $data->direction]);
// }
// if ($data->country) {
// $raceDays->addConditionParam('country = :country', ['country' => $data->country]);
// }
if ($data->racingtrack) {
$raceDays->addConditionParam('racingtrack__id = :id', ['id' => $data->racingtrack->getId()]);
}
if ($data->period) {
$raceDays->addConditionParam('date'.($data->period == 'future' ? '>=' : '<').' :now', ['now' => Carbon::now()->format('Y-m-d')]);
// $raceDays->addConditionParam('date '.($data->period == 'future' ? '>=' : '<').' :now', ['now' => Carbon::now()->format('Y-m-d')]);
$data->period == 'past' ? $raceDays->setOrder('desc') : null;
$data->period == 'future' ? $raceDays->setOrder('asc') : null;
}
// dd($raceDays);
$pagination = $paginator->paginate(
$raceDays,
$page,
$maxItemsPerPage
);
if (!$pagination->getItems() and $pagination->getTotalItemCount() > 0) {
$documentPath = $this->document->getFullPath();
$redirectUrl = $documentPath.'?'.http_build_query(array_merge((array) $data, ['page' => 1]));
return $this->redirect($redirectUrl);
}
$pagination = $paginator->paginate(
$raceDays,
$page,
$maxItemsPerPage
);
if (!$pagination->getItems() and $pagination->getTotalItemCount() > 0) {
$documentPath = $this->document->getFullPath();
$redirectUrl = $documentPath.'?'.http_build_query(array_merge((array) $data, ['page' => 1]));
return $this->redirect($redirectUrl);
}
}
$pagination = $paginator->paginate(
$raceDays,
$page,
$maxItemsPerPage
);
if (!$pagination->getItems()) {
$pagination->setCurrentPageNumber(1);
}
$timelineposts = TimelinePost::getList();
$timelineposts->onCreateQueryBuilder(function (QueryBuilder $queryBuilder) {
$queryBuilder->leftJoin('object_timelinepost', 'object_relations_timelinepost', 'relation', 'relation.src_id = object_timelinepost.oo_id AND relation.fieldname = "showPostAt"');
$queryBuilder->leftJoin('object_timelinepost', 'objects', 'auctions', 'auctions.o_id = relation.dest_id');
$queryBuilder->where('auctions.o_className = "Race" AND object_timelinepost.o_published = 1');
});
$timelineposts->setOrderKey('postedAt');
$timelineposts->setOrder('desc');
$timelineposts->setLimit(3);
return $this->renderTemplate('race/list.html.twig', [
'pagination' => $pagination,
'racedays' => $raceDays,
'now' => Carbon::now(),
'filter' => $filter->createView(),
'timelineposts' => $timelineposts,
]);
}
/**
* Race List.
*
* @return Response
*/
public function race(Request $request, RaceManager $raceManager)
{
$filter = $request->get('filter');
$folder = Folder::getById($request->get('id'))->getFullPath();
$limit = $request->get('limit');
$days = Race::getList();
$days->setCondition('object_race.o_path LIKE :folder', ['folder' => $folder.'%']);
$days->addConditionParam('start >= :now', ['now' => Carbon::now()->format('Y-m-d')]);
$days->setOrderKey('start');
$days->setOrder('asc');
if ($limit) {
$days->setLimit($limit);
} else {
$days->setLimit(3);
}
$days->onCreateQueryBuilder(
function (QueryBuilder $queryBuilder) use ($filter) {
$queryBuilder->join('object_race', 'object_racingtrack', 'racingtrack', 'object_race.racingtrack__id = racingtrack.oo_id');
if ($filter && $filter != []) {
$queryBuilder->andWhere('racingtrack.country = "'.$filter.'"');
}
$queryBuilder->groupBy(['DATE(start)', 'racingtrack__id']);
}
);
$days = $days->load();
// $days->setCondition('o_path LIKE :folder', ['folder' => '%'.$folder.'%']);
// $db = \Pimcore\Db::get();
// $days = $db->fetchAll('SELECT *
// FROM object_race
// Right Join object_racingtrack on object_race.racingtrack__id = object_racingtrack.oo_id
// Where object_racingtrack.country = :filter AND object_race.o_path LIKE :folder AND start >= :now
// GROUP BY start
// ORDER BY start ASC
// ',
// ['filter' => $filter, 'folder' => '%'.$folder.'%', 'now' => Carbon::now()->format('Y-m-d')]);
$racedays = [];
foreach ($days as $day) {
$races = $raceManager->getRacesByDayAndRacingtrack($day->getStart(), $day->getRacingtrack());
$races->setCondition('o_path LIKE :folder', ['folder' => $folder.'%']);
$races->addConditionParam('start >= :now', ['now' => Carbon::now()->format('Y-m-d')]);
$racedays[] = [
'day' => $day,
'races' => $races->load(),
];
}
// Erweitere Renntage um iFrame Angabe der Rennen
$racedays = array_map(function ($raceday) {
$iframe = null;
foreach ($raceday['races'] as $race) {
if (!$race->getIFrame()) {
continue;
}
$iframe = $race->getIframe();
}
return [
'day' => $raceday['day'],
'races' => $raceday['races'],
'iframe' => $iframe,
];
}, $racedays);
$elfsight = null;
if (array_key_exists('elfsight', $request->attributes->all())) {
$elfsight = $request->attributes->all()['elfsight'];
}
return $this->renderTemplate('document/areabricks/races/listing.html.twig', [
'racedays' => $racedays,
'elfsight' => $elfsight,
]);
}
/**
* Hovercard for Race.
*
* @param int $raceId
*
* @Route("/race/{raceId}/hovercard",name="race_hovercard")
*/
public function hovercard(Request $request, $raceId, TranslatorInterface $translator, ProfileService $profileService)
{
$hovercardUid = Uuid::v4();
$user = $this->getUser();
$request->setLocale($request->get('_locale', 'en'));
if (!$translator instanceof Translator) {
throw new \Exception('wrong translator service', 1);
}
$translator->setLocale($request->getLocale());
$race = Race::getById($raceId);
// if (!$user instanceof Profile) {
// throw new \Exception('user is not of type profile', 1);
// }
if ($user instanceof Profile || $user instanceof ModelProfile) {
$userIsAttending = count(array_filter($race->getAttendees(), fn ($v) => $v->getObjectId() == $user->getId())) > 0;
} else {
$userIsAttending = null;
}
$form = null;
if ($user and $user instanceof Profile) {
$form = $this->createForm(ProfileAttendType::class, [
'userId' => $user->getId(),
'uuid' => $hovercardUid,
], [
'method' => 'POST',
'csrf_protection' => false,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$hovercardUid = $form->get('uuid')->getData();
if (!$form instanceof Form) {
throw new \Exception('field is not of type form');
}
if ($form->getClickedButton() === $form->get('attend')) {
$profileService->attendRace($user, $race->getId());
$userIsAttending = true;
}
if ($form->getClickedButton() === $form->get('cancel')) {
$profileService->cancelAttendRace($user, $race->getId());
$userIsAttending = false;
}
return $this->renderForm('race/hovercard_attend.html.twig', [
'uuid' => $hovercardUid,
'race' => $race,
'form' => $form,
'userIsAttending' => $userIsAttending,
]);
}
}
if (!$race) {
throw $this->createNotFoundException("Race with id {$raceId} not found");
}
return $this->renderForm('race/hovercard.html.twig', [
'uuid' => $hovercardUid,
'race' => $race,
'form' => $form,
'userIsAttending' => $userIsAttending,
]);
}
#[Route('{_locale}/race/{raceId}/attend', name: 'race_attend')]
public function attend(Request $request, $raceId, ProfileService $profileService, EventDispatcherInterface $eventDispatcher)
{
$user = $this->getUser();
$race = Race::getById($raceId);
if (!$user instanceof Profile and !$user instanceof ModelProfile) {
throw new \Exception('user is not of type profile', 1);
}
$userIsAttending = count(array_filter($race->getAttendees(), fn ($v) => $v->getObjectId() == $user->getId())) > 0;
$form = $this->createForm(ProfileAttendType::class, [
'userId' => $user->getId(),
], [
'method' => 'POST',
'csrf_protection' => false,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if (!$form instanceof Form) {
throw new \Exception('field is not of type form');
}
if ($form->getClickedButton() === $form->get('attend')) {
$post = $profileService->attendRace($user, $race->getId());
$event = new TimelinePostPublishedEvent($post);
$eventDispatcher->dispatch($event, TimelinePostEvents::PUBLISHED);
$event = new RaceAttendEvent($race, $user);
$eventDispatcher->dispatch($event, RaceEvents::ATTEND);
return $this->renderForm('race/race_attend_success.html.twig', [
'race' => $race,
'post' => $post,
'user' => $user,
'form' => $form,
'createPostForm' => false,
]);
} elseif ($form->getClickedButton() === $form->get('cancel')) {
$postId = $profileService->cancelAttendRace($user, $race->getId());
if ($postId) {
$event = new TimelinePostDeletedEvent($postId);
$eventDispatcher->dispatch($event, TimelinePostEvents::DELETED);
}
$event = new RaceAttendEvent($race, $user);
$eventDispatcher->dispatch($event, RaceEvents::UNATTEND);
return $this->renderForm('race/race_attend_cancel.html.twig', [
'race' => $race,
'postId' => $postId,
'user' => $user,
'form' => $form,
'createPostForm' => false,
]);
}
}
$response = $this->renderForm('race/race_attend.html.twig', [
'race' => $race,
'user' => $user,
'form' => $form,
'userIsAttending' => $userIsAttending,
]);
return $response;
}
#[Route('{_locale}/race/{raceId}/attendees', name: 'race_attendees')]
public function attendees(Request $request, $raceId)
{
$race = Race::getById($raceId);
$response = $this->renderTemplate('race/race_attendees.html.twig', [
'race' => $race,
]);
return $response;
}
}