<?php
namespace App\Auction\Controller;
use App\Auction\Event\AuctionAttendEvent;
use App\Auction\Event\AuctionEvents;
use App\Auction\Form\Type\AuctionFilterType;
use App\Profile\Form\Type\ProfileAttendType;
use App\Profile\Model\Profile;
use App\Profile\Service\ProfileService;
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\Auction;
use Pimcore\Model\DataObject\Auctionlot;
use Pimcore\Model\DataObject\Profile as DataObjectProfile;
use Pimcore\Model\DataObject\TimelinePost;
use Pimcore\Translation\Translator;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Uid\Uuid;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class AuctionController extends FrontendController
{
#[Route('{_locale}/auction/{auction}/auctionlots', name: 'auction_auctionlots')]
public function auctionLots(Request $request, Auction $auction)
{
$order = $request->get('order', 'asc');
$orderKey = $request->get('orderKey', 'number + 0');
$limit = (int) $request->get('limit', 20);
$auctionlots = Auctionlot::getList();
$auctionlots->filterByAuction($auction);
$auctionlots->orderByHorseField($orderKey, $order);
$auctionlots->setLimit($limit);
return $this->render('auction/auction_auctionlots.html.twig', [
'auction' => $auction,
'auctionlots' => $auctionlots,
'limit' => $limit,
'order' => $order,
'orderKey' => $orderKey,
]);
}
/**
* List with auctions and filter.
*/
public function auctions(Request $request, PaginatorInterface $paginator)
{
$filter = $this->createForm(AuctionFilterType::class, [
'period' => $request->get('period', 'future'),
], ['method' => 'get']);
$filter->handleRequest($request);
$auctions = Auction::getList();
if ($filter->isSubmitted() && $filter->isValid()) {
$data = (object) $filter->getData();
$data->title ? $auctions->addConditionParam('title LIKE :title', ['title' => '%'.$data->title.'%']) : null;
$data->auctionhouse ? $auctions->addConditionParam('auctionhouse__id = :auctionhouse', ['auctionhouse' => $data->auctionhouse->getId()]) : null;
$data->type ? $auctions->addConditionParam('auctionType = :type', ['type' => $data->type]) : null;
$auctions->setOrderKey('end');
$data->period == 'past' ? $auctions->addConditionParam('end < :end', ['end' => Carbon::now()->format('Y-m-d')])->setOrder('desc') : null;
$data->period == 'future' ? $auctions->addConditionParam('end >= :end', ['end' => Carbon::now()->format('Y-m-d')])->setOrder('asc') : null;
} else {
$auctions->setOrder('asc');
$auctions->setOrderKey('end');
$auctions->addConditionParam('end >= :end', ['end' => Carbon::now()->format('Y-m-d')]);
}
$pagination = $paginator->paginate(
$auctions,
$request->get('page', 1),
10
);
$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 = "Auction" AND object_timelinepost.o_published = 1');
});
$timelineposts->setOrderKey('postedAt');
$timelineposts->setOrder('desc');
$timelineposts->setLimit(3);
// $posts->addConditionParam('ServiceTimelinePost.serviceCategory = ?', ['servicecategory.offer']);
return $this->renderForm('auction/list.html.twig', [
'pagination' => $pagination,
'filter' => $filter,
'timelineposts' => $timelineposts,
]);
}
#[Route('{_locale}/auction/{auctionId}/hovercard', name: 'auction_hovercard')]
public function hovercard(Request $request, $auctionId, 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());
$auction = Auction::getById($auctionId);
// if (!$user instanceof Profile && !$user instanceof DataObjectProfile) {
// throw new \Exception('user is not of type Profile');
// }
if ($user instanceof Profile || $user instanceof DataObjectProfile) {
$userIsAttending = $user && count(array_filter($auction->getAttendees(), fn ($v) => $v->getObjectId() == $user->getId())) > 0;
} else {
$userIsAttending = null;
}
$form = null;
if ($user && $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->attendEvent($user, $auction->getId());
$userIsAttending = true;
}
if ($form->getClickedButton() === $form->get('cancel')) {
$profileService->cancelAttendEvent($user, $auction->getId());
$userIsAttending = false;
}
return $this->renderForm('auction/hovercard_attend.html.twig', [
'uuid' => $hovercardUid,
'auction' => $auction,
'form' => $form,
'userIsAttending' => $userIsAttending,
]);
}
}
if (!$auction) {
throw $this->createNotFoundException("Auction with id {$auctionId} not found");
}
return $this->renderForm('auction/hovercard.html.twig', [
'uuid' => $hovercardUid,
'auction' => $auction,
'form' => $form,
'userIsAttending' => $userIsAttending,
]);
}
#[Route('{_locale}/auction/{auctionId}/attend', name: 'auction_attend')]
public function attend(Request $request, $auctionId, ProfileService $profileService, EventDispatcherInterface $eventDispatcher)
{
$user = $this->getUser();
$auction = Auction::getById($auctionId);
if (!$user instanceof Profile and !$user instanceof DataObjectProfile) {
throw new \Exception('user is not of type profile', 1);
}
$userIsAttending = $user && count(array_filter($auction->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->attendEvent($user, $auction->getId());
$event = new TimelinePostPublishedEvent($post);
$eventDispatcher->dispatch($event, TimelinePostEvents::PUBLISHED);
$event = new AuctionAttendEvent($auction, $user);
$eventDispatcher->dispatch($event, AuctionEvents::ATTEND);
return $this->render('auction/auction_attend_success.html.twig', [
'auction' => $auction,
'post' => $post,
'user' => $user,
'formObject' => $form,
'createPostForm' => false,
]);
} elseif ($form->getClickedButton() === $form->get('cancel')) {
$postId = $profileService->cancelAttendEvent($user, $auction->getId());
if ($postId) {
$event = new TimelinePostDeletedEvent($postId);
$eventDispatcher->dispatch($event, TimelinePostEvents::DELETED);
}
$event = new AuctionAttendEvent($auction, $user);
$eventDispatcher->dispatch($event, AuctionEvents::UNATTEND);
return $this->render('auction/auction_attend_cancel.html.twig', [
'auction' => $auction,
'postId' => $postId,
'user' => $user,
'formObject' => $form,
'createPostForm' => false,
]);
}
}
$response = $this->renderForm('auction/auction_attend.html.twig', [
'auction' => $auction,
'user' => $user,
'form' => $form,
'target' => $request->get('turbo_id'),
'userIsAttending' => $userIsAttending,
]);
return $response;
}
#[Route('{_locale}/auction/{auctionId}/attendees', name: 'auction_attendees')]
public function attendees(Request $request, $auctionId)
{
$auction = Auction::getById($auctionId);
$response = $this->renderTemplate('auction/auction_attendees.html.twig', [
'auction' => $auction,
]);
return $response;
}
}