<?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\Demi\Accommodation\Search;
use Carbon\Carbon;
use DateTime;
use Elements\Demi\Dependency\DependencyContainer;
use Elements\Demi\Deskline\SearchParameter\AccommodationInterface;
use Elements\Demi\Helper;
use Elements\Demi\Model\AccommodationProduct;
use Elements\Demi\Model\AccommodationService;
use Elements\Demi\Model\AccommodationServiceProvider;
use Elements\Demi\Model\FacilityGroup;
use Elements\Demi\Model\MarketingGroup;
use Elements\Demi\Model\MealType;
use Elements\Demi\Model\Region;
use Elements\Demi\Model\SalesChannel;
use Elements\Demi\Model\Town;
use JetBrains\PhpStorm\Pure;
use Pimcore\Db;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\DataObject\DemiSystemObject;
class Parameter extends AbstractParameter
{
public const SORT_ORDER_RANDOM = 'Random';
public const SORT_ORDER_PRICE_ASC = 'TotalPrice';
public const SORT_ORDER_PRICE_DESC = 'TotalPriceDesc';
public const SORT_ORDER_BASEPRICE_ASC = 'Price';
public const SORT_ORDER_BASEPRICE_DESC = 'BasePriceDesc';
public const SORT_ORDER_STARS_ASC = 'StarsAsc';
public const SORT_ORDER_STARS_DESC = 'StarsDesc';
public const SORT_ORDER_BOOKABLE_ASC = 'Bookable';
public const SORT_ORDER_BOOKABLE_DESC = 'BookableDesc';
public const SORT_ORDER_RATING_ASC = 'Rating';
public const SORT_ORDER_RATING_DESC = 'RatingDesc';
public const SORT_ORDER_TOWN_ASC = 'Town';
public const SORT_ORDER_TOWN_DESC = 'TownDesc';
public const SORT_ORDER_NAME_ASC = 'Name';
public const SORT_ORDER_NAME_DESC = 'NameDesc';
public const SORT_ORDER_PRIORITY_ASC = 'priorityAsc';
public const SORT_ORDER_PRIORITY_DESC = 'priority';
public const SORT_ORDER_RATING_AVERAGE_DESC = 'ratingAverageDesc';
public const SORT_ORDER_RATING_AVERAGE_ASC = 'ratingAverageAsc';
public const DEMI_SORT_ORDER_RANDOM = 'random';
public const DEMI_SORT_ORDER_PRICE_ASC = 'priceAsc';
public const DEMI_SORT_ORDER_PRICE_DESC = 'priceDesc';
public const DEMI_SORT_ORDER_STARS_ASC = 'starsAsc';
public const DEMI_SORT_ORDER_STARS_DESC = 'starsDesc';
public const DEMI_SORT_ORDER_RATING_ASC = 'rating';
public const DEMI_SORT_ORDER_RATINGAVERAGE_ASC = 'ratingAverageAsc';
public const DEMI_SORT_ORDER_RATINGAVERAGE_DESC = 'ratingAverageDesc';
public const DEMI_SORT_ORDER_RATING_DESC = 'ratingDesc';
public const DEMI_SORT_ORDER_BOOKABLE_ASC = 'bookable';
public const DEMI_SORT_ORDER_CONTENTSCORE = 'contentScore';
public const SEARCH_TYPE_ONE_PRODUCT_PER_HOTEL = 'OneProductPerHotel';
public const SEARCH_TYPE_STANDARD = 'Standard';
public const SEARCH_TYPE_EACH_PRODUCT_SEPARATED = 'EachProductSeparated';
public const SEARCH_TYPE_ONE_PRODUCT_PER_PACKAGE = 'OneProductPerPackage';
public const PRODUCT_TYPE_ACCOMMODATION = 'Accommodation';
public const PRODUCT_TYPE_ADDITIONAL_SERVICE = 'AdditionalService';
public const PRODUCT_TYPE_PACKAGE = 'Package';
public const RESPONSE_TYPE_EXPANDED = 'Expanded';
public const RESPONSE_TYPE_STANDARD = 'Standard';
public const SPECIAL_TYPE_LASTMINUTE = 'LastMinute';
public const SPECIAL_TYPE_EARLYBOOKER = 'EarlyBooker';
public const SPECIAL_TYPE_SPLIT = 'split';
protected bool $bookOnRequestAsBookable = false;
protected array $refilterCustomOrder = [];
protected string $language = '';
protected int $priority = 0;
protected string $priorityOperator = 'greaterThan';
protected bool $useMultiLineMerge = false;
protected bool $daccoRelTableNeeded = false;
protected bool $serviceTableNeeded = false;
protected bool $serviceRelTableNeeded = false;
protected bool $productTableNeeded = false;
protected bool $starsTableNeeded = false;
protected bool $skipCleaningSortAfterFactory = false;
protected bool $skipBaseFilter = false;
protected bool $unpublished = false;
protected bool $isCorridor = false;
protected bool $isAlternative = false;
protected int $previousResults = 0;
/** feratel specific parameters */
protected ?string $mealCode = null;
protected ?array $order = null;
protected ?string $searchType = null;
protected ?array $excludeAccoIds = null;
protected ?array $accoFIds = null;
protected ?Carbon $dateTo = null;
protected array $towns = [];
protected array $regions = [];
protected int $period = 0;
protected array $nights = [];
protected string $responseType = \Elements\Demi\Deskline\Constant\SearchParameter\AccommodationInterface::RESPONSE_TYPE_EXPANDED;
protected int $minPrice = 0;
protected float $priceFrom = 0.0;
protected float $priceTo = 0.0;
protected float $priceRangeFrom = 0.0;
protected float $priceRangeTo = 0.0;
protected array $roomrows = [];
protected array $districts = [];
protected array $stars = [];
protected array $hotelChains = [];
protected array $classifications = [];
protected string $classificationOperator = 'OR';
protected string $classificationStarsOperator = 'OR';
protected array $marketingGroups = [];
protected string $marketingGroupOperator = 'OR';
protected array $holidayThemes = [];
protected string $holidayThemesOperator = 'OR';
protected array $facilities = [];
protected array $roomFacilities = [];
protected array $apartmentFacilities = [];
protected string $facilityOperator = 'AND';
protected array $facilityCombinations = [];
protected string $facilityCombinationOperator = 'AND';
protected ?string $fullText = null; //TODO not yet supported
protected ?bool $topOnly = null;
protected ?int $topFirst = null;
protected bool $allTopsFirst = false;
protected ?bool $bookOnly = null;
protected ?bool $notBookOnly = null;
protected ?bool $ticketingOnly = null;
//specials and bestprice
protected string $specialsOperator = 'OR';
protected mixed $specialsOnly = false;
protected array $specialSpecific = [];
protected array $excludeSpecialSpecific = [];
protected bool $bestpriceOnly = false;
protected mixed $bestpriceProvider = false;
protected array $accommodationType = [];
protected array $serviceCode = [];
protected ?string $productType = null;
protected mixed $productId = 0;
protected ?array $productIds = null;
protected ?string $lastAvailabilitiyChangeDays = null;
protected ?int $minAmountSleepingRooms = null;
protected int|float $minPriceBound = 1;
protected int $orderRandSeed = 0;
protected int $minRatingCountForSort = 1;
protected ?int $currentItemCountPerPage = 1;
protected bool $calculateStandardPrice = true;
protected bool $extendedResultset = false;
protected bool $checkTestHotels = false;
protected array $ignoreFiltersInAccoDetailSearch = [
'freeCancellation',
'minAmountSleepingRooms',
'priceFrom',
'priceTo',
'serviceCode',
'roomFacilities',
'stars',
'classificationIds',
];
protected bool $freeCancellation = false;
protected int $contentScore = 0;
protected ?int $currentPage = 1;
public function __construct()
{
}
public function setMarketingGroupOperator(string $marketingGroupOperator): void
{
$this->marketingGroupOperator = $marketingGroupOperator;
}
public function getMarketingGroupOperator(): string
{
return $this->marketingGroupOperator;
}
public function getIgnoreFiltersInAccoDetailSearch(): array
{
return $this->ignoreFiltersInAccoDetailSearch;
}
#[Pure]
public function getSortOrder(): array|string|null
{
return $this->getOrder();
}
public function isSkipCleaningSortAfterFactory(): bool
{
return $this->skipCleaningSortAfterFactory;
}
public function setSkipCleaningSortAfterFactory(bool $skipCleaningSortAfterFactory): void
{
$this->skipCleaningSortAfterFactory = $skipCleaningSortAfterFactory;
}
public function setPage($currentPage): Parameter
{
$this->setCurrentPage($currentPage);
return $this;
}
#[Pure]
public function getPerPage(): int
{
return $this->getCurrentItemCountPerPage();
}
public function setPerPage(int $currentItemCountPerPage): Parameter
{
$this->setCurrentItemCountPerPage($currentItemCountPerPage);
return $this;
}
public function setCurrentItemCountPerPage(?int $currentItemCountPerPage): self
{
$this->currentItemCountPerPage = $currentItemCountPerPage;
return $this;
}
public function getCurrentItemCountPerPage(): int
{
return $this->currentItemCountPerPage;
}
public function setCurrentPage(?int $currentPage): Parameter
{
$this->currentPage = $currentPage;
return $this;
}
public function getCurrentPage(): int
{
return $this->currentPage;
}
public function getTownsForParent($parent): array
{
$towns = [];
if ($parent) {
$childs = $parent->getChildren();
foreach ($childs as $child) {
if ($child instanceof Town) {
$towns[] = $child->getId();
} elseif ($child instanceof Region) {
array_merge($towns, $this->getTownsForParent($child));
}
}
}
return $towns;
}
public function getQueryCondition(DependencyContainer $dc, string $accoTable = 'dacco', string $serviceTable = 'services', string $productTable = 'products'): string
{
$condition = [];
if (!$this->getUnpublished()) {
$condition[] = ' ' . $accoTable . '.o_published = 1 ';
}
if ($this->getClientKey()) {
/** @var \Pimcore\Model\DataObject\DemiSystemObject\Listing $systemObjects */
$systemObjects = DemiSystemObject::getByClientKey($this->getClientKey());
$condition[] = 'dacco.systemObject__id in ( ' . implode(',', array_map(
static function (DemiSystemObject $systemObject) {
return $systemObject->getId();
},
$systemObjects->getObjects()
)) . ') ';
}
if (!empty($this->accoId)) { //for detail page
$ids = [];
foreach ((array)$this->accoIds as $accoId) {
$ids[] = (int)$accoId;
}
$condition[] = ' oo_id IN (' . implode(', ', $ids) . ') ';
}
if (!empty($this->productType)) {
$condition[] = '(' . $productTable . '.o_published = 1 ' . ' AND ' . $productTable . '.productType = ' . Db::get()->quote($this->productType) . ')';
}
if (!empty($this->accommodationType)) {
//\Pimcore\Db::get()->quote()
$tmpTypes = [];
foreach ($this->accommodationType as $accoType) {
$tmpTypes[] = Db::get()->quote($accoType);
}
$condition[] = '(' . $productTable . '.accommodationType IN (' . implode(', ', $tmpTypes) . '))';
}
if (!empty($this->districts)) {
$tmpConditions = [];
foreach ($this->districts as $district) {
if (is_numeric($district)) {
$tmpConditions[] = $accoTable . '.district__id = ' . (int)$district;
}
}
$condition[] = '(' . implode(' OR ', $tmpConditions) . ')';
}
$tmpTowns = [];
if (!empty($this->regions)) {
//$tmpConditionsRegions = array();
foreach ($this->regions as $region) {
if (!is_object($region) && is_numeric($region)) {
$region = \Elements\Demi\AbstractObject::getById($region);
}
$childs = $this->getTownsForParent($region);
foreach ($childs as $town) {
$tmpTowns[] = $town;
}
}
}
if (!empty($this->towns)) {
foreach ($this->towns as $town) {
if (is_numeric($town)) {
$tmpTowns[] = (int)$town;
}
}
}
if (!empty($tmpTowns)) {
$areaCondition[] = $accoTable . '.town__id IN (' . implode(', ', $tmpTowns) . ')';
}
if (!empty($areaCondition)) {
$condition[] = '(' . implode(' OR ', $areaCondition) . ')';
}
if (!empty($this->name)) {
$tmpCond = $accoTable . '.name LIKE ' . Db::get()->quote('%' . $this->name . '%');
if (!empty($this->getLanguage())) {
$tmpCond .= ' OR localized.nameLocalized LIKE ' . Db::get()->quote('%' . $this->name . '%');
}
$condition[] = ' (' . $tmpCond . ') ';
}
$starcondition = [];
if (!empty($this->stars)) {
$tmpConditions = [];
foreach ($this->stars as $star) {
$tmpConditions[] = $accoTable . '.stars__id = ' . (int)$star;
}
$starcondition[] = '(' . implode(' OR ', $tmpConditions) . ')';
}
if (!empty($this->classifications)) {
$tmpConditions = [];
foreach ($this->classifications as $classification) {
$tmpConditions[] = $accoTable . ".classifications LIKE '%," . (int)$classification . ",%'";
}
$starcondition[] = '(' . implode(' ' . $this->classificationOperator . ' ', $tmpConditions) . ')';
}
if (!empty($starcondition)) {
$condition[] = '(' . implode(' OR ', $starcondition) . ')';
}
if (!empty($this->hotelChains)) {
$tmpConditions = [];
foreach ($this->hotelChains as $hotelChain) {
$tmpConditions[] = $accoTable . '.hotelChain__id = ' . (int)$hotelChain;
}
$condition[] = '(' . implode(' OR ', $tmpConditions) . ')';
}
if (!empty($this->priority)) {
if ($this->getPriorityOperator() === 'greaterThan') {
$condition[] = $this->priority . ' <= ' . $accoTable . '.priority';
} elseif ($this->getPriorityOperator() === 'smallerThan') {
$condition[] = $this->priority . ' > ' . $accoTable . '.priority';
}
}
$dummyProduct = new AccommodationProduct();
$dummyService = new AccommodationService();
if ($this->salesChannelId) {
$condition[] = "$this->salesChannelId in (SELECT dest_id
FROM {$dc->getUsedPimcoreDb()}.object_relations_{$dummyProduct->getClassId()} salesprodrel
INNER JOIN {$dc->getUsedPimcoreDb()}.object_{$dummyProduct->getClassId()} salesprod ON salesprodrel.src_id = salesprod.oo_id
INNER JOIN {$dc->getUsedPimcoreDb()}.object_{$dummyService->getClassId()} salesservice ON salesprod.o_parentId = salesservice.oo_id
WHERE fieldname = 'salesChannels'
AND salesservice.o_parentId = dacco.oo_id
)";
}
$dummyAcco = new \Elements\Demi\Model\AccommodationServiceProvider();
if (!empty($this->categories)) {
$tmpCats = [];
foreach ($this->categories as $category) {
$tmpCats[] = intval($category);
}
$condition[] = 'EXISTS (
SELECT 1 FROM
' . $dc->getUsedPimcoreDb() . '.object_relations_' . $dummyAcco->getClassId() . ' subfacrel
WHERE subfacrel.src_id = dacco.o_id AND subfacrel.dest_id IN (' . implode(',', $tmpCats) . ") AND subfacrel.fieldname = 'categories'
)";
}
if (!empty($this->facilities)) {
foreach ($this->facilities as $facility) {
$dummyObj = AbstractObject::getById($facility);
if ($dummyObj instanceof FacilityGroup) {
foreach ($dummyObj->getChildren() as $facilityChild) {
$facIds[] = $facilityChild->getId();
}
} else {
$facIds[] = (int)$facility;
}
}
$facilityMatchCount = count($facIds ?? []);
if ($this->getFacilityOperator() === 'OR') {
$facilityMatchCount = 1;
}
$condition[] = '(
SELECT count(*) FROM
' . $dc->getUsedPimcoreDb() . '.object_relations_' . AccommodationServiceProvider::classId() . ' subfacrel
WHERE subfacrel.src_id = dacco.o_id AND subfacrel.dest_id IN (' . implode(',', $facIds ?? []) . ") AND subfacrel.fieldname = 'facility'
) = " . $facilityMatchCount;
}
if (!empty($this->roomFacilities) || !empty($this->apartmentFacilities)) {
$facIds = [];
$unitFacilities = array_unique(array_merge($this->roomFacilities, $this->apartmentFacilities));
foreach ($unitFacilities as $facility) {
$dummyObj = AbstractObject::getById($facility);
if ($dummyObj instanceof FacilityGroup) {
foreach ($dummyObj->getChildren() as $facilityChild) {
$facIds[] = $facilityChild->getId();
}
} else {
$facIds[] = (int)$facility;
}
}
$facilityMatchCount = count($facIds);
if ($this->getFacilityOperator() === 'OR') {
$facilityMatchCount = 1;
}
$serviceIdCondition = '';
$condition[] = '(
SELECT count(*) FROM
' . $dc->getUsedPimcoreDb() . '.object_relations_' . $dummyService->getClassId() . ' servicefacrel
WHERE ' . $serviceIdCondition . ' servicefacrel.src_id = services.oo_id AND servicefacrel.dest_id IN (' . implode(',', $facIds) . ") AND servicefacrel.fieldname = 'facility' AND services.o_published = 1
) = " . $facilityMatchCount;
}
if (!empty($this->facilityCombinations)) {
$tmpConditions = [];
foreach ($this->facilityCombinations as $facilityArray) {
$accoIds = [];
$mgIds = [];
$facIds = [];
foreach ($facilityArray as $facility) {
$dummyObj = AbstractObject::getById($facility);
if ($dummyObj instanceof FacilityGroup) {
foreach ($dummyObj->getChildren() as $facilityChild) {
$facIds[] = $facilityChild->getId();
}
} elseif ($dummyObj instanceof AccommodationServiceProvider) {
$accoIds[] = $dummyObj->getId();
} elseif ($dummyObj instanceof MarketingGroup) {
$mgIds[] = $dummyObj->getId();
} else {
$facIds[] = (int)$facility;
}
}
$facilityMatchCount = 1;
$tmptmpConditions = [];
if (!empty($facIds)) {
$tmptmpConditions[] = '((
SELECT count(*) FROM
' . $dc->getUsedPimcoreDb() . '.object_relations_' . AccommodationServiceProvider::classId() . ' subfacrel
WHERE subfacrel.src_id = dacco.o_id AND subfacrel.dest_id IN (' . implode(',', $facIds) . ") AND subfacrel.fieldname = 'facility'
) = " . $facilityMatchCount . ')';
}
if (!empty($mgIds)) {
$tmptmpConditions[] = '((
SELECT count(*) FROM
' . $dc->getUsedPimcoreDb() . '.object_relations_' . AccommodationServiceProvider::classId() . ' subfacrelmg
WHERE subfacrelmg.src_id = dacco.o_id AND subfacrelmg.dest_id IN (' . implode(',', $mgIds) . ") AND subfacrelmg.fieldname = 'marketingGroups'
) = " . $facilityMatchCount . ')';
}
if (!empty($accoIds)) {
$tmptmpConditions[] .= '(dacco.oo_id IN (' . implode(', ', $accoIds) . '))';
}
$tmpCondition = '(' . implode(' OR ', $tmptmpConditions) . ')';
$tmpConditions[] = $tmpCondition;
}
$condition[] = ' (' . implode(' ' . $this->getFacilityCombinationOperator() . ' ', $tmpConditions) . ') ';
}
if (!empty($this->marketingGroups)) {
$tmpConditions = [];
if (is_array(current($this->marketingGroups))) { //is mg Collection
$collectionOperator = 'AND';
if ($this->marketingGroupOperator === 'AND') {
$collectionOperator = 'OR';
}
foreach ($this->marketingGroups as $marketingGroupCollection) {
$mgCollCondition = [];
foreach ($marketingGroupCollection as $marketingGroup) {
$mgCollCondition[] = $accoTable . ".marketingGroups LIKE '%," . (int)$marketingGroup . ",%'";
}
$tmpConditions[] = '(' . implode(' ' . $this->marketingGroupOperator . ' ', $mgCollCondition) . ')';
}
$condition[] = '(' . implode(' ' . $collectionOperator . ' ', $tmpConditions) . ')';
} else {
foreach ($this->marketingGroups as $marketingGroup) {
$tmpConditions[] = $accoTable . ".marketingGroups LIKE '%," . (int)$marketingGroup . ",%'";
}
$condition[] = '(' . implode(' ' . $this->marketingGroupOperator . ' ', $tmpConditions) . ')';
}
}
$holidayThemes = $this->getHolidayThemes();
if (!empty($holidayThemes)) {
$tmpConditions = [];
foreach ($holidayThemes as $holidayTheme) {
$tmpConditions[] = $productTable . ".holidayThemes LIKE '%," . (int)$holidayTheme . ",%'";
}
$condition[] = '(' . implode(' ' . $this->getHolidayThemesOperator() . ' ', $tmpConditions) . ')';
}
if ($this->topOnly) {
$condition[] = $accoTable . '.isTop = 1';
}
//check acco bookable (for nodate search)
if ($this->bookOnly) {
$condition[] = $accoTable . '.bookable = 1';
} elseif ($this->notBookOnly) {
if (!$this->dateFrom || !$this->dateTo) {
$condition[] = $accoTable . '.bookable = 0';
}
}
//bookonly check is done in resultbuilder
if ($this->isTicketingOnly()) {
$condition[] = $accoTable . '.allowTicketing = 1';
}
if ($this->bestpriceProvider) {
$condition[] = $accoTable . '.bestPrice = 1';
}
if (is_int($this->minAmountSleepingRooms) || $this->minAmountSleepingRooms > 0) {
$condition[] = "$serviceTable.bedrooms >= $this->minAmountSleepingRooms";
}
if ($this->serviceCode) {
$serviceCodeCondition = [];
foreach ($this->serviceCode as $serviceCode) {
$serviceCodeCondition[] = "$serviceTable.code LIKE " . Db::get()->quote('%' . strtoupper($serviceCode) . '%');
}
$condition[] = '( ' . implode(' OR ', $serviceCodeCondition) . ' )';
}
if ($this->isNoDate() && $this->getProductType() === 'Package') {
$today = new DateTime();
$condition[] = '(
' . $productTable . '.oo_id IN (SELECT DISTINCT o_id FROM ' . $dc->getUsedPimcoreDb() . '.object_collection_demiDate_' . $dummyProduct->getClassId() . '
WHERE `to` > ' . $today->getTimestamp() . ") OR validDatesType = 'Always'
)";
}
if ($this->getCheckTestHotels()) {
$condition[] = '(' . $accoTable . '.isTesthotel = 0 OR isTesthotel IS NULL)';
}
return implode(' AND ', $condition);
}
public function setDateTo(?Carbon $dateTo): self
{
$this->dateTo = Helper::dateTimeClearTime($dateTo);
return $this;
}
public function getDateTo(): ?Carbon
{
return $this->dateTo;
}
public function setPeriod($period): Parameter
{
$this->period = $period;
return $this;
}
public function getPeriod(): int
{
return $this->period;
}
public function setRegions($regionId): Parameter
{
$this->regions = $regionId;
return $this;
}
public function getRegions(): array
{
return $this->regions;
}
public function setTowns($townId): Parameter
{
$this->towns = $townId;
return $this;
}
public function getTowns(): array
{
return $this->towns;
}
public function validateRequiredVacancySearchParameter(): bool
{
$requiredFields = $this->getRequiredFields();
$missingFields = [];
foreach ($requiredFields as $field) {
$value = $this->{'get' . ucfirst($field)}();
if (empty($value)) {
$missingFields[] = $field;
}
}
$roomConfig = $this->getRoomrows();
if (count($roomConfig) <= 0) {
$missingFields[] = 'rooms';
} else {
$firstRow = $roomConfig[0];
if (empty($firstRow->getBeds())) {
$missingFields[] = 'beds';
}
}
if (!empty($missingFields)) {
return false;
}
return true;
}
protected function getRequiredFields(): array
{
return [
'dateFrom',
'dateTo',
'period',
'roomrows',
//"beds"
];
}
public function setRoomrows(array $roomrows): Parameter
{
$this->roomrows = $roomrows;
return $this;
}
public function getRoomrows(): array
{
return $this->roomrows;
}
public function getDaysUntilArrival(): int|string
{
if ($this->getDateFrom()) {
return $this->getDateFrom()->diff(new DateTime())->format('%a');
}
return 0;
}
public function getCompleteCacheHash(?int $page = null, ?int $pagesize = null): string
{
$string = serialize($this) . ':' . $page . ':' . $pagesize; //needed for live search
return md5($string);
}
public function getVacancyCacheHash(): string
{
$roomRowString = '';
foreach ($this->getRoomrows() as $row) {
$roomRowString .= $row->getVacancyCacheString();
}
if ($this->dateFrom && $this->dateTo) {
return md5($this->dateFrom->format('YMD') . ',' .
$this->dateTo->format('YMD') . ',' .
$this->getPeriod() . ',' .
$roomRowString);
}
return md5($roomRowString);
}
public function addRoomRow($row): Parameter
{
$this->roomrows[] = $row;
return $this;
}
public function setBookOnly(bool $bookOnly): self
{
$this->bookOnly = $bookOnly;
return $this;
}
public function getBookOnly(): ?bool
{
return $this->bookOnly;
}
public function setClassifications($classifications): Parameter
{
$this->classifications = $classifications;
return $this;
}
public function getClassifications(): array
{
return $this->classifications;
}
public function setFacilities($facilities): Parameter
{
$this->facilities = $facilities;
return $this;
}
public function getFacilities(): array
{
return $this->facilities;
}
public function setFullText(string $fullText): self
{
$this->fullText = $fullText;
return $this;
}
public function getFullText(): ?string
{
return $this->fullText;
}
public function setMarketingGroups(array $marketingGroups): self
{
$this->marketingGroups = $marketingGroups;
return $this;
}
public function getMarketingGroups(): array
{
return $this->marketingGroups;
}
public function setStars(array $stars): self
{
$this->stars = $stars;
return $this;
}
public function getStars(): array
{
return $this->stars;
}
public function setTopOnly(bool $topOnly): Parameter
{
$this->topOnly = $topOnly;
return $this;
}
public function getTopOnly(): ?bool
{
return $this->topOnly;
}
public function setDistricts($districts): Parameter
{
$this->districts = $districts;
return $this;
}
public function getDistricts(): array
{
return $this->districts;
}
public function getFacilityOperator(): string
{
return $this->facilityOperator;
}
public function setHotelChains($hotelChains): Parameter
{
$this->hotelChains = $hotelChains;
return $this;
}
public function getHotelChains(): array
{
return $this->hotelChains;
}
public function setAccommodationType(array $accommodationTypeId): self
{
$this->accommodationType = $accommodationTypeId;
return $this;
}
public function getAccommodationType(): array
{
return $this->accommodationType;
}
public function setProductType(string $productType): self
{
$this->productType = $productType;
return $this;
}
public function getProductType(): ?string
{
return $this->productType;
}
public function setLastAvailabilitiyChangeDays(string $lastAvailabilitiyChangeDays): Parameter
{
$this->lastAvailabilitiyChangeDays = $lastAvailabilitiyChangeDays;
return $this;
}
public function getLastAvailabilitiyChangeDays(): ?string
{
return $this->lastAvailabilitiyChangeDays;
}
public function getHolidayThemesOperator(): string
{
return $this->holidayThemesOperator;
}
public function setHolidayThemes($holidayThemes): Parameter
{
$this->holidayThemes = $holidayThemes;
return $this;
}
public function getHolidayThemes(): array
{
return $this->holidayThemes;
}
public function setSearchType(?string $searchType): self
{
$this->searchType = $searchType;
return $this;
}
public function getSearchType(): ?string
{
return $this->searchType;
}
public function setOrder(array|string|null $order): self
{
$this->order = $order;
return $this;
}
public function getOrder(): array|string|null
{
return $this->order;
}
public function setResponseType(string $responseType): Parameter
{
$this->responseType = $responseType;
return $this;
}
public function getResponseType(): string
{
return $this->responseType;
}
public function convertToDesklineParams(): array
{
$desklineSearchParams = [];
$singleAccoLiveSearch = is_array($this->getAccoIds()) && count($this->accoIds) == 1 && !$this->getIsCorridor() && !$this->isNoDate();
foreach ($this->getRoomrows() as $roomConfig) {
$desklineSearchParam = new AccommodationInterface(
$roomConfig->getUnits(),
$roomConfig->getAdults(),
$this->getDateFrom(),
$this->getDateTo()
);
if ($roomConfig->getChildAges()) {
$desklineSearchParam->setChildrenAges($roomConfig->getChildAges());
}
if (!($singleAccoLiveSearch && in_array('bookOnly', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setBookOnly(boolval($this->getBookOnly()));
}
if (!($singleAccoLiveSearch && in_array('facilities', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setAccommodationFacilityIds($this->getFacilities());
}
if (!($singleAccoLiveSearch && in_array('apartmentFacilities', $this->ignoreFiltersInAccoDetailSearch) && in_array('roomFacilities', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setServiceFacilityIds(array_unique(array_merge($this->getRoomFacilities(), $this->getApartmentFacilities())));
}
if (!($singleAccoLiveSearch && in_array('accommodationTypeId', $this->ignoreFiltersInAccoDetailSearch))) {
$accommodationTypes = $this->getAccommodationType();
if (!empty($accommodationTypes)) {
$desklineSearchParam->setAccommodationTypeId($accommodationTypes[0] ?? '');
}
}
//servicecode is an array locally
if (!($singleAccoLiveSearch && in_array('serviceCode', $this->ignoreFiltersInAccoDetailSearch))) {
$serviceCodes = $this->getServiceCode();
if (!empty($serviceCodes)) {
$desklineSearchParam->setServiceCode($serviceCodes[0]);
}
}
if (!($singleAccoLiveSearch && in_array('categories', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setCategoryIds($this->getCategories());
}
if (!($singleAccoLiveSearch && in_array('hotelChains', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setChainIds($this->getHotelChains());
}
if (!($singleAccoLiveSearch && in_array('districts', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setDistrictIds($this->getDistricts());
}
if (!($singleAccoLiveSearch && in_array('classificationIds', $this->ignoreFiltersInAccoDetailSearch))) {
//leave classification out for live search if classificationStarsOperater is OR because deskline cant do that
if ($this->getClassificationStarsOperator() !== 'OR') {
$desklineSearchParam->setClassificationIds($this->getClassifications());
}
}
if ($this->getLastAvailabilitiyChangeDays() !== null) {
$desklineSearchParam->setLastAvailabilityChangeDays($this->getLastAvailabilitiyChangeDays());
}
if (!($singleAccoLiveSearch && in_array('holidayThemes', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setHolidayThemeIds($this->getHolidayThemes());
}
if (!($singleAccoLiveSearch && in_array('marketingGroupIds', $this->ignoreFiltersInAccoDetailSearch))) {
//check if mgs are Collections. IF so set Marketinggroups to empty as Deskline does not support it
$mgs = is_array(current($this->getMarketingGroups())) ? [] : $this->getMarketingGroups();
$desklineSearchParam->setMarketingGroupIds($mgs);
}
//todo: searchParams should return townIds not only one! same for region!
if (!($singleAccoLiveSearch && in_array('towns', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setTownIds($this->getTowns());
}
if (!($singleAccoLiveSearch && in_array('regions', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setRegionIds($this->getRegions());
}
if (!($singleAccoLiveSearch && in_array('stars', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setStarIds($this->getStars());
}
$desklineSearchParam->setNights($this->getPeriod());
if (!($singleAccoLiveSearch && in_array('productType', $this->ignoreFiltersInAccoDetailSearch))) {
if ($this->getProductType() !== null) {
$desklineSearchParam->setProductTypeId($this->getProductType());
}
}
if ($this->getMealTypeId()) {
$mealtype = $this->getMealTypeId();
if (is_array($mealtype)) {
$mealtype = $mealtype[0];
}
$mealtype = MealType::getById($mealtype);
if ($mealtype) {
$desklineSearchParam->setMealTypeId($mealtype->getFid());
}
}
if ($this->getProductId()) {
$desklineSearchParam->setProductId($this->getProductId());
}
$pids = $this->getProductIds();
if (!empty($pids) && count($pids) == 1) {
$desklineSearchParam->setProductId($pids[0]);
}
$desklineSearchParam->setServiceProviderIds($this->accoIds ?? []);
$desklineSearchParam->setServiceProviderFIds($this->accoFIds ?? []);
if (empty($this->accoFIds) && empty($this->accoIds) && $this->getName() !== null) {
$desklineSearchParam->setServiceProviderName($this->getName());
}
if ($this->salesChannelId) {
$salesChannel = SalesChannel::getById($this->salesChannelId);
if ($salesChannel) {
$desklineSearchParam->setSalesChannel($salesChannel->getFid());
}
}
if (!($singleAccoLiveSearch && in_array('minAmountSleepingRooms', $this->ignoreFiltersInAccoDetailSearch))) {
$minSleepingRooms = $roomConfig->getMinSleepingRooms() ?: $this->getMinAmountSleepingRooms();
if ($minSleepingRooms !== null) {
$desklineSearchParam->setMinAmountSleepingRooms($minSleepingRooms);
}
}
if (!($singleAccoLiveSearch && in_array('accommodationType', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setAccommodationTypeId($roomConfig->getAccommodationType());
}
if (!($singleAccoLiveSearch && in_array('priceFrom', $this->ignoreFiltersInAccoDetailSearch) && in_array('priceTo', $this->ignoreFiltersInAccoDetailSearch))) {
$desklineSearchParam->setMaxPrice($this->getPriceTo());
if ($this->getPriceFrom() >= 0 && $this->getPriceTo() > 0) {
$desklineSearchParam->setRangeMaxPrice($this->getPriceTo());
$desklineSearchParam->setRangeMinPrice($this->getPriceFrom());
}
}
$desklineSearchParams[] = $desklineSearchParam;
}
return $desklineSearchParams;
}
public function getMealCode(): ?string
{
if (!$this->mealCode && $this->mealTypeId) {
$mealType = MealType::getById($this->mealTypeId);
if ($mealType) {
$this->mealCode = $mealType->getFid();
return $this->mealCode;
}
$mealType = MealType::getByFid($this->mealTypeId);
if ($mealType) {
$this->mealCode = $mealType->getFid();
return $this->mealCode;
}
}
return $this->mealCode;
}
public function setProductId(mixed $productId): self
{
$this->productId = $productId;
return $this;
}
public function getProductId(): mixed
{
return $this->productId;
}
public function setAccoFIds($accoFIds): Parameter
{
$this->accoFIds = $accoFIds;
return $this;
}
public function getAccoFIds(): ?array
{
return $this->accoFIds;
}
public function getMinAmountSleepingRooms(): ?int
{
return $this->minAmountSleepingRooms;
}
public function setMinAmountSleepingRooms(?int $minAmountSleepingRooms): self
{
$this->minAmountSleepingRooms = $minAmountSleepingRooms;
return $this;
}
public function setOrderRandSeed(int $orderRandSeed): Parameter
{
$this->orderRandSeed = $orderRandSeed;
return $this;
}
public function getOrderRandSeed(): int
{
return $this->orderRandSeed;
}
public function getBookOnRequestAsBookable(): bool
{
return $this->bookOnRequestAsBookable;
}
public function getDaccoRelTableNeeded(): bool
{
return $this->daccoRelTableNeeded;
}
public function getProductTableNeeded(): bool
{
return $this->productTableNeeded;
}
public function setRefilterCustomOrder($refilterCustomOrder): Parameter
{
$this->refilterCustomOrder = $refilterCustomOrder;
return $this;
}
public function getRefilterCustomOrder(): array
{
return $this->refilterCustomOrder;
}
public function getServiceRelTableNeeded(): bool
{
return $this->serviceRelTableNeeded;
}
public function setServiceTableNeeded($serviceTableNeeded): Parameter
{
$this->serviceTableNeeded = $serviceTableNeeded;
return $this;
}
public function getServiceTableNeeded(): bool
{
return $this->serviceTableNeeded;
}
public function setPriceFrom(float $priceFrom): self
{
$this->priceFrom = $priceFrom;
return $this;
}
public function getPriceFrom(): float
{
return $this->priceFrom;
}
public function setPriceTo(float $priceTo): self
{
$this->priceTo = $priceTo;
return $this;
}
public function getPriceTo(): float
{
return $this->priceTo;
}
#[Pure]
public function getPriceRangeFrom(): ?float
{
if (empty($this->priceRangeFrom)) {
return $this->getPriceFrom();
}
return $this->priceRangeFrom;
}
#[Pure]
public function getPriceRangeTo(): float
{
if (empty($this->priceRangeTo)) {
return $this->getPriceTo();
}
return $this->priceRangeTo;
}
public function setUnpublished($unpublished): Parameter
{
$this->unpublished = $unpublished;
return $this;
}
public function getUnpublished(): bool
{
return $this->unpublished;
}
public function setExtendedResultset(bool $extendedResultset): self
{
$this->extendedResultset = $extendedResultset;
return $this;
}
public function getExtendedResultset(): bool
{
return $this->extendedResultset;
}
public function setMinPrice($minPrice): Parameter
{
$this->minPrice = $minPrice;
return $this;
}
public function getMinPrice(): int
{
return $this->minPrice;
}
public function getMinPriceBound(): float|int
{
return $this->minPriceBound;
}
public function getTopFirst(): ?int
{
return $this->topFirst;
}
public function setServiceCode(mixed $serviceCode): self
{
$this->serviceCode = (array)$serviceCode;
return $this;
}
public function getServiceCode(): array
{
return $this->serviceCode;
}
public function getClassificationStarsOperator(): string
{
return $this->classificationStarsOperator;
}
public function setNotBookOnly(bool $notBookOnly): self
{
$this->notBookOnly = $notBookOnly;
return $this;
}
public function getNotBookOnly(): ?bool
{
return $this->notBookOnly;
}
public function setCheckTestHotels(bool $checkTestHotels): self
{
$this->checkTestHotels = $checkTestHotels;
return $this;
}
public function getCheckTestHotels(): bool
{
return $this->checkTestHotels;
}
public function setIsCorridor(bool $isCorridor): self
{
$this->isCorridor = $isCorridor;
return $this;
}
public function getIsCorridor(): bool
{
return $this->isCorridor;
}
public function setIsAlternative(bool $isAlternative): self
{
$this->isAlternative = $isAlternative;
return $this;
}
public function getIsAlternative(): bool
{
return $this->isAlternative;
}
public function setPreviousResults(int $previousResults): self
{
$this->previousResults = $previousResults;
return $this;
}
public function getPreviousResults(): int
{
return $this->previousResults;
}
public function setNights(array $nights): self
{
$this->nights = $nights;
return $this;
}
public function getNights(): array
{
return $this->nights;
}
public function setProductIds(mixed $productIds): self
{
$ints = [];
foreach ((array)$productIds as $productId) {
$ints[] = (int)$productId;
}
$this->productIds = $ints;
return $this;
}
public function getProductIds(): ?array
{
return $this->productIds;
}
public function getMinRatingCountForSort(): int
{
return $this->minRatingCountForSort;
}
public function getSkipBaseFilter(): bool
{
return $this->skipBaseFilter;
}
public function setCalculateStandardPrice(bool $calculateStandardPrice): self
{
$this->calculateStandardPrice = $calculateStandardPrice;
return $this;
}
public function getCalculateStandardPrice(): bool
{
return $this->calculateStandardPrice;
}
public function getFacilityGroup(): array
{
//dummy return value
return [];
}
public function setParameterFromMixedObjects(array $filterObjects): static
{
foreach ($filterObjects as $obj) {
// set all Towns from region
if ($obj instanceof Region) {
$currentFilters = $this->getTowns();
foreach ($obj->getChildren() as $town) {
if ($town instanceof Town) {
$currentFilters[] = $town->getId();
}
}
$this->setTowns($currentFilters);
continue;
}
$class = get_class($obj);
$classArray = explode('\\', $class);
$setter = 'set' . end($classArray);
$getter = 'get' . end($classArray);
$ssetter = 'set' . end($classArray) . 's';
$sgetter = 'get' . end($classArray) . 's';
if (method_exists($this, $getter) && method_exists($this, $setter)) {
$currentFilters = $this->$getter();
$currentFilters[] = $obj->getId();
$this->$setter($currentFilters);
} elseif (method_exists($this, $sgetter) && method_exists($this, $ssetter)) {
$currentFilters = $this->$sgetter();
$currentFilters[] = $obj->getId();
$this->$ssetter((array)$currentFilters);
}
}
return $this;
}
public function setAccommodationServiceProvider(array $accoIds): Parameter
{
$this->setAccoIds($accoIds);
return $this;
}
#[Pure]
public function getAccommodationServiceProvider(): ?array
{
return $this->getAccoIds();
}
public function setAccommodationProducts($productIds): Parameter
{
$this->setProductIds($productIds);
return $this;
}
#[Pure]
public function getAccommodationProducts(): ?array
{
return $this->getProductIds();
}
public function setLanguage($language): self
{
$this->language = $language;
return $this;
}
public function getLanguage(): ?string
{
return $this->language;
}
public function setCategory($categories): Parameter
{
$cats = [];
foreach ($categories as $cat) {
if (empty($cat)) {
continue;
}
if ($cat instanceof AbstractObject) {
$cats[] = $cat->getId();
} else {
$cats[] = $cat;
}
}
$this->setCategories($cats);
return $this;
}
#[Pure]
public function getCategory(): array
{
return $this->getCategories();
}
public function setFacility($facilities): Parameter
{
$objs = [];
foreach ($facilities as $obj) {
if (empty($obj)) {
continue;
}
if ($obj instanceof AbstractObject) {
$objs[] = $obj->getId();
} else {
$objs[] = $obj;
}
}
$this->setFacilities($objs);
return $this;
}
#[Pure]
public function getFacility(): array
{
return $this->getFacilities();
}
public function setMealType($mealTypeId): Parameter
{
$this->setMealTypeId($mealTypeId);
return $this;
}
#[Pure]
public function getMealType(): ?string
{
return $this->getMealTypeId();
}
public function getFacilityCombinationOperator(): string
{
return $this->facilityCombinationOperator;
}
public function getUseMultiLineMerge(): ?bool
{
return $this->useMultiLineMerge;
}
public function setUseMultiLineMerge(bool $useMultiLineMerge): self
{
$this->useMultiLineMerge = $useMultiLineMerge;
return $this;
}
public function getRoomFacilities(): array
{
return $this->roomFacilities;
}
public function setRoomFacilities(mixed $roomFacilities): self
{
//check if empty
$tmp = [];
if (is_array($roomFacilities)) {
foreach ($roomFacilities as $roomFacility) {
if (!empty($roomFacility)) {
$tmp[] = $roomFacility;
}
}
} elseif (!empty($roomFacilities)) {
$tmp[] = (int)$roomFacilities;
}
$this->roomFacilities = $tmp;
return $this;
}
public function getApartmentFacilities(): array
{
return $this->apartmentFacilities;
}
public function setApartmentFacilities(mixed $apartmentFacilities): self
{
//check if empty
$tmp = [];
if (is_array($apartmentFacilities)) {
foreach ($apartmentFacilities as $apartmentFacility) {
if (!empty($apartmentFacility)) {
$tmp[] = $apartmentFacility;
}
}
} elseif (!empty($apartmentFacilities)) {
$tmp[] = (int)$apartmentFacilities;
}
$this->apartmentFacilities = $tmp;
return $this;
}
public function getExcludeAccoIds(): ?array
{
return $this->excludeAccoIds;
}
public function setExcludeAccoIds(array $excludeAccoIds): self
{
$this->excludeAccoIds = $excludeAccoIds;
return $this;
}
public function getPriority(): ?int
{
return $this->priority;
}
public function setPriority(int $priority): self
{
$this->priority = $priority;
return $this;
}
public function getPriorityOperator(): string
{
return $this->priorityOperator;
}
public function isSpecialsOnly(): mixed
{
return $this->specialsOnly;
}
public function setSpecialsOnly(mixed $specialsOnly): self
{
$this->specialsOnly = $specialsOnly;
return $this;
}
public function isBestpriceOnly(): bool
{
return $this->bestpriceOnly;
}
public function setBestpriceOnly(bool $bestpriceOnly): self
{
$this->bestpriceOnly = $bestpriceOnly;
return $this;
}
public function isBestpriceProvider(): mixed
{
return $this->bestpriceProvider;
}
public function setBestpriceProvider(mixed $bestpriceProvider): self
{
$this->bestpriceProvider = $bestpriceProvider;
return $this;
}
public function getSpecialsOperator(): string
{
return $this->specialsOperator;
}
public function getAllTopsFirst(): bool
{
return $this->allTopsFirst;
}
public function isTicketingOnly(): ?bool
{
return $this->ticketingOnly;
}
public function getStarsTableNeeded(): bool
{
return $this->starsTableNeeded;
}
public function setStarsTableNeeded(bool $starsTableNeeded): self
{
$this->starsTableNeeded = $starsTableNeeded;
return $this;
}
public function getSpecialSpecific(): array
{
return $this->specialSpecific;
}
public function setSpecialSpecific(array $specialSpecific): ?self
{
if (!empty($this->getExcludeSpecialSpecific())) {
return null;
}
$this->specialSpecific = $specialSpecific;
return $this;
}
public function getExcludeSpecialSpecific(): array
{
return $this->excludeSpecialSpecific;
}
public function setExcludeSpecialSpecific(mixed $excludeSpecialSpecific): ?self
{
if (!empty($this->getSpecialSpecific())) {
return null;
}
if (!is_array($excludeSpecialSpecific)) {
$excludeSpecialSpecific = [$excludeSpecialSpecific];
}
$this->excludeSpecialSpecific = $excludeSpecialSpecific;
return $this;
}
public function getFreeCancellation(): bool
{
return $this->freeCancellation;
}
public function setFreeCancellation(bool $freeCancellation): void
{
$this->freeCancellation = $freeCancellation;
}
public function getContentScore(): int
{
return $this->contentScore;
}
public function setContentScore(int $contentScore): void
{
$this->contentScore = $contentScore;
}
public function setBookOnRequestAsBookable(bool $bookOnRequestAsBookable): void
{
$this->bookOnRequestAsBookable = $bookOnRequestAsBookable;
}
}