From 8e2b251003079de6dfa272df8f779a705b4a0ad3 Mon Sep 17 00:00:00 2001
From: Fabian Galinski <fabian@sgalinski.de>
Date: Fri, 27 Mar 2020 20:18:56 +0100
Subject: [PATCH] [FEATURE] Repair the overview plugin for TYPO3 9. See
 description

- Group by Tags: Not respecting the rootline, if the option onlyNewsWithinThisPageSection is true.
- Group by Categories: Not resprecting the rootline, if the option onlyNewsWithinThisPageSection is true. Also not respecting the multi language behaviour of the TYPO3 9 pages table.
- No grouping:  Not respecting the rootline, if the option onlyNewsWithinThisPageSection is true.
---
 Classes/Controller/OverviewController.php     | 146 ++++++++++--------
 .../Domain/Repository/CategoryRepository.php  |  24 ++-
 Classes/Domain/Repository/TagRepository.php   |  24 +++
 3 files changed, 126 insertions(+), 68 deletions(-)

diff --git a/Classes/Controller/OverviewController.php b/Classes/Controller/OverviewController.php
index aedc5c4..16a74fd 100644
--- a/Classes/Controller/OverviewController.php
+++ b/Classes/Controller/OverviewController.php
@@ -151,10 +151,13 @@ class OverviewController extends AbstractController {
 		$offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsLimitPerCategory);
 
 		if ($this->settings['onlyNewsWithinThisPageSection']) {
-			/** @noinspection PhpUndefinedMethodInspection */
-			$categories = $this->categoryRepository->findByPid($GLOBALS['TSFE']->id);
+			$categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id);
 		} else {
-			$categories = $this->categoryRepository->findAll();
+			$categories = $this->categoryRepository->findAll()->toArray();
+		}
+
+		if (count($categories) <= 0) {
+			return;
 		}
 
 		$startTime = (int) $this->settings['starttime'];
@@ -170,13 +173,16 @@ class OverviewController extends AbstractController {
 		foreach ($categories as $category) {
 			/** @var $category Category */
 			$categoryId = $category->getUid();
+			$categoryIdsForSelect = [$categoryId];
 			$categoryIds[] = $category->getUid();
 			$categoriesById[$categoryId] = $category;
-			if ($category->_getProperty('_languageUid')>0) {
+			if ($category->_getProperty('_languageUid') > 0) {
 				$originalLangCategory = $this->categoryRepository->findOriginalLanguageById($category->getUid());
 				if ($originalLangCategory) {
-					$categoryIds[] = $originalLangCategory->getUid();
-					$categoriesById[$originalLangCategory->getUid()] = $originalLangCategory;
+					$originalLangCategoryId = $originalLangCategory->getUid();
+					$categoryIdsForSelect[] = $originalLangCategoryId;
+					$categoryIds[] = $originalLangCategoryId;
+					$categoriesById[$originalLangCategoryId] = $originalLangCategory;
 				}
 			}
 
@@ -184,28 +190,31 @@ class OverviewController extends AbstractController {
 			if ($newsFilter['tag']) {
 				$tagIds = [(int) $newsFilter['tag']];
 			}
-			$news = $this->newsRepository->findAllSortedNewsByCategories(
-				[$categoryId], $newsLimitPerCategory, $offset, $sortBy, $tagIds, $startTime, $endTime, $sortDirection
-			);
-			$newsMetaData[$categoryId] = [];
-			foreach ($news as $newsEntry) {
-				/** @var News $newsEntry */
-				$categoryId = $newsEntry->getPid();
-				$category = $categoriesById[$categoryId];
-				if (!$category) {
-					// Category isn't visible.
-					continue;
-				}
+			foreach ($categoryIdsForSelect as $categoryIdsForSelectId) {
+				$news = $this->newsRepository->findAllSortedNewsByCategories(
+					[$categoryIdsForSelectId], $newsLimitPerCategory, $offset, $sortBy, $tagIds, $startTime, $endTime, $sortDirection
+				);
+
+				$newsMetaData[$categoryIdsForSelectId] = [];
+				foreach ($news as $newsEntry) {
+					/** @var News $newsEntry */
+					$categoryId = $newsEntry->getPid();
+					$category = $categoriesById[$categoryIdsForSelectId];
+					if (!$category) {
+						// Category isn't visible.
+						continue;
+					}
 
-				$data = $this->getMetaDataForNews($newsEntry, $category);
-				$newsMetaData[$categoryId][] = $data;
+					$data = $this->getMetaDataForNews($newsEntry, $category);
+					$newsMetaData[$categoryIdsForSelectId][] = $data;
+				}
 			}
 		}
 
 		$maxNewsPerCategory = 0;
 		foreach ($categoriesById as $categoryId => $category) {
-			if (\count($newsMetaData[$categoryId]) <= 0) {
-				// Hide empty tags.
+			if (!isset($newsMetaData[$categoryId]) || count($newsMetaData[$categoryId]) <= 0) {
+				// Hide empty categories.
 				continue;
 			}
 
@@ -220,7 +229,7 @@ class OverviewController extends AbstractController {
 					'recordId' => $categoryId,
 					'recordType' => 'category',
 					'newsMetaData' => $newsMetaData[$categoryId],
-					'newsCount' => \count($newsMetaData[$categoryId])
+					'newsCount' => count($newsMetaData[$categoryId])
 				];
 			}
 
@@ -265,17 +274,16 @@ class OverviewController extends AbstractController {
 		// find all tags
 		$tagPid = $GLOBALS['TSFE']->id;
 		if ($this->settings['onlyNewsWithinThisPageSection']) {
-			/** @noinspection PhpUndefinedMethodInspection */
-			$tags = $this->tagRepository->findByPid($tagPid);
+			$tags = $this->tagRepository->findTagsInRootLine($tagPid);
 		} else {
-			$tags = $this->tagRepository->findAll();
+			$tags = $this->tagRepository->findAll()->toArray();
 		}
 
 		// remember selection of the filter values, if any
 		$selectedTag = $this->tagRepository->findByUid((int) $newsFilter['tag']);
 		$this->view->assign('selectedTag', $selectedTag);
-		$this->view->assign('tags', $tags->toArray());
-		$this->view->assign('categories', $categories->toArray());
+		$this->view->assign('tags', $tags);
+		$this->view->assign('categories', $categories);
 		$this->view->assign('numberOfPages', $numberOfPages);
 		$this->view->assign('newsItems', $newsByCategory);
 		$this->view->assign('groupBy', 'category');
@@ -318,10 +326,9 @@ class OverviewController extends AbstractController {
 
 		$this->tagRepository->setDefaultOrderings(['sorting' => QueryInterface::ORDER_ASCENDING]);
 		if ($this->settings['onlyNewsWithinThisPageSection']) {
-			/** @noinspection PhpUndefinedMethodInspection */
-			$tags = $this->tagRepository->findByPid($tagPid);
+			$tags = $this->tagRepository->findTagsInRootLine($tagPid);
 		} else {
-			$tags = $this->tagRepository->findAll();
+			$tags = $this->tagRepository->findAll()->toArray();
 		}
 
 		// Get news by tag id
@@ -414,17 +421,16 @@ class OverviewController extends AbstractController {
 		}
 
 		if ($this->settings['onlyNewsWithinThisPageSection']) {
-			/** @noinspection PhpUndefinedMethodInspection */
-			$categories = $this->categoryRepository->findByPid($GLOBALS['TSFE']->id);
+			$categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id);
 		} else {
-			$categories = $this->categoryRepository->findAll();
+			$categories = $this->categoryRepository->findAll()->toArray();
 		}
 
 		// remember selection of the filter values, if any
 		$selectedCategory = $this->categoryRepository->findByUid((int) $newsFilter['category']);
 		$this->view->assign('selectedCategory', $selectedCategory);
-		$this->view->assign('tags', $tags->toArray());
-		$this->view->assign('categories', $categories->toArray());
+		$this->view->assign('tags', $tags);
+		$this->view->assign('categories', $categories);
 		$this->view->assign('numberOfPages', $numberOfPages);
 		$this->view->assign('newsItems', $newsByTag);
 		$this->view->assign('groupBy', 'tag');
@@ -472,54 +478,61 @@ class OverviewController extends AbstractController {
 		$newsPerPage = (int) $this->settings['newsLimit'];
 		$offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsPerPage);
 
+		$newsCount = 0;
 		$startTime = (int) $this->settings['starttime'];
 		$endTime = (int) $this->settings['endtime'];
 		if ($this->settings['onlyNewsWithinThisPageSection']) {
-			/** @noinspection PhpUndefinedMethodInspection */
-			$categories = $this->categoryRepository->findByPid($GLOBALS['TSFE']->id);
-
-			$categoryIds = [];
-			$categoriesById = [];
-			/** @var QueryResult $categories */
-			foreach ($categories as $category) {
-				/** @var $category Category */
-				$categoriesById[$category->getUid()] = $category;
-				$categoryIds[] = $category->getUid();
-				if ($category->_getProperty('_languageUid')>0) {
-					$originalLangCategory = $this->categoryRepository->findOriginalLanguageById($category->getUid());
-					if ($originalLangCategory) {
-						$categoryIds[] = $originalLangCategory->getUid();
-						$categoriesById[$originalLangCategory->getUid()] = $originalLangCategory;
+			$categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id);
+			if (count($categories) > 0) {
+				$categoryIds = [];
+				$categoriesById = [];
+				/** @var QueryResult $categories */
+				foreach ($categories as $category) {
+					/** @var $category Category */
+					$categoriesById[$category->getUid()] = $category;
+					$categoryIds[] = $category->getUid();
+					if ($category->_getProperty('_languageUid') > 0) {
+						$originalLangCategory = $this->categoryRepository->findOriginalLanguageById($category->getUid());
+						if ($originalLangCategory) {
+							$categoryIds[] = $originalLangCategory->getUid();
+							$categoriesById[$originalLangCategory->getUid()] = $originalLangCategory;
+						}
 					}
 				}
-			}
 
-			// filter by category and tag if selected in the filter
-			if ($newsFilter['category']) {
-				$categoryIds = [(int) $newsFilter['category']];
-			}
-			$tagIds = NULL;
-			if ($newsFilter['tag']) {
-				$tagIds = [(int) $newsFilter['tag']];
-			}
+				// filter by category and tag if selected in the filter
+				if ($newsFilter['category']) {
+					$categoryIds = [(int) $newsFilter['category']];
+				}
+
+				$tagIds = NULL;
+				if ($newsFilter['tag']) {
+					$tagIds = [(int) $newsFilter['tag']];
+				}
 
-			$newsCount = $this->newsRepository->newsCountByCategories($categoryIds, $tagIds, $startTime, $endTime);
+				$newsCount = $this->newsRepository->newsCountByCategories($categoryIds, $tagIds, $startTime, $endTime);
+			}
 		} else {
 			$newsCount = $this->newsRepository->countAll($startTime, $endTime);
 			$categoryIds = NULL;
 
 			$categoriesById = [];
-			$categories = $this->categoryRepository->findAll();
+			$categories = $this->categoryRepository->findAll()->toArray();
 			foreach ($categories as $category) {
 				/** @var $category Category */
 				$categoriesById[$category->getUid()] = $category;
 			}
 		}
 
+		if ($newsCount <= 0) {
+			return;
+		}
+
 		// filter by category and tag if selected in the filter
 		if ($newsFilter['category']) {
 			$categoryIds = [(int) $newsFilter['category']];
 		}
+
 		$tagIds = NULL;
 		if ($newsFilter['tag']) {
 			$tagIds = [(int) $newsFilter['tag']];
@@ -551,14 +564,13 @@ class OverviewController extends AbstractController {
 		// find all tags
 		$currentPageId = $GLOBALS['TSFE']->id;
 		if ($this->settings['onlyNewsWithinThisPageSection']) {
-			/** @noinspection PhpUndefinedMethodInspection */
-			$tags = $this->tagRepository->findByPid($currentPageId);
+			$tags = $this->tagRepository->findTagsInRootLine($currentPageId);
 		} else {
-			$tags = $this->tagRepository->findAll();
+			$tags = $this->tagRepository->findAll()->toArray();
 		}
 
-		$this->view->assign('tags', $tags->toArray());
-		$this->view->assign('categories', $categories->toArray());
+		$this->view->assign('tags', $tags);
+		$this->view->assign('categories', $categories);
 		$this->view->assign('numberOfPages', $numberOfPages);
 		$this->view->assign('newsMetaData', $newsMetaData);
 	}
diff --git a/Classes/Domain/Repository/CategoryRepository.php b/Classes/Domain/Repository/CategoryRepository.php
index e27a850..81f0076 100644
--- a/Classes/Domain/Repository/CategoryRepository.php
+++ b/Classes/Domain/Repository/CategoryRepository.php
@@ -29,6 +29,7 @@ namespace SGalinski\SgNews\Domain\Repository;
 use SGalinski\SgNews\Domain\Model\Category;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\RootlineUtility;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
 use TYPO3\CMS\Extbase\Persistence\QueryInterface;
 
@@ -50,7 +51,7 @@ class CategoryRepository extends AbstractRepository {
 	 * @param int $uid
 	 * @return Category|null
 	 */
-	public function findOriginalLanguageById(int $uid): ?Category {
+	public function findOriginalLanguageById(int $uid) {
 		$dataMapper = $this->objectManager->get(DataMapper::class);
 		$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
 		$row = $queryBuilder->select('default.*')
@@ -67,4 +68,25 @@ class CategoryRepository extends AbstractRepository {
 			return NULL;
 		}
 	}
+
+	/**
+	 * Returns all categories, with given page id in it's rootline.
+	 *
+	 * @param int $pageId
+	 *
+	 * @return array
+	 */
+	public function findCategoriesInRootLine(int $pageId): array {
+		$matchedCategories = [];
+		$allCategories = $this->findAll();
+		foreach ($allCategories as $category) {
+			/** @var Category $category */
+			$rootLineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $category->getUid());
+			if (in_array($pageId, array_column($rootLineUtility->get(), 'uid'), TRUE)) {
+				$matchedCategories[] = $category;
+			}
+		}
+
+		return $matchedCategories;
+	}
 }
diff --git a/Classes/Domain/Repository/TagRepository.php b/Classes/Domain/Repository/TagRepository.php
index fce1d72..bd98089 100644
--- a/Classes/Domain/Repository/TagRepository.php
+++ b/Classes/Domain/Repository/TagRepository.php
@@ -26,8 +26,32 @@ namespace SGalinski\SgNews\Domain\Repository;
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
 
+use SGalinski\SgNews\Domain\Model\Tag;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\RootlineUtility;
+
 /**
  * Tag Repository
  */
 class TagRepository extends AbstractRepository {
+	/**
+	 * Returns all categories, with given page id in it's rootline.
+	 *
+	 * @param int $pageId
+	 *
+	 * @return array
+	 */
+	public function findTagsInRootLine(int $pageId): array {
+		$matchedTags = [];
+		$allTags = $this->findAll();
+		foreach ($allTags as $tag) {
+			/** @var Tag $tag */
+			$rootLineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $tag->getPid());
+			if (in_array($pageId, array_column($rootLineUtility->get(), 'uid'), TRUE)) {
+				$matchedTags[] = $tag;
+			}
+		}
+
+		return $matchedTags;
+	}
 }
-- 
GitLab