diff --git a/package-lock.json b/package-lock.json index 28988012..0b22b2d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "bourbon": "^4.3.2", "cookieconsent": "^3.1.0", "dayjs": "^1.10.6", + "es6-slide-up-down": "^1.0.0", "flatpickr": "^4.6.9", "font-awesome": "^4.7.0", "glightbox": "^3.0.9", @@ -28,11 +29,14 @@ "picturefill": "^3.0.3", "slick-carousel": "^1.8.1", "sticky-js": "^1.3.0", + "stimulus": "^2.0.0", + "stimulus-use": "^0.25.4", "vue": "^2.6.14", "vue-router": "^3.5.2", "vue-scrollto": "^2.20.0", "vue-session": "^1.0.0", - "vuex": "^3.6.2" + "vuex": "^3.6.2", + "whatwg-fetch": "^3.6.2" }, "devDependencies": { "@babel/plugin-proposal-object-rest-spread": "^7.14.7", @@ -1650,6 +1654,32 @@ "resolved": "https://registry.npmjs.org/@splidejs/splide/-/splide-2.4.21.tgz", "integrity": "sha512-LdIwSnmNsGybCCnA3QG2dOeRv/rQl46jf7FflXxMGX0ADYWyL6UJHWJbMZvHBi5I67uRJY1ga/W+CvJ39nH26A==" }, + "node_modules/@stimulus/core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stimulus/core/-/core-2.0.0.tgz", + "integrity": "sha512-ff70GafKtzc8zQ1/cG+UvL06GcifPWovf2wBEdjLMh9xO2GOYURO3y2RYgzIGYUIBefQwyfX2CLfJdZFJrEPTw==", + "dependencies": { + "@stimulus/mutation-observers": "^2.0.0" + } + }, + "node_modules/@stimulus/multimap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stimulus/multimap/-/multimap-2.0.0.tgz", + "integrity": "sha512-pMBCewkZCFVB3e5mEMoyO9+9aKzHDITmf3OnPun51YWxlcPdHcwbjqm1ylK63fsoduIE+RowBpFwFqd3poEz4w==" + }, + "node_modules/@stimulus/mutation-observers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stimulus/mutation-observers/-/mutation-observers-2.0.0.tgz", + "integrity": "sha512-kx4VAJdPhIGBQKGIoUDC2tupEKorG3A+ckc2b1UiwInKTMAC1axOHU8ebcwhaJIxRqIrs8//4SJo9YAAOx6FEg==", + "dependencies": { + "@stimulus/multimap": "^2.0.0" + } + }, + "node_modules/@stimulus/webpack-helpers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stimulus/webpack-helpers/-/webpack-helpers-2.0.0.tgz", + "integrity": "sha512-D6tJWsAC024MwGEIKlUVYU8Ln87mlrmiwHvYAjipg+s8H4eLxUMQ3PZkWyPevfipH+oR3leuHsjYsK1gN5ViQA==" + }, "node_modules/@symfony/webpack-encore": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@symfony/webpack-encore/-/webpack-encore-1.5.0.tgz", @@ -4305,6 +4335,11 @@ "es6-symbol": "^3.1.1" } }, + "node_modules/es6-slide-up-down": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es6-slide-up-down/-/es6-slide-up-down-1.0.0.tgz", + "integrity": "sha1-RTBJFkFvRliBBk6Q7t8SHTZmT14=" + }, "node_modules/es6-symbol": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", @@ -5242,6 +5277,11 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, + "node_modules/hotkeys-js": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.8.7.tgz", + "integrity": "sha512-ckAx3EkUr5XjDwjEHDorHxRO2Kb7z6Z2Sxul4MbBkN8Nho7XDslQsgMJT+CiJ5Z4TgRxxvKHEpuLE3imzqy4Lg==" + }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -9394,6 +9434,26 @@ "resolved": "https://registry.npmjs.org/sticky-js/-/sticky-js-1.3.0.tgz", "integrity": "sha512-X5zWjFrw7c2xE4tUtSeK7I+1o252JOyZOlzxsu1Q9qZ6hlk2NCd9Sr/AFxf8hfGkLnE1Pak+iLaDyd883LFRgw==" }, + "node_modules/stimulus": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stimulus/-/stimulus-2.0.0.tgz", + "integrity": "sha512-xipy7BS5TVpg4fX6S8LhrYZp7cmHGjmk09WSAiVx1gF5S5g43IWsuetfUhIk8HfHUG+4MQ9nY0FQz4dRFLs/8w==", + "dependencies": { + "@stimulus/core": "^2.0.0", + "@stimulus/webpack-helpers": "^2.0.0" + } + }, + "node_modules/stimulus-use": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/stimulus-use/-/stimulus-use-0.25.4.tgz", + "integrity": "sha512-Rr4m4PpcOni7y4KiwUMdCuUJ5IPE2LEELwoz8e+VB3jbfPb9DNjrurCTKCWT5BiPBrn9OEfhnWJIRPcbxUpQvQ==", + "dependencies": { + "hotkeys-js": ">=3" + }, + "peerDependencies": { + "stimulus": ">=1.1.1 <3" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -10835,6 +10895,11 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -12236,6 +12301,32 @@ "resolved": "https://registry.npmjs.org/@splidejs/splide/-/splide-2.4.21.tgz", "integrity": "sha512-LdIwSnmNsGybCCnA3QG2dOeRv/rQl46jf7FflXxMGX0ADYWyL6UJHWJbMZvHBi5I67uRJY1ga/W+CvJ39nH26A==" }, + "@stimulus/core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stimulus/core/-/core-2.0.0.tgz", + "integrity": "sha512-ff70GafKtzc8zQ1/cG+UvL06GcifPWovf2wBEdjLMh9xO2GOYURO3y2RYgzIGYUIBefQwyfX2CLfJdZFJrEPTw==", + "requires": { + "@stimulus/mutation-observers": "^2.0.0" + } + }, + "@stimulus/multimap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stimulus/multimap/-/multimap-2.0.0.tgz", + "integrity": "sha512-pMBCewkZCFVB3e5mEMoyO9+9aKzHDITmf3OnPun51YWxlcPdHcwbjqm1ylK63fsoduIE+RowBpFwFqd3poEz4w==" + }, + "@stimulus/mutation-observers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stimulus/mutation-observers/-/mutation-observers-2.0.0.tgz", + "integrity": "sha512-kx4VAJdPhIGBQKGIoUDC2tupEKorG3A+ckc2b1UiwInKTMAC1axOHU8ebcwhaJIxRqIrs8//4SJo9YAAOx6FEg==", + "requires": { + "@stimulus/multimap": "^2.0.0" + } + }, + "@stimulus/webpack-helpers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stimulus/webpack-helpers/-/webpack-helpers-2.0.0.tgz", + "integrity": "sha512-D6tJWsAC024MwGEIKlUVYU8Ln87mlrmiwHvYAjipg+s8H4eLxUMQ3PZkWyPevfipH+oR3leuHsjYsK1gN5ViQA==" + }, "@symfony/webpack-encore": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@symfony/webpack-encore/-/webpack-encore-1.5.0.tgz", @@ -14384,6 +14475,11 @@ "es6-symbol": "^3.1.1" } }, + "es6-slide-up-down": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es6-slide-up-down/-/es6-slide-up-down-1.0.0.tgz", + "integrity": "sha1-RTBJFkFvRliBBk6Q7t8SHTZmT14=" + }, "es6-symbol": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", @@ -15116,6 +15212,11 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, + "hotkeys-js": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.8.7.tgz", + "integrity": "sha512-ckAx3EkUr5XjDwjEHDorHxRO2Kb7z6Z2Sxul4MbBkN8Nho7XDslQsgMJT+CiJ5Z4TgRxxvKHEpuLE3imzqy4Lg==" + }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -18251,6 +18352,23 @@ "resolved": "https://registry.npmjs.org/sticky-js/-/sticky-js-1.3.0.tgz", "integrity": "sha512-X5zWjFrw7c2xE4tUtSeK7I+1o252JOyZOlzxsu1Q9qZ6hlk2NCd9Sr/AFxf8hfGkLnE1Pak+iLaDyd883LFRgw==" }, + "stimulus": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stimulus/-/stimulus-2.0.0.tgz", + "integrity": "sha512-xipy7BS5TVpg4fX6S8LhrYZp7cmHGjmk09WSAiVx1gF5S5g43IWsuetfUhIk8HfHUG+4MQ9nY0FQz4dRFLs/8w==", + "requires": { + "@stimulus/core": "^2.0.0", + "@stimulus/webpack-helpers": "^2.0.0" + } + }, + "stimulus-use": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/stimulus-use/-/stimulus-use-0.25.4.tgz", + "integrity": "sha512-Rr4m4PpcOni7y4KiwUMdCuUJ5IPE2LEELwoz8e+VB3jbfPb9DNjrurCTKCWT5BiPBrn9OEfhnWJIRPcbxUpQvQ==", + "requires": { + "hotkeys-js": ">=3" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -19317,6 +19435,11 @@ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true }, + "whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index e03665d1..6f70f276 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "bourbon": "^4.3.2", "cookieconsent": "^3.1.0", "dayjs": "^1.10.6", + "es6-slide-up-down": "^1.0.0", "flatpickr": "^4.6.9", "font-awesome": "^4.7.0", "glightbox": "^3.0.9", @@ -28,11 +29,14 @@ "picturefill": "^3.0.3", "slick-carousel": "^1.8.1", "sticky-js": "^1.3.0", + "stimulus": "^2.0.0", + "stimulus-use": "^0.25.4", "vue": "^2.6.14", "vue-router": "^3.5.2", "vue-scrollto": "^2.20.0", "vue-session": "^1.0.0", - "vuex": "^3.6.2" + "vuex": "^3.6.2", + "whatwg-fetch": "^3.6.2" }, "devDependencies": { "@babel/plugin-proposal-object-rest-spread": "^7.14.7", @@ -54,8 +58,8 @@ "tailwindcss": "^2.2.7", "tailwindcss-alt": "^3.0.0", "tinycolor2": "^1.4.1", - "vue-loader": "^15.9.7", "vue-custom-element": "^3.3.0", + "vue-loader": "^15.9.7", "vue-template-compiler": "^2.6.14" } } diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/AjaxDateController.php b/public/typo3conf/ext/ep_products/Classes/Controller/AjaxDateController.php index db0b0d60..297f36bc 100644 --- a/public/typo3conf/ext/ep_products/Classes/Controller/AjaxDateController.php +++ b/public/typo3conf/ext/ep_products/Classes/Controller/AjaxDateController.php @@ -27,7 +27,6 @@ namespace EP\EpProducts\Controller; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Domain\Model\Hotel; use EP\EpProducts\Domain\Model\Product; use EP\EpProducts\Domain\Repository\ProductRepository; @@ -85,12 +84,6 @@ class AjaxDateController extends ActionController $this->productRepository = $productRepository; } - public function initializeAction() - { - $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true); - $this->processFilterSettingsArgument($forcedConceptUids); - } - public function initializeDatesAction() { if ($this->request->hasArgument('dateFrom')) { diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/AjaxSearchController.php b/public/typo3conf/ext/ep_products/Classes/Controller/AjaxSearchController.php index 62c0e780..267631bc 100644 --- a/public/typo3conf/ext/ep_products/Classes/Controller/AjaxSearchController.php +++ b/public/typo3conf/ext/ep_products/Classes/Controller/AjaxSearchController.php @@ -27,7 +27,6 @@ namespace EP\EpProducts\Controller; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Service\FilterService; use EP\EpProducts\Service\SearchResultUrlService; use EP\EpProducts\Service\SearchResultService; @@ -66,8 +65,7 @@ class AjaxSearchController extends ActionController FilterService $filterService, SearchResultService $searchResultService, SearchResultUrlService $searchResultUrlService - ) - { + ) { parent::__construct(); $this->filterService = $filterService; @@ -75,34 +73,26 @@ class AjaxSearchController extends ActionController $this->searchResultUrlService = $searchResultUrlService; } - public function initializeAction() + /** + * @param array $filterSettings + */ + public function searchresultAction(array $filterSettings = []) { $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true); - $this->processFilterSettingsArgument($forcedConceptUids); - } - /** - * @param FilterSettings $filterSettings - * @return string - * @throws \Doctrine\DBAL\DBALException - */ - public function searchresultAction(FilterSettings $filterSettings = null) - { $dateSelected = false; $organic = true; $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true); $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']); $excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']); - if ($filterSettings === null) { - $filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUids); - } - - if ($filterSettings->getDateFrom() !== null || $filterSettings->getDateTo() !== null) { + if (isset($filterSettings['dateFrom']) || isset($filterSettings['dateTo'])) { $dateSelected = true; } - $searchResult = $this->searchResultService->getResult($filterSettings, $excludedConceptUids); + $searchResult = $this + ->searchResultService + ->getResult($filterSettings, $excludedConceptUids); if ($searchResult->getTotal() === 0) { $filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUids); @@ -110,11 +100,7 @@ class AjaxSearchController extends ActionController $organic = false; } - $options = [ - 'defaultDetailPageUid' => $this->settings['defaultDetailPageUid'], - ]; - - $this->searchResultUrlService->process($searchResult, $options); + $this->searchResultUrlService->process($searchResult, $this->settings['defaultDetailPageUid']); $filterOptions = $this->filterService->getFilterOptions( $filterSettings, @@ -129,7 +115,7 @@ class AjaxSearchController extends ActionController ->setTargetPageUid($this->settings['defaultSearchPageUid']) ->uriFor( 'searchresult', - ['filterSettings' => $filterSettings->toArray()], + ['filterSettings' => $filterSettings], 'Search', null, 'searchresult' @@ -144,7 +130,7 @@ class AjaxSearchController extends ActionController 'meta' => [ 'organic' => $organic, 'total' => $searchResult->getTotal(), - 'dateRange' => DateUtility::formatDateRange($filterSettings->getDateFrom(), $filterSettings->getDateTo()), + 'dateRange' => DateUtility::formatDateRange($filterSettings['dateFrom'], $filterSettings['dateTo']), 'dateSelected' => $dateSelected, ], ]); diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/AjaxSearchbarController.php b/public/typo3conf/ext/ep_products/Classes/Controller/AjaxSearchbarController.php index 109a4b63..d3e6dc0d 100644 --- a/public/typo3conf/ext/ep_products/Classes/Controller/AjaxSearchbarController.php +++ b/public/typo3conf/ext/ep_products/Classes/Controller/AjaxSearchbarController.php @@ -27,7 +27,6 @@ namespace EP\EpProducts\Controller; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Domain\Model\SearchParams; use EP\EpProducts\Service\FilterService; use EP\EpProducts\Traits\RequestArgumentTypeConversionTrait; @@ -70,7 +69,7 @@ class AjaxSearchbarController extends ActionController $searchParams = new SearchParams(); $filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUids); } else { - $filterSettings = FilterSettings::fromSearchParams($searchParams); + $filterSettings = $searchParams->toFilterSettings(); } $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']); $excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']); diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/ConceptController.php b/public/typo3conf/ext/ep_products/Classes/Controller/ConceptController.php index 95a8d9fa..bfe7ad74 100644 --- a/public/typo3conf/ext/ep_products/Classes/Controller/ConceptController.php +++ b/public/typo3conf/ext/ep_products/Classes/Controller/ConceptController.php @@ -28,7 +28,6 @@ namespace EP\EpProducts\Controller; ***************************************************************/ use EP\EpProducts\Domain\Model\Concept; -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Domain\Repository\ConceptRepository; use EP\EpProducts\Service\ProductDataService; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -69,11 +68,13 @@ class ConceptController extends ActionController } $teaserConceptUids = GeneralUtility::trimExplode(',', $this->settings['additionalConceptUids']); array_unshift($teaserConceptUids, $concept->getUid()); - $filterSettings = new FilterSettings(); - $filterSettings->setConceptUids($teaserConceptUids); + $filterSettings = [ + 'conceptUids' => $teaserConceptUids, + ]; $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'], true); $limit = $this->settings['showMoreLink'] ? 4 : 0; $teasers = $this->productDataService->getTeasergroup($filterSettings, $excludedConceptUids, $limit); + $this->view->assignMultiple([ 'teasers' => $teasers, 'concept' => $concept, diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/CountryController.php b/public/typo3conf/ext/ep_products/Classes/Controller/CountryController.php index 703017cc..109854da 100644 --- a/public/typo3conf/ext/ep_products/Classes/Controller/CountryController.php +++ b/public/typo3conf/ext/ep_products/Classes/Controller/CountryController.php @@ -28,7 +28,6 @@ namespace EP\EpProducts\Controller; ***************************************************************/ use EP\EpProducts\Domain\Model\Country; -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Domain\Repository\CountryRepository; use EP\EpProducts\Service\ProductDataService; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -67,8 +66,9 @@ class CountryController extends ActionController $countryUid = $this->settings['countryUid']; $country = $this->countryRepository->findByIdentifier($countryUid); } - $filterSettings = new FilterSettings(); - $filterSettings->setCountryUids([$countryUid]); + $filterSettings = [ + 'countryUids' => [ $countryUid ], + ]; $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'], true); $limit = $this->settings['showMoreLink'] ? 4 : 0; $teasers = $this->productDataService->getTeasergroup($filterSettings, $excludedConceptUids, $limit); diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/HotelController.php b/public/typo3conf/ext/ep_products/Classes/Controller/HotelController.php index 4a9cb6b6..4e7e6309 100644 --- a/public/typo3conf/ext/ep_products/Classes/Controller/HotelController.php +++ b/public/typo3conf/ext/ep_products/Classes/Controller/HotelController.php @@ -27,7 +27,6 @@ namespace EP\EpProducts\Controller; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Domain\Model\Hotel; use EP\EpProducts\Domain\Repository\HotelRepository; use EP\EpProducts\Domain\Repository\ProductRepository; @@ -92,8 +91,9 @@ class HotelController extends ActionController /** @var Hotel $hotel */ $hotel = $this->hotelRepository->findByIdentifier($hotelUid); } - $filterSettings = new FilterSettings(); - $filterSettings->setHotelUid($hotelUid); + $filterSettings = [ + 'hotelUid' => $hotelUid, + ]; $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'], true); $limit = $this->settings['showMoreLink'] ? 4 : 0; $teasers = $this->productDataService->getTeasergroup($filterSettings, $excludedConceptUids, $limit); diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/ProductController.php b/public/typo3conf/ext/ep_products/Classes/Controller/ProductController.php index 1c66d36b..1d6846fc 100644 --- a/public/typo3conf/ext/ep_products/Classes/Controller/ProductController.php +++ b/public/typo3conf/ext/ep_products/Classes/Controller/ProductController.php @@ -122,7 +122,7 @@ class ProductController extends ActionController 'searchresult', 'Search', null, - ['filterSettings' => $filterSettings->toArray()], + ['filterSettings' => $filterSettings], $this->settings['defaultSearchPageUid'] ); } diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/RegionController.php b/public/typo3conf/ext/ep_products/Classes/Controller/RegionController.php index 8a4c714b..71bd9b97 100644 --- a/public/typo3conf/ext/ep_products/Classes/Controller/RegionController.php +++ b/public/typo3conf/ext/ep_products/Classes/Controller/RegionController.php @@ -27,7 +27,6 @@ namespace EP\EpProducts\Controller; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Domain\Model\Region; use EP\EpProducts\Domain\Repository\RegionRepository; use EP\EpProducts\Service\ProductDataService; @@ -72,8 +71,9 @@ class RegionController extends ActionController return (int)$uid; }, $additionalRegionUids); $teaserRegionUids = array_merge([$region->getUid()], $additionalRegionUids); - $filterSettings = new FilterSettings(); - $filterSettings->setRegionUids($teaserRegionUids); + $filterSettings = [ + 'regionUids' => $teaserRegionUids, + ]; $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'], true); $limit = $this->settings['showMoreLink'] ? 4 : 0; $teasers = $this->productDataService->getTeasergroup($filterSettings, $excludedConceptUids, $limit); diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/SearchController.php b/public/typo3conf/ext/ep_products/Classes/Controller/SearchController.php index cf39eaef..12cb6972 100644 --- a/public/typo3conf/ext/ep_products/Classes/Controller/SearchController.php +++ b/public/typo3conf/ext/ep_products/Classes/Controller/SearchController.php @@ -27,11 +27,13 @@ namespace EP\EpProducts\Controller; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Domain\Model\SearchParams; use EP\EpProducts\Service\FilterService; use EP\EpProducts\Service\FilterSettingsEncoder; +use EP\EpProducts\Service\SearchResultService; +use EP\EpProducts\Service\SearchResultUrlService; use EP\EpProducts\Traits\RequestArgumentTypeConversionTrait; +use EP\EpProducts\Utility\DateUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException; @@ -47,7 +49,17 @@ class SearchController extends ActionController protected $filterService; /** - * @var \EP\EpProducts\Domain\Model\FilterSettings + * @var SearchResultService + */ + private $searchResultService; + + /** + * @var SearchResultUrlService + */ + private $searchResultUrlService; + + /** + * @var array */ protected $defaultFilterSettings; @@ -59,10 +71,16 @@ class SearchController extends ActionController /** * @param FilterService $filterService */ - public function __construct(FilterService $filterService) - { + public function __construct + ( + FilterService $filterService, + SearchResultService $searchResultService, + SearchResultUrlService $searchResultUrlService + ) { parent::__construct(); $this->filterService = $filterService; + $this->searchResultService = $searchResultService; + $this->searchResultUrlService = $searchResultUrlService; $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true); $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids'], true); $excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids'], true); @@ -104,19 +122,17 @@ class SearchController extends ActionController /** * @param SearchParams $searchParams - * @throws StopActionException - * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException */ public function processSearchAction(SearchParams $searchParams) { - $filterSettings = FilterSettings::fromSearchParams($searchParams); + $filterSettings = $searchParams->toFilterSettings(); $redirectUri = $this->uriBuilder ->reset() ->setCreateAbsoluteUri(true) ->uriFor( 'searchresult', - ['filterSettings' => $filterSettings->toArray()], + ['filterSettings' => $filterSettings], null, null, 'searchresult' @@ -128,17 +144,33 @@ class SearchController extends ActionController public function initializeSearchresultAction() { $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true); - $this->processFilterSettingsArgument($forcedConceptUids); + //$this->processFilterSettingsArgument($forcedConceptUids); } /** - * @param \EP\EpProducts\Domain\Model\FilterSettings $filterSettings + * @param array $filterSettings */ - public function searchresultAction(FilterSettings $filterSettings) + public function searchresultAction(array $filterSettings = []) { + $dateSelected = false; + $organic = true; + $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true); $excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']); $excludedRegionUids = GeneralUtility::trimExplode(',', $this->settings['excludedRegionUids']); - $forcedConceptUids = GeneralUtility::trimExplode(',', $this->settings['forcedConceptUids'], true); + + if (!empty($filterSettings['dateFrom']) || !empty($filterSettings['dateTo'])) { + $dateSelected = true; + } + + $searchResult = $this->searchResultService->getResult($filterSettings, $excludedConceptUids); + + if ($searchResult->getTotal() === 0) { + $filterSettings = $this->defaultFilterSettings; + $searchResult = $this->searchResultService->getResult($filterSettings, $excludedConceptUids); + $organic = false; + } + + $this->searchResultUrlService->process($searchResult, $this->settings['defaultDetailPageUid']); $filterOptions = $this->filterService->getFilterOptions( $filterSettings, @@ -147,10 +179,30 @@ class SearchController extends ActionController $forcedConceptUids ); + $referringPageUri = $this + ->uriBuilder + ->reset() + ->setTargetPageUid($this->settings['defaultSearchPageUid']) + ->uriFor( + 'searchresult', + ['filterSettings' => $filterSettings], + 'Search', + null, + 'searchresult' + ) + ; + $this->view->assignMultiple([ - 'referringPageUid' => $this->settings['defaultSearchPageUid'], - 'filterOptions' => $filterOptions, 'filterSettings' => $filterSettings, + 'filterOptions' => $filterOptions, + 'searchResult' => $searchResult->getData(), + 'referringPageUri' => $referringPageUri, + 'meta' => [ + 'organic' => $organic, + 'total' => $searchResult->getTotal(), + 'dateRange' => DateUtility::formatDateRange($filterSettings['dateFrom'], $filterSettings['dateTo']), + 'dateSelected' => $dateSelected, + ], ]); } diff --git a/public/typo3conf/ext/ep_products/Classes/Domain/Model/FilterSettings.php b/public/typo3conf/ext/ep_products/Classes/Domain/Model/FilterSettings.php index e90e3e96..a72e3630 100644 --- a/public/typo3conf/ext/ep_products/Classes/Domain/Model/FilterSettings.php +++ b/public/typo3conf/ext/ep_products/Classes/Domain/Model/FilterSettings.php @@ -262,7 +262,7 @@ class FilterSettings implements \JsonSerializable /** * @param array $countryUids */ - public function setCountryUids(array $countryUids) + public function setCountryUids(?array $countryUids) { $this->countryUids = $countryUids; } @@ -278,7 +278,7 @@ class FilterSettings implements \JsonSerializable /** * @param array $regionUids */ - public function setRegionUids(array $regionUids) + public function setRegionUids(?array $regionUids) { $this->regionUids = $regionUids; } @@ -294,7 +294,7 @@ class FilterSettings implements \JsonSerializable /** * @param array $cityUids */ - public function setCityUids($cityUids) + public function setCityUids(?array $cityUids) { $this->cityUids = $cityUids; } @@ -310,7 +310,7 @@ class FilterSettings implements \JsonSerializable /** * @param array $conceptUids */ - public function setConceptUids($conceptUids) + public function setConceptUids(?array $conceptUids) { $this->conceptUids = $conceptUids; } @@ -421,7 +421,7 @@ class FilterSettings implements \JsonSerializable /** * @param array $boardTypes */ - public function setBoardTypes($boardTypes) + public function setBoardTypes(?array $boardTypes) { $this->boardTypes = $boardTypes; } @@ -437,7 +437,7 @@ class FilterSettings implements \JsonSerializable /** * @param array $hotelTypes */ - public function setHotelTypes($hotelTypes) + public function setHotelTypes(?array $hotelTypes) { $this->hotelTypes = $hotelTypes; } @@ -453,7 +453,7 @@ class FilterSettings implements \JsonSerializable /** * @param array $roomTypes */ - public function setRoomTypes($roomTypes) + public function setRoomTypes(?array $roomTypes) { $this->roomTypes = $roomTypes; } diff --git a/public/typo3conf/ext/ep_products/Classes/Domain/Model/SearchParams.php b/public/typo3conf/ext/ep_products/Classes/Domain/Model/SearchParams.php index 75fa7385..b976c98a 100644 --- a/public/typo3conf/ext/ep_products/Classes/Domain/Model/SearchParams.php +++ b/public/typo3conf/ext/ep_products/Classes/Domain/Model/SearchParams.php @@ -235,6 +235,46 @@ class SearchParams implements \JsonSerializable $this->pageUid = $pageUid; } + public function toFilterSettings(): array + { + $filterSettings = []; + + if ($this->getDestinationType() && $this->getDestinationUid()) { + $destinationUid = $this->getDestinationUid(); + switch ($this->getDestinationType()) { + case SearchParams::DESTINATION_TYPE_COUNTRY: + $filterSettings['countryUids'] = [ $destinationUid ]; + break; + case SearchParams::DESTINATION_TYPE_REGION: + $filterSettings['regionUids'] = [ $destinationUid ]; + break; + case SearchParams::DESTINATION_TYPE_CITY: + $filterSettings['cityUids'] = [ $destinationUid ]; + break; + case SearchParams::DESTINATION_TYPE_CONCEPT: + $filterSettings['conceptUids'] = [ $destinationUid ]; + break; + } + } + if (null !== $this->getDateFrom()) { + $filterSettings['dateFrom'] = $this->getDateFrom()->format('Y-m-d'); + } + if (null !== $this->getDateTo()) { + $filterSettings['dateTo'] = $this->getDateTo()->format('Y-m-d'); + } + if (null !== $this->getPriceRange()) { + $filterSettings['priceRanges'] = [ $this->getPriceRange() ]; + } + if (null !== $this->getPax()) { + $filterSettings['pax'] = $this->getPax(); + } + if (null !== $this->getNights()) { + $filterSettings['nights'] = $this->getNights(); + } + + return $filterSettings; + } + public function toArray(): array { return [ diff --git a/public/typo3conf/ext/ep_products/Classes/Domain/Model/SearchResult.php b/public/typo3conf/ext/ep_products/Classes/Domain/Model/SearchResult.php index a9edf078..e4b83956 100644 --- a/public/typo3conf/ext/ep_products/Classes/Domain/Model/SearchResult.php +++ b/public/typo3conf/ext/ep_products/Classes/Domain/Model/SearchResult.php @@ -40,21 +40,14 @@ class SearchResult */ protected $data = []; - /** - * @var FilterSettings - */ - protected $filterSettings; - /** * @param array $data * @param int $total - * @param FilterSettings $filterSettings */ - public function __construct(array $data = [], $total = 0, FilterSettings $filterSettings = null) + public function __construct(array $data = [], $total = 0) { $this->data = $data; $this->total = $total; - $this->filterSettings = $filterSettings; } /** @@ -89,20 +82,4 @@ class SearchResult $this->data = $data; } - /** - * @return FilterSettings - */ - public function getFilterSettings() - { - return $this->filterSettings; - } - - /** - * @param FilterSettings $filterSettings - */ - public function setFilterSettings($filterSettings) - { - $this->filterSettings = $filterSettings; - } - } diff --git a/public/typo3conf/ext/ep_products/Classes/Domain/Repository/AbstractRepository.php b/public/typo3conf/ext/ep_products/Classes/Domain/Repository/AbstractRepository.php index c4ea8eea..1590ecb0 100644 --- a/public/typo3conf/ext/ep_products/Classes/Domain/Repository/AbstractRepository.php +++ b/public/typo3conf/ext/ep_products/Classes/Domain/Repository/AbstractRepository.php @@ -42,7 +42,7 @@ abstract class AbstractRepository extends \TYPO3\CMS\Extbase\Persistence\Reposit { /** @var $querySettings \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings */ $querySettings = $this->objectManager->get(Typo3QuerySettings::class); - $querySettings->setRespectStoragePage(FALSE); + $querySettings->setRespectStoragePage(false); $this->setDefaultQuerySettings($querySettings); } @@ -60,114 +60,90 @@ abstract class AbstractRepository extends \TYPO3\CMS\Extbase\Persistence\Reposit return $query->execute(); } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addDateFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addDateFilterConditions(QueryBuilder $query, array $filterSettings): void { // Date Start - if ($filterSettings->getDateFrom() !== null) { + if (!empty($filterSettings['dateFrom'])) { $query ->andWhere('date.date_start >= :dateStart') - ->setParameter('dateStart', $filterSettings->getDateFrom()->format('Y-m-d')) + ->setParameter('dateStart', $filterSettings['dateFrom']) ; } // Date End - if ($filterSettings->getDateTo() !== null) { + if (!empty($filterSettings['dateTo'])) { $query ->andWhere('date.date_end <= :dateEnd') - ->setParameter('dateEnd', $filterSettings->getDateTo()->format('Y-m-d')) + ->setParameter('dateEnd', $filterSettings['dateTo']) ; } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addHotelFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addHotelFilterConditions(QueryBuilder $query, array $filterSettings): void { // Hotel - if ((int) $filterSettings->getHotelUid() > 0) { + if (!empty($filterSettings['hotelUid'])) { $query ->andWhere('date.hotel = :hotelUid') - ->setParameter('hotelUid', $filterSettings->getHotelUid()) + ->setParameter('hotelUid', (int)$filterSettings['hotelUid']) ; } // Hotel types - if (count($filterSettings->getHotelTypes()) > 0) { + if (!empty($filterSettings['hotelTypes'])) { $query ->andWhere('date.hotel_type IN (:hotelTypes)') - ->setParameter('hotelTypes', $filterSettings->getHotelTypes(), Connection::PARAM_INT_ARRAY) + ->setParameter('hotelTypes', (array)$filterSettings['hotelTypes'], Connection::PARAM_INT_ARRAY) ; } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addCountryRegionAndCityFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addCountryRegionAndCityFilterConditions(QueryBuilder $query, array $filterSettings): void { - if (count($filterSettings->getCityUids()) > 0) { + if (!empty($filterSettings['cityUids'])) { $query ->andWhere('date.city IN (:cityUids)') - ->setParameter('cityUids', $filterSettings->getCityUids(), Connection::PARAM_INT_ARRAY) + ->setParameter('cityUids', (array)$filterSettings['cityUids'], Connection::PARAM_INT_ARRAY) ; - } elseif (count($filterSettings->getRegionUids()) > 0) { + } elseif (!empty($filterSettings['regionUids'])) { $query ->andWhere('date.region IN (:regionUids)') - ->setParameter('regionUids', $filterSettings->getRegionUids(), Connection::PARAM_INT_ARRAY) + ->setParameter('regionUids', (array)$filterSettings['regionUids'], Connection::PARAM_INT_ARRAY) ; - } elseif (count($filterSettings->getCountryUids()) > 0) { + } elseif (!empty($filterSettings['countryUids'])) { $query ->andWhere('date.country IN (:countryUids)') - ->setParameter('countryUids', $filterSettings->getCountryUids(), Connection::PARAM_INT_ARRAY) + ->setParameter('countryUids', (array)$filterSettings['countryUids'], Connection::PARAM_INT_ARRAY) ; } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addConceptFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addConceptFilterConditions(QueryBuilder $query, array $filterSettings): void { - if (count($filterSettings->getConceptUids()) > 0) { + if (!empty($filterSettings['conceptUids'])) { $query ->andWhere('date.concept IN (:conceptUids)') - ->setParameter('conceptUids', $filterSettings->getConceptUids(), Connection::PARAM_INT_ARRAY) + ->setParameter('conceptUids', (array)$filterSettings['conceptUids'], Connection::PARAM_INT_ARRAY) ; } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addPaxFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addPaxFilterConditions(QueryBuilder $query, array $filterSettings): void { // Pax - if ((int) $filterSettings->getPax() > 0) { + if (!empty($filterSettings['pax'])) { $query ->andWhere('date.available >= :pax') - ->setParameter('pax', $filterSettings->getPax()) + ->setParameter('pax', (int)$filterSettings['pax']) ; } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addPriceRangeFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addPriceRangeFilterConditions(QueryBuilder $query, array $filterSettings): void { // Price ranges - if (count($filterSettings->getPriceRanges()) > 0) { + if (!empty($filterSettings['priceRanges'])) { $orX = $query->expr()->orX(); - foreach ($filterSettings->getPriceRanges() as $priceRange) { + foreach ((array)$filterSettings['priceRanges'] as $priceRange) { [ $priceMin, $priceMax ] = FilterOptions::$priceRangeOptions[$priceRange]; $orX->add($query->expr()->andX( $query->expr()->gte('date.min_price', ':priceMin'), @@ -182,79 +158,63 @@ abstract class AbstractRepository extends \TYPO3\CMS\Extbase\Persistence\Reposit } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addDurationFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addDurationFilterConditions(QueryBuilder $query, array $filterSettings): void { // Duration - if ((int) $filterSettings->getNights() === FilterSettings::DURATION_SHORT) { + if (empty($filterSettings['nights'])) { + return; + } + $nights = (int)$filterSettings['nights']; + if ($nights === FilterSettings::DURATION_SHORT) { $query ->andWhere('date.nights <= :nights') - ->setParameter('nights', $filterSettings->getNights()) + ->setParameter('nights', $nights) ; - } elseif ((int) $filterSettings->getNights() === FilterSettings::DURATION_LONG) { + } elseif ($nights === FilterSettings::DURATION_LONG) { $query ->andWhere('date.nights >= :nights') - ->setParameter('nights', $filterSettings->getNights()) + ->setParameter('nights', $nights) ; } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addHotelTypesFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addHotelTypesFilterConditions(QueryBuilder $query, array $filterSettings): void { // Hotel types - if (count($filterSettings->getHotelTypes()) > 0) { + if (!empty($filterSettings['hotelTypes'])) { $query ->andWhere('date.hotel_type IN (:hotelTypes)') - ->setParameter('hotelTypes', $filterSettings->getHotelTypes(), Connection::PARAM_INT_ARRAY) + ->setParameter('hotelTypes', (array)$filterSettings['hotelTypes'], Connection::PARAM_INT_ARRAY) ; } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addBoardTypesFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addBoardTypesFilterConditions(QueryBuilder $query, array $filterSettings): void { // Board types - if (count($filterSettings->getBoardTypes()) > 0) { + if (!empty($filterSettings['boardTypes'])) { $query ->andWhere('date.board_bus_pro_id IN (:boardTypes)') - ->setParameter('boardTypes', $filterSettings->getBoardTypes(), Connection::PARAM_STR_ARRAY) + ->setParameter('boardTypes', (array)$filterSettings['boardTypes'], Connection::PARAM_STR_ARRAY) ; } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addRoomTypesFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addRoomTypesFilterConditions(QueryBuilder $query, array $filterSettings): void { // Room types - if (count($filterSettings->getRoomTypes()) > 0) { + if (!empty($filterSettings['roomTypes'])) { $query ->andWhere('room.type IN (:roomTypes)') - ->setParameter('roomTypes', $filterSettings->getRoomTypes(), Connection::PARAM_INT_ARRAY) + ->setParameter('roomTypes', (array)$filterSettings['roomTypes'], Connection::PARAM_INT_ARRAY) ; } } - /** - * @param QueryBuilder $query - * @param FilterSettings $filterSettings - */ - protected function addTransportationFilterConditions(QueryBuilder $query, FilterSettings $filterSettings) + protected function addTransportationFilterConditions(QueryBuilder $query, array $filterSettings): void { // Transportation - if ($filterSettings->getBus() === true) { + if (!empty($filterSettings['bus'])) { $query->andWhere('date.bus_available = 1'); } } @@ -263,10 +223,10 @@ abstract class AbstractRepository extends \TYPO3\CMS\Extbase\Persistence\Reposit * Adds general conditions for provided filtersettings * * @param QueryBuilder $query - * @param FilterSettings $filterSettings + * @param array $filterSettings * @param bool $constraintDates */ - protected function addFiltersettingsConditions(QueryBuilder $query, FilterSettings $filterSettings, $constraintDates = true) + protected function addFiltersettingsConditions(QueryBuilder $query, array $filterSettings, $constraintDates = true) { if ($constraintDates) { $this->addDateFilterConditions($query, $filterSettings); @@ -281,41 +241,21 @@ abstract class AbstractRepository extends \TYPO3\CMS\Extbase\Persistence\Reposit $this->addRoomTypesFilterConditions($query, $filterSettings); $this->addTransportationFilterConditions($query, $filterSettings); - // Default fulltext search in case autocompletion has not been used -// if ((int) $filterSettings->getDestinationUid() === 0 && !empty($filterSettings->getDestinationName())) { -// $query -// ->andWhere($query->expr()->orX( -// $query->expr()->like('LOWER(date.country_name) COLLATE utf8_bin',':destination'), -// $query->expr()->like('LOWER(date.country_keywords) COLLATE utf8_bin', ':destination'), -// $query->expr()->like('LOWER(date.region_name) COLLATE utf8_bin', ':destination'), -// $query->expr()->like('LOWER(date.region_keywords) COLLATE utf8_bin', ':destination'), -// $query->expr()->like('LOWER(date.city_name) COLLATE utf8_bin', ':destination'), -// $query->expr()->like('LOWER(date.city_keywords) COLLATE utf8_bin', ':destination'), -// $query->expr()->like('LOWER(date.hotel_name) COLLATE utf8_bin', ':destination'), -// $query->expr()->like('LOWER(date.hotel_keywords) COLLATE utf8_bin', ':destination'), -// $query->expr()->like('LOWER(date.product_name) COLLATE utf8_bin', ':destination'), -// $query->expr()->like('LOWER(date.product_keywords) COLLATE utf8_bin', ':destination') -// )) -// ->setParameter('destination', '%' . mb_strtolower($filterSettings->getDestinationName()) . '%') -// ; -// } - // Product - if ((int) $filterSettings->getProductUid() > 0) { + if (!empty($filterSettings['productUid'])) { $query ->andWhere('date.product = :productUid') - ->setParameter('productUid', $filterSettings->getProductUid()) + ->setParameter('productUid', (int)$filterSettings['productUid']) ; } // Hotel - if ((int) $filterSettings->getHotelUid() > 0) { + if (!empty($filterSettings['hotelUid'])) { $query ->andWhere('date.hotel = :hotel') - ->setParameter(':hotel', $filterSettings->getHotelUid()) + ->setParameter(':hotel', (int)$filterSettings['hotelUid']) ; } - } } diff --git a/public/typo3conf/ext/ep_products/Classes/Domain/Repository/DateRepository.php b/public/typo3conf/ext/ep_products/Classes/Domain/Repository/DateRepository.php index 8e2fc9ef..fd7d269a 100644 --- a/public/typo3conf/ext/ep_products/Classes/Domain/Repository/DateRepository.php +++ b/public/typo3conf/ext/ep_products/Classes/Domain/Repository/DateRepository.php @@ -27,7 +27,6 @@ namespace EP\EpProducts\Domain\Repository; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Domain\Model\Product; use TYPO3\CMS\Core\Database\Connection; @@ -73,7 +72,7 @@ class DateRepository extends AbstractRepository } public function getFilterOptions( - FilterSettings $filterSettings, + array $filterSettings, array $excludedConceptUids = [], array $excludedRegionUids = [], array $forcedConceptUids = [] @@ -131,11 +130,11 @@ class DateRepository extends AbstractRepository /** * @param string $search - * @param FilterSettings $filterSettings + * @param array $filterSettings * @return array * @throws \Doctrine\DBAL\DBALException */ - public function searchHotels($search, FilterSettings $filterSettings) + public function searchHotels($search, array $filterSettings) { $qb = $this->getDbConnection()->createQueryBuilder(); @@ -166,12 +165,12 @@ class DateRepository extends AbstractRepository /** * @param string $search - * @param FilterSettings $filterSettings + * @param array $filterSettings * @param array $excludedConceptUids * @return array * @throws \Doctrine\DBAL\DBALException */ - public function searchProducts($search, FilterSettings $filterSettings, $excludedConceptUids = []) + public function searchProducts($search, array $filterSettings, $excludedConceptUids = []) { $qb = $this->getDbConnection()->createQueryBuilder(); @@ -215,12 +214,12 @@ class DateRepository extends AbstractRepository /** * @param string $type * @param string $search - * @param FilterSettings $filterSettings + * @param array $filterSettings * @param array $excludedRegionUids * @return array * @throws \Doctrine\DBAL\DBALException */ - public function searchDestinations($type, $search, FilterSettings $filterSettings, $excludedRegionUids = []) + public function searchDestinations($type, $search, array $filterSettings, $excludedRegionUids = []) { $qb = $this->getDbConnection()->createQueryBuilder(); diff --git a/public/typo3conf/ext/ep_products/Classes/Domain/Repository/ProductRepository.php b/public/typo3conf/ext/ep_products/Classes/Domain/Repository/ProductRepository.php index db99be4c..6f3759d8 100644 --- a/public/typo3conf/ext/ep_products/Classes/Domain/Repository/ProductRepository.php +++ b/public/typo3conf/ext/ep_products/Classes/Domain/Repository/ProductRepository.php @@ -28,7 +28,6 @@ namespace EP\EpProducts\Domain\Repository; ***************************************************************/ use EP\EpProducts\Domain\Model\Date; -use EP\EpProducts\Domain\Model\FilterSettings; use EP\EpProducts\Domain\Model\Hotel; use EP\EpProducts\Domain\Model\Product; use TYPO3\CMS\Core\Database\Connection; @@ -78,12 +77,12 @@ class ProductRepository extends AbstractRepository } /** - * @param FilterSettings $filterSettings + * @param array $filterSettings * @param array $excludedConceptUids * @return array * @throws \Doctrine\DBAL\DBALException */ - public function getSearchResult(FilterSettings $filterSettings, $excludedConceptUids = []) + public function getSearchResult(array $filterSettings, $excludedConceptUids = []) { $qb = $this->getDbConnection()->createQueryBuilder(); @@ -131,13 +130,13 @@ class ProductRepository extends AbstractRepository } /** - * @param FilterSettings $filterSettings + * @param array $filterSettings * @param array $excludedConceptUids * @param int $limit * @return array * @throws \Doctrine\DBAL\DBALException */ - public function getTeasers(FilterSettings $filterSettings, $excludedConceptUids = [], $limit = 0) + public function getTeasers(array $filterSettings, $excludedConceptUids = [], $limit = 0) { $qb = $this->getDbConnection()->createQueryBuilder(); @@ -173,12 +172,12 @@ class ProductRepository extends AbstractRepository $query->setMaxResults($limit); } - if (!$filterSettings->getProductUid()) { + if (empty($filterSettings['productUid'])) { $query->andWhere('product_searchable = 1'); } else { $query ->andWhere('product = :productUid') - ->setParameter('productUid', $filterSettings->getProductUid()) + ->setParameter('productUid', (int)$filterSettings['productUid']) ; } @@ -195,18 +194,18 @@ class ProductRepository extends AbstractRepository ; } - return $query->execute()->fetchAllAssociative(\PDO::FETCH_ASSOC); + return $query->execute()->fetchAllAssociative(); } /** * @param Product $product * @param Hotel $hotel - * @param FilterSettings $filterSettings + * @param array $filterSettings * @param Date $date * @return array * @throws \Doctrine\DBAL\DBALException */ - public function getPricetable(Product $product, Hotel $hotel, FilterSettings $filterSettings, Date $date = null) + public function getPricetable(Product $product, Hotel $hotel, array $filterSettings, Date $date = null) { $qb = $this->getDbConnection()->createQueryBuilder(); @@ -248,11 +247,11 @@ class ProductRepository extends AbstractRepository /** * @param Product $product * @param Hotel $hotel - * @param FilterSettings $filterSettings + * @param array $filterSettings * @return array * @throws \Doctrine\DBAL\DBALException */ - public function getAvailableDates(Product $product, Hotel $hotel, FilterSettings $filterSettings) + public function getAvailableDates(Product $product, Hotel $hotel, array $filterSettings) { $qb = $this->getDbConnection()->createQueryBuilder(); diff --git a/public/typo3conf/ext/ep_products/Classes/Service/FilterService.php b/public/typo3conf/ext/ep_products/Classes/Service/FilterService.php index ea583d5b..67d16338 100644 --- a/public/typo3conf/ext/ep_products/Classes/Service/FilterService.php +++ b/public/typo3conf/ext/ep_products/Classes/Service/FilterService.php @@ -61,22 +61,23 @@ class FilterService implements SingletonInterface bool $respectBookableDaterange = true, string $dateFromYmd = null, string $dateToYmd = null - ): FilterSettings { + ): array { + $filterSettings = []; + [ $dateFrom, $dateTo ] = $this->constrainDateRange($this->dateRepository->getDateRange()); if (null !== $dateFromYmd) { - $dateFrom = new \DateTime($dateFromYmd); + $filterSettings['dateFrom'] = $dateFromYmd; } elseif (!$respectBookableDaterange) { - $dateFrom = new \DateTime('now'); + $dateFrom = (new \DateTime('now'))->format('Y-m-d'); } if (null !== $dateToYmd) { - $dateTo = new \DateTime($dateToYmd); + $filterSettings['dateTo'] = $dateToYmd; } - $filterSettings = new FilterSettings($dateFrom, $dateTo); if ($forcedConceptUids) { - $filterSettings->setConceptUids($forcedConceptUids); + $filterSettings['conceptUids'] = $forcedConceptUids; } return $filterSettings; @@ -84,7 +85,7 @@ class FilterService implements SingletonInterface public function getFilterOptions ( - FilterSettings $filterSettings, + array $filterSettings, array $excludedConceptUids = [], array $excludedRegionUids = [], array $forcedConceptUids = [] @@ -250,36 +251,36 @@ class FilterService implements SingletonInterface return [$dateFrom, $dateTo]; } - public function getFiltersettingsFromSettings(array $settings): FilterSettings + public function getFiltersettingsFromSettings(array $settings): array { - $filterSettings = new FilterSettings(); + $filterSettings = []; if (isset($settings['regionUid']) && (int) $settings['regionUid'] > 0) { - $filterSettings->setRegionUids([$settings['regionUid']]); + $filterSettings['regionUids'] = [ $settings['regionUid'] ]; } elseif (isset($settings['countryUid']) && (int) $settings['countryUid'] > 0) { - $filterSettings->setCountryUids([$settings['countryUid']]); + $filterSettings['countryUids'] = [ $settings['countryUid'] ]; } elseif (isset($settings['hotelUid']) && (int) $settings['hotelUid'] > 0) { - $filterSettings->setHotelUid($settings['hotelUid']); + $filterSettings['hotelUid'] = $settings['hotelUid']; } $conceptUids = GeneralUtility::trimExplode(',', $settings['conceptUid'], true); if ($conceptUids) { - $filterSettings->setConceptUids($conceptUids); + $filterSettings['conceptUids'] = $conceptUids; } if (isset($settings['dateFrom']) && (int) $settings['dateFrom'] > 0) { $dateFrom = new \DateTime(); $dateFrom->setTimestamp($settings['dateFrom']); - $filterSettings->setDateFrom($dateFrom); + $filterSettings['dateFrom'] = $dateFrom->format('Y-m-d'); } if (isset($settings['dateTo']) && (int) $settings['dateTo'] > 0) { $dateTo = new \DateTime(); $dateTo->setTimestamp($settings['dateTo']); - $filterSettings->setDateTo($dateTo); + $filterSettings['dateTo'] = $dateTo->format('Y-m-d'); } if (isset($settings['busAvailable']) && (bool) $settings['busAvailable'] === true) { - $filterSettings->setBus(true); + $filterSettings['bus'] = true; } if (array_key_exists('hotelTypes', $settings)) { $hotelTypes = GeneralUtility::trimExplode(',', $settings['hotelTypes'], true); - $filterSettings->setHotelTypes($hotelTypes); + $filterSettings['hotelTypes'] = $hotelTypes; } return $filterSettings; diff --git a/public/typo3conf/ext/ep_products/Classes/Service/FilterSettingsEncoder.php b/public/typo3conf/ext/ep_products/Classes/Service/FilterSettingsEncoder.php index c2f40c83..3e10fb8d 100644 --- a/public/typo3conf/ext/ep_products/Classes/Service/FilterSettingsEncoder.php +++ b/public/typo3conf/ext/ep_products/Classes/Service/FilterSettingsEncoder.php @@ -27,7 +27,6 @@ namespace EP\EpProducts\Service; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use EP\EpProducts\Domain\Model\FilterSettings; use TYPO3\CMS\Core\Utility\GeneralUtility; class FilterSettingsEncoder @@ -55,18 +54,20 @@ class FilterSettingsEncoder ]; } - public static function encode(FilterSettings $filterSettings): string + public static function encode(array $filterSettings): string { $encoded = []; - foreach (static::getMapping() as $property) - { + foreach (static::getMapping() as $property) { [$name, $type] = $property; - $method = 'get' . ucfirst($name); - $value = $filterSettings->{$method}(); + if (!isset($filterSettings[$name])) { + $encoded[] = ''; + continue; + } + $value = $filterSettings[$name]; if ($type === 'array') { $encoded[] = implode(';', $value); } elseif ($type === 'date') { - $encoded[] = ($value !== null) ? $value->format('Y-m-d') : ''; + $encoded[] = $value ?? ''; } else { $encoded[] = preg_replace('/[\r\n]/', '', $value); } diff --git a/public/typo3conf/ext/ep_products/Classes/Service/ProductDataService.php b/public/typo3conf/ext/ep_products/Classes/Service/ProductDataService.php index 567e20cd..865580f0 100644 --- a/public/typo3conf/ext/ep_products/Classes/Service/ProductDataService.php +++ b/public/typo3conf/ext/ep_products/Classes/Service/ProductDataService.php @@ -95,13 +95,13 @@ class ProductDataService implements SingletonInterface } /** - * @param FilterSettings $filterSettings + * @param array $filterSettings * @param array $excludedConceptUids * @param int $limit * * @return array */ - public function getTeasergroup(FilterSettings $filterSettings, $excludedConceptUids = [], $limit = 0) + public function getTeasergroup(array $filterSettings, $excludedConceptUids = [], $limit = 0) { $teaserData = $this->productRepository->getTeasers($filterSettings, $excludedConceptUids); return $this->preprocessTeasergroup($teaserData, $limit); diff --git a/public/typo3conf/ext/ep_products/Classes/Service/SearchResultService.php b/public/typo3conf/ext/ep_products/Classes/Service/SearchResultService.php index 54123951..6f24f450 100644 --- a/public/typo3conf/ext/ep_products/Classes/Service/SearchResultService.php +++ b/public/typo3conf/ext/ep_products/Classes/Service/SearchResultService.php @@ -66,7 +66,7 @@ class SearchResultService implements SingletonInterface $this->flagIconService = $flagIconService; } - public function getResult(FilterSettings $filterSettings, array $excludedConceptUids = []): SearchResult + public function getResult(array $filterSettings, array $excludedConceptUids = []): SearchResult { $searchResultData = $this->productRepository->getSearchResult($filterSettings, $excludedConceptUids); diff --git a/public/typo3conf/ext/ep_products/Classes/Service/SearchResultUrlService.php b/public/typo3conf/ext/ep_products/Classes/Service/SearchResultUrlService.php index 8f962b56..fbc74495 100644 --- a/public/typo3conf/ext/ep_products/Classes/Service/SearchResultUrlService.php +++ b/public/typo3conf/ext/ep_products/Classes/Service/SearchResultUrlService.php @@ -48,16 +48,10 @@ class SearchResultUrlService implements SingletonInterface /** * @param SearchResult $searchResult - * @param array $options + * @param int $defaultDetailPageUid */ - public function process(SearchResult $searchResult, array $options): void + public function process(SearchResult $searchResult, $defaultDetailPageUid): void { - $optionsResolver = new OptionsResolver(); - $optionsResolver->setRequired([ 'defaultDetailPageUid' ]); - $resolvedOptions = $optionsResolver->resolve($options); - - $defaultDetailPageUid = $resolvedOptions['defaultDetailPageUid']; - $data = $searchResult->getData(); foreach ($data as $conceptUid => $conceptData) { diff --git a/public/typo3conf/ext/ep_products/Classes/Utility/DateUtility.php b/public/typo3conf/ext/ep_products/Classes/Utility/DateUtility.php index e3ff9d08..12286fb1 100644 --- a/public/typo3conf/ext/ep_products/Classes/Utility/DateUtility.php +++ b/public/typo3conf/ext/ep_products/Classes/Utility/DateUtility.php @@ -32,19 +32,21 @@ class DateUtility public static function formatDateRange ( - \DateTime $dateFrom = null, - \DateTime $dateTo = null, + ?string $dateFromString = '', + ?string $dateToString = '', bool $includeLabel = true, string $format = 'd.m.Y' ): string { - if ($dateFrom === null && $dateTo === null) { + if (empty($dateFromString) && empty($dateToString)) { return ''; } + $dateFrom = new \DateTime($dateFromString); + $dateTo = new \DateTime($dateToString); $label = $includeLabel ? 'im Zeitraum ' : ''; - if ($dateFrom !== null && $dateTo === null) { + if ($dateFromString !== '' && $dateToString === '') { return $label . 'ab ' . $dateFrom->format($format); } - if ($dateFrom === null && $dateTo !== null) { + if ($dateFromString === '' && $dateToString !== '') { return $label . '-' . $dateTo->format($format); } return $label . $dateFrom->format($format) . '-' . $dateTo->format($format); diff --git a/public/typo3conf/ext/ep_theme/Classes/ViewHelpers/DateRangeViewHelper.php b/public/typo3conf/ext/ep_theme/Classes/ViewHelpers/DateRangeViewHelper.php index 882b6f9b..94ce30ad 100644 --- a/public/typo3conf/ext/ep_theme/Classes/ViewHelpers/DateRangeViewHelper.php +++ b/public/typo3conf/ext/ep_theme/Classes/ViewHelpers/DateRangeViewHelper.php @@ -40,8 +40,8 @@ class DateRangeViewHelper extends AbstractViewHelper { parent::initializeArguments(); - $this->registerArgument('dateFrom', 'mixed', 'Date range start'); - $this->registerArgument('dateTo', 'mixed', 'Date range end'); + $this->registerArgument('dateFrom', 'string', 'Date range start'); + $this->registerArgument('dateTo', 'string', 'Date range end'); $this->registerArgument('includeLabel', 'Bool', 'Whether to include a label', false, true); $this->registerArgument('format', 'String', 'The date format', false, 'd.m.Y'); } @@ -56,27 +56,12 @@ class DateRangeViewHelper extends AbstractViewHelper array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext - ) - { - $dateFrom = static::ensureDateObject($arguments['dateFrom']); - $dateTo = static::ensureDateObject($arguments['dateTo']); - + ) { return DateUtility::formatDateRange( - $dateFrom, - $dateTo, + $arguments['dateFrom'], + $arguments['dateTo'], $arguments['includeLabel'], $arguments['format'] ); } - - private static function ensureDateObject($argument): \DateTime - { - if ($argument instanceof \DateTime) { - $dateTime = $argument; - } else { - $dateTime = new \DateTime($argument); - } - - return $dateTime; - } } diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/_app.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/_app.js index 08ef770c..aa1eda40 100644 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/_app.js +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/_app.js @@ -14,21 +14,12 @@ import Alpine from 'alpinejs' import parseAppConfig from './components/appconfig' import initSliders from './components/sliders' import appendPaCode from './components/pacode' -import scrollTop from './components/scoll-top' -import scrollTo from './components/scroll-to' -import sticky from './components/sticky' import watchlistToggle from './components/watchlist-toggle' import watchlistButton from './components/watchlist-button' import watchlist from './components/watchlist' -import collapse from './components/collapse' -import fbpixel from './components/fbpixel' -import ajaxContent from './components/ajax-content' -import faq from './components/faq' -import osmMap from './components/osm-map' import productDetail from './components/product-detail' import daytripDateSelect from './components/daytrip-date-select' import searchBar from './components/search-bar' -import search from './components/search' import calendar from './components/calendar' import contactForm from './components/contact-form' @@ -54,21 +45,12 @@ Alpine.store('show', { Alpine.store('watchlist', storedWatchlist) Alpine.store('filterSettings', defaultFilterSettings) Alpine.store('filterOptions', defaultFilterOptions) -Alpine.data('scrollTop', scrollTop) -Alpine.data('scrollTo', scrollTo) -Alpine.data('sticky', sticky) Alpine.data('watchlistToggle', watchlistToggle) Alpine.data('watchlistButton', watchlistButton) Alpine.data('watchlist', watchlist) -Alpine.data('collapse', collapse) -Alpine.data('fbpixel', fbpixel) -Alpine.data('ajaxContent', ajaxContent) -Alpine.data('faq', faq) -Alpine.data('osmMap', osmMap) Alpine.data('productDetail', productDetail) Alpine.data('daytripDateSelect', daytripDateSelect) Alpine.data('searchBar', searchBar) -Alpine.data('search', search) Alpine.data('calendar', calendar) Alpine.data('contactForm', contactForm) Alpine.start() @@ -77,3 +59,10 @@ Glightbox({ selector: 'data-glightbox', slideEffect: 'fade', }) + +import { Application } from 'stimulus' +import { definitionsFromContext } from 'stimulus/webpack-helpers' + +const application = Application.start() +const context = require.context('./controllers', true, /\.js$/) +application.load(definitionsFromContext(context)) diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/ajax-content.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/ajax-content.js deleted file mode 100644 index f16a9000..00000000 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/ajax-content.js +++ /dev/null @@ -1,44 +0,0 @@ -import axios from 'axios' -import { debounce } from './throttle-debounce' - -export default uri => ({ - uri, - loaded: false, - loading: false, - init() { - window.addEventListener('scroll', debounce(() => { - if (true === this.loaded) { - return - } - this.load() - }, 250)) - }, - load() { - if (false === this.inViewport()) { - return - } - this.loading = true - axios({ - url: this.uri, - responseType: 'text' - }).then((response) => { - this.loaded = true - this.$refs.container.innerHTML = response.data - this.$refs.trigger.remove() - }).catch(() => { - this.loaded = false - }).finally(() => { - this.loading = false - }) - }, - inViewport () { - const rect = this.$refs.trigger.getBoundingClientRect() - - return ( - rect.top >= 0 && - rect.left >= 0 && - rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && - rect.right <= (window.innerWidth || document.documentElement.clientWidth) - ) - } -}) diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/collapse.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/collapse.js deleted file mode 100644 index 69840811..00000000 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/collapse.js +++ /dev/null @@ -1,31 +0,0 @@ -import { debounce } from './throttle-debounce' - -export default (isCollapsed = true, until = null, from = null) => ({ - collapsed: isCollapsed, - collapsedUntil: until, - collapsedFrom: from, - init() { - this.checkBreakpoints() - window.addEventListener('resize', debounce(() => { - this.checkBreakpoints() - }, 250)) - }, - checkBreakpoints() { - if (null !== this.collapsedUntil) { - this.collapsed = window.innerWidth < parseInt(this.collapsedUntil) - } - if (null !== this.collapsedFrom) { - this.collapsed = window.innerWidth > parseInt(this.collapsedFrom) - } - }, - trigger: { - ['@click.prevent']() { - this.collapsed = !this.collapsed - }, - }, - container: { - ['x-show']() { - return this.collapsed === false - }, - } -}) diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/faq.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/faq.js deleted file mode 100644 index c628799b..00000000 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/faq.js +++ /dev/null @@ -1,24 +0,0 @@ -import { debounce } from './throttle-debounce' - -export default () => ({ - query: '', - init() { - this.entries = this.$el.querySelectorAll('[x-data^="collapse"]') - this.$watch('query', debounce(value => { - if (value.length < 3) { - this.entries.forEach(entry => { - entry.classList.remove('hidden') - }) - return - } - const pattern = new RegExp(value, 'i') - this.entries.forEach(entry => { - const question = entry.childNodes[0].textContent - const answer = entry.childNodes[1].textContent - if (!question.match(pattern) && !answer.match(pattern)) { - entry.classList.add('hidden') - } - }) - }, 200)) - }, -}) diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/fbpixel.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/fbpixel.js deleted file mode 100644 index b987a75c..00000000 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/fbpixel.js +++ /dev/null @@ -1,5 +0,0 @@ -export default props => ({ - init() { - fbq('track', 'ViewContent', props) - } -}) diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/osm-map.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/osm-map.js deleted file mode 100644 index e3615476..00000000 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/osm-map.js +++ /dev/null @@ -1,52 +0,0 @@ -import L from 'leaflet'; - -export default () => ({ - init() { - this.lat = this.$el.dataset.lat - this.lng = this.$el.dataset.lng - this.zoom = this.$el.dataset.zoom || 12 - this.externalLink = this.$el.dataset.link - this.markers = this.$el.dataset.markers ? JSON.parse(this.$el.dataset.markers) : [] - this.map = L.map(this.$el, { - scrollWheelZoom: false - }); - this.map.setZoom(this.zoom); - if (this.lat && this.lng) { - const position = L.latLng(this.lat, this.lng); - const marker = L.marker(position); - if (this.externalLink) { - marker.on('click', () => { - window.open(this.externalLink, '_blank') - }); - } else { - marker.on('click', () => { - window.open('https://www.google.com/maps/search/?api=1&zoom=15&query=' + this.lat + ',' + this.lng, '_blank') - }); - } - marker.addTo(this.map); - this.map.setView(position); - } else if (this.markers.length) { - const bounds = L.latLngBounds(); - for (let item of this.markers) { - const position = L.latLng(item.lat, item.lng); - const marker = L.marker(position); - if (item.externalLink) { - marker.on('click', () => { - window.open(item.externalLink, '_blank'); - }); - } else { - const popupContent = '
'; - marker.bindPopup(popupContent); - } - marker.addTo(this.map); - bounds.extend(position); - } - this.map.fitBounds(bounds); - } - L.tileLayer('https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', { - maxZoom: 19, - attribution: '© OpenStreetMap' - }).addTo(this.map); - } -}) diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/scoll-top.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/scoll-top.js deleted file mode 100644 index 06912f2e..00000000 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/scoll-top.js +++ /dev/null @@ -1,18 +0,0 @@ -import { debounce } from './throttle-debounce' - -export default () => ({ - show: false, - trigger: { - ['@click.prevent']() { - window.scroll({top: 0, left: 0, behavior: 'smooth'}) - }, - ['x-show']() { - return this.show - } - }, - init() { - window.addEventListener('scroll', debounce(() => { - this.show = window.scrollY > window.innerHeight / 3 - }, 250)) - }, -}) diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/scroll-to.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/scroll-to.js deleted file mode 100644 index 9305cd20..00000000 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/scroll-to.js +++ /dev/null @@ -1,9 +0,0 @@ -export default targetId => ({ - targetId, - init() { - this.$el.addEventListener('click', e => { - e.preventDefault() - document.getElementById(this.targetId).scrollIntoView({behavior: 'smooth'}) - }) - } -}) diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/sticky.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/sticky.js deleted file mode 100644 index 1bca5cc4..00000000 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/components/sticky.js +++ /dev/null @@ -1,11 +0,0 @@ -import { debounce } from './throttle-debounce' - -export default offset => ({ - offset, - sticky: false, - init() { - window.addEventListener('scroll', debounce(() => { - this.sticky = window.scrollY > this.offset - }, 250)) - } -}) diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/ajax_content_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/ajax_content_controller.js new file mode 100644 index 00000000..b87db9a4 --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/ajax_content_controller.js @@ -0,0 +1,72 @@ +import { Controller } from 'stimulus' +import { useDebounce } from 'stimulus-use' +import { useFetch} from '../mixins/use_fetch' + +export default class extends Controller { + + static debounces = [ 'load' ] + + static values = { + uri: String, + loading: Boolean, + loaded: Boolean, + } + + static targets = [ 'container', 'trigger' ] + + initialize() { + useDebounce(this) + useFetch(this) + } + + connect() { + window.addEventListener('scroll', () => { + this.load() + }) + } + + disconnect() { + window.removeEventListener('scroll', () => { + this.load() + }) + } + + load() { + if (true === this.loadedValue) { + return + } + if (false === this.inViewport()) { + return + } + this.loadHtml() + } + + loadHtml() { + this.loadingValue = true + fetch(this.uriValue) + .then(this.checkStatus) + .then(this.parseHTML) + .then(html => { + this.loadedValue = true + this.containerTarget.innerHTML = html + this.triggerTarget.remove() + }) + .catch(() => { + this.loadedValue = false + }) + .finally(() => { + this.loadingValue = false + }) + } + + inViewport() { + const rect = this.triggerTarget.getBoundingClientRect() + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ) + } + +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/collapse_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/collapse_controller.js new file mode 100644 index 00000000..3a0f5a6a --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/collapse_controller.js @@ -0,0 +1,48 @@ +import { Controller } from 'stimulus' +import { useWindowResize, useDebounce } from 'stimulus-use' + +export default class extends Controller { + + static debounces = [ 'checkBreakpoints' ] + + static values = { + collapsed: Boolean, + from: Number, + until: Number, + } + + static targets = [ 'container', 'icon' ] + + initialize() { + useWindowResize(this) + useDebounce(this) + } + + connect() { + this.toggleByWindowWidth(window.innerWidth) + } + + windowResize({ width, height, event }) { + this.toggleByWindowWidth(width) + } + + toggle() { + this.collapsedValue = !this.collapsedValue + } + + toggleByWindowWidth(width) { + if (0 !== this.untilValue) { + this.collapsedValue = width < this.untilValue + } + if (0 !== this.fromValue) { + this.collapsedValue = width > this.fromValue + } + } + + collapsedValueChanged() { + this.containerTarget.classList.toggle('hidden', this.collapsedValue === true) + if (this.hasIconTarget) { + this.iconTarget.classList.toggle('rotate-180', this.collapsedValue === false) + } + } +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/datepicker_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/datepicker_controller.js new file mode 100644 index 00000000..1b5d1d8d --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/datepicker_controller.js @@ -0,0 +1,56 @@ +import { Controller } from 'stimulus' +import { useDispatch } from 'stimulus-use' +import flatpickr from 'flatpickr' +import { German } from 'flatpickr/dist/l10n/de' + +export default class extends Controller { + + static targets = [ 'field' ] + + static values = { + minDate: String, + dateFrom: String, + dateTo: String, + } + + initialize() { + useDispatch(this) + + this.picker = flatpickr(this.fieldTarget, { + mode: 'range', + locale: German, + inline: true, + minDate: this.minDateValue, + onChange: selectedDates => { + if (selectedDates.length === 2) { + this.dispatch('range-select', { + from: flatpickr.formatDate(selectedDates[0], 'Y-m-d'), + to: flatpickr.formatDate(selectedDates[1], 'Y-m-d'), + }) + } + } + }) + } + + connect() { + if ('' !== this.dateFromValue && '' !== this.dateToValue) { + let dateFrom = new Date(this.dateFromValue) + let dateTo = new Date(this.dateToValue) + this.picker.setDate([ dateFrom, dateTo ]) + } + } + + selectPreset(e) { + e.preventDefault() + const preset = JSON.parse(e.currentTarget.dataset.preset) + this.picker.setDate([ new Date(preset.dateFrom), new Date(preset.dateTo) ]) + this.dispatch('range-select', { from: preset.dateFrom, to: preset.dateTo }) + } + + reset(e) { + e.preventDefault() + this.picker.clear() + this.picker.jumpToDate() + this.dispatch('range-select', { from: null, to: null }) + } +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/faq_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/faq_controller.js new file mode 100644 index 00000000..fa2e181f --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/faq_controller.js @@ -0,0 +1,31 @@ +import { Controller } from 'stimulus' +import { useDebounce } from 'stimulus-use' + +export default class extends Controller { + + static debounces = [ 'filter' ] + + static targets = [ 'entry' ] + + initialize() { + useDebounce(this) + } + + filter(e) { + let value = e.target.value + if (value.length < 3) { + this.entryTargets.forEach(entry => { + entry.classList.remove('hidden') + }) + return + } + const pattern = new RegExp(value, 'i') + this.entryTargets.forEach(entry => { + const question = entry.childNodes[0].textContent + const answer = entry.childNodes[1].textContent + if (!question.match(pattern) && !answer.match(pattern)) { + entry.classList.add('hidden') + } + }) + } +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/fbpixel_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/fbpixel_controller.js new file mode 100644 index 00000000..26ad24b5 --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/fbpixel_controller.js @@ -0,0 +1,11 @@ +import { Controller } from 'stimulus' + +export default class extends Controller { + + static values = { props: Object } + + connect() { + fbq('track', 'ViewContent', this.propsValue) + } + +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/osm_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/osm_controller.js new file mode 100644 index 00000000..5c4cd4b1 --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/osm_controller.js @@ -0,0 +1,58 @@ +import { Controller } from 'stimulus' +import L from 'leaflet' + +export default class extends Controller { + + static values = { + lat: Number, + lng: Number, + zoom: Number, + externalLink: String, + markers: Array, + } + + connect() { + this.map = L.map(this.element, { + scrollWheelZoom: false + }) + const zoom = this.hasZoomValue ? this.zoomValue : 12 + this.map.setZoom(zoom) + if (this.hasLatValue && this.hasLngValue) { + const position = L.latLng(this.latValue, this.lngValue) + const marker = L.marker(position) + if (this.hasExternalLinkValue) { + marker.on('click', () => { + window.open(this.externalLinkValue, '_blank') + }) + } else { + marker.on('click', () => { + window.open('https://www.google.com/maps/search/?api=1&zoom=15&query=' + this.latValue + ',' + this.lngValue, '_blank') + }) + } + marker.addTo(this.map) + this.map.setView(position) + } else if (this.hasMarkersValue && this.markersValue.length) { + const bounds = L.latLngBounds() + for (let item of this.markers) { + const position = L.latLng(item.lat, item.lng) + const marker = L.marker(position) + if (item.externalLink) { + marker.on('click', () => { + window.open(item.externalLink, '_blank') + }) + } else { + const popupContent = '' + marker.bindPopup(popupContent) + } + marker.addTo(this.map) + bounds.extend(position) + } + this.map.fitBounds(bounds) + } + L.tileLayer('https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', { + maxZoom: 19, + attribution: '© OpenStreetMap' + }).addTo(this.map) + } +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/scroll_to_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/scroll_to_controller.js new file mode 100644 index 00000000..8cd4a51e --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/scroll_to_controller.js @@ -0,0 +1,10 @@ +import { Controller } from 'stimulus' + +export default class extends Controller { + + static values = { target: String } + + scroll() { + document.getElementById(this.targetValue).scrollIntoView({ behavior: 'smooth' }) + } +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/scroll_top_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/scroll_top_controller.js new file mode 100644 index 00000000..f9c241cc --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/scroll_top_controller.js @@ -0,0 +1,25 @@ +import { Controller } from 'stimulus' +import { useDebounce} from 'stimulus-use' + +export default class extends Controller { + + static debounces = [ 'toggle' ] + + initialize() { + useDebounce(this) + } + + connect() { + window.addEventListener('scroll', () => { + this.toggle() + }) + } + + toggle() { + this.element.classList.toggle('hidden', window.scrollY < window.innerHeight / 3) + } + + scroll() { + window.scroll({ top: 0, left: 0, behavior: 'smooth' }) + } +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/search_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/search_controller.js new file mode 100644 index 00000000..ef83b10b --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/search_controller.js @@ -0,0 +1,53 @@ +import { Controller } from 'stimulus' +import { useDispatch } from 'stimulus-use' +import { useFetch } from '../mixins/use_fetch' + +export default class extends Controller { + + static values = { + loading: Boolean, + uri: String, + } + + static targets = [ + 'form', + 'resultsContainer', + 'loadingIndicator', + 'dateFrom', + 'dateTo', + ] + + initialize() { + useFetch(this) + useDispatch(this) + } + + filter() { + this.loadingValue = true + let data = new FormData(this.formTarget) + fetch(this.uriValue, { method: 'POST', body: data }) + .then(this.checkStatus) + .then(this.parseHTML) + .then(html => { + this.resultsContainerTarget.innerHTML = html + }) + .finally(() => { + this.loadingValue = false + this.element.scrollIntoView({ behavior: 'smooth' }) + }) + } + + reset() { + this.filter() + } + + selectDateRange(e) { + this.dateFromTarget.value = e.detail.from + this.dateToTarget.value = e.detail.to + this.filter() + } + + loadingValueChanged() { + this.loadingIndicatorTarget.classList.toggle('hidden', this.loadingValue === false) + } +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/sticky_controller.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/sticky_controller.js new file mode 100644 index 00000000..65cb6587 --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/controllers/sticky_controller.js @@ -0,0 +1,38 @@ +import { Controller } from 'stimulus' +import { useDebounce } from 'stimulus-use' + +export default class extends Controller { + + static debounces = [ 'toggle' ] + + static classes = [ 'sticky' ] + + static values = { + sticky: Boolean, + offset: Number, + } + + initialize() { + useDebounce(this) + } + + connect() { + window.addEventListener('scroll', () => { + this.toggle() + }) + } + + disconnect() { + window.removeEventListener('scroll', () => { + this.toggle() + }) + } + + toggle() { + this.stickyValue = window.scrollY > this.offsetValue + } + + stickyValueChanged() { + this.element.classList.toggle(this.stickyClass, this.stickyValue) + } +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/mixins/use_config.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/mixins/use_config.js new file mode 100644 index 00000000..acef946c --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/mixins/use_config.js @@ -0,0 +1,11 @@ +export const useConfig = controller => { + Object.assign(controller, { + getConfig() { + const configElement = document.getElementById('appconfig') + if (null === configElement) { + return {} + } + return JSON.parse(configElement.innerHTML) + } + }) +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/mixins/use_debounce.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/mixins/use_debounce.js new file mode 100644 index 00000000..1d1fd4ef --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/mixins/use_debounce.js @@ -0,0 +1,11 @@ +export const useDebounce = controller => { + Object.assign(controller, { + debounce(callback, interval) { + let debounceId + return (...args) => { + clearTimeout(debounceId) + debounceId = setTimeout(() => callback.apply(this, args), interval) + } + } + }); +}; diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/mixins/use_fetch.js b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/mixins/use_fetch.js new file mode 100644 index 00000000..bd4c4733 --- /dev/null +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/mixins/use_fetch.js @@ -0,0 +1,21 @@ +import 'whatwg-fetch' + +export const useFetch = controller => { + Object.assign(controller, { + checkStatus(response) { + if (response.status >= 200 && response.status < 300) { + return response + } else { + const error = new Error(response.statusText) + error.response = response + throw error + } + }, + parseJSON(response) { + return response.json() + }, + parseHTML(response) { + return response.text() + } + }) +} diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/scss/components/_background.scss b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/scss/components/_background.scss index 79a02345..b1e94853 100644 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Assets/scss/components/_background.scss +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Assets/scss/components/_background.scss @@ -1,27 +1,11 @@ .bg-winter { - @apply relative bg-cover bg-no-repeat bg-center; + @apply bg-cover bg-no-repeat bg-center; background-image: url(../../images/background/winter.jpg); - z-index: -5; - - &:before { - @apply block absolute top-0 left-0 inset-0 opacity-80; - @apply bg-ep-primary sbw:bg-sbw-primary uch:bg-uch-primary; - z-index: -10; - content: ''; - } } .bg-pattern { - @apply relative bg-cover bg-no-repeat bg-center; + @apply bg-cover bg-no-repeat bg-center; background-image: url(../../images/background/pattern.jpg); - z-index: -5; - - &:before { - @apply block absolute top-0 left-0 inset-0 opacity-80; - @apply bg-ep-primary sbw:bg-sbw-primary uch:bg-uch-primary; - z-index: -10; - content: ''; - } } .bg-header-season-w { diff --git a/public/typo3conf/ext/ep_theme/Resources/Private/Partials/Disrupter/Large.html b/public/typo3conf/ext/ep_theme/Resources/Private/Partials/Disrupter/Large.html index 5920c2f6..43141e41 100644 --- a/public/typo3conf/ext/ep_theme/Resources/Private/Partials/Disrupter/Large.html +++ b/public/typo3conf/ext/ep_theme/Resources/Private/Partials/Disrupter/Large.html @@ -4,64 +4,66 @@ xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">