src/Elements/Bundle/DemiFrontendBundle/Service/DemiFrontendHelper.php line 186

Open in your IDE?
  1. <?php
  2. /**
  3.  * Elements DeMI
  4.  *
  5.  * This source file is available under the elements DeMI license version 1
  6.  *
  7.  *  @copyright  Copyright (c) elements.at New Media Solutions GmbH (https://www.elements.at/)
  8.  *  @license    elements DeMI Lizenz Version 1 (https://www.elements.at/de/demi-lizenz)
  9.  */
  10. namespace Elements\Bundle\DemiFrontendBundle\Service;
  11. use App\Twig\LayoutExtension;
  12. use Carbon\Carbon;
  13. use Elements\Bundle\CmsToolsBundle\Tool\Helper\ElementsCustomDateFormat;
  14. use Elements\Demi\AbstractObject;
  15. use Elements\Demi\Accommodation\Search\Parameter\RoomRow;
  16. use Elements\Demi\Accommodation\Search\ResultSet;
  17. use Elements\Demi\Deskline\Booking\StandardInformation;
  18. use Elements\Demi\Deskline\Constant\AddressInterface;
  19. use Elements\Demi\Deskline\Constant\DescriptionInterface;
  20. use Elements\Demi\Deskline\Constant\DocumentInterface;
  21. use Elements\Demi\EcommerceFramework\Checkout\SessionCartItem;
  22. use Elements\Demi\Frontend\Service\Configuration;
  23. use Elements\Demi\Model\AccommodationProduct;
  24. use Elements\Demi\Model\AccommodationService;
  25. use Elements\Demi\Model\AccommodationServiceProvider;
  26. use Elements\Demi\Model\DocumentImage;
  27. use Elements\Demi\Model\Event;
  28. use Elements\Demi\Model\HousePackageContainer;
  29. use Elements\Demi\Model\HousePackageMaster;
  30. use Elements\Demi\Model\Infrastructure;
  31. use Elements\Demi\Model\Package;
  32. use Elements\Demi\Model\Stars;
  33. use Exception;
  34. use JetBrains\PhpStorm\ArrayShape;
  35. use Pimcore\Config;
  36. use Pimcore\Db;
  37. use Pimcore\Model\Asset;
  38. use Pimcore\Model\Asset\Image;
  39. use Pimcore\Model\DataObject\DemiAccommodationProduct;
  40. use Pimcore\Model\DataObject\DemiAccommodationServiceProvider;
  41. use Pimcore\Model\DataObject\DemiAdditionalProduct;
  42. use Pimcore\Model\DataObject\DemiAdditionalServiceProvider;
  43. use Pimcore\Model\DataObject\DemiEvent;
  44. use Pimcore\Model\DataObject\DemiInfrastructure;
  45. use Pimcore\Model\DataObject\Fieldcollection\Data\DemiAddress;
  46. use Pimcore\Model\Document;
  47. use Pimcore\Translation\Translator;
  48. class DemiFrontendHelper
  49. {
  50.     public function __construct(protected Translator $translator, protected Configuration $configurationService, protected ElementsCustomDateFormat $elementsCustomDateFormat, protected DemiUrl $demiUrl, protected \Elements\Bundle\DemiFrontendBundle\Service\Stars $accoStarsService, protected LayoutExtension $layoutExtension)
  51.     {
  52.     }
  53.     public function getStars(AccommodationServiceProvider $serviceProviderbool $forceChars false): string
  54.     {
  55.         $stars $serviceProvider->getStars();
  56.         $starArray = [];
  57.         if ($stars instanceof Stars) {
  58.             $starNumbers $stars->getStarsNumbers();
  59.             if (!$forceChars) {
  60.                 $starArray[] = '<span class="star-holder" title="' $starNumbers ' ' ' Stars' '" aria-label="' $starNumbers ' ' ' Stars' '">';
  61.             }
  62.             for ($i 0$i $starNumbers$i++) {
  63.                 if (!$forceChars) {
  64.                     $starArray[] = '<span class="star demi-icon demi-icon-star"></span>';
  65.                 } else {
  66.                     $starArray[] = '*';
  67.                 }
  68.             }
  69.             if ($stars->getIsSuperior()) {
  70.                 if (!$forceChars) {
  71.                     $starArray[] = '<span class="superior">S</span>';
  72.                 } else {
  73.                     $starArray[] = 'S';
  74.                 }
  75.             }
  76.             if (!$forceChars) {
  77.                 $starArray[] = '</span>';
  78.             }
  79.         }
  80.         return implode(''$starArray);
  81.     }
  82.     public function fillTranslation(array $argumentsstring $translationKeystring $lang ''): array|string
  83.     {
  84.         $translation $this->translator->trans($translationKey, [], null$lang);
  85.         foreach ($arguments as $key => $value) {
  86.             $translation str_replace($key$value$translation);
  87.         }
  88.         return $translation;
  89.     }
  90.     /**
  91.      * @param $link
  92.      *
  93.      * @return string
  94.      */
  95.     public function findNiceUrl($link): string
  96.     {
  97.         $pos strpos($link'http://');
  98.         $pos1 strpos($link'https://');
  99.         if ($pos !== false || $pos1 !== false) {
  100.             $newlink $link;
  101.         } else {
  102.             $newlink 'http://' $link;
  103.         }
  104.         if ($newlink === 'http://' || $newlink === 'https://') {
  105.             $newlink '';
  106.         }
  107.         return $newlink;
  108.     }
  109.     public function findFirstRegionforLanguage(string $language): string
  110.     {
  111.         try {
  112.             $languageRegionMapping = include PIMCORE_PATH '/bundles/CoreBundle/Resources/misc/cldr-language-territory-mapping.php';
  113.             if (!$languageRegionMapping) {
  114.                 $languageRegionMapping = include PIMCORE_PATH '/lib/Pimcore/Bundle/CoreBundle/Resources/misc/cldr-language-territory-mapping.php';
  115.             }
  116.         } catch (\Throwable $e) {
  117.             //TODO: is this still necessary?
  118.         }
  119.         return $languageRegionMapping[$language][0];
  120.     }
  121.     public function getAllDemiTranslationKeys(): array
  122.     {
  123.         return array_filter($this->translator->getCatalogue()->all('messages'), static function ($v$k) {
  124.             return str_starts_with($k'demi.');
  125.         }, ARRAY_FILTER_USE_BOTH);
  126.     }
  127.     public function getStaticMapUrl(float $latfloat $lonstring $size '450x300'Bool $marker falsestring $markerColor 'red'int $zoom 15, array $customParams = []): string
  128.     {
  129.         $params = [];
  130.         if ($size != '') {
  131.             $params['size'] = $size;
  132.         }
  133.         if ($marker) {
  134.             $params['markers'] = 'color:' $markerColor ?? 'red';
  135.         }
  136.         if ($zoom != '') {
  137.             $params['zoom'] = $zoom;
  138.         }
  139.         $params['center'] = $lat ',' $lon;
  140.         if (count($customParams) > 0) {
  141.             $params array_merge($params$customParams);
  142.         }
  143.         $queryString http_build_query($params);
  144.         $browserApiKey Config::getSystemConfiguration()['services']['google']['browserapikey'] ?? Config::getSystemConfiguration()['services']['google']['simpleapikey'];
  145.         $queryString .= (($queryString && $browserApiKey '&' '') . ($browserApiKey ? ('key=' $browserApiKey) : ''));
  146.         return '//maps.googleapis.com/maps/api/staticmap?' $queryString;
  147.     }
  148.     public function getGoogleMapsUrl(string $accommodationNameDemiAddress $addressstring $language 'de'float $lat 0.0float $lon 0.0$googlePlaceId nullint $zoom 17): string
  149.     {
  150.         $addressArray = [];
  151.         if ($address->getAddressLine1() != '') {
  152.             $addressArray[] = $address->getAddressLine1();
  153.         }
  154.         if ($address->getAddressLine2() != '') {
  155.             $addressArray[] = $address->getAddressLine2();
  156.         }
  157.         if ($address->getZipcode() != '') {
  158.             $addressArray['zip'] = $address->getZipcode() . ' ';
  159.         }
  160.         if ($address->getTown() != '') {
  161.             $addressArray['zip'] .= $address->getTown() . ' ';
  162.         }
  163.         if ($address->getCity() != '') {
  164.             $addressArray['zip'] .= $address->getCity();
  165.         }
  166.         if ($address->getCountry() != '') {
  167.             $addressArray[] = $address->getCountry();
  168.         }
  169.         $accommodationName str_replace(['/'','], ' '$accommodationName);
  170.         if ($googlePlaceId) {
  171.             return 'https://www.google.com/maps/search/?api=1&query=' urlencode($accommodationName) . '&query_place_id=' $googlePlaceId '&hl=' $language;
  172.         }
  173.         return 'https://www.google.at/maps/dir//' $accommodationName ', ' implode(', '$addressArray) . '/@' $lat ',' $lon ',' $zoom 'z?hl=' $language;
  174.     }
  175.     public function getKeyFromString($string): string|array|null
  176.     {
  177.         $key strtolower(preg_replace('/[^a-zA-Z0-9]/''-'$string));
  178.         return preg_replace_callback('#([\-.~_/]+)#', static function ($matches) {
  179.             return substr($matches[1], 01);
  180.         }, $key);
  181.     }
  182.     public function getOccupancyString(RoomRow $roomRow): string
  183.     {
  184.         $adultStr $this->translator->trans('demi.detail.enquiry.mail.adult', [], 'messages');
  185.         if ($roomRow->getAdults() > 1) {
  186.             $adultStr $this->translator->trans('demi.detail.enquiry.mail.adults');
  187.         }
  188.         $occupancyStr $roomRow->getUnits() . ' x ' $roomRow->getAdults() . ' ' $adultStr;
  189.         if (count($roomRow->getChildAges()) > 0) {
  190.             $kidStr $this->translator->trans('demi.detail.enquiry.mail.child');
  191.             if (count($roomRow->getChildAges()) > 1) {
  192.                 $kidStr $this->translator->trans('demi.detail.enquiry.mail.children');
  193.             }
  194.             $occupancyStr .= ' ' $this->translator->trans('demi.detail.enquiry.mail.and') . ' ' count($roomRow->getChildAges()) . ' ' $kidStr;
  195.             $occupancyStr .= ' (' implode(', '$roomRow->getChildAges()) . ')';
  196.         }
  197.         return $occupancyStr;
  198.     }
  199.     public function getFirstImageForHousePackageMaster(HousePackageMaster $housePackageMasterAccommodationServiceProvider $accommodation$fromDate): Image
  200.     {
  201.         $types $this->getAccoImagesTypesAsArray($housePackageMaster);
  202.         if ($housePackageMaster->getFirstImage($types$fromDate) instanceof Asset) {
  203.             return $housePackageMaster->getFirstImage($types$fromDate);
  204.         }
  205.         $serviceImg null;
  206.         foreach ($housePackageMaster->getProducts() as $accommodationProduct) {
  207.             if ($accommodationProduct->getService()->getFirstImage($types$fromDate) instanceof Asset) {
  208.                 $serviceImg $accommodationProduct->getService()->getFirstImage($types$fromDate);
  209.                 break;
  210.             }
  211.         }
  212.         $imgSrc null;
  213.         if ($serviceImg !== null) {
  214.             $imgSrc $serviceImg;
  215.         } elseif ($accommodation->getFirstImage(null$fromDate) instanceof Asset) {
  216.             $imgSrc $accommodation->getFirstImage(null$fromDate);
  217.         }
  218.         return $imgSrc;
  219.     }
  220.     public function hasRoomDetails(AccommodationProduct $accommodationProductCarbon $dateFromstring $localebool $tableOnSide): bool
  221.     {
  222.         if (!$tableOnSide) {
  223.             return true;
  224.         }
  225.         $service $accommodationProduct->getService();
  226.         $productText $accommodationProduct->getDescription(null$locale$dateFrom);
  227.         if (empty($productText) && $this->configurationService->getFallbackLanguage()) {
  228.             $productText $accommodationProduct->getDescription(null$this->configurationService->getFallbackLanguage(), $dateFrom);
  229.         }
  230.         $serviceText $service->getDescription(null$locale$dateFrom);
  231.         if (empty($serviceText) && $this->configurationService->getFallbackLanguage()) {
  232.             $serviceText $service->getDescription(null$this->configurationService->getFallbackLanguage(), $dateFrom);
  233.         }
  234.         $facilities $service->getFacilities();
  235.         return $productText || $serviceText || ($facilities && count($facilities->getItems()) > 0);
  236.     }
  237.     #[ArrayShape(['hostImages' => "array"'hostDescriptions' => "array"])]
  238.     public function getHostInformation(AccommodationServiceProvider $accommodation): array
  239.     {
  240.         $hostImages = [];
  241.         $hostDescriptions = [];
  242.       if ($accommodation->getAddresses()) {
  243.           foreach ($accommodation->getAddresses() as $address) {
  244.               //16.7.2019 info von christoph ebner - für die Anzeige nur die vom Adresstyp LandLord verwenden!
  245.               if ($address->getAddressType() === AddressInterface::ADDRESS_LANDLORD) {
  246.                   if (!empty($address->getDocuments())) {
  247.                       foreach ($address->getDocuments() as $item) {
  248.                           if($item instanceof DocumentImage){
  249.                               if (($item->getDocumentType() === DocumentInterface::DOCUMENT_TYPE_HOST_INFORMATION) && !in_array($item->getId(), array_keys($hostImages))) {
  250.                                   $hostImages[$item->getId()] = $item->getDocument();
  251.                               }
  252.                           }
  253.                       }
  254.                   }
  255.                   if (!empty($address->getDescriptions())) {
  256.                       foreach ($address->getDescriptions() as $item) {
  257.                           if ($item->getDescriptionType() === DescriptionInterface::DESCRIPTION_SERVICE_PROVIDER_HOST_INFORMATION && $item->getDescriptionLanguage() == $this->translator->getLocale() && !in_array($item->getId(), $hostDescriptionstrue)) {
  258.                               $hostDescriptions[$item->getId()] = $item->getText();
  259.                           }
  260.                       }
  261.                   }
  262.               }
  263.           }
  264.       }
  265.         return ['hostImages' => $hostImages'hostDescriptions' => $hostDescriptions];
  266.     }
  267.     public function getRoomPictures(AccommodationProduct $accommodationProduct, ?Carbon $dateFrom): array
  268.     {
  269.         $serviceImages = [];
  270.         if ($accommodationProduct->getService()) {
  271.             $serviceImages $accommodationProduct->getService()->getImages(null$dateFromfalse);
  272.         }
  273.         $productImages $accommodationProduct->getImages(null$dateFrom);
  274.         return array_merge($productImages$serviceImages);
  275.     }
  276.     public function getCheapestProducts(array $packageProducts) : int
  277.     {
  278.         $myMinPrice 0;
  279.         $productKey 0;
  280.         $count 0;
  281.         foreach ($packageProducts as $product) {
  282.             if (($myMinPrice === || $myMinPrice $product->getBasePrice()) && $product->getBasePrice() != null) {
  283.                 $myMinPrice $product->getBasePrice();
  284.                 $product->getPriceInfo();
  285.                 $productKey $count;
  286.             }
  287.             $count++;
  288.         }
  289.         return $productKey;
  290.     }
  291.     #[ArrayShape(['price' => "int|mixed"'priceInfo' => "mixed"'cP' => "mixed"])]
  292.     public function getMinPriceOfHousePackageMasterResultSet(mixed $resultSet): array
  293.     {
  294.         if (!is_array($resultSet) && $resultSet instanceof ResultSet\HousePackageMaster) {
  295.             $productKeys array_keys($resultSet->getProducts());
  296.             $firstProductId $productKeys[0];
  297.             $cheapestProducts = [$resultSet->getProduct($firstProductId)];
  298.         } else {
  299.             $cheapestProducts $resultSet;
  300.         }
  301.         $price 0;
  302.         if ($cheapestProducts) {
  303.             foreach ($cheapestProducts as $cP) {
  304.                 $price += $cP->getBasePrice();
  305.                 //this is not entirely correct ... price info could vary from room row to roomrow
  306.                 $priceInfo $cP->getPriceInfo();
  307.                 $cheapestProduct $cP;
  308.             }
  309.         }
  310.         return ['price' => $price'priceInfo' => $priceInfo ?? [], 'cP' => $cheapestProduct ?? ''];
  311.     }
  312.     public function getAccoImagesTypesAsArray(AbstractObject $object): ?array
  313.     {
  314.         $types null;
  315.         if ($object instanceof AccommodationServiceProvider || $object instanceof HousePackageMaster) {
  316.             $types $this->configurationService->getImageTypesForAccos();
  317.         }
  318.         if ($types !== null) {
  319.             $typesToUse = [];
  320.             if ($object instanceof HousePackageMaster) {
  321.                 $typesToUse[] = constant(get_class($object->getAdapter()) . '::' 'DOCUMENT_TYPE_PACKAGE');
  322.             }
  323.             foreach ($types as $type) {
  324.                 $typesToUse[] = constant(get_class($object->getAdapter()) . '::' $type);
  325.             }
  326.             return $typesToUse;
  327.         }
  328.         return null;
  329.     }
  330.     public function sortCartItems(array $sessionCartItems): array
  331.     {
  332.         usort($sessionCartItems, static function (SessionCartItem $aSessionCartItem $b) {
  333.             $productA $a->getProduct();
  334.             $parentA $productA->getParent()?->getParent();
  335.             $productB $b->getProduct();
  336.             $parentB $productB->getParent()?->getParent();
  337.             if ($a->getCartItemInfo()->getIsShipping()) {
  338.                 return 1;
  339.             }
  340.             if ($b->getCartItemInfo()->getIsShipping()) {
  341.                 return -1;
  342.             }
  343.             if ($productA instanceof DemiAccommodationProduct && $productB instanceof DemiAccommodationProduct &&
  344.                 $parentA instanceof DemiAccommodationServiceProvider && $parentB instanceof DemiAccommodationServiceProvider) {
  345.                 return -1;
  346.             }
  347.             if ($productA instanceof DemiAccommodationProduct && $productB instanceof DemiAccommodationProduct &&
  348.                 $parentA instanceof DemiAccommodationServiceProvider && $parentB instanceof DemiAdditionalServiceProvider) {
  349.                 return -1;
  350.             }
  351.             if ($productA instanceof DemiAccommodationProduct && $productB instanceof DemiAccommodationProduct &&
  352.                 $parentA instanceof DemiAdditionalServiceProvider && $parentB instanceof DemiAccommodationServiceProvider) {
  353.                 return 1;
  354.             }
  355.             if ($productA instanceof DemiAccommodationProduct && $productB instanceof DemiAccommodationProduct &&
  356.                 $parentA instanceof DemiAdditionalServiceProvider && $parentB instanceof DemiAdditionalServiceProvider) {
  357.                 return -1;
  358.             }
  359.             if ($productA instanceof DemiAccommodationProduct && $productB instanceof DemiAdditionalProduct &&
  360.                 $parentA instanceof DemiAccommodationServiceProvider && $parentB instanceof DemiAccommodationServiceProvider) {
  361.                 return -1;
  362.             }
  363.             if ($productA instanceof DemiAccommodationProduct && $productB instanceof DemiAdditionalProduct &&
  364.                 $parentA instanceof DemiAccommodationServiceProvider && $parentB instanceof DemiAdditionalServiceProvider) {
  365.                 return -1;
  366.             }
  367.             if ($productA instanceof DemiAccommodationProduct && $productB instanceof DemiAdditionalProduct &&
  368.                 $parentA instanceof DemiAdditionalServiceProvider && $parentB instanceof DemiAccommodationServiceProvider) {
  369.                 return -1;
  370.             }
  371.             if ($productA instanceof DemiAccommodationProduct && $productB instanceof DemiAdditionalProduct &&
  372.                 $parentA instanceof DemiAdditionalServiceProvider && $parentB instanceof DemiAdditionalServiceProvider) {
  373.                 return -1;
  374.             }
  375.             if ($productA instanceof DemiAdditionalProduct && $productB instanceof DemiAccommodationProduct &&
  376.                 $parentA instanceof DemiAccommodationServiceProvider && $parentB instanceof DemiAccommodationServiceProvider) {
  377.                 return 1;
  378.             }
  379.             if ($productA instanceof DemiAdditionalProduct && $productB instanceof DemiAccommodationProduct &&
  380.                 $parentA instanceof DemiAccommodationServiceProvider && $parentB instanceof DemiAdditionalServiceProvider) {
  381.                 return -1;
  382.             }
  383.             if ($productA instanceof DemiAdditionalProduct && $productB instanceof DemiAccommodationProduct &&
  384.                 $parentA instanceof DemiAdditionalServiceProvider && $parentB instanceof DemiAccommodationServiceProvider) {
  385.                 return 1;
  386.             }
  387.             if ($productA instanceof DemiAdditionalProduct && $productB instanceof DemiAccommodationProduct &&
  388.                 $parentA instanceof DemiAdditionalServiceProvider && $parentB instanceof DemiAdditionalServiceProvider) {
  389.                 return 1;
  390.             }
  391.             if ($productA instanceof DemiAdditionalProduct && $productB instanceof DemiAdditionalProduct &&
  392.                 $parentA instanceof DemiAccommodationServiceProvider && $parentB instanceof DemiAccommodationServiceProvider) {
  393.                 return -1;
  394.             }
  395.             if ($productA instanceof DemiAdditionalProduct && $productB instanceof DemiAdditionalProduct &&
  396.                 $parentA instanceof DemiAccommodationServiceProvider && $parentB instanceof DemiAdditionalServiceProvider) {
  397.                 return -1;
  398.             }
  399.             if ($productA instanceof DemiAdditionalProduct && $productB instanceof DemiAdditionalProduct &&
  400.                 $parentA instanceof DemiAdditionalServiceProvider && $parentB instanceof DemiAccommodationServiceProvider) {
  401.                 return 1;
  402.             }
  403.             return -1;
  404.         });
  405.         return $sessionCartItems;
  406.     }
  407.     public function getJsonTelephone(DemiAddress $addr): string
  408.     {
  409.         if (method_exists($addr'getPhone') && !empty($addr->getPhone())) {
  410.             return $addr->getPhone();
  411.         }
  412.         if (method_exists($addr'getMobile') && !empty($addr->getMobile())) {
  413.             return $addr->getMobile();
  414.         }
  415.         return '';
  416.     }
  417.     #[ArrayShape(['from' => "string"'tio' => "string"])]
  418.     public function getDestinationPackageRangesAsTimestring(HousePackageContainer|Package $package): array
  419.     {
  420.         $ranges = [];
  421.         if ($package->getValidDates() && $package->getValidDates()->getItems()) {
  422.             foreach ($package->getValidDates()->getItems() as $item) {
  423.                 $from $this->elementsCustomDateFormat->dateToString($item->getDateFrom()->startOfDay());
  424.                 $to $this->elementsCustomDateFormat->dateToString($item->getDateTo()->endOfDay());
  425.                 $ranges[] = ['from' => $from'to' => $to];
  426.             }
  427.         }
  428.         return $ranges;
  429.     }
  430.     public function getDestinationPackageWeekdayDurations(HousePackageContainer|Package $package): array
  431.     {
  432.         $weekdayDurationDaysArray = [];
  433.         foreach ($package->getPackageDuration() as $entry) {
  434.             $getters = [=> 'getSun'=> 'getMon'=> 'getTue'=> 'getWed'=> 'getThu'=> 'getFri'=> 'getSat'];
  435.             foreach ($getters as $weekday => $getter) {
  436.                 if ($entry->$getter()) {
  437.                     if ($weekdayDurationDaysArray[$weekday]) {
  438.                         $weekdayDurationDaysArray[$weekday][] = $entry->getDurationDays() - 1;
  439.                     } else {
  440.                         $weekdayDurationDaysArray[$weekday] = [$entry->getDurationDays() - 1];
  441.                     }
  442.                 }
  443.             }
  444.         }
  445.         return $weekdayDurationDaysArray;
  446.     }
  447.     public function getNextPossibleArrivalDay(HousePackageContainer|Package $package): ?Carbon
  448.     {
  449.         $currentTime time();
  450.         $todayDefinition = new Carbon('now');
  451.         $bookingStopOffset 0;
  452.         if ($package instanceof Package) {
  453.             $bookingStopOffset $package->getBookingstop();
  454.         }
  455.         $todayDefinition->addDays($bookingStopOffset);
  456.         $possibleWeekDays array_keys($this->getDestinationPackageWeekdayDurations($package));
  457.         foreach ($package->getValidDates() as $item) {
  458.             if ($item->getDateFrom()->copy()->subDays($bookingStopOffset)->getTimestamp() >= $currentTime) {
  459.                 //next possible
  460.                 return $item->getDateFrom();
  461.             }
  462.             if (($item->getDateFrom()->getTimestamp() < $currentTime && $item->getDateTo()->getTimestamp() >= $currentTime)
  463.                 || ($item->getDateFrom()->getTimestamp() > $currentTime && $item->getDateFrom()->copy()->subDays($bookingStopOffset)->getTimestamp() < $currentTime)) {
  464.                 //current possible
  465.                 $today $todayDefinition->clone();
  466.                 for ($i 0$i 7$i++) {
  467.                     if (in_array($today->dayOfWeek$possibleWeekDays)) {
  468.                         if ($today->getTimestamp() < $item->getDateTo()->getTimestamp()) {
  469.                             return $today->setTime('0''0''0');
  470.                         }
  471.                     } else {
  472.                         $today->addDay();
  473.                     }
  474.                 }
  475.             }
  476.         }
  477.         return null;
  478.     }
  479.     public function findHousePackageMasterSelfAssignList(Document $docHousePackageMaster $destinationPackage) : ?Document
  480.     {
  481.         $documentListing = new Document\Listing();
  482.         $documentListing->setCondition("path like '" $doc->getRealFullPath() . "%'");
  483.         foreach ($documentListing->load() as $document) {
  484.             if ($document instanceof Document\Page) {
  485.                 $docPackage $document->getProperty('demi_housePackageMasterSelfAssign');
  486.                 if ($docPackage instanceof HousePackageMaster && $docPackage->getId() == $destinationPackage->getId()) {
  487.                     return $document;
  488.                 }
  489.             }
  490.         }
  491.         return null;
  492.     }
  493.     public function findHousePackageContainerList(Document $docHousePackageContainer $destinationPackage): Document\Page|Document|null
  494.     {
  495.         $documentListing = new Document\Listing();
  496.         $documentListing->setCondition("path like '" $doc->getRealFullPath() . "%'");
  497.         foreach ($documentListing->load() as $document) {
  498.             if ($document instanceof Document\Page) {
  499.                 $docPackage $document->getProperty('demi_housePackageContainer');
  500.                 if ($docPackage instanceof HousePackageContainer && $docPackage->getId() == $destinationPackage->getId()) {
  501.                     return $document;
  502.                 }
  503.             }
  504.         }
  505.         return null;
  506.     }
  507.     public function findDestinationPackageAccoList(Document $docPackage $destinationPackage): Document\Page|Document|null
  508.     {
  509.         $documentListing = new Document\Listing();
  510.         $documentListing->setCondition("path like '" $doc->getRealFullPath() . "%'");
  511.         foreach ($documentListing->load() as $document) {
  512.             if ($document instanceof Document\Page && $document->getEditable('package')) {
  513.                 $docPackage $document->getEditable('package')->getElement();
  514.                 if ($docPackage instanceof Package && $docPackage->getId() == $destinationPackage->getId()) {
  515.                     return $document;
  516.                 }
  517.             }
  518.         }
  519.         return null;
  520.     }
  521.     public function getFromFilterElement(Document\Editable\Relation $filterSnippetstring $filterName): array
  522.     {
  523.         $elementArray = [];
  524.         if ($parentElement $filterSnippet->getElement()) {
  525.             $elements $parentElement->getElements();
  526.             foreach ($elements as $key => $element) {
  527.                 if (str_contains($key$filterName)) {
  528.                     $elementArray = [...$elementArray, ...$element->getElements()];
  529.                 }
  530.             }
  531.         }
  532.         return $elementArray;
  533.     }
  534.     public function getDestinationPackageHolidayThemeFilter(Document $documentbool $predefined false): bool|array
  535.     {
  536.         $holidayThemes = [];
  537.         $showOnSiteHolidayThemes $holidayThemesList $holidayThemesObjectList null;
  538.         foreach ($document->getEditables() as $element) {
  539.             if (str_contains($element->getName(), 'showOnSiteDestinationPackagesHolidayThemes')) {
  540.                 $showOnSiteHolidayThemes $element;
  541.             } elseif (str_contains($element->getName(), 'destinationPackagesHolidayThemesList')) {
  542.                 $holidayThemesList $element;
  543.             } elseif (str_contains($element->getName(), 'destinationPackagesHolidayThemesObjectList')) {
  544.                 $holidayThemesObjectList $element;
  545.             }
  546.         }
  547.         if ($holidayThemesObjectList !== null && $holidayThemesList !== null && (($showOnSiteHolidayThemes !== null && $showOnSiteHolidayThemes->isChecked()) || $predefined)) {
  548.             $holidayThemesIds $holidayThemesList->getData() ?: [];
  549.             if (count($holidayThemesIds) == 0) {
  550.                 $holidayThemesIds $holidayThemesObjectList->getData() ?: [];
  551.             }
  552.             foreach ($holidayThemesIds as $id) {
  553.                 $holidayThemes[] = (is_string($id) || is_int($id)) ? \Pimcore\Model\DataObject\AbstractObject::getById($id) : $id;
  554.             }
  555.             return $holidayThemes;
  556.         }
  557.         // predefined filter
  558.         return false;
  559.     }
  560.     public function getDestinationPackageRegionFilter(Document $document): bool|array
  561.     {
  562.         $showOnSiteOwners null;
  563.         foreach ($document->getEditables() as $element) {
  564.             if (str_contains($element->getName(), 'showOnSiteOwners')) {
  565.                 $showOnSiteOwners $element;
  566.             }
  567.         }
  568.         if ($showOnSiteOwners !== null && $showOnSiteOwners->isChecked()) {
  569.             $allOwners = [];
  570.             $dummyPackage = new Package();
  571.             $query 'SELECT DISTINCT owner from object_' $dummyPackage->getClassId();
  572.             $db Db::get();
  573.             $result $db->fetchAll($query);
  574.             foreach ($result as $r) {
  575.                 if ($r['owner'] !== null) {
  576.                     $allOwners[] = $r['owner'];
  577.                 }
  578.             }
  579.             return $allOwners;
  580.         }
  581.         return false;
  582.     }
  583.     public function getStandardInformation(StandardInformation $standardInformationstring $paymentbool $linked false): string|array
  584.     {
  585.         if (stripos($payment'nopayment') !== false) {
  586.             $payment 'NoPayment';
  587.         } else {
  588.             $payment 'Payment';
  589.         }
  590.         $standardInformationType $standardInformation->getType() . $payment;
  591.         $info = match ($standardInformationType) {
  592.             'PackagePayment' => $linked $standardInformation->getPackageLinkedPayment() : $standardInformation->getPackagePayment(),
  593.             'PackageNoPayment' => $linked $standardInformation->getPackageLinkedNoPayment() : $standardInformation->getPackageNoPayment(),
  594.             'CombinedArrangementPayment' => $linked $standardInformation->getCombinedArrangementLinkedPayment() : $standardInformation->getCombinedArrangementPayment(),
  595.             'CombinedArrangementNoPayment' => $linked $standardInformation->getCombinedArrangementLinkedNoPayment() : $standardInformation->getCombinedArrangementNoPayment(),
  596.             default => '',
  597.         };
  598.         return str_replace(['[OPERATORNAME]''[ORGANISATIONNAME]''[INSURANCENAME]''[INSURANCEADDRESS]''<a '],
  599.             [$standardInformation->getOperator(), $standardInformation->getOrganisation(), $standardInformation->getInsuranceName(),
  600.                 $standardInformation->getInsuranceAddress(), '<a target="_blank"'], $info);
  601.     }
  602.     public function getNameAndCopyrightForImage(Image $assetImagebool $noHtml false): string
  603.     {
  604.         $parts = [];
  605.         $imageTexts $this->layoutExtension->getImageTexts($assetImage);
  606.         $parsedCopyright $this->parseImageTexts($imageTextsfalse);
  607.         if ($title $assetImage->getMetadata('title')) {
  608.             $part trim(htmlentities($title));
  609.             if (!$noHtml) {
  610.                 $part str_replace("'"''$part);
  611.                 $part '<span class=\'demi-image-name\'>' $part '</span>';
  612.             }
  613.             $parts[] = $part;
  614.         }
  615.         if ($parsedCopyright) {
  616.             $part trim(htmlentities($parsedCopyright));
  617.             if (!$noHtml) {
  618.                 $part str_replace("'"''$part);
  619.                 $part '<span class=\'demi-image-copyright\'>' $part '</span>';
  620.             }
  621.             $parts[] = $part;
  622.         }
  623.         return implode(' | '$parts);
  624.     }
  625.     public function getStaticImageMap(AccommodationServiceProvider $acco): ?Image
  626.     {
  627.         $town $acco->getTown();
  628.         $district $acco->getDistrict();
  629.         $region $acco->getRegion();
  630.         if ($town && method_exists($town'getImageMap') && $town->getImageMap() instanceof Image) {
  631.             return $town->getImageMap();
  632.         }
  633.         if ($district && method_exists($district'getImageMap') && $district->getImageMap() instanceof Image) {
  634.             return $district->getImageMap();
  635.         }
  636.         if ($region && method_exists($region'getImageMap') && $region->getImageMap() instanceof Image) {
  637.             return $region->getImageMap();
  638.         }
  639.         if ($this->configurationService->getFallbackImageMap() instanceof Image) {
  640.             return $this->configurationService->getFallbackImageMap();
  641.         }
  642.         return null;
  643.     }
  644.     public function getMinBedroomsForFilter()
  645.     {
  646.         $dummy = new AccommodationService();
  647.         $classId $dummy->getClassId();
  648.         $query 'select MIN(bedrooms) as min from object_' $classId;
  649.         $db Db::get();
  650.         $result $db->fetchRow($query);
  651.         return $result['min'] ?: 0;
  652.     }
  653.     public function getMaxBedroomsForFilter()
  654.     {
  655.         $dummy = new AccommodationService();
  656.         $classId $dummy->getClassId();
  657.         $query 'select MAX(bedrooms) as max from object_' $classId;
  658.         $db Db::get();
  659.         $result $db->fetchRow($query);
  660.         return $result['max'] ?: 0;
  661.     }
  662.     public function getDestinationPackageDurationInfo(Package|HousePackageContainer $destinationPackage): string
  663.     {
  664.         $info '';
  665.         if ($destinationPackage->getPackageDuration()) {
  666.             $possibleNights = [];
  667.             foreach ($destinationPackage->getPackageDuration() as $item) {
  668.                 $possibleNights[] = (int)$item->getDurationDays() - 1;
  669.             }
  670.             $singleNight true;
  671.             if (count($possibleNights) > 1|| $possibleNights[0] > 1) {
  672.                 $singleNight false;
  673.             }
  674.             sort($possibleNights);
  675.             if (empty($possibleNights) || (count($possibleNights) == && $possibleNights[0] == 0)) {
  676.                 $info $this->translator->trans('demi.destinationpackage.without-accommodation');
  677.             } else {
  678.                 $info implode(' ' $this->translator->trans('demi.or-short') . ' '$possibleNights) . ' ' $this->translator->trans($singleNight 'demi.night' 'demi.nights');
  679.             }
  680.         }
  681.         return $info;
  682.     }
  683.     public function getLinktypeIconArray(): array
  684.     {
  685.         return [
  686.             => 'link',
  687.             => 'link',
  688.             => 'map',
  689.             => 'play-circle',
  690.             => 'image',
  691.             => 'live-cam',
  692.             => 'facebook',
  693.             => 'link',
  694.             => 'share',
  695.             => 'image',
  696.             10 => 'play-circle',
  697.             11 => 'twitter',
  698.             12 => 'instagram',
  699.             13 => 'foursquare',
  700.             14 => 'tumbler',
  701.             15 => 'youtube',
  702.             16 => 'vimeo',
  703.             17 => 'pinterest',
  704.             18 => 'flickr',
  705.         ];
  706.     }
  707.     public function parseAddressData(AbstractObject $object, array $availableBlocks = []): array
  708.     {
  709.         if (!method_exists($object'getAddresses')) {
  710.             return [];
  711.         }
  712.         if (!empty($object->getAddresses())) {
  713.             foreach ($object->getAddresses() as $address) {
  714.                 //Address Block
  715.                 if (array_key_exists($address->getAddressType(), $availableBlocks)) {
  716.                     $addressBlock = [];
  717.                     if ($address->getCompany() !== '') {
  718.                         $addressBlock[] = $address->getCompany();
  719.                     }
  720.                     if ($address->getFirstname() !== '') {
  721.                         $addressBlock[] = $address->getFirstname() . ' ' $address->getLastname();
  722.                     }
  723.                     if ($address->getAddressLine1() !== '') {
  724.                         $addressBlock[] = $address->getAddressLine1();
  725.                     }
  726.                     if ($address->getAddressLine2() !== '') {
  727.                         $addressBlock[] = $address->getAddressLine2();
  728.                     }
  729.                     if ($address->getZipcode() !== '' || $address->getTown()) {
  730.                         $addressBlock[] = $address->getZipcode() . ' ' $address->getTown();
  731.                     }
  732.                     $availableBlocks[$address->getAddressType()]['inhalt']['address'] = implode('<br>'$addressBlock);
  733.                     $availableBlocks[$address->getAddressType()]['inhalt']['phone'] = $address->getPhone();
  734.                     $availableBlocks[$address->getAddressType()]['inhalt']['mobile'] = $address->getMobile();
  735.                     $availableBlocks[$address->getAddressType()]['inhalt']['mail'] = $address->getEmail();
  736.                     $availableBlocks[$address->getAddressType()]['inhalt']['url'] = $address->getUrl();
  737.                 }
  738.             }
  739.         }
  740.         return $availableBlocks;
  741.     }
  742.     public function parseImageTexts(array|bool $imageTextsbool $withTitle false) : string
  743.     {
  744.         if(!is_array($imageTexts)) {
  745.             return '';
  746.         }
  747.         $text '';
  748.         if ($withTitle && isset($imageTexts['title']) && $imageTexts['title'] !== '') {
  749.             $text $imageTexts['title'];
  750.         }
  751.         if ((isset($imageTexts['copyright']) || isset($imageTexts['author'])) && $withTitle) {
  752.             $text .= ' | ';
  753.         }
  754.         if (isset($imageTexts['copyright'])) {
  755.             $text .= $imageTexts['copyright'];
  756.         }
  757.         if (isset($imageTexts['copyright'], $imageTexts['author'])) {
  758.             $text .= ' | ';
  759.         }
  760.         if (isset($imageTexts['author'])) {
  761.             $text .= $imageTexts['author'];
  762.         }
  763.         return $text;
  764.     }
  765.     public function getBookingLink(DemiEvent|DemiInfrastructure $objectstring $language): string
  766.     {
  767.         $detailPath $this->configurationService->getAdditionalServiceDetailPath($language);
  768.         if (!empty($detailPath)) {
  769.             foreach ($object->getConnectedEntries() as $connectedEntry) {
  770.                 if ($connectedEntry instanceof \Elements\Demi\Model\AdditionalService) {
  771.                     return $this->demiUrl->__invoke([
  772.                         'name' => $connectedEntry->getName(),
  773.                         'id' => $connectedEntry->getId(),
  774.                         'path' => $detailPath->getFullPath()
  775.                     ], 'demi_additionalservice_detail'true);
  776.                 }
  777.             }
  778.         }
  779.         return "";
  780.     }
  781.     #[ArrayShape(['id' => "int"'image' => "object""link" => "string"])]
  782.     public function getConnectedEntries(DemiEvent|DemiInfrastructure|DemiAccommodationServiceProvider $objectstring $language, array $types = ['Event''Infrastructure''AdditionalService''AccommodationServiceProvider']): array
  783.     {
  784.         $entries = [];
  785.         foreach ($object->getConnectedEntries() as $connectedEntry) {
  786.             if ($connectedEntry instanceof \Elements\Demi\Model\AdditionalService && in_array('AdditionalService'$types)) {
  787.                 $detailPath $this->configurationService->getAdditionalServiceDetailPath($language);
  788.                 if (!empty($detailPath)) {
  789.                     $path $this->demiUrl->__invoke([
  790.                         'name' => $connectedEntry->getName(),
  791.                         'id' => $connectedEntry->getId(),
  792.                         'path' => $detailPath->getFullPath()
  793.                     ], 'demi_additionalservice_detail'true);
  794.                     $entries[] = [
  795.                         'id' => $connectedEntry->getId(),
  796.                         'image' => $connectedEntry->getFirstImage(),
  797.                         'link' => $path,
  798.                         'title' => $connectedEntry->getName(),
  799.                         'type' => "additionalService"
  800.                     ];
  801.                 }
  802.             } else if ($connectedEntry instanceof Infrastructure && in_array('Infrastructure'$types)){
  803.                 $detailPath $this->configurationService->getInfrastructureDetailPath($language);
  804.                 if (!empty($detailPath)) {
  805.                     $path $this->demiUrl->__invoke([
  806.                         'name' => $connectedEntry->getName(),
  807.                         'id' => $connectedEntry->getId(),
  808.                         'path' => $detailPath->getFullPath()
  809.                     ], 'demi_infrastructure_detail'true);
  810.                     $entries[] = [
  811.                         'id' => $connectedEntry->getId(),
  812.                         'image' => $connectedEntry->getFirstImage(),
  813.                         'link' => $path,
  814.                         'title' => $connectedEntry->getName(),
  815.                         'type' => "infrastructure"
  816.                     ];
  817.                 }
  818.             } else if ($connectedEntry instanceof Event && in_array('Event'$types)){
  819.                 $detailPath $this->configurationService->getEventDetailPath($language);
  820.                 if (!empty($detailPath)) {
  821.                     $path $this->demiUrl->__invoke([
  822.                         'name' => $connectedEntry->getName(),
  823.                         'id' => $connectedEntry->getId(),
  824.                         'path' => $detailPath->getFullPath()
  825.                     ], 'demi_event_detail'true);
  826.                     $entries[] = [
  827.                         'id' => $connectedEntry->getId(),
  828.                         'image' => $connectedEntry->getFirstImage(),
  829.                         'link' => $path,
  830.                         'title' => $connectedEntry->getName(),
  831.                         'type' => "event"
  832.                     ];
  833.                 }
  834.             } else if ($connectedEntry instanceof AccommodationServiceProvider && in_array('AccommodationServiceProvider'$types)){
  835.                 $path $this->demiUrl->__invoke([
  836.                     'accommodation' => $connectedEntry
  837.                 ], 'demi_acco_detail_page'true);
  838.                 $entries[] = [
  839.                     'id' => $connectedEntry->getId(),
  840.                     'image' => $connectedEntry->getFirstImage(),
  841.                     'link' => $path,
  842.                     'title' => $this->accoStarsService->getAccoNameWithStars($connectedEntry),
  843.                     'type' => 'accommodation'
  844.                 ];
  845.             }
  846.         }
  847.         return $entries;
  848.     }
  849. }