From 80b6494e93ae6255bb9f63d2e2c992032627e0d6 Mon Sep 17 00:00:00 2001
From: Michael Kessler <michael.kessler@sgalinski.de>
Date: Wed, 30 Mar 2022 12:22:54 +0200
Subject: [PATCH] [FEATURE] Enable filtering by all filters

---
 Classes/Controller/OverviewController.php     | 175 ++++++++++++++++--
 Configuration/FlexForms/Overview.xml          |  37 ++--
 .../Private/Language/de.locallang_db.xlf      |  12 +-
 Resources/Private/Language/locallang_db.xlf   |   7 +-
 4 files changed, 202 insertions(+), 29 deletions(-)

diff --git a/Classes/Controller/OverviewController.php b/Classes/Controller/OverviewController.php
index 1194824..89c861d 100644
--- a/Classes/Controller/OverviewController.php
+++ b/Classes/Controller/OverviewController.php
@@ -35,13 +35,13 @@ use SGalinski\SgNews\Domain\Repository\TagRepository;
 use SGalinski\SgNews\Service\ConfigurationService;
 use SGalinski\SgNews\Service\HeaderMetaDataService;
 use TYPO3\CMS\Core\Http\ImmediateResponseException;
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Persistence\Generic\Query;
 use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
 use TYPO3\CMS\Extbase\Persistence\QueryInterface;
 use TYPO3\CMS\Frontend\Controller\ErrorController;
 use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 
 /**
  * Controller that handles the overview page of categories and their news
@@ -108,17 +108,170 @@ class OverviewController extends AbstractController {
 	 * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
 	 */
 	public function overviewAction(array $newsFilter = [], int $currentPageBrowserPage = 0) {
-		switch ((int) $this->settings['groupBy']) {
-			case 1:
-				$this->overviewWithCategories([], [], $newsFilter, $currentPageBrowserPage);
-				break;
-			case 2:
-				$this->overviewWithTags([], [], $newsFilter, $currentPageBrowserPage);
-				break;
-			default:
-				$this->forward('overviewWithoutCategories', NULL, NULL, $this->request->getArguments());
-				break;
+		if ((bool) $this->settings['enableFilter'] === TRUE) {
+			$this->overviewWithAllFilters([], [], $newsFilter, $currentPageBrowserPage);
+		} else {
+			switch ((int) $this->settings['groupBy']) {
+				case 1:
+					$this->overviewWithCategories([], [], $newsFilter, $currentPageBrowserPage);
+					break;
+				case 2:
+					$this->overviewWithTags([], [], $newsFilter, $currentPageBrowserPage);
+					break;
+				default:
+					$this->forward('overviewWithoutCategories', NULL, NULL, $this->request->getArguments());
+					break;
+			}
+		}
+	}
+
+	/**
+	 * Renders the news overview by all filters
+	 *
+	 * @param array $newsByFilters
+	 * @param array $allNews
+	 * @param array $newsFilter
+	 * @param int $currentPageBrowserPage
+	 * @return void
+	 * @throws \InvalidArgumentException
+	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
+	 * @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
+	 * @throws ImmediateResponseException
+	 * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException
+	 */
+	protected function overviewWithAllFilters(
+		array $newsByFilters = [], array $allNews = [], array $newsFilter = [], int $currentPageBrowserPage = 0
+	) {
+		// Setup settings
+		$startTime = (int) $this->settings['starttime'];
+		$endTime = (int) $this->settings['endtime'];
+		$newsLimit = (int) $this->settings['newsLimit'];
+		$offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsLimit);
+		$configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
+		$sortBy = $configurationService->getConfiguration('sortBy', $this->settings);
+		$sortDirection = $configurationService->getConfiguration('sortDirection', $this->settings);
+		$this->tagRepository->setDefaultOrderings(['sorting' => QueryInterface::ORDER_ASCENDING]);
+		$this->categoryRepository->setDefaultOrderings(['sorting' => QueryInterface::ORDER_ASCENDING]);
+
+		// Get tag pid
+		$tagPid = (int) $this->settings['tagPid'];
+		if (!$tagPid) {
+			$tagPid = $GLOBALS['TSFE']->id;
+		}
+
+		if ($this->settings['onlyNewsWithinThisPageSection']) {
+			$categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id);
+			$tags = $this->tagRepository->findTagsInRootLine($tagPid);
+		} else {
+			$tags = $this->tagRepository->findAll()->toArray();
+			$categories = $this->categoryRepository->findAll()->toArray();
+		}
+
+		// Get category restrictions
+		$categoryRestrictions = GeneralUtility::intExplode(',', $this->settings['categoryRestrictions'], TRUE);
+		if (count($categoryRestrictions) > 0) {
+			foreach ($categories as $key => $category) {
+				$categoryId = $category->getUid();
+
+				// older version compatibility with selection of categories in translations and so on
+				$categoryIdTranslated = $categoryId;
+				if ($category->_getProperty('_languageUid') > 0) {
+					$originalLangCategory = $this->categoryRepository->findOriginalLanguageById($categoryId);
+					if ($originalLangCategory) {
+						$categoryIdTranslated = $originalLangCategory->getUid();
+					}
+				}
+
+				if (!in_array($categoryId, $categoryRestrictions, TRUE) &&
+					!in_array($categoryIdTranslated, $categoryRestrictions, TRUE)
+				) {
+					unset($categories[$key]);
+				}
+			}
+		} else {
+			return;
+		}
+
+		// Get tag restrictions
+		$tagRestrictions = GeneralUtility::intExplode(',', $this->settings['tagRestrictions'], TRUE);
+		if (count($tagRestrictions) > 0) {
+			foreach ($tags as $key => $tag) {
+				if (!in_array($tag->getUid(), $tagRestrictions, TRUE)) {
+					unset($tags[$key]);
+				}
+			}
+		} else {
+			return;
+		}
+
+		// Get category ids or use the one in the filter
+		$categoryIds = [];
+		if ($newsFilter['category']) {
+			$categoryIds = [(int) $newsFilter['category']];
+		} else {
+			foreach ($categories as $category) {
+				$categoryIds[] = $category->getUid();
+			}
+		}
+
+		// Get tag ids or use the one in the filter
+		$tagIds = [];
+		if ($newsFilter['tag']) {
+			$tagIds = [(int) $newsFilter['tag']];
+		} else {
+			foreach ($tags as $tag) {
+				$tagIds[] = $tag->getUid();
+			}
+		}
+
+		// Get all news by category and tag ids
+		$news = $this->newsRepository->findAllSortedNewsByCategories(
+			$categoryIds, $newsLimitPerTag, $offset, $sortBy, $tagIds, $startTime, $endTime, $sortDirection
+		);
+
+		// Process news result query into meta data
+		$newsMetaData = [];
+		foreach ($news as $newsEntry) {
+			/** @var News $newsEntry */
+			$categoryId = $newsEntry->getPid();
+			if (!isset($categoriesById[$categoryId])) {
+				$categoriesById[$categoryId] = $this->categoryRepository->findByUid($categoryId);
+			}
+			$category = $categoriesById[$categoryId];
+			if (!$category) {
+				// Category isn't visible.
+				continue;
+			}
+			$newsMetaData[] = $this->getMetaDataForNews($newsEntry, $category);
 		}
+
+		$this->highlightBestFitNews([], $tagIds);
+
+		// Check to achieve less Ajax calls.
+		$newsCount = $this->newsRepository->newsCountByCategories([], $tagIds, $startTime, $endTime);
+		$numberOfPages = (int) ($newsLimitPerTag <= 0 ? 0 : ceil($newsCount / $newsLimitPerTag));
+		if ($numberOfPages !== 0 && $currentPageBrowserPage >= $numberOfPages) {
+			/** @var ErrorController $errorController */
+			$errorController = GeneralUtility::makeInstance(ErrorController::class);
+			$response = $errorController->pageNotFoundAction(
+				$GLOBALS['TYPO3_REQUEST'],
+				'The requested page does not exist',
+				['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
+			);
+			throw new ImmediateResponseException($response);
+		}
+
+		// remember selection of the filter values, if any
+		$selectedTag = $this->tagRepository->findByUid((int) $newsFilter['tag']);
+		$selectedCategory = $this->categoryRepository->findByUid((int) $newsFilter['category']);
+		$this->view->assign('selectedCategory', $selectedCategory);
+		$this->view->assign('selectedTag', $selectedTag);
+		$this->view->assign('tags', $tags);
+		$this->view->assign('categories', $categories);
+		$this->view->assign('numberOfPages', $numberOfPages);
+		$this->view->assign('newsItems', $newsByTag);
+		$this->view->assign('groupBy', $this->settings['groupBy']);
+		$this->view->assign('allNews', $newsMetaData);
 	}
 
 	/**
diff --git a/Configuration/FlexForms/Overview.xml b/Configuration/FlexForms/Overview.xml
index 23ce498..6ce2261 100644
--- a/Configuration/FlexForms/Overview.xml
+++ b/Configuration/FlexForms/Overview.xml
@@ -13,6 +13,7 @@
 					<settings.groupBy>
 						<TCEforms>
 							<label>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.groupBy</label>
+							<description>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.groupBy.description</description>
 							<onChange>reload</onChange>
 							<config>
 								<type>select</type>
@@ -36,11 +37,28 @@
 						</TCEforms>
 					</settings.groupBy>
 
+					<settings.enableFilter>
+						<TCEforms>
+							<label>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.enableFilter</label>
+							<description>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.enableFilter.description</description>
+							<onChange>reload</onChange>
+							<config>
+								<type>check</type>
+								<default>0</default>
+							</config>
+						</TCEforms>
+					</settings.enableFilter>
+
 					<settings.categoryRestrictions>
 						<TCEforms>
 							<label>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.categoryRestrictions</label>
 							<description>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.categoryRestrictions.description</description>
-							<displayCond>FIELD:settings.groupBy:=:1</displayCond>
+							<displayCond>
+								<or>
+									<value1>FIELD:settings.groupBy:=:1</value1>
+									<value2>FIELD:settings.enableFilter:=:1</value2>
+								</or>
+							</displayCond>
 							<config>
 								<type>select</type>
 								<renderType>selectMultipleSideBySide</renderType>
@@ -57,7 +75,12 @@
 						<TCEforms>
 							<label>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.flexForm.tags</label>
 							<description>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.tags.description</description>
-							<displayCond>FIELD:settings.groupBy:=:2</displayCond>
+							<displayCond>
+								<or>
+									<value1>FIELD:settings.groupBy:=:2</value1>
+									<value2>FIELD:settings.enableFilter:=:1</value2>
+								</or>
+							</displayCond>
 							<config>
 								<type>select</type>
 								<renderType>selectTree</renderType>
@@ -77,16 +100,6 @@
 						</TCEforms>
 					</settings.tagRestrictions>
 
-					<settings.enableFilter>
-						<TCEforms>
-							<label>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.enableFilter</label>
-							<description>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.enableFilter.description</description>
-							<config>
-								<type>check</type>
-								<default>0</default>
-							</config>
-						</TCEforms>
-					</settings.enableFilter>
 					<settings.categoryLabel>
 						<TCEforms>
 							<label>LLL:EXT:sg_news/Resources/Private/Language/locallang_db.xlf:plugin.overview.flexForm.categoryLabel</label>
diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf
index 22069fc..249b0d9 100644
--- a/Resources/Private/Language/de.locallang_db.xlf
+++ b/Resources/Private/Language/de.locallang_db.xlf
@@ -232,16 +232,20 @@ If none are selected, all categories will be available in the frontend.]]></sour
 Wenn keine ausgewählt werden, sind alle Kategorien im Frontend verfügbar.]]></target>
 			</trans-unit>
 			<trans-unit id="plugin.overview.flexForm.enableFilter" approved="yes">
-				<source><![CDATA[Enable filtering by all criteria.]]></source>
-				<target><![CDATA[Ermögliche das Filtern mit allen Krierien.]]></target>
+				<source><![CDATA[Show all filters]]></source>
+				<target><![CDATA[Zeige alle Filter an]]></target>
 			</trans-unit>
 			<trans-unit id="plugin.overview.flexForm.enableFilter.description" approved="yes">
 				<source><![CDATA[Filters will be rendered as select boxes and tabs will be hidden.]]></source>
 				<target><![CDATA[Filter werden als Dropdown-Box angezeigt und die Tabs ausgeblendet.]]></target>
 			</trans-unit>
 			<trans-unit id="plugin.overview.flexForm.groupBy" approved="yes">
-				<source><![CDATA[Group news pages in tabs by]]></source>
-				<target><![CDATA[News-Seiten nach folgendem Kriterium in Tabs gruppieren]]></target>
+				<source><![CDATA[Group news pages by]]></source>
+				<target><![CDATA[News-Seiten nach folgendem Kriterium gruppieren]]></target>
+			</trans-unit>
+			<trans-unit id="plugin.overview.flexForm.groupBy.description" approved="yes">
+				<source><![CDATA[News pages will be grouped in tabs.]]></source>
+				<target><![CDATA[News-Seiten werden in Tabs gruppiert.]]></target>
 			</trans-unit>
 			<trans-unit id="plugin.overview.flexForm.groupBy.I.0" approved="yes">
 				<source><![CDATA[No grouping]]></source>
diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf
index a24ed7c..a1abc3a 100644
--- a/Resources/Private/Language/locallang_db.xlf
+++ b/Resources/Private/Language/locallang_db.xlf
@@ -176,13 +176,16 @@
 If none are selected, all categories will be available in the frontend.]]></source>
 			</trans-unit>
 			<trans-unit id="plugin.overview.flexForm.enableFilter">
-				<source><![CDATA[Enable filtering by all criteria.]]></source>
+				<source><![CDATA[Show all filters]]></source>
 			</trans-unit>
 			<trans-unit id="plugin.overview.flexForm.enableFilter.description">
 				<source><![CDATA[Filters will be rendered as select boxes and tabs will be hidden.]]></source>
 			</trans-unit>
 			<trans-unit id="plugin.overview.flexForm.groupBy">
-				<source><![CDATA[Group news pages in tabs by]]></source>
+				<source><![CDATA[Group news pages by]]></source>
+			</trans-unit>
+			<trans-unit id="plugin.overview.flexForm.groupBy.description">
+				<source><![CDATA[News pages will be grouped in tabs.]]></source>
 			</trans-unit>
 			<trans-unit id="plugin.overview.flexForm.groupBy.I.0">
 				<source><![CDATA[No grouping]]></source>
-- 
GitLab