diff --git a/packages/ep_products/Classes/Controller/AjaxTableController.php b/packages/ep_products/Classes/Controller/AjaxTableController.php index 0023b37..afd71e4 100644 --- a/packages/ep_products/Classes/Controller/AjaxTableController.php +++ b/packages/ep_products/Classes/Controller/AjaxTableController.php @@ -126,7 +126,7 @@ class AjaxTableController extends ActionController ?string $dateFrom = null, ?string $dateTo = null ): ResponseInterface { - $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true); + $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'] ?? '', true); $filterSettings = $this->filterService->getNormalizedFilterSettings([], $forcedConceptUids); $filterSettings['dateFrom'] = $dateFrom; $filterSettings['dateTo'] = $dateTo; @@ -184,7 +184,7 @@ class AjaxTableController extends ActionController $hasSurchargeOrDiscount = $this->dateService->checkSurcharcheOrDiscount($allDates); // $hasIncludedServices = $this->dateService->hasIncludedServices($allDates); $hasIncludedServices = true; - $noInfoConceptUids = GeneralUtility::trimExplode(',', $this->settings['noInfoConceptUids']); + $noInfoConceptUids = GeneralUtility::trimExplode(',', $this->settings['noInfoConceptUids'] ?? ''); $isProductWithNoInfoConcept = ($product->getConcept() !== null) && \in_array($product->getConcept()->getUid(), $noInfoConceptUids, false); @@ -223,7 +223,7 @@ class AjaxTableController extends ActionController Date $date, bool $singleDate = false ): ResponseInterface { - $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true); + $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'] ?? '', true); $filterSettings = $this->filterService->getNormalizedFilterSettings([], $forcedConceptUids); $myEpUrl = $this->myEpUrlResolverService->resolve(); @@ -242,7 +242,7 @@ class AjaxTableController extends ActionController $dateEnd = $date ? $date->getDateEnd()->format('d.m.y') : ''; $dateRange = sprintf('%s - %s', $dateStart, $dateEnd); - $noInfoConceptUids = GeneralUtility::trimExplode(',', $this->settings['noInfoConceptUids']); + $noInfoConceptUids = GeneralUtility::trimExplode(',', $this->settings['noInfoConceptUids'] ?? ''); $isProductWithNoInfoConcept = ($product->getConcept() !== null) && \in_array($product->getConcept()->getUid(), $noInfoConceptUids); $nonBookableInfo = $this->getNonBookableInfobox($product); @@ -298,7 +298,7 @@ class AjaxTableController extends ActionController */ public function eventPricetableAction(Product $product): ResponseInterface { - $roomTypes = GeneralUtility::trimExplode(',', $this->settings['priceTableRoomTypes']); + $roomTypes = GeneralUtility::trimExplode(',', $this->settings['priceTableRoomTypes'] ?? ''); $roomTypesPax = array_map(function ($type) { return (int) $type; }, $roomTypes); @@ -326,7 +326,7 @@ class AjaxTableController extends ActionController 'pricetable' => $priceTable, 'hasIncludedServices' => $hasIncludedServices, 'categories' => $categories, - 'themekey' => $this->settings['themekey'], + 'themekey' => ($this->settings['themekey'] ?? null), 'nonBookableInfo' => $nonBookableInfo, 'myEpUrl' => $myEpUrl, ]); diff --git a/packages/ep_products/Classes/Controller/ProductController.php b/packages/ep_products/Classes/Controller/ProductController.php index 9bc3f8a..30e1562 100644 --- a/packages/ep_products/Classes/Controller/ProductController.php +++ b/packages/ep_products/Classes/Controller/ProductController.php @@ -130,8 +130,8 @@ class ProductController extends ActionController ): ResponseInterface { // Get product to display from flexform settings if not provided via url if ($product === null) { - $productUid = $this->settings['productUid']; - $product = $this->productRepository->findByIdentifier($productUid); + $productUid = ($this->settings['productUid'] ?? null); + $product = $productUid ? $this->productRepository->findByIdentifier($productUid) : null; } // Redirect to search page in case no product can be determined if ($product === null) { @@ -141,12 +141,12 @@ class ProductController extends ActionController 'Search', null, ['filterSettings' => $filterSettings], - $this->settings['defaultSearchPageUid'] + ($this->settings['defaultSearchPageUid'] ?? null) ); } // Get hotel to display from flexform settings if not provided via url - if ((int)$this->settings['hotelUid'] > 0) { - $hotelUid = $this->settings['hotelUid']; + if ((int)($this->settings['hotelUid'] ?? null) > 0) { + $hotelUid = ($this->settings['hotelUid'] ?? null); $hotel = $this->hotelRepository->findByIdentifier($hotelUid); } if ($hotel === null) { @@ -165,11 +165,11 @@ class ProductController extends ActionController } $concept = $product->getConcept(); - $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'], true); + $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'] ?? '', true); $isProductWithExcludedConcept = ($concept !== null) && \in_array($concept->getUid(), $excludedConceptUids); - $noInfoConceptUids = GeneralUtility::trimExplode(',', $this->settings['noInfoConceptUids'], true); + $noInfoConceptUids = GeneralUtility::trimExplode(',', $this->settings['noInfoConceptUids'] ?? '', true); $isProductWithNoInfoConcept = ($concept !== null) && \in_array($concept->getUid(), $noInfoConceptUids); - $groupInquiryFormConceptUids = GeneralUtility::trimExplode(',', $this->settings['groupInquiryFormConceptUids'], true); + $groupInquiryFormConceptUids = GeneralUtility::trimExplode(',', $this->settings['groupInquiryFormConceptUids'] ?? '', true); $isProductWithGroupInquiryForm = ($concept !== null) && \in_array($concept->getUid(), $groupInquiryFormConceptUids); $nonBookableInfo = $product->getNonBookableInfo(); @@ -198,10 +198,10 @@ class ProductController extends ActionController public function pricetableAction(): ResponseInterface { - $productUid = $this->settings['productUid']; + $productUid = ($this->settings['productUid'] ?? null); /** @var Product $product */ $product = $this->productRepository->findByIdentifier($productUid); - $hotelUid = $this->settings['hotelUid']; + $hotelUid = ($this->settings['hotelUid'] ?? null); /** @var Hotel $hotel */ $hotel = $this->hotelRepository->findByIdentifier($hotelUid); $pricetable = $this->dateService->getPriceTable([ @@ -230,14 +230,14 @@ class ProductController extends ActionController public function teasergroupAction(): ResponseInterface { $filterSettings = $this->filterService->getFiltersettingsFromSettings($this->settings); - $dateAuto = !$this->settings['dateFrom'] && !$this->settings['dateTo']; - $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'], true); - $limit = $this->settings['hideMoreLink'] ? 0 : 6; + $dateAuto = !($this->settings['dateFrom'] ?? null) && !($this->settings['dateTo'] ?? null); + $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'] ?? '', true); + $limit = ($this->settings['hideMoreLink'] ?? null) ? 0 : 6; $teasers = $this->productDataService->getTeasergroup($filterSettings, $excludedConceptUids, $limit); - $dateFrom = $this->settings['dateFrom'] ? date('Y-m-d', $this->settings['dateFrom']) : null; - $dateTo = $this->settings['dateTo'] ? date('Y-m-d', $this->settings['dateTo']) : null; + $dateFrom = ($this->settings['dateFrom'] ?? null) ? date('Y-m-d', ($this->settings['dateFrom'] ?? null)) : null; + $dateTo = ($this->settings['dateTo'] ?? null) ? date('Y-m-d', ($this->settings['dateTo'] ?? null)) : null; $data = $this->request->getAttribute('currentContentObject')->data; - $nonBookableInfo = $this->settings['infoboxUid'] ? $this->infoboxRepository->findByUid($this->settings['infoboxUid']) : $this->infoboxRepository->getDefault(); + $nonBookableInfo = ($this->settings['infoboxUid'] ?? null) ? $this->infoboxRepository->findByUid($this->settings['infoboxUid']) : $this->infoboxRepository->getDefault(); $this->view->assign('data', $data); $this->view->assign('teasers', $teasers); diff --git a/packages/ep_products/Classes/Service/DateService.php b/packages/ep_products/Classes/Service/DateService.php index 95e54eb..52f4bf1 100644 --- a/packages/ep_products/Classes/Service/DateService.php +++ b/packages/ep_products/Classes/Service/DateService.php @@ -267,7 +267,7 @@ class DateService implements SingletonInterface } if (!array_key_exists($key, $processed)) { $processed[$key] = [ - 'label' => $this->serviceSections[$key], + 'label' => $this->serviceSections[$key] ?? null, 'services' => [], ]; } @@ -436,7 +436,7 @@ class DateService implements SingletonInterface public function hasIncludedServices(array $tableData): bool { foreach ($tableData as $row) { - if ($row['busIncluded'] || $row['skiPassIncluded']) { + if (($row['busIncluded'] ?? null) || ($row['skiPassIncluded'] ?? null)) { return true; } } @@ -516,10 +516,10 @@ class DateService implements SingletonInterface ]; foreach ($tableData as $row) { - if ($row['busPrice'] && $row['busPrice'] > 0) { + if (($row['busPrice'] ?? null) && $row['busPrice'] > 0) { $data['surcharge'] = true; } - if ($row['discount'] && $row['discount'] < 0) { + if (($row['discount'] ?? null) && $row['discount'] < 0) { $data['discount'] = true; } } diff --git a/packages/ep_products/Classes/Service/HotelDataService.php b/packages/ep_products/Classes/Service/HotelDataService.php index e5fa649..9a37881 100644 --- a/packages/ep_products/Classes/Service/HotelDataService.php +++ b/packages/ep_products/Classes/Service/HotelDataService.php @@ -88,20 +88,20 @@ class HotelDataService implements SingletonInterface return [ 'minDateStart' => $dateStart, 'maxDateEnd' => $dateEnd, - 'minPrice' => $hotelData['minPrice'], - 'pseudoPrice' => $hotelData['pseudoPrice'], - 'available' => $hotelData['available'], - 'detailPage' => $hotelData['hotelDetailPage'], - 'name' => $hotelData['hotelName'], - 'teaser' => $hotelData['hotelTeaser'], + 'minPrice' => $hotelData['minPrice'] ?? null, + 'pseudoPrice' => $hotelData['pseudoPrice'] ?? null, + 'available' => $hotelData['available'] ?? null, + 'detailPage' => $hotelData['hotelDetailPage'] ?? null, + 'name' => $hotelData['hotelName'] ?? null, + 'teaser' => $hotelData['hotelTeaser'] ?? null, 'category' => $hotelCategory, 'images' => $this->hotelImageService->getImages($hotelUid), 'country' => [ - 'name' => $hotelData['country'], - 'code' => $hotelData['countryCode'], + 'name' => $hotelData['country'] ?? null, + 'code' => $hotelData['countryCode'] ?? null, ], 'region' => [ - 'name' => $hotelData['regionName'], + 'name' => $hotelData['regionName'] ?? null, ] ]; } diff --git a/packages/ep_products/Classes/Service/ProductDataService.php b/packages/ep_products/Classes/Service/ProductDataService.php index f1d65b2..f8085cc 100644 --- a/packages/ep_products/Classes/Service/ProductDataService.php +++ b/packages/ep_products/Classes/Service/ProductDataService.php @@ -131,11 +131,11 @@ class ProductDataService implements SingletonInterface $teaser['dates'][] = $row['dateStart']; } - if (!$teaser['skiPassIncluded'] && $row['skiPassIncluded']) { + if (!($teaser['skiPassIncluded'] ?? false) && ($row['skiPassIncluded'] ?? null)) { $teaser['skiPassIncluded'] = true; } - if (!$teaser['busIncluded'] && $row['busIncluded']) { + if (!($teaser['busIncluded'] ?? false) && ($row['busIncluded'] ?? null)) { $teaser['busIncluded'] = true; } @@ -182,47 +182,47 @@ class ProductDataService implements SingletonInterface 'maxDateEnd' => null, 'minPrice' => null, 'hotelCount' => 1, - 'pseudoPrice' => $teaserData['pseudoPrice'], - 'board' => $teaserData['board'], - 'earlybird' => $teaserData['earlybird'], - 'new' => $teaserData['new'], - 'daytrip' => $teaserData['daytrip'], - 'hideBookingButton' => $teaserData['hideBookingButton'], - 'lowContingent' => $teaserData['lowContingent'], - 'servicesIncluded' => unserialize($teaserData['servicesIncluded'], ['allowed_classes' => false]), - 'season' => $teaserData['season'], + 'pseudoPrice' => $teaserData['pseudoPrice'] ?? null, + 'board' => $teaserData['board'] ?? null, + 'earlybird' => $teaserData['earlybird'] ?? null, + 'new' => $teaserData['new'] ?? null, + 'daytrip' => $teaserData['daytrip'] ?? null, + 'hideBookingButton' => $teaserData['hideBookingButton'] ?? null, + 'lowContingent' => $teaserData['lowContingent'] ?? null, + 'servicesIncluded' => unserialize((string)($teaserData['servicesIncluded'] ?? ''), ['allowed_classes' => false]), + 'season' => $teaserData['season'] ?? null, 'product' => [ - 'uid' => $teaserData['productUid'], - 'name' => $teaserData['productName'], - 'subline' => $teaserData['productSubline'], - 'detailPage' => $teaserData['productDetailPage'], - 'slug' => $teaserData['productSlug'], - 'fact' => $teaserData['productFact'], - 'feature' => $teaserData['productFeature'], - 'teaser' => $teaserData['productTeaser'], - 'images' => $this->productImageService->getImages($teaserData['productUid']), + 'uid' => $teaserData['productUid'] ?? null, + 'name' => $teaserData['productName'] ?? null, + 'subline' => $teaserData['productSubline'] ?? null, + 'detailPage' => $teaserData['productDetailPage'] ?? null, + 'slug' => $teaserData['productSlug'] ?? null, + 'fact' => $teaserData['productFact'] ?? null, + 'feature' => $teaserData['productFeature'] ?? null, + 'teaser' => $teaserData['productTeaser'] ?? null, + 'images' => $this->productImageService->getImages($teaserData['productUid'] ?? null), ], 'concept' => [ - 'uid' => $teaserData['conceptUid'], - 'name' => $teaserData['conceptName'], - 'code' => $teaserData['conceptCode'], - 'popupText' => $teaserData['conceptPopupText'], + 'uid' => $teaserData['conceptUid'] ?? null, + 'name' => $teaserData['conceptName'] ?? null, + 'code' => $teaserData['conceptCode'] ?? null, + 'popupText' => $teaserData['conceptPopupText'] ?? null, ], 'hotel' => [ - 'name' => $teaserData['hotelName'], + 'name' => $teaserData['hotelName'] ?? null, 'category' => $hotelCategory, - 'fact' => $teaserData['hotelFact'], - 'uid' => $teaserData['hotelUid'], - 'images' => $this->hotelImageService->getImages($teaserData['hotelUid']), + 'fact' => $teaserData['hotelFact'] ?? null, + 'uid' => $teaserData['hotelUid'] ?? null, + 'images' => $this->hotelImageService->getImages($teaserData['hotelUid'] ?? null), ], 'country' => [ - 'name' => $teaserData['countryName'], - 'code' => $teaserData['countryCode'], + 'name' => $teaserData['countryName'] ?? null, + 'code' => $teaserData['countryCode'] ?? null, ], 'region' => [ - 'name' => $teaserData['regionName'], - 'fact' => $teaserData['regionFact'], - 'feature' => $teaserData['regionFeature'], + 'name' => $teaserData['regionName'] ?? null, + 'fact' => $teaserData['regionFact'] ?? null, + 'feature' => $teaserData['regionFeature'] ?? null, ], 'dates' => [], 'nights' => [], diff --git a/packages/ep_theme/Classes/DataProcessing/ContextProcessor.php b/packages/ep_theme/Classes/DataProcessing/ContextProcessor.php index 68d1ffa..ee58d4c 100644 --- a/packages/ep_theme/Classes/DataProcessing/ContextProcessor.php +++ b/packages/ep_theme/Classes/DataProcessing/ContextProcessor.php @@ -61,7 +61,7 @@ class ContextProcessor implements DataProcessorInterface if ($regionUid > 0) { $processedData['context']['region'] = $this->getContextRecord($regionUid, 'tx_epproducts_domain_model_region'); } - if ($data['tx_eptheme_context_pacode']) { + if ($data['tx_eptheme_context_pacode'] ?? null) { $processedData['context']['paCode'] = $data['tx_eptheme_context_pacode']; } elseif ($paCode = $this->getPaCodeFromRequest()) { $processedData['context']['paCode'] = $paCode; diff --git a/packages/ep_theme/Classes/ViewHelpers/Uri/ProductViewHelper.php b/packages/ep_theme/Classes/ViewHelpers/Uri/ProductViewHelper.php index 027bddf..50dcba6 100644 --- a/packages/ep_theme/Classes/ViewHelpers/Uri/ProductViewHelper.php +++ b/packages/ep_theme/Classes/ViewHelpers/Uri/ProductViewHelper.php @@ -27,6 +27,12 @@ namespace EP\EpTheme\ViewHelpers\Uri; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ +use Psr\Http\Message\ServerRequestInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters; +use TYPO3\CMS\Extbase\Mvc\Request; +use TYPO3\CMS\Extbase\Mvc\RequestInterface; +use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; @@ -73,10 +79,9 @@ class ProductViewHelper extends AbstractViewHelper ]; } $targetPageUid = is_array($product) ? (int)$product['detailPage'] : $product->getDetailPage(); - $uri = $this->renderingContext - ->getControllerContext() - ->getUriBuilder() + $uri = GeneralUtility::makeInstance(UriBuilder::class) ->reset() + ->setRequest($this->getExtbaseRequest()) ->setTargetPageUid($targetPageUid) ->uriFor('detail', $linkArguments, 'Product', 'epproducts', 'product_detail') ; @@ -89,4 +94,19 @@ class ProductViewHelper extends AbstractViewHelper return $uri; } + /** + * The view helper is also used in content elements, which render without an Extbase request + */ + private function getExtbaseRequest(): RequestInterface + { + $request = $this->renderingContext->getAttribute(ServerRequestInterface::class); + if ($request instanceof RequestInterface) { + return $request; + } + if ($request->getAttribute('extbase') === null) { + $request = $request->withAttribute('extbase', new ExtbaseRequestParameters()); + } + return new Request($request); + } + }