<?php
/**
* Elements DeMI
*
* This source file is available under the elements DeMI license version 1
*
* @copyright Copyright (c) elements.at New Media Solutions GmbH (https://www.elements.at/)
* @license elements DeMI Lizenz Version 1 (https://www.elements.at/de/demi-lizenz)
*/
namespace Elements\Bundle\DemiFrontendBundle\Controller;
use Carbon\Carbon;
use DateTime;
use Elements\Bundle\CmsToolsBundle\Tool\Helper\ElementsCustomDateFormat;
use Elements\Bundle\DemiFrontendBundle\Service\DemiUrl;
use Elements\Demi\Frontend\Service\Configuration;
use Elements\Bundle\DemiFrontendBundle\Service\ConnectedEntryProvider;
use Elements\Demi\Frontend\Service\EventSearchFrontend;
use Elements\Demi\Frontend\Service\EventsHelper;
use Elements\Bundle\DemiFrontendBundle\Service\PaginatorHelper;
use Elements\Demi\Helper;
use Elements\Demi\Model\District;
use Elements\Demi\Model\Event;
use Elements\Demi\Model\Region;
use Elements\Demi\Model\Town;
use Pimcore\Model\DataObject;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\DataObject\DemiFacilityGroup;
use Pimcore\Model\DataObject\DemiFilterObject;
use Pimcore\Model\DataObject\DemiSerialEvent;
use Pimcore\Model\DataObject\Fieldcollection;
use Pimcore\Model\Document;
use Pimcore\Model\Document\Editable\Areablock;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\GoneHttpException;
use Symfony\Component\Routing\Annotation\Route;
class EventsController extends AbstractDemiController
{
protected bool $isArchive = false;
public function __construct(protected EventSearchFrontend $searchParams,
protected EventsHelper $eventsHelper,
protected ConnectedEntryProvider $connectedEntryProvider,
ElementsCustomDateFormat $elementsCustomDateFormat,
protected PaginatorHelper $paginatorHelper,
Configuration $configuration,
protected DemiUrl $demiUrl)
{
$this->setConfiguration($configuration);
$this->setElementsCustomDateFormat($elementsCustomDateFormat);
}
/**
* @Route ("{path}/eventlist")
*/
public function overviewAction(Request $request): Response
{
$this->addResponseHeader('X-Robots-Tag', 'noindex,nofollow');
$viewParams['isAjax'] = $request->isXmlHttpRequest();
$editablePrefix = $this->findEditablePrefix($this->document);
$this->setParams($request, $editablePrefix);
$this->searchParams->setLocale($request->getLocale());
$this->eventsHelper->applyCustomFilters($this->searchParams, $request);
$this->eventsHelper->applyCustomSorting($this->searchParams, $request);
$this->searchParams->setVisibility($this->document->getEditable($editablePrefix . 'event-visibility')?->getData() ?? [] );
$searchParams = $this->searchParams->getObjectListing();
$editable = $this->document->getEditable($editablePrefix . 'perPage');
$perPage = $editable ? $editable->getData() : 12;
$editable = $this->document->getEditable($editablePrefix.'layout');
$predefinedTemplate = $editable ? $editable->getData() : 'undefined';
$fallbackLayout = $this->configuration->getEventsLayout();
$useTemplate = null;
if ($predefinedTemplate !== 'undefined') {
$useTemplate = $predefinedTemplate;
}
if ($useTemplate === null) {
$useTemplate = $fallbackLayout;
}
if ($request->get('nopaging')) {
$paginator = $this->paginatorHelper->getPaginator($searchParams, -1);
$paginator->setItemNumberPerPage(-1);
} else {
$paginator = $this->paginatorHelper->getPaginator($searchParams, $perPage, (int)$request->get('page',1));
}
$viewParams["paginator"] = $paginator;
$viewParams['eventNoResultText'] = $this->configuration->getEventNoResultText($request->getLocale());
$viewParams['teaserTemplate'] = "@ElementsDemiFrontend/Events/includes/teaser-$useTemplate.html.twig";
$viewParams['fallbackLayout'] = $fallbackLayout;
$viewParams['useTemplate'] = $useTemplate;
$viewParams['isTeaserGrid'] = false;
if ($request->headers->get('format') === 'json') {
$response = [
'status' => 'success',
'html' => $this->renderTemplate('@ElementsDemiFrontend/Events/event-result.html.twig', $viewParams)->getContent()
];
return $this->json($response);
}
return $this->renderTemplate('@ElementsDemiFrontend/Events/event-result.html.twig', $viewParams);
}
protected function setParams(Request $request, string $editablePrefix): void
{
$propagateRecurrent = $this->document->getEditable($editablePrefix. 'propagateRecurrent');
$this->searchParams->setPropagateRecurrent(!empty($propagateRecurrent) && !$propagateRecurrent->isEmpty() && $propagateRecurrent->isChecked());
$editable = $this->document->getEditable($editablePrefix. 'regions');
$predRegions = $editable ? $editable->getData() : null;
$reqregions = $request->get('region');
if (Helper::checkIfParamIsEmpty($reqregions)) {
$regions = [];
if (is_array($reqregions)) {
foreach ($reqregions as $region) {
$obj = AbstractObject::getById($region);
if ($obj instanceof DemiFilterObject) {
$regions = array_merge($regions, $obj->getFilterElements());
} else {
$regions[] = $region;
}
}
} else {
$obj = AbstractObject::getById($reqregions);
if ($obj instanceof DemiFilterObject) {
$regions = array_merge($regions, $obj->getFilterElements());
} else {
$regions[] = (int)$reqregions;
}
}
$this->searchParams->setRegionsToTowns($regions);
} elseif (!empty($predRegions)) {
$townIds = $districtIds = [];
foreach ($predRegions as $region) {
if ($region instanceof DemiFilterObject) {
foreach ($region->getFilterElements() as $filterElement) {
if ($filterElement instanceof Region) {
foreach ($filterElement->getChildren() as $town) {
$townIds[] = $town->getId();
}
} elseif ($filterElement instanceof Town) {
$townIds[] = $filterElement->getId();
} elseif ($filterElement instanceof District) {
$districtIds[] = $filterElement->getId();
}
}
} elseif ($region instanceof Region) {
foreach ($region->getChildren() as $town) {
$townIds[] = $town->getId();
}
} elseif ($region instanceof Town) {
$townIds[] = $region->getId();
} elseif ($region instanceof District) {
$districtIds[] = $region->getId();
}
}
$allRegionFilterIds = array_unique(array_merge($townIds, $districtIds));
$this->searchParams->setRegionsToTowns($allRegionFilterIds);
}
$editable = $this->document->getEditable($editablePrefix. 'holidayThemes');
$predefinedHolidayThemes = $editable ? $editable->getData() : null;
$reqThemes = $request->get('holidaytheme');
if (!empty($reqThemes) && !empty(current($reqThemes))) {
$themes = [];
if (is_array($reqThemes)) {
foreach ($reqThemes as $reqTheme) {
$obj = AbstractObject::getById($reqTheme);
if ($obj instanceof DemiFilterObject) {
$themes = array_merge($themes, $obj->getFilterElements());
} else {
$themes[] = $reqTheme;
}
}
} else {
$obj = AbstractObject::getById($reqThemes);
if ($obj instanceof DemiFilterObject) {
$themes = array_merge($themes, $obj->getFilterElements());
} else {
$themes[] = (int)$reqThemes;
}
}
$this->searchParams->setHolidayThemes($themes);
} elseif (!empty($predefinedHolidayThemes)) {
$themes = [];
if (is_array($predefinedHolidayThemes)) {
foreach ($predefinedHolidayThemes as $predTheme) {
$obj = AbstractObject::getById($predTheme);
if ($obj instanceof DemiFilterObject) {
$themes = array_merge($themes, $obj->getFilterElements());
} else {
$themes[] = $predTheme;
}
}
}
$this->searchParams->setHolidayThemes($themes);
}
$editable = $this->document->getEditable($editablePrefix . 'category');
$predefinedCategories = $editable ? $editable->getData() : null;
$reqcats = $request->get('category');
if (Helper::checkIfParamIsEmpty($reqcats)) {
if (!is_array($reqcats)) {
$catobj = AbstractObject::getById($reqcats);
if ($catobj instanceof DemiFacilityGroup) {
$this->searchParams->setFacility([$request->get('category')]);
} elseif ($catobj instanceof DemiSerialEvent) {
$this->searchParams->addSerialEvent($reqcats);
}
} else {
$catobj = AbstractObject::getById($reqcats[0]);
if ($catobj instanceof DemiFacilityGroup) {
$this->searchParams->setFacility($reqcats);
} elseif ($catobj instanceof DemiSerialEvent) {
$this->searchParams->addSerialEvent($reqcats);
}
}
} elseif ($predefinedCategories) {
$catobj = AbstractObject::getById($predefinedCategories[0]);
if ($catobj instanceof DemiFacilityGroup) {
$this->searchParams->setFacility($predefinedCategories);
} elseif ($catobj instanceof DemiSerialEvent) {
$this->searchParams->setSerialEvents($predefinedCategories);
}
}
//TODO: Add hidden Flag in Editmode for EventArchive
if ($request->get('archive')) {
$this->searchParams->setArchive(true);
$this->searchParams->setPropagateRecurrent(false);
} else {
$datefrom = new Carbon();
if ($from = $request->get('from')) {
$this->searchParams->setFromDate($from);
} else {
$this->searchParams->setFromDate($datefrom->toIso8601String());
}
$predefinedRangeTo = $this->document->getEditable($editablePrefix. 'rangeTo');
if ($to = $request->get('to')) {
$this->searchParams->setToDate($to);
} elseif ($predefinedRangeTo instanceof Document\Editable\Select && !$predefinedRangeTo->isEmpty()) {
$to = $this->searchParams->getFromDate()->clone();
$to = match ($predefinedRangeTo->getData()) {
'oneweek' => $to->addWeek(),
'onemonth' => $to->addMonth(),
'threemonths' => $to->addMonths(3),
'sixmonths' => $to->addMonths(6),
default => $to->addYear(),
};
$dateEndString = $this->elementsCustomDateFormat->dateToString($to);
$this->searchParams->setToDate($dateEndString);
} else {
$datefrom = new Carbon();
$to = $datefrom->copy()->addYear();
$this->searchParams->setToDate($to->toIso8601String());
}
}
if ($this->configuration->getContentScoreFilterEvent() > 0) {
$this->searchParams->setContentScore($this->configuration->getContentScoreFilterEvent());
}
$predefinedTopEventsOnly = $this->document->getEditable($editablePrefix.'top-events-only');
$predefinedTopEventsUpfront = $this->document->getEditable($editablePrefix.'put-topevents-upfront');
if ($topEvents = $request->get('top-events')) {
$this->searchParams->setTopEventsOnly($topEvents);
} elseif ($predefinedTopEventsOnly instanceof Document\Editable\Checkbox && $predefinedTopEventsOnly->isChecked()) {
$this->searchParams->setTopEventsOnly(true);
}
if ($predefinedTopEventsUpfront instanceof Document\Editable\Checkbox && $predefinedTopEventsUpfront->isChecked()) {
$this->searchParams->setTopEventsUpfront(true);
}
if ($keyword = $request->get('keyword')) {
$this->searchParams->setFullText($keyword);
}
}
public function detailAction(Request $request) : Response
{
$object = Event::getById((int)($request->get('id')));
if (!$object) {
throw new GoneHttpException("the requested object doesn't exist anymore");
}
if($object && !$object->isPublished() && $object->getProperty('feratelId')){
return $this->forward(self::class. '::redirectViaFeratelIdProperty', [
'request' => $request,
'object' => $object,
'demiUrl' => $this->demiUrl
]);
} elseif ($object && !$object->isPublished() && $this->document->getProperty('demi_config') && $this->document->getProperty('demi_config')->getFullPath() == "/deskline/config/Graz"){
//redirect to event overview - only for Graz
return $this->redirect($this->configuration->getEventDetailPath(), 301);
}
if (!isset($_COOKIE['pimcore_admin_sid']) && !$this->editmode && !$object->isPublished() && !$request->get('pimcore_object_preview')) {
return $this->forward(self::class. '::unavailableAction', [
'request' => $request,
'unavailableType' => 'event'
]);
}
if ($object->getDateEnd()) {
$endDate = (Carbon::createFromTimestamp($object->getDateEnd()->getTimestamp())->endOfDay());
$this->addResponseHeader('X-Robots-Tag', 'unavailable_after: ' . $endDate);
} elseif ($object->getRecurringDates() instanceof Fieldcollection) {
$endDate = null;
foreach ($object->getRecurringDates()->getItems() as $dates) {
if (!$endDate instanceof Carbon || $endDate->lt($dates->getDateTo())) {
$endDate = $dates->getDateTo();
}
}
if ($endDate) {
$endDateString = (Carbon::createFromTimestamp($endDate->getTimestamp())->endOfDay())->toRfc850String();
$this->addResponseHeader('X-Robots-Tag', 'unavailable_after: ' . $endDateString);
}
}
return $this->renderTemplate("@ElementsDemiFrontend/Events/detail.html.twig", [
'event' => $object,
'connectedEntries' => $this->connectedEntryProvider->getConnectedEntriesForEvent($object, $request),
'endDate' => $endDate ?? null,
]);
}
protected function findEditablePrefix(Document $document): string
{
if ($document->getEditables() !== null) {
$areaBlock = current(array_filter($document->getEditables(), static function ($editable) {
return $editable instanceof Areablock;
}));
if ($areaBlock !== null && !empty($areaBlock->getIndices())) {
$correctIndex = array_filter($areaBlock->getIndices(), function ($index) {
if ($index['type'] === 'demi-event-archive') {
$this->isArchive = true;
return true;
}
return $index['type'] === 'demi-event-list' ||
$index['type'] === 'demi-event-teaser-grid';
});
return $areaBlock->getName() . ':' . current($correctIndex)['key'] . '.';
}
}
// Fallback for overriden documents
if ($document->getContentMasterDocument() !== null) {
return $this->findEditablePrefix($document->getContentMasterDocument());
}
return '';
}
}