<?php
/**
* Created by Elements.at New Media Solutions GmbH
*
*/
namespace App\Service;
use Carbon\Carbon;
use Elements\Bundle\SeoHelperBundle\Service\PrettyUrl;
use Exception;
use Pimcore\Model\DataObject;
use Pimcore\Model\DataObject\Lift;
use Pimcore\Model\DataObject\Listing\Concrete;
use Pimcore\Model\DataObject\Miscellaneous;
use Pimcore\Model\DataObject\Resort;
use Pimcore\Model\DataObject\Slope;
use Pimcore\Model\Document\Editable;
class FacilityService
{
const NO_INFORMATION = 0;
const OPEN = 1;
const IN_PREPARATION = 2;
const CLOSED_TECHNICAL = 3;
const CLOSED_OPERATIONAL = 5;
const CLOSED_ATMOSPHERIC = 6;
const OUT_OF_ORDER = 7;
const SLOPE_OPEN = 8;
const SLOPE_IN_PREPARATION = 9;
const SLOPE_CLOSED_AVALANCHE = 10;
const SLOPE_CLOSED_ICE = 11;
const SLOPE_CLOSED_WIND = 12;
const SLOPE_CLOSED_STORM = 13;
const SLOPE_OUT_OF_ORDER = 14;
const SLOPE_CLOSED = 15;
const CLOSED = 16;
const DAY_OF_REST = 17;
const COMPANY_VACATION = 18;
public function __construct(protected PrettyUrl $prettyUrl, protected FormService $formService)
{
}
/**
* @param Editable|null $resortRelations
*
* @return array<mixed>
*/
public function getResortTabs(Editable $resortRelations = null, ?string $date = null): array
{
$listing = new Resort\Listing();
$resorts = $resortRelations && !$resortRelations->isEmpty() && method_exists($resortRelations, 'getElements') ? $resortRelations->getElements() : $listing->load();
return array_map(function ($r) use ($resorts, $date) {
return [
'text' => $r->getName(),
'id' => $r->getId(),
'targetId' => 'tab-' . $r->getId(),
'isActive' => $r->getId() == $resorts[0]->getId(),
'contentUrl' => $this->prettyUrl->prettyUrl([ 'tab' => $r->getId(), 'date' => $date ], 'facility_tab'),
];
}, $resorts);
}
/**
* @return array<mixed>
*/
public function getFacilitiesCount(): array
{
$resort = new Resort\Listing();
$resort->addConditionParam('openLiftCount != 0 OR totalLiftCount != 0 OR openSlopeLength != 0 OR totalSlopeLength != 0');
$resort->setLimit(1);
$resort = $resort->current();
return [
'openLifts' => $resort ? $resort->getOpenLiftCount() : 0,
'totalLifts' => $resort ? $resort->getTotalLiftCount() : 0,
'openSlopes' => $resort ? $resort->getOpenSlopeLength() : 0,
'totalSlopes' => $resort ? $resort->getTotalSlopeLength() : 0,
];
}
/**
* @param Resort|null $resort
*
* @return array<mixed>
*
* @throws Exception
*/
public function getFacilitiesViewData(Resort $resort = null, string $date = null): array
{
if (!$resort instanceof Resort) {
return [];
}
$conditions = [ 'area__id = :resortId' ];
$params = [ 'resortId' => $resort->getId() ];
if ($date) {
$date = Carbon::createFromFormat('Y-m-d\\T00:00:00', $date)->startOfDay();
$conditions[] = 'o_id IN (select distinct id from bundle_recurringdates_occurrences where (dateFrom >= :dateFrom and dateTo <= :dateTo))';
$params['dateFrom'] = $date->format('Y-m-d H:i:s');
$params['dateTo'] = $date->endOfDay()->format('Y-m-d H:i:s');
$slopes = [];
} else {
$slopes = $this->filterAndSortListing(new Slope\Listing(), $conditions, $params);
}
$lifts = $this->filterAndSortListing(new Lift\Listing(), $conditions, $params);
$misc = $this->filterAndSortListing(new Miscellaneous\Listing(), $conditions, $params);
$salesPoints = $this->filterAndSortListing(new Miscellaneous\Listing(), $conditions, $params, true);
$lifts = $this->customSortFunction($lifts->load());
$mappedLiftTypes = [];
foreach ($lifts as $lift) {
$mappedLiftType = $this->getTypeImageMapping($lift);
if (!in_array($mappedLiftType, $mappedLiftTypes)) {
$mappedLiftTypes[] = $mappedLiftType;
}
}
return [
'modificationDate' => $this->getModificationDate(),
'snippet' => $resort->getSnippet(),
'liftTypes' => $mappedLiftTypes,
'slopeTypes' => $slopes ? $this->formService->getRelatedObjects($slopes, 'facilityType') : [],
'lifts' => $lifts,
'slopes' => $slopes ? $this->customSortFunction($slopes->load()) : [],
'misc' => $this->customSortFunction($misc->load()),
'salesPoints' => $this->customSortFunction($salesPoints->load()),
'weather' => DataObject\Weather::getByArea($resort, 1),
];
}
public function getTypeImageMapping(Lift $lift): string
{
$type = $lift->getFacilityType();
if (in_array($type, ['4', '5', '6', '7'])) {
$type = '9';
}
return $type;
}
public function isOpen(?DataObject $object = null): bool
{
if ($object && method_exists($object, 'getStatus') &&
($object->getStatus() == FacilityService::OPEN || $object->getStatus() == FacilityService::SLOPE_OPEN)) {
return true;
}
return false;
}
/**
* @param Concrete $listing
* @param array<mixed> $conditions
* @param array<mixed> $params
* @param bool $salesPoint
*
* @return Concrete
*/
private function filterAndSortListing(Concrete $listing, array $conditions = [], array $params = [], bool $salesPoint = false): Concrete
{
if ($listing instanceof Miscellaneous\Listing) {
$listing->addConditionParam('showOnWebsite = 1');
if($salesPoint) {
$listing->addConditionParam('isSalesPoint = 1');
} else {
$listing->addConditionParam('isSalesPoint IS NULL OR isSalesPoint != 1');
}
} else {
$listing->addConditionParam('hideOnWebsite IS NULL OR hideOnWebsite != 1');
}
if ($listing instanceof Lift\Listing) {
if (!array_key_exists('dateFrom', $params) && !array_key_exists('dateTo', $params) || array_key_exists('dateFrom', $params) && Carbon::parse($params['dateFrom'])->isToday()) {
$listing->addConditionParam('status = :open', [
'open' => FacilityService::OPEN,
]);
$conditions[] = 'o_id IN (select distinct id from bundle_recurringdates_occurrences where (dateFrom >= :dateFrom and dateTo <= :dateTo))';
$params['dateFrom'] = Carbon::now()->startOfDay()->format('Y-m-d H:i:s');
$params['dateTo'] = Carbon::now()->endOfDay()->format('Y-m-d H:i:s');
}
} else {
$listing->addConditionParam('status != :outOfOrder AND status != :slopeOutOfOrder', [
'outOfOrder' => FacilityService::OUT_OF_ORDER,
'slopeOutOfOrder' => FacilityService::SLOPE_OUT_OF_ORDER,
]);
if ($listing instanceof Slope\Listing) {
$listing->addConditionParam('status != :noInformation', [
'noInformation' => FacilityService::NO_INFORMATION,
]);
}
}
if ($conditions != []) {
$listing->addConditionParam(implode(' AND ', $conditions), $params);
}
$listing->setOrderKey(['status', 'sort']);
$listing->setOrder('ASC');
return $listing;
}
private function getModificationDate(): int
{
$lifts = new Lift\Listing();
$lifts->addConditionParam('hideOnWebsite IS NULL OR hideOnWebsite != 1');
$lifts->setOrderKey('o_modificationDate');
$lifts->setOrder('DESC');
$lifts->setLimit(1);
$lastModificatedLift = $lifts->current();
return $lastModificatedLift->getModificationDate();
}
/**
* @param array<mixed> $objects
*
* @return array<mixed>
*/
private function customSortFunction(array $objects): array
{
usort($objects, function ($a, $b) {
$statusA = $a->getStatus();
$statusB = $b->getStatus();
if ($statusA == 0) {
return 1;
}
if ($statusB == 0) {
return -1;
}
$statusComparison = $statusA - $statusB;
if ($statusComparison !== 0) {
return $statusComparison;
}
return $a->getSort() - $b->getSort();
});
return $objects;
}
}