src/Twig/LayoutExtension.php line 791

Open in your IDE?
  1. <?php
  2. namespace App\Twig;
  3. use App\Model\DataObject\WeatherStation;
  4. use App\Service\CanonicalRedirectHelper;
  5. use App\Service\NewsletterService;
  6. use Carbon\Carbon;
  7. use Pimcore\Cache;
  8. use Pimcore\Config;
  9. use Pimcore\Google\Cse\Item;
  10. use Pimcore\Image;
  11. use Pimcore\Model\Asset;
  12. use Pimcore\Model\DataObject;
  13. use Pimcore\Model\DataObject\AlpsteinRegion;
  14. use Pimcore\Model\DataObject\AlpsteinTour;
  15. use Pimcore\Model\DataObject\BlogTheme;
  16. use Pimcore\Model\DataObject\Community;
  17. use Pimcore\Model\DataObject\DemiInfrastructure;
  18. use Pimcore\Model\DataObject\Fieldcollection\Data\WeatherTextStationDataSet;
  19. use Pimcore\Model\DataObject\MediaUser;
  20. use Pimcore\Model\DataObject\Region;
  21. use Pimcore\Model\DataObject\WeatherAvalancheStation;
  22. use Pimcore\Model\DataObject\WeatherLiveStation;
  23. use Pimcore\Model\DataObject\WeatherTextStation;
  24. use Pimcore\Model\Document;
  25. use Pimcore\Model\Site;
  26. use Pimcore\Tool;
  27. use Pimcore\Translation\Translator;
  28. use Symfony\Component\HttpFoundation\Request;
  29. use Symfony\Component\HttpFoundation\RequestStack;
  30. use Symfony\Component\Intl\Countries;
  31. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  32. use Twig\Extension\AbstractExtension;
  33. use Twig\TwigFunction;
  34. class LayoutExtension extends AbstractExtension
  35. {
  36.     /**
  37.      * @var Config
  38.      */
  39.     private $systemConfig;
  40.     /**
  41.      * @var Translator
  42.      */
  43.     private $translator;
  44.     /**
  45.      * @var LinkGenerator
  46.      */
  47.     private $linkGenerator;
  48.     /**
  49.      * @var RequestStack
  50.      */
  51.     private $requestStack;
  52.     /**
  53.      * @var ObjectExtension
  54.      */
  55.     private $objectExtension;
  56.     private UrlGeneratorInterface $router;
  57.     public const ROOT_DOCUMENT_ID 1;
  58.     /**
  59.      * LayoutExtension constructor.
  60.      * @param Config $systemConfig
  61.      * @param Translator $translator
  62.      * @param LinkGenerator $linkGenerator
  63.      */
  64.     public function __construct(Config $systemConfigTranslator $translatorLinkGenerator $linkGeneratorRequestStack $requestStackObjectExtension $objectExtensionUrlGeneratorInterface $router)
  65.     {
  66.         $this->systemConfig $systemConfig;
  67.         $this->translator $translator;
  68.         $this->linkGenerator $linkGenerator;
  69.         $this->requestStack $requestStack;
  70.         $this->objectExtension $objectExtension;
  71.         $this->router $router;
  72.     }
  73.     /**
  74.      * @return string
  75.      */
  76.     public function getName()
  77.     {
  78.         return "Layout Extension";
  79.     }
  80.     /**
  81.      * @return array|TwigFunction[]
  82.      */
  83.     public function getFunctions()
  84.     {
  85.         return [
  86.             new TwigFunction('getEnv', [$this'getEnv']),
  87.             new TwigFunction('googleApiKey', [$this'googleApiKey']),
  88.             new TwigFunction('selectableIcons', [$this'getSelectableIcons']),
  89.             new TwigFunction('isValidAsset', [$this'isValidAsset']),
  90.             new TwigFunction('getImageDescription', [$this'getImageDescription']),
  91.             new TwigFunction('getImageTexts', [$this'getImageTexts']),
  92.             new TwigFunction('getTourLocation', [$this'getTourLocation']),
  93.             new TwigFunction('getWeatherIcon', [$this'getWeatherIcon']),
  94.             new TwigFunction('getSocialIcons', [$this'getSocialIcons']),
  95.             new TwigFunction('getRegionsArray', [$this'getRegionsArray']),
  96.             new TwigFunction('getIndexFromRegion', [$this'getIndexFromRegion']),
  97.             new TwigFunction('getWeatherPrognosis', [$this'getWeatherPrognosis']),
  98.             new TwigFunction('getThemeByCategoryId', [$this'getThemeByCategoryId']),
  99.             new TwigFunction('getUseRelativeLink', [$this'getUseRelativeLink']),
  100.             new TwigFunction('hostUrl', [$this'getHostUrl']),
  101.             new TwigFunction('getHotspotData', [$this'getHotspotData']),
  102.             new TwigFunction('getCountrySelectData', [$this'getCountrySelectData']),
  103.             new TwigFunction('getPathInfo', [$this'getPathInfo']),
  104.             new TwigFunction('getVideoEditable', [$this'getVideoEditable']),
  105.             new TwigFunction('getNewsletterPools', [$this'getNewsletterPools']),
  106.             new TwigFunction('getMediaUser', [$this'getMediaUser']),
  107.             new TwigFunction('getPressWishlistCount', [$this'getPressWishlistCount']),
  108.             new TwigFunction('getMasterRequest', [$this'getMasterRequest']),
  109.             new TwigFunction('getMainRequest', [$this'getMainRequest']),
  110.             new TwigFunction('randomizeRelationEvery24h', [$this'randomizeRelationEvery24h']),
  111.             new TwigFunction('randomizeBlock', [$this'randomizeBlock']),
  112.             new TwigFunction('getImageType', [$this'getImageType']),
  113.             new TwigFunction('getBadgesForAsset', [$this'getBadgesForAsset']),
  114.             new TwigFunction('getFormattedVideoDuration', [$this'getFormattedVideoDuration']),
  115.             new TwigFunction('getYoutubeIdFromHref', [$this'getYoutubeIdFromHref']),
  116.             new TwigFunction('getAccessiblityObjects', [$this'getAccessiblityObjects']),
  117.             new TwigFunction('getSubttitleOfAudio', [$this'getSubttitleOfAudio']),
  118.             new TwigFunction('checkIfNoRenderletIsValid', [$this'checkIfNoRenderletIsValid']),
  119.             new TwigFunction('getAuthorForQuote', [$this'getAuthorForQuote']),
  120.             new TwigFunction('getCurrentWeatherImage', [$this'getCurrentWeatherImage']),
  121.             new TwigFunction('getWeatherStationByAlpsteinTour', [$this'getWeatherStationByAlpsteinTour']),
  122.             new TwigFunction('getDownloadItemDataByAsset', [$this'getDownloadItemDataByAsset']),
  123.             new TwigFunction('getPackagesByPackageCategories', [$this'getPackagesByPackageCategories']),
  124.             new TwigFunction('hasGetParams', [$this'hasGetParams']),
  125.             new TwigFunction('removeUnpublishedElements', [$this'removeUnpublishedElements']),
  126.             new TwigFunction('chooseDescription', [$this'chooseDescription']),
  127.             new TwigFunction('getMainLogo', [$this'getMainLogo']),
  128.             new TwigFunction('getMainConfig', [$this'getMainConfig']),
  129.             new TwigFunction('getFileContent', [$this'getFileContent']),
  130.             new TwigFunction('getSVGPathForExperienceTeaserBackgroundText', [$this'getSVGPathForExperienceTeaserBackgroundText']),
  131.             new TwigFunction('getObjectImageFromCSEResult', [$this'getObjectImageFromCSEResult']),
  132.             new TwigFunction('getTimeOfDay', [$this'getTimeOfDay']),
  133.             new TwigFunction('getCache', [$this'getCache']),
  134.             new TwigFunction('saveInCache', [$this'saveInCache']),
  135.             new TwigFunction('cachingAllowed', [$this'cachingAllowed']),
  136.             new TwigFunction('getAssetOrientation', [$this'getAssetOrientation']),
  137.         ];
  138.     }
  139.     /**
  140.      * @param array $params
  141.      * @return bool
  142.      */
  143.     public function hasGetParams($params = []) {
  144.         if (empty($params)) {
  145.             return !empty($_GET);
  146.         }
  147.         foreach ($params as $param) {
  148.             if (array_key_exists($param$_GET))  {
  149.                 return true;
  150.             }
  151.         }
  152.         return false;
  153.     }
  154.     public function getEnv(string $envName) {
  155.         return $_ENV[$envName];
  156.     }
  157.     /**
  158.      * @return bool
  159.      */
  160.     public function getUseRelativeLink() {
  161.         return CanonicalRedirectHelper::USE_RELATIVE_LINK;
  162.     }
  163.     /**
  164.      * @param DataObject\DemiAccommodationServiceProvider|DemiInfrastructure $object
  165.      */
  166.     public function getAccessiblityObjects(DataObject $object) {
  167.         $accessibilityCategories = [];
  168.         if ($object->getDemiExtension() && $object->getDemiExtension()->getDemiAccessibilityCategories()) {
  169.             foreach($object->getDemiExtension()->getDemiAccessibilityCategories()->getAccessibilityCategories() ?: [] as $entry) {
  170.                 $category $entry->getObject();
  171.                 $percent $entry->getPercent();
  172.                 if($percent >= 80) {
  173.                     $accessibilityCategories[$category->getId()] = ['category' => $category'percent' => $percent'isTop' => $percent >= 85];
  174.                 }
  175.             }
  176.         }
  177.         return $accessibilityCategories;
  178.     }
  179.     /**
  180.      * @return Request|null
  181.      */
  182.     public function getMasterRequest() {
  183.         return $this->requestStack->getMainRequest();
  184.     }
  185.     /**
  186.      * @return Request|null
  187.      */
  188.     public function getMainRequest() {
  189.         return $this->requestStack->getMainRequest();
  190.     }
  191.     /**
  192.      * @return string[]
  193.      */
  194.     public function getNewsletterPools() {
  195.         return NewsletterService::ALLOWED_NEWSLETTER_LISTS;
  196.     }
  197.     /**
  198.      * @return mixed
  199.      */
  200.     public function googleApiKey() {
  201.         return $this->systemConfig['services']['google']['browser_api_key'];
  202.     }
  203.     /**
  204.      * @return string[][]
  205.      */
  206.     public function getSelectableIcons() {
  207.         return [
  208.             ['''No Icon'],
  209.             ['hiking''<span class="icon icon-hiking" style="font-size: 20px"></span> Hiking'],
  210.             ['baggage''<span class="icon icon-baggage" style="font-size: 20px"></span> Baggage'],
  211.             ['calendar''<span class="icon icon-calendar" style="font-size: 20px"></span> Calendar'],
  212.             ['eye''<span class="icon icon-eye" style="font-size: 20px"></span> Eye'],
  213.             ['heart-outline''<span class="icon icon-heart-outline" style="font-size: 20px"></span> Heart outline'],
  214.             ['heart''<span class="icon icon-heart" style="font-size: 20px"></span> Heart'],
  215.             ['infrastructure''<span class="icon icon-infrastructure" style="font-size: 20px"></span> Infrastructure'],
  216.             ['mountain''<span class="icon icon-mountain" style="font-size: 20px"></span> Mountain'],
  217.             ['regions''<span class="icon icon-regions" style="font-size: 20px"></span> Regions'],
  218.             ['pin''<span class="icon icon-pin" style="font-size: 20px"></span> Pin'],
  219.             ['search''<span class="icon icon-search" style="font-size: 20px"></span> Search'],
  220.             ['sightseeing''<span class="icon icon-sightseeing" style="font-size: 20px"></span> Sightseeing'],
  221.             ['tag''<span class="icon icon-tag" style="font-size: 20px"></span> Tag'],
  222.             ['traffic''<span class="icon icon-traffic" style="font-size: 20px"></span> Traffic'],
  223.             ['corona''<span class="icon icon-corona" style="font-size: 20px"></span> Corona'],
  224.         ];
  225.     }
  226.     /**
  227.      * @param Asset $asset
  228.      * @return bool
  229.      */
  230.     public function isValidAsset(Asset $asset) {
  231.         // check if contains neccessary data based on CC License
  232.         return true;
  233.     }
  234.     /**
  235.      * @param Asset\Image|null $image
  236.      * @return array|false
  237.      * @throws \Exception
  238.      */
  239.     public function getImageTexts(Asset $image null$noCopyrightIfInMetadata falsebool $onlyCopyright false) {
  240.         if (!$image instanceof Asset\Image) {
  241.             return false;
  242.         }
  243.         $arrayKey $image->getId() . ($noCopyrightIfInMetadata '_noCopyright' '');
  244.         $cacheKey $arrayKey '_' $this->requestStack->getCurrentRequest()?->getLocale();
  245.         if (!array_key_exists($arrayKey$this->imageMetadata)) {
  246.             $texts Cache::load($cacheKey);
  247.             if(!$texts) {
  248.                 $metadataCopyright $image->getMetadata('copyright');
  249.                 $copyright null;
  250.                 $metaData $image->getEmbeddedMetaData(true);
  251.                 if (!$noCopyrightIfInMetadata || $metadataCopyright == '') {
  252.                     $copyrightObject $image->getMetadata('General.copyright');
  253.                     if ($copyrightObject instanceof DataObject\MediaCopyright && !($noCopyrightIfInMetadata && $metadataCopyright != '')) {
  254.                         $copyright $copyrightObject->getText();
  255.                     }
  256.                     if ($copyright == '') {
  257.                         $copyright $metadataCopyright;
  258.                         if ($copyright == '') {
  259.                             if (isset($metaData['Copyright']) && $metaData['Copyright']) {
  260.                                 $copyright $metaData['Copyright'];
  261.                             } elseif (isset($metaData['CopyrightNotice']) && $metaData['CopyrightNotice']) {
  262.                                 $copyright $metaData['CopyrightNotice'];
  263.                             } elseif (isset($metaData['Rights'])) {
  264.                                 $copyright $metaData['Rights'];
  265.                             }
  266. //                    $copyright = $metaData['Copyright'] ?: ($metaData['CopyrightNotice'] ?: $metaData['Rights']);
  267.                         }
  268.                     }
  269.                     if ($copyright != '' && strpos($copyright'©') === false) {
  270.                         $copyright '© ' $copyright;
  271.                     }
  272.                 }
  273.                 $title $image->getMetadata('General.title');
  274.                 if ($title == '') {
  275.                     $title $image->getMetadata('title');
  276.                     if ($title == '') {
  277.                         if (isset($metaData['Title']) && $metaData['Title']) {
  278.                             $title $metaData['Title'];
  279.                         } elseif (isset($metaData['ObjectName'])) {
  280.                             $title $metaData['ObjectName'];
  281.                         }
  282. //                    $title = $metaData['Title'] ?: $metaData['ObjectName'];
  283.                     }
  284.                 }
  285.                 $author $image->getMetadata('General.author');
  286.                 if ($author instanceof DataObject\Contact) {
  287.                     $author $author->getName() ?: (trim($author->getFirstname() . ' ' $author->getLastname()));
  288.                 }
  289.                 if ($author == '') {
  290.                     $author $image->getMetadata('author');
  291.                     if ($author == '') {
  292.                         if (isset($metaData['Artist']) && $metaData['Artist']) {
  293.                             $author $metaData['Artist'];
  294.                         } elseif (isset($metaData['Creator']) && $metaData['Creator']) {
  295.                             $author $metaData['Creator'];
  296.                         } elseif (isset($metaData['By-line'])) {
  297.                             $author $metaData['By-line'];
  298.                         }
  299. //                    $author = $metaData['Artist'] ?: ($metaData['Creator'] ?: $metaData['By-line']);
  300.                     }
  301.                 }
  302.                 $texts = [];
  303.                 if ($title != '' && !$onlyCopyright) {
  304.                     $texts['title'] = $title;
  305.                 }
  306.                 if ($copyright != '') {
  307.                     $texts['copyright'] = $copyright;
  308.                 }
  309.                 if ($author != '' && !$onlyCopyright) {
  310.                     $texts['author'] = $author;
  311.                 }
  312.                 $usage $image->getMetadata('General.usage');
  313.                 if ($usage && !$onlyCopyright) {
  314.                     $texts['usage'] = $usage;
  315.                 }
  316.                 // save cache for 4 hours
  317.                 Cache::save($texts$cacheKey, [$image->getCacheTag()], 14400);
  318.             }
  319.             $this->imageMetadata[$arrayKey] = $texts;
  320.         }
  321.         return $this->imageMetadata[$arrayKey];
  322.     }
  323.     protected $imageMetadata = [];
  324.     /**
  325.      * @param Asset\Image|DataObject\Data\Hotspotimage|null $image
  326.      * @return false|string
  327.      * @throws \Exception
  328.      */
  329.     public function getImageDescription($image null$noCopyrightIfInMetadata falsebool $onlyCopyright false) {
  330.         if ($image == null) {
  331.             return false;
  332.         }
  333.         if ($image instanceof DataObject\Data\Hotspotimage) {
  334.             $image $image->getImage();
  335.         }
  336.         if($image instanceof Document\Editable\Image) {
  337.             $image $image->getImage();
  338.         }
  339.         if ($image instanceof Asset\Image) {
  340.             $texts $this->getImageTexts($image$noCopyrightIfInMetadata$onlyCopyright);
  341.         }
  342.         if (!empty($texts)) {
  343.             return implode(' | '$texts );
  344.         }
  345.         return false;
  346.     }
  347.     public function getTourLocation(AlpsteinTour $tour) {
  348.         $location false;
  349.         $regions $tour->getRegions();
  350.         if (isset($regions[0]) && $regions[0]->getElement()) {
  351.             $location $regions[0]->getElement();
  352.         }
  353.         foreach($regions as $regionData){
  354.             if ($regionData->getIsStartingRegion()) {
  355.                 $location $regionData->getElement();
  356.                 break;
  357.             }
  358.         }
  359.         if ($location instanceof AlpsteinRegion) {
  360.             return $location->getName();
  361.         }
  362.         return false;
  363.     }
  364.     public const WEATHER_ICON_MAPPING = [
  365.         '01'    => '01',
  366.         '02'    => '02',
  367.         '03'    => '03',     #wetter_wolkig.svg
  368.         '04'    => '03',
  369.         '05'    => '07',
  370.         '06'    => '12',
  371.         '07'    => '12',
  372.         '08'    => '08',
  373.         '09'    => '06',
  374.         '10'    => '05',
  375.         '11'    => '11',
  376.         '12'    => '11',
  377.         '13'    => '11',
  378.         '14'    => '09',
  379.         '15'    => '10',
  380.         '16'    => '10',
  381.         '17'    => '04',
  382.         '18'    => '04',
  383.         '19'    => '04',
  384.         '20'    => '08',
  385.         '21'    => '08',
  386.         '22'    => '08',
  387.         '23'    => '08',
  388.         '24'    => '08',
  389.         '25'    => '08',
  390.         '26'    => '13',
  391.         '27'    => '13',
  392.         '28'    => '14',
  393.         '29'    => '08',
  394.         '30'    => '10',
  395.         '31'    => '08',
  396.         '32'    => '10',
  397.         '41'    => '01',
  398.         '42'    => '12',
  399.         '43'    => '15',     #wetter_wolkig.svg
  400.         '44'    => '03',
  401.         '45'    => '12',
  402.         '48'    => '12',
  403.         '49'    => '12',
  404.         '61'    => '04',
  405.         '62'    => '04',
  406.         '63'    => '08',     #wetter_leichter_regen.svg
  407.         '64'    => '04',
  408.         '65'    => '04',
  409.         '66'    => '06',
  410.         '67'    => '04',
  411.         '68'    => '05',
  412.         '69'    => '05',
  413.         '71'    => '08',
  414.         '72'    => '08',
  415.         '73'    => '09',
  416.         '74'    => '08',
  417.         '75'    => '08',
  418.         '76'    => '10',
  419.         '77'    => '08',
  420.         '78'    => '10',
  421.         '79'    => '10',
  422.         '81'    => '08',
  423.         '82'    => '08',
  424.         '83'    => '11',
  425.         '84'    => '08',
  426.         '85'    => '08',
  427.         '86'    => '11',
  428.         '87'    => '08',
  429.         '88'    => '11',
  430.         '89'    => '11',
  431.         '90'    => '02',
  432.         '91'    => '13',
  433.         '92'    => '13',
  434.         '93'    => '14',
  435.         '94'    => '13',
  436.         '95'    => '13',
  437.         '96'    => '14',
  438.         '97'    => '08',
  439.         '98'    => '10',
  440.         '99'    => '08',
  441.     ];
  442.     /**
  443.      * @param $symb
  444.      * @return string
  445.      */
  446.     public function getWeatherIcon($symb) {
  447.         return self::WEATHER_ICON_MAPPING[$symb];
  448.     }
  449.     public const SOCIAL_ICONs = [
  450.         "mail",
  451.         "linkedin",
  452.         "instagram",
  453.         "facebook",
  454.         "pinterest",
  455.         "twitter",
  456.         "whatsapp",
  457.         "youtube",
  458.         "tiktok",
  459.     ];
  460.     /**
  461.      * @return array
  462.      */
  463.     public function getSocialIcons() {
  464.         $icons = [];
  465.         foreach (self::SOCIAL_ICONs as $icon) {
  466.             $icons[] = [$icon'<span class=\'icon icon-' $icon '\' style=\'display:inline-block;width: 20px;font-size: 16px\'></span> ' ucfirst($icon)];
  467.         }
  468.         return $icons;
  469.     }
  470.     /**
  471.      * @param bool $includeMainRegion
  472.      * @return array
  473.      */
  474.     public function getRegionsArray($includeMainRegion false) {
  475.         $regions = [
  476.             'regiongraz' => Region::getById(326447),
  477.             'suedweststeiermark' => Region::getById(324085),
  478.             'thermenvulkanland' => Region::getById(326440),
  479.             'schladmingdachstein' => Region::getById(326444),
  480.             'oststeiermark' => Region::getById(326443),
  481.             'hochsteiermark' => Region::getById(326445),
  482.             'murau' => Region::getById(326446),
  483.             'murtal' => Region::getById(1037676),
  484.             'gesaeuse' => Region::getById(326441),
  485.             'ausseerland' => Region::getById(326442),
  486.             'erzbergleoben' => Region::getById(889409),
  487.         ];
  488.         if ($includeMainRegion) {
  489.             $regions array_merge(['steiermark' => Region::getById(324083)], $regions);
  490.         }
  491.         return $regions;
  492.     }
  493.     /**
  494.      * @param Region|null $currentRegion
  495.      * @return int
  496.      */
  497.     public function getIndexFromRegion(Region $currentRegion null$includeMainRegion false) {
  498.         $index 0;
  499.         if ($currentRegion != '') {
  500.             foreach ($this->getRegionsArray($includeMainRegion) as $region) {
  501.                 if ($region->getId() == $currentRegion->getId()) {
  502.                     return $index;
  503.                 }
  504.                 $index++;
  505.             }
  506.         }
  507.         return 0;
  508.     }
  509.     /**
  510.      * @return array
  511.      */
  512.     public function getWeatherPrognosis() {
  513.         $weatherTextStation = new WeatherTextStation\Listing();
  514.         $weatherTextStation->addConditionParam('IFNULL(isMountain,0) = 0');
  515.         $weatherTextStation->setOrderKey('o_modificationdate');
  516.         $weatherTextStation->setOrder('DESC');
  517.         $weatherTextStation->setLimit(1);
  518.         $weatherTextStation $weatherTextStation->current();
  519.         $prognosis = [
  520.             'today' => [],
  521.             'tomorrow' => [],
  522.             'modifiedDate' => null
  523.         ];
  524.         $duplicateTextCheck = [];
  525.         if ($weatherTextStation instanceof WeatherTextStation) {
  526.             /** @var WeatherTextStationDataSet $item */
  527.             foreach ($weatherTextStation->getWeatherData()->getItems() as $item) {
  528.                 $hash md5($item->getTitle() . $item->getText());
  529.                 if (!in_array($hash$duplicateTextCheck)) {
  530.                     if ($item->getDate()->isToday()) {
  531.                         $prognosis['today'][$item->getDaytime()] = [
  532.                             'title' => $item->getTitle(),
  533.                             'text' => $item->getText()
  534.                         ];
  535.                     } else if ($item->getDate()->isTomorrow()) {
  536.                         $prognosis['tomorrow'][$item->getDaytime()] = [
  537.                             'title' => $item->getTitle(),
  538.                             'text' => $item->getText()
  539.                         ];
  540.                     }
  541.                     $duplicateTextCheck[] = $hash;
  542.                 }
  543.             }
  544.             $prognosis['modifiedDate'] = Carbon::createFromTimestamp($weatherTextStation->getModificationDate());
  545.         }
  546.         return $prognosis;
  547.     }
  548.     /**
  549.      * @param $categoryId
  550.      * @return BlogTheme
  551.      */
  552.     public function getThemeByCategoryId($categoryId){
  553.         $blogTheme = new BlogTheme\Listing();
  554.         $blogTheme->addConditionParam('name != "" AND name IS NOT NULL AND blogCategories LIKE :categoryId', ['categoryId' => "%," $categoryId ",%"]);
  555.         $blogTheme->setLimit(1);
  556.         return $blogTheme->current();
  557.     }
  558.     public function getHostUrl() {
  559.         return \Pimcore\Tool::getHostUrl();
  560.     }
  561.     public function getHotspotData($left$top$item null$weatherOnly false$title '') {
  562.         if ($item) {
  563.             $link '';
  564.             $linkText '';
  565.             if ($item instanceof Region && $weatherOnly) {
  566.                 if ($item->getIsLive()) {
  567.                     $link $item->getSiteConfig()->getWeatherOverview();
  568.                     $linkText $item->getNameLocalized() ?: $item->getName();
  569.                 }
  570.                 $item $item->getWeatherLiveStation() ?: $item->getWeatherStation();
  571.             }
  572.             if ($item instanceof Community && $weatherOnly) {
  573.                 $link $this->linkGenerator->generate($item);
  574.                 $linkText $item->getNameLocalized() ?: $item->getName();
  575.                 $item $item->getLiveWeather() ?: $item->getPrognosis();
  576.             }
  577.             if ($item instanceof WeatherLiveStation) {
  578.                 return [
  579.                     'left' => $left,
  580.                     'top' => $top,
  581.                     'value' => $item->getTemperature() . '°',
  582.                     'img' => "/static/img/weather/" $this->getWeatherIcon($item->getSymbol()) . '.svg',
  583.                     'detail' => [
  584.                         'title' => $item->getName() . ', ' $item->getAltitude() . 'm',
  585.                         'subtitle' => '',
  586.                         'link' => [
  587.                             'href' => $link,
  588.                             'text' => $linkText ?: $this->translator->trans('weather.Details')
  589.                         ],
  590.                         'hasWeatherDetail' => true
  591.                     ]
  592.                 ];
  593.             }
  594.             if ($item instanceof WeatherStation) {
  595.                 return [
  596.                     'left' => $left,
  597.                     'top' => $top,
  598.                     'value' => $item->getTempNow() . '°',
  599.                     'img' => "/static/img/weather/" $this->getWeatherIcon($item->getSymbNow()) . '.svg',
  600.                     'detail' => [
  601.                         'title' => $item->getName() . ', ' $item->getAltitude() . 'm',
  602.                         'subtitle' => '',
  603.                         'link' => [
  604.                             'href' => $link,
  605.                             'text' => $linkText ?: $this->translator->trans('weather.Details')
  606.                         ],
  607.                         'hasWeatherDetail' => true
  608.                     ]
  609.                 ];
  610.             }
  611.             if ($item instanceof Region) {
  612.                 return [
  613.                     'left' => $left,
  614.                     'top' => $top,
  615.                     'smallHotspot' => true,
  616.                     'detail' => [
  617.                         'title' => $item->getNameLocalized() ?: $item->getName(),
  618.                         'subtitle' => '',
  619.                         'link' => [
  620.                             'href' => $item->getSiteConfig()->getHome(),
  621.                             'target' => '_blank',
  622.                             'text' => $this->translator->trans('generic.Details')
  623.                         ]
  624.                     ]
  625.                 ];
  626.             }
  627.             if ($item instanceof Community) {
  628.                 return [
  629.                     'left' => $left,
  630.                     'top' => $top,
  631.                     'smallHotspot' => true,
  632.                     'detail' => [
  633.                         'title' => $item->getNameLocalized() ?: $item->getName(),
  634.                         'subtitle' => '',
  635.                         'link' => [
  636.                             'href' => $this->linkGenerator->generate($item),
  637.                             'target' => '_blank',
  638.                             'text' => $this->translator->trans('generic.Details')
  639.                         ]
  640.                     ]
  641.                 ];
  642.             }
  643.             if ($item instanceof WeatherAvalancheStation) {
  644.                 return [
  645.                     'left' => $left,
  646.                     'top' => $top,
  647.                     'isPlain' => true,
  648.                     'avalanche' => 'avalanche-icon-' $item->getSymbol()
  649.                 ];
  650.             }
  651.             if($item instanceof DemiInfrastructure) {
  652.                 return [
  653.                     'left' => $left,
  654.                     'top' => $top,
  655.                     'smallHotspot' => true,
  656.                     'value' => null,
  657.                     'img' => null,
  658.                     'icon' => true,
  659.                     'detail' => true,
  660.                     'title' => $item->getName(),
  661.                     'subtitle' => '',
  662.                     'link' =>  [
  663.                         'href' => $this->linkGenerator->generate($item),
  664.                         'text' => $this->translator->trans('arrival.marker.buttontext'),
  665.                     ]
  666.                 ];
  667.             }
  668.             if($item instanceof Asset\Image) {
  669.                 return [
  670.                     'left' => $left,
  671.                     'top' => $top,
  672.                     'smallHotspot' => true,
  673.                     'value' => null,
  674.                     'img' => null,
  675.                     'icon' => true,
  676.                     'detail' => [
  677.                         'image' => $item,
  678.                     ],
  679.                     'title' => $title ?: $item->getMetadata('General.title'),
  680.                     'subtitle' => '',
  681.                     'isPlain' => false,
  682.                 ];
  683.             }
  684.         }
  685.         return [];
  686.     }
  687.     public function getCountrySelectData($locale 'en'$currentSelectedCountryCode '')  {
  688.         $retArray = [[
  689.             "label" => "",
  690.             "value" => "",
  691.             "disabled" => true,
  692.             "selected" => empty($currentSelectedCountryCode),
  693.             "class" => "sr-only"
  694.         ]];
  695.         foreach (Countries::getNames($locale) as $countryCode => $countryName) {
  696.             $retArray[] = [
  697.                 "label" => $countryName,
  698.                 "value" => $countryCode,
  699.                 "class" => '',
  700.                 "selected" => !empty($currentSelectedCountryCode) && $currentSelectedCountryCode == $countryCode
  701.             ];
  702.         }
  703.         return $retArray;
  704.     }
  705.     public function getPathInfo(string $filename) {
  706.         return pathinfo($filename)['extension'];
  707.     }
  708.     public function getVideoEditable(\Pimcore\Model\DataObject\Data\Video $v$optionalPoster null) {
  709.         $videoData $v->getData();
  710.         if($videoData) {
  711.             $video = new  \Pimcore\Model\Document\Editable\Video();
  712.             $video->setConfig([
  713.                 "thumbnail" => "video"// specify your thumbnail here - IMPORTANT!
  714.                 "attributes" => [
  715.                     "class" => "embed-responsive-item js-play-video__video",
  716.                     "preload" => "auto",
  717.                     "lowQualityPlaceholder" => true,
  718.                     "controls" => "false",
  719.                     "controlsList" => "nodownload",
  720.                 ]
  721.             ]);
  722.             $video->setDataFromEditmode([
  723.                 'type' => $v->getType(),
  724.                 'id' => $videoData instanceof Asset $videoData->getId() : $videoData,
  725.                 'title' => $v->getTitle(),
  726.                 'description' => $v->getDescription(),
  727.                 'poster' => $optionalPoster instanceof Asset\Image $optionalPoster : ($v->getPoster() ?: null)
  728.             ]);
  729.             return $video;
  730.         }
  731.         return null;
  732.     }
  733.     public function getMediaUser(Request $request) {
  734.         $pressSession $request->getSession()->getBag('pressLogin');
  735.         if($userId $pressSession->get('userid')) {
  736.             if($user MediaUser::getById($userId)) {
  737.                 return $user;
  738.             }
  739.         }
  740.         return null;
  741.     }
  742.     public function getPressWishlistCount(Request $request) : int {
  743.         $dossiers $request->getSession()?->get('pressDossierWishlistIds', []);
  744.         $articles $request->getSession()?->get('pressArticleWishlistIds', []);
  745.         $image $request->getSession()?->get('pressImageWishlistIds', []);
  746.         $album $request->getSession()?->get('pressAlbumWishlistIds', []);
  747.         $albumItems $request->getSession()?->get('pressAlbumItemsWishlistIds', []);
  748.         return count($dossiers) + count($articles) + count($image) + count($album) + count($albumItems);
  749.     }
  750.     public function randomizeRelationEvery24h(array $elementsDocument $document) {
  751.         $ids implode(',',array_map(function($element) {
  752.             return $element->getId();
  753.         }, $elements));
  754.         $cacheKey md5('radnomizeRelations' $ids $document->getId());
  755.         if (!($data \Pimcore\Cache::load($cacheKey))) {
  756.             $cacheTime 86400//== 1 day in seconds
  757.             shuffle($elements);
  758.             \Pimcore\Cache::save($elements$cacheKey, [], $cacheTime0true);
  759.             return $elements;
  760.         } else {
  761.             return $data;
  762.         }
  763.     }
  764.     public function randomizeBlock(array $elementsDocument $document) : array {
  765.         $ids implode(',',array_map(function($element) {
  766.             return $element->getEditable('headline')->getData();
  767.         }, $elements));
  768.         $cacheKey md5('randomizeRelations' $ids $document->getId());
  769.         if (!($data \Pimcore\Cache::load($cacheKey))) {
  770.             $cacheTime 86400//== 1 day in seconds
  771.             shuffle($elements);
  772.             \Pimcore\Cache::save($elements$cacheKey, [], $cacheTime0true);
  773.             return $elements;
  774.         } else {
  775.             return $data;
  776.         }
  777.     }
  778.     public function getImageType(Asset $asset) {
  779.         $mimetype $asset->getMimetype();
  780.         $posSlash strpos($mimetype'/' );
  781.         return substr($mimetype$posSlash+1);
  782.     }
  783.     public function getBadgesForAsset(Asset $assetDataObject\MediaAsset $mediaAsset null) {
  784.         $badges = [];
  785.         $categories $asset->getMetadata('General.categories');
  786.         $number $asset->getMetadata('General.number');
  787.         if($mediaAsset instanceof DataObject\MediaAsset) {
  788.             if(!empty($mediaAsset->getCategories())) {
  789.                 $categories $mediaAsset->getCategories();
  790.             }
  791.             if($mediaAsset->getNumber()) {
  792.                 $number $mediaAsset->getNumber();
  793.             }
  794.         }
  795.         if(!empty($categories)) {
  796.             if(is_array($categories)) {
  797.                 $badges[] = $categories[0]->getName();
  798.             } else {
  799.                 $badges[] = $categories->getName();
  800.             }
  801.         }
  802.         if(!empty($number)) {
  803.             $badges[] = $this->translator->trans('general.Nr') . ' ' $number;
  804.         }
  805.         return $badges;
  806.     }
  807.     public function getFormattedVideoDuration(Asset\Video $video) {
  808.         $duration $video->getDuration();
  809.         $mins floor($duration 60);
  810.         if($mins 10) {
  811.             $mins $mins;
  812.         }
  813.         $sec ceil($duration 60);
  814.         if($sec 10) {
  815.             $sec $sec;
  816.         }
  817.         return $mins ':' $sec;
  818.     }
  819.     public function getYoutubeIdFromHref(string $youtubeUrl) {
  820.         $pos strpos($youtubeUrl'v=') + 2;
  821.         return substr($youtubeUrl$pos);
  822.     }
  823.     public function getSubttitleOfAudio(Asset\Audio $audiostring $locale 'de') : string {
  824.         $subtitle '';
  825.         if($copyright $audio->getMetadata('General.copyright'$locale)) {
  826.             $subtitle .= '© ' $copyright->getText();
  827.         }
  828.         /** @var DataObject\PressAuthor $author */
  829.         if($author $audio->getMetadata('General.author')) {
  830.             if(!empty($subtitle)) $subtitle .= '<br>';
  831.             $subtitle .= $author->getName();
  832.         }
  833.         if($description $audio->getMetadata('General.usage'$locale)) {
  834.             if(!empty($subtitle)) $subtitle .= '<br>';
  835.             $subtitle .= $description;
  836.         }
  837.         if($description $audio->getMetadata('General.description'$locale)) {
  838.             if(!empty($subtitle)) $subtitle .= '<br>';
  839.             $subtitle .= $description;
  840.         }
  841.         return $subtitle;
  842.     }
  843.     /**
  844.      * @param Document\Editable\Renderlet[] $renderlets
  845.      * @return bool
  846.      */
  847.     public function checkIfNoRenderletIsValid($renderlets) : bool {
  848.         /**
  849.          * @var Document\Editable\Renderlet $renderlet
  850.          */
  851.         foreach ($renderlets as $renderlet) {
  852.             if(!$renderlet->isEmpty()) {
  853.                 if($renderlet->getType() == 'object') {
  854.                     if(($o $renderlet->getO()) && $o instanceof DataObject) {
  855.                         if($o instanceof DataObject\DemiEvent) {
  856.                             if($this->objectExtension->isEventNotExpired($o)) {
  857.                                 return false;
  858.                             }
  859.                         } elseif($o instanceof DataObject\BlogArticle) {
  860.                             if(!$o->getArticleDate()->isFuture()) {
  861.                                 return false;
  862.                             }
  863.                         } elseif($o instanceof DataObject\Package) {
  864.                             if($this->objectExtension->isPackageNotExpired($o)) {
  865.                                 return false;
  866.                             }
  867.                         }
  868.                     }
  869.                 } else { // is document or asset => cannot expire
  870.                     return false;
  871.                 }
  872.             }
  873.         }
  874.         return true;
  875.     }
  876.     /**
  877.      * @param $object
  878.      * @param string $authorText
  879.      * @return string
  880.      */
  881.     public function getAuthorForQuote($objectstring $authorText) : string {
  882.         if($object instanceof DataObject\PressAuthor) {
  883.             return $object->getName();
  884.         } elseif($object instanceof DataObject\BlogAuthor) {
  885.             return $object->getName();
  886.         } elseif(!empty($authorText)) {
  887.             return $authorText;
  888.         }
  889.         return '';
  890.     }
  891.     public function getCurrentWeatherImage(WeatherStation $weatherStationDataObject\SiteConfig $config) : ?Asset\Image {
  892.         $icon $this->getCurrentWeatherIcon($weatherStation);
  893.         if( $icon !== null ){
  894.             $icon $this->getWeatherIcon$icon ); //get mapped icon
  895.         }
  896.         if($icon && ($image $config->get('icon' $icon))) {
  897.             return $image;
  898.         } elseif($image $config->getIconDefault()) {
  899.             return $image;
  900.         }
  901.         return null;
  902.     }
  903.     public function getWeatherStationByAlpsteinTour(AlpsteinTour $tour) : ?WeatherStation {
  904.         foreach($tour->getRegions() as $region) {
  905.             $region $region->getElement();
  906.             if($region instanceof AlpsteinRegion) {
  907.                 $community $this->getFirstCommunityByAlpsteinRegion($region);
  908.                 if($community && $community->getPrognosis()) {
  909.                     return $community->getPrognosis();
  910.                 }
  911.             }
  912.         }
  913.         return null;
  914.     }
  915.     private function getCurrentWeatherIcon(WeatherStation $weatherStation)
  916.     {
  917.         $currentHour Carbon::now()->hour;
  918.         $today $weatherStation->today();
  919.         if($today) {
  920.             if($currentHour >= && $currentHour 11) { //morning
  921.                 return $today->getSymb06();
  922.             }elseif($currentHour >= 11 && $currentHour 16) { //lunch
  923.                 return $today->getSymb12();
  924.             }elseif($currentHour >= 16 && $currentHour 21) { //evening
  925.                 return $today->getSymb18();
  926.             } else { // night 21-03
  927.                 return $today->getSymb24();
  928.             }
  929.         }
  930.         return null;
  931.     }
  932.     private function getFirstCommunityByAlpsteinRegion(AlpsteinRegion $region) : ?Community {
  933.         $list =  new Community\Listing();
  934.         $list->addConditionParam("alpsteinObjects like '%," $region->getId() .",%'");
  935.         return $list->getCount() > $list->getObjects()[0]: null;
  936.     }
  937.     public function getDownloadItemDataByAsset(Asset $asset) {
  938.         $image false;
  939.         $viewLink false;
  940.         if ($asset instanceof Asset\Image) {
  941.             $image $asset->getThumbnail('download-list-item');
  942.             $viewLink $asset->getFullPath();
  943.         } else if ($asset instanceof Asset\Video) {
  944.             $image $asset->getImageThumbnail('download-list-item');
  945.         } else if ($asset instanceof Asset\Document) {
  946.             $image $asset->getImageThumbnail('download-list-item');
  947.             if ($asset->getMimetype() == 'application/pdf') {
  948.                 $viewLink $asset->getFullPath();
  949.             }
  950.         }
  951.         $filename $asset->getFilename();
  952.         $fileEnding pathinfo($filename)['extension'];
  953.         return [
  954.             'file' => strtoupper($fileEnding),
  955.             'image' => $image,
  956.             'href' => $this->router->generate('app_asset_download', ['id' => $asset->getId()]),
  957.             'text' => $asset->getFilename(),
  958.             'fileSize' => $asset->getFileSize(true),
  959.             'viewLink' =>  $viewLink
  960.         ];
  961.     }
  962.     /**
  963.      * @param DataObject\PackageCategory[] $categories
  964.      */
  965.     public function getPackagesByPackageCategories(array $categories) : array {
  966.         $elements = [];
  967.         $allCategories = [];
  968.         foreach($categories as $category) {
  969.             $this->getChildPackageCategories($category$allCategories);
  970.         }
  971.         $packageListing = new DataObject\Package\Listing();
  972.         $conditions = [];
  973.         foreach ($allCategories as $key => $category) {
  974.             $conditions[] = 'categories LIKE "%,' $key ',%"';
  975.         }
  976.         if(!empty($conditions)) {
  977.             $packageListing->addConditionParam(implode(' OR '$conditions));
  978.         }
  979.         return $packageListing->getObjects();
  980.     }
  981.     public function removeUnpublishedElements(array $elements) : array {
  982.         $publishedElements = [];
  983.         foreach ($elements as $element) {
  984.             if(method_exists($element'getPublished') && $element->getPublished()) {
  985.                 $publishedElements[] = $element;
  986.             }
  987.         }
  988.         return $publishedElements;
  989.     }
  990.     public function chooseDescription(?string $shortDescription, ?string $longDescriptionint $numSignsShortDescription 100) {
  991.         //returns the sD if it has a min. of letters, otherwise returns the lD except it is empty.
  992.         if(strlen($shortDescription) > $numSignsShortDescription) {
  993.             return $shortDescription;
  994.         } elseif(!empty($longDescription)) {
  995.             return $longDescription;
  996.         }
  997.         return $shortDescription;
  998.     }
  999.     /**
  1000.      * @return Asset\Image|null
  1001.      */
  1002.     public function getMainLogo():?Asset\Image{
  1003.         $rootDocument Document::getById(self::ROOT_DOCUMENT_ID);
  1004.         if($rootDocument) {
  1005.             $mainConfig $rootDocument->getProperty('siteConfig');
  1006.             if ($mainConfig) {
  1007.                 $logo $mainConfig->getLogo();
  1008.                 if ($logo instanceof Asset\Image) {
  1009.                     return $logo;
  1010.                 }
  1011.             }
  1012.         }
  1013.         return null;
  1014.     }
  1015.     public function getMainConfig(){
  1016.         $rootDocument Document::getById(self::ROOT_DOCUMENT_ID);
  1017.         if($rootDocument) {
  1018.             $mainConfig $rootDocument->getProperty('siteConfig');
  1019.             if ($mainConfig) {
  1020.                 return $mainConfig->getId();
  1021.             }
  1022.         }
  1023.         return null;
  1024.     }
  1025.     private function getChildPackageCategories(DataObject\PackageCategory $category, array & $categories) {
  1026.         $categories[$category->getId()] = $category;
  1027.         foreach ($category->getChildren() as $child) {
  1028.             if($child instanceof DataObject\PackageCategory) {
  1029.                 $this->getChildPackageCategories($child$categories);
  1030.             }
  1031.         }
  1032.     }
  1033.     public function getFileContent($file) {
  1034.         return file_get_contents$file );
  1035.     }
  1036.     public function getSVGPathForExperienceTeaserBackgroundText(string $textstring $lang) {
  1037.         $mapping = [
  1038.             "discover-en" => "en/discover.svg",
  1039.             "enjoy-en" => "en/enjoy.svg",
  1040.             "experience-en" => "en/experience.svg",
  1041.             "visit-en"  => "en/visit.svg",
  1042.             "discover-de" => "de/entdecken.svg",
  1043.             "enjoy-de" => "de/genießen.svg",
  1044.             "experience-de" => "de/erleben.svg",
  1045.             "visit-de"  => "de/besuchen.svg",
  1046.             "discover-cz" => "cze/objevte.svg",
  1047.             "enjoy-cz" => "cze/užívejte si.svg",
  1048.             "experience-cz" => "cze/zažijte.svg",
  1049.             "visit-cz"  => "cze/navštivte.svg",
  1050.             "discover-hu" => "hun/kalandok.svg",
  1051.             "enjoy-hu" => "hun/élvezetek.svg",
  1052.             "experience-hu" => "hun/élmények.svg",
  1053.             "visit-hu"  => "hun/látnivalók.svg",
  1054.             "discover-nl" => "nl/ontdekken.svg",
  1055.             "enjoy-nl" => "nl/genieten.svg",
  1056.             "experience-nl" => "nl/beleven.svg",
  1057.             "visit-nl"  => "nl/bezoeken.svg",
  1058.             "discover-pl" => "pl/odkryj.svg",
  1059.             "enjoy-pl" => "pl/ciesz się.svg",
  1060.             "experience-pl" => "pl/doświadcz.svg",
  1061.             "visit-pl"  => "pl/odwiedź.svg",
  1062.         ];
  1063.         return $mapping[$text '-' $lang];
  1064.     }
  1065.     public function getObjectImageFromCSEResult(Item $cseItem) {
  1066.         $path parse_url($cseItem->getLink())['path'];
  1067.         $id $this->getIdFromPath($path);
  1068.         if($id) {
  1069.             $object DataObject::getById($id);
  1070.             if($object instanceof DataObject\DemiAccommodationServiceProvider) {
  1071.                 return $object->getImages() ? current($object->getImages()) : null;
  1072.             }
  1073.         }
  1074.         return null;
  1075.     }
  1076.     private function getIdFromPath(string $path) : int {
  1077.         $matches = array();
  1078.         if (preg_match('#(\d+)$#'$path$matches)) {
  1079.             return $matches[1];
  1080.         }
  1081.         return 0;
  1082.     }
  1083.     public function getTimeOfDay(int $hourint $minuteint $second) {
  1084.         $timeString '';
  1085.         if($hour 10) {
  1086.             $timeString .= '0';
  1087.         }
  1088.         $timeString .= $hour ':';
  1089.         if($minute 10) {
  1090.             $timeString .= '0';
  1091.         }
  1092.         $timeString .= $minute ':';
  1093.         if($second 10) {
  1094.             $timeString .= '0';
  1095.         }
  1096.         $timeString .= $second;
  1097.         return $timeString;
  1098.     }
  1099.     public function getCache($cacheKey) {
  1100.         return \Pimcore\Cache::load($cacheKey) ?? false;
  1101.     }
  1102.     public function saveInCache($cacheKey$data$lifetime 86400) {
  1103.         \Pimcore\Cache::save($data$cacheKey, [], $lifetime0true);
  1104.     }
  1105.     public function cachingAllowed() : bool {
  1106.         if($this->getEnv('APP_CACHE') !== 'true') {
  1107.             return false;
  1108.         }
  1109.         $request $this->getMainRequest(); # no caching if pimcore_preview
  1110.         if(Tool::isFrontendRequestByAdmin($request)) {
  1111.             return false;
  1112.         }
  1113.         if($request) {
  1114.             // no caching if path starts with a site root document like /steiermark.com/
  1115.             $sites = new Site\Listing();
  1116.             foreach ($sites as $site) {
  1117.                 if ($site && $site->getRootDocument() instanceof Document\Page) {
  1118.                     if(str_starts_with($request->getPathInfo(), $site->getRootDocument()->getRealFullPath() . '/')) {
  1119.                         return false;
  1120.                     }
  1121.                 }
  1122.             }
  1123.         }
  1124.         return true;
  1125. //        old:
  1126. //        return $this->getEnv('APP_CACHE') === 'true' && !$request?->get('pimcore_preview') && !str_starts_with($request->getPathInfo(), '/steiermark.com/');
  1127.     }
  1128.     public function getAssetOrientation($asset) : string {
  1129.         $orientation 'landscape';
  1130.         if($asset instanceof Asset\Image) {
  1131.             $orientation $asset->getWidth() >= $asset->getHeight() ? 'landscape' 'portrait';
  1132.         }
  1133.         return $orientation;
  1134.     }
  1135. }