<?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\Service;
use Carbon\Carbon;
use Elements\Bundle\CmsToolsBundle\Tool\Helper\ElementsCustomDateFormat;
use Elements\Demi\Model\AccommodationServiceProvider;
use Pimcore\Event\Traits\RequestAwareTrait;
use Pimcore\Http\Request\Resolver\DocumentResolver;
use Pimcore\Model\Document;
use stdClass;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Pimcore\Translation\Translator;
class DemiStateHelper
{
use RequestAwareTrait;
private array $sorting = [];
private array $search = [];
private array $searchForm = [];
private array $filter = [];
private array $accList = [];
private array $nearbySearch = [];
private bool $showMap;
private array $rooms = [
'occupancy' => [
'rooms' => [],
'type' => ''
]
];
protected bool $initialized;
protected ?Document $document = null;
public function __construct(protected RequestStack $requestStack, protected DocumentResolver $documentResolver, protected Translator $translator, protected ElementsCustomDateFormat $elementsCustomDateFormat)
{
$this->initialized = false;
}
protected function initOnce(): void
{
if ($this->requestStack->getMainRequest()) {
$this->request = $this->requestStack->getMainRequest();
$this->document = $this->request ? $this->documentResolver->getDocument($this->request) ?? $this->documentResolver->getDocument() : null;
$this->initialized = true;
// page
if ($this->request->get('page')) {
$this->setPage((int)$this->request->get('page'));
}
// From Timestamp -> JS timestamp
if ($this->request->get('from')) {
$this->setSearchFrom((string)$this->request->get('from'));
}
// To Timestamp -> JS timestamp
if ($this->request->get('to')) {
$this->setSearchTo((string)$this->request->get('to'));
}
// sort factory param
if ($this->request->get('sortFactoryParam')) {
$this->setSortFactoryParam($this->request->get('sortFactoryParam'));
}
// Duration Type like exact/variable
if ($this->request->get('durationType')) {
$this->setDurationType($this->request->get('durationType'));
}
// Duration Nights
if ($this->request->get('durationNights')) {
$this->setDurationNights($this->request->get('durationNights'));
}
// Room type like: double-room
if ($this->request->get('occupancyType')) {
$this->setOccupancyType($this->request->get('occupancyType'));
}
// Stars
if ($this->request->get('stars')) {
$this->setFilterArray('stars[]', $this->request->get('stars'));
}
// Classifications
if ($this->request->get('classifications')) {
$this->setFilterArray('classifications[]', $this->request->get('classifications'));
}
// Occupancy of Rooms
if ($this->request->get('a0')) {
$this->setRooms($this->request);
}
// towns
if ($this->request->get('towns')) {
$this->setFilterArray('towns[]', $this->request->get('towns'));
}
// regions
if ($this->request->get('regions')) {
$this->setFilterArray('regions[]', $this->request->get('regions'));
}
// districts
if ($this->request->get('districts')) {
$this->setFilterArray('districts[]', $this->request->get('districts'));
}
// Categories
if ($this->request->get('categories')) {
$this->setFilterArray('categories[]', $this->request->get('categories'));
}
// Holiday Themes
if ($this->request->get('holidayThemes')) {
$this->setFilterArray('holidayThemes[]', $this->request->get('holidayThemes'));
}
// Language
if ($this->request->get('language') && is_array($this->request->get('language'))) {
$this->setFilterArray('language[]', $this->request->get('language'));
}
// AccommodationType
if (!empty($this->request->get('type')) && $this->request->get('type')) {
$this->setFilterArray('type[]', $this->request->get('type'));
}
// AccommodationFacilities
if ($this->request->get('facilities')) {
$this->setFilterArray('facilities[]', $this->request->get('facilities'));
}
// RoomFacilities
if ($this->request->get('roomFacilities')) {
$this->setFilterArray('roomFacilities[]', $this->request->get('roomFacilities'));
}
// Facilities
if ($this->request->get('apartmentFacilities')) {
$this->setFilterArray('apartmentFacilities[]', $this->request->get('apartmentFacilities'));
}
// Mealtypes
if ($this->request->get('mealtype')) {
$this->setFilter('mealtype', $this->request->get('mealtype'));
}
// Marketing Groups
if ($this->request->get('marketingGroups')) {
$this->setFilterArray('marketingGroups[]', $this->request->get('marketingGroups'));
}
// Book Only
if ($this->request->get('bookonly')) {
$this->setFilter('bookonly', $this->request->get('bookonly'));
}
//Not Book ONly
if ($this->request->get('notBookOnly')) {
$this->setFilter('notBookOnly', $this->request->get('notBookOnly'));
}
//Free Cancellation
if ($this->request->get('freeCancellation')) {
$this->setFilter('freeCancellation', $this->request->get('freeCancellation'));
}
// Best price Provider
if ($this->request->get('bestPriceProvider')) {
$this->setFilter('bestPriceProvider', $this->request->get('bestPriceProvider'));
}
// Best price
if ($this->request->get('bestpriceOnly')) {
$this->setFilter('bestpriceOnly', $this->request->get('bestpriceOnly'));
}
//Price
if ($this->request->get('price') && !is_array($this->request->get('price'))) {
$this->setFilter('price', $this->request->get('price'));
}
// Accommodation name
if ($this->request->get('acconame')) {
$this->setFilter('acconame', $this->request->get('acconame'));
}
//Accommodation id
if ($this->request->get('accoId')) {
$this->addHotel($this->request);
}
// Special Types
if ($this->request->get('specialTypes')) {
$this->setFilterArray('specialTypes[]', $this->request->get('specialTypes'));
}
// Specials Only
if ($this->request->get('specialsOnly')) {
$this->setFilter('specialsOnly', $this->request->get('specialsOnly'));
}
// Sales Channel (hidden filter)
if ($this->request->get('salesChannel')) {
$this->setFilter('salesChannel', $this->request->get('salesChannel'));
}
// Filter Objects
if ($this->request->get('fo')) {
$this->setFilterArray('fo[]', $this->request->get('fo'));
}
// Mapped Filter Objects
if ($this->request->get('mfo')) {
$this->setFilterArray('mfo[]', $this->request->get('mfo'));
}
// Sorting
if ($this->request->get('sorting')) {
$this->setSorting($this->request->get('sorting'));
}
// Nearby Search
if ($this->request->get('nearbySearchId')) {
$this->setNearbySearch($this->request->get('nearbySearchId'), $this->request->get('nearbySearchLat'), $this->request->get('nearbySearchLong'));
}
// AccommodationType
if ($this->request->get('atsc')) {
$this->setFilter('atsc', $this->request->get('atsc'));
}
//Bedrooms
if ($this->request->get('minBed')) {
$this->setFilter('minBed', $this->request->get('minBed'));
}
// Show Map
if (!is_null($this->request->get('showMap'))) {
$this->setShowMap($this->request->get('showMap'));
} elseif ($this->document && $this->document->getEditable('hideMapInitially')) {
$hideMap = $this->document->getEditable('hideMapInitially')->getData();
$this->setShowMap(!$hideMap);
} else {
$this->setShowMap(true);
}
}
}
public function addHotel(Request $request): void
{
$accoIds = $request->get('accoId', []);
foreach ($accoIds as $hotelId) {
$hotelObj = AccommodationServiceProvider::getById(htmlspecialchars($hotelId));
$this->filter[] = [
'name' => 'accoId[]',
'value' => $hotelObj?->getId(),
'text' => $hotelObj?->getName()
];
}
}
private function setFilterArray(string $name, mixed $filter): void
{
if (is_array($filter)) {
foreach ($filter as $star) {
$this->filter[] = [
'name' => $name,
'value' => htmlspecialchars($star),
];
}
}
}
private function setFilter(string $name, string $value): void
{
$value = htmlspecialchars($value);
if ($name !== '' && $value !== '') {
$this->filter[] = [
'name' => $name,
'value' => $value,
];
}
}
private function setNearbySearch(string $id, string|null $lat, string|null $long): void
{
if($lat == null || $long == null){
//do nothing if lat/lon is missing
return;
}
$lat = htmlspecialchars($lat);
$long = htmlspecialchars($long);
$name = $this->translator->trans('demi.search.nearby.my-location');
if(is_integer($id)){
$obj = AbstractObject::getById((int)$id);
if($obj){
$name=$obj->getName();
}
}
if ($id !== '' && $lat !== '' && $long !== '') {
$this->nearbySearch = [
'nearbySearchId' => $id,
'nearbySearchName' => $name,
'nearbySearchLat' => $lat,
'nearbySearchLong' => $long,
];
}
}
private function setSorting(string $value): void
{
$value = htmlspecialchars($value);
$this->sorting = [
'value' => $value,
'asc' => !strpos($value, 'Desc') || strpos($value, 'Asc'),
'field' => str_replace(['Desc', 'Asc'], '', $value),
];
}
private function setShowMap(bool $value): void
{
$this->showMap = $value;
}
/**
* Set Rooms / Adults / Children for Search
*/
private function setRooms(Request $request): void
{
$maxRooms = 100;
$roomArray = $this->getRooms();
// iterate rooms (til 100)
for ($roomNumber = 0; $roomNumber <= $maxRooms; $roomNumber++) {
if ($request->get('a' . $roomNumber, false) !== false) {
// iterate children
$childAgesArray = [];
$maxAges = (int)$request->get('c' . $roomNumber, 0);
for ($childAge = 0; $childAge < $maxAges; $childAge++) {
$age = $request->get('ca' . $roomNumber)[$childAge];
if(!empty($age) || $age === "0"){
$childAgesArray[] = htmlspecialchars($age);
} else {
//faulty parameters - no matching child age found. Don't allow $childAgesArray to be filled with empty string
}
}
// fill roomArray
$roomArray['occupancy']['rooms'][$roomNumber] = [
'adults' => (int)$request->get('a' . $roomNumber),
'childAges' => $childAgesArray,
'quantity' => (int)$request->get('u' . $roomNumber),
];
} else {
break;
}
}
$this->rooms = $roomArray;
}
public function getRooms(): array
{
if (!$this->initialized) {
$this->initOnce();
}
$this->rooms['occupancy']['type'] = $this->getOccupancyType();
return $this->rooms;
}
public function getOccupancyType()
{
if (!$this->initialized) {
$this->initOnce();
}
return $this->search['occupancyType'] ?? '' ;
}
private function setPage(int $page): void
{
$this->accList['page'] = htmlspecialchars($page);
}
private function setSearchFrom(string $timestring): void
{
$this->search['from'] = htmlspecialchars($timestring);
}
public function getSearchFrom(): Carbon
{
if (!$this->initialized) {
$this->initOnce();
}
if (isset($this->search['from'])) {
return $this->elementsCustomDateFormat->stringToCarbon($this->search['from']);
}
return Carbon::now();
}
private function setSearchTo(string $timestring): void
{
$this->search['to'] = htmlspecialchars($timestring);
}
private function setSortFactoryParam(string $sortFactoryParam): void
{
$this->search['sortFactoryParam'] = htmlspecialchars($sortFactoryParam);
}
public function getSearchTo(): Carbon
{
if (!$this->initialized) {
$this->initOnce();
}
if (isset($this->search['to'])) {
return $this->elementsCustomDateFormat->stringToCarbon($this->search['to']);
}
return Carbon::now()->addDays(7);
}
private function setDurationType(string $durationType): void
{
$this->search['durationType'] = htmlspecialchars($durationType);
}
private function setDurationNights(string $durationNights): void
{
$this->search['durationNights'] = htmlspecialchars($durationNights);
}
private function setOccupancyType(string $occupancyType): void
{
$this->search['occupancyType'] = htmlspecialchars($occupancyType);
}
public function getSearchArray(): array
{
if (!$this->initialized) {
$this->initOnce();
}
$stateArray = [];
$stateArray['search'] = empty($this->search) ? new stdClass() : $this->search;
$stateArray['searchForm'] = empty($this->searchForm) ? new stdClass() : $this->searchForm ;
$stateArray['filter'] = $this->filter ;
$stateArray['sorting'] = $this->sorting;
$stateArray['occupancy'] = $this->rooms['occupancy'];
$stateArray['accList'] = $this->accList;
$stateArray['nearbySearch'] = $this->nearbySearch;
$stateArray['showMap'] = $this->showMap;
return $stateArray;
}
}