<?php namespace SGalinski\SgNews\Controller; /*************************************************************** * Copyright notice * * (c) sgalinski Internet Services (https://www.sgalinski.de) * * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is * free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * The GNU General Public License can be found at * http://www.gnu.org/copyleft/gpl.html. * * This script is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ use SGalinski\SgNews\Domain\Model\Category; use SGalinski\SgNews\Domain\Model\Tag; use SGalinski\SgNews\Domain\Model\News; use SGalinski\SgNews\Service\HeaderMetaDataService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Persistence\Generic\Query; use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult; /** * Controller that handles the overview page of categories and their news */ class OverviewController extends AbstractController { /** * @inject * @var \SGalinski\SgNews\Domain\Repository\CategoryRepository */ protected $categoryRepository; /** * @inject * @var \SGalinski\SgNews\Domain\Repository\TagRepository */ protected $tagRepository; /** * @inject * @var \SGalinski\SgNews\Domain\Repository\NewsRepository */ protected $newsRepository; /** * Renders the news overview * * @param array $newsFilter * @return void * @throws \InvalidArgumentException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException */ public function overviewAction(array $newsFilter = []) { switch ((int) $this->settings['groupBy']) { case 1: $this->overviewWithCategories([], [], $newsFilter); break; case 2: $this->overviewWithTags([], [], $newsFilter); break; default: $this->forward('overviewWithoutCategories', NULL, NULL, $this->request->getArguments()); break; } } /** * Highlights the best fitting news in the meta data of the page * * @param array $categoryIds * @param array $tagIds * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException * @throws \InvalidArgumentException */ protected function highlightBestFitNews(array $categoryIds = NULL, array $tagIds = NULL) { $startTime = (int) $this->settings['starttime']; $endTime = (int) $this->settings['endtime']; /** @var News $highlightedNews */ $highlightedNews = $this->newsRepository ->findLastUpdatedOrHighlightedNewsByCategories( 1, FALSE, $categoryIds, 0, FALSE, $this->settings['sortBy'], $tagIds, $startTime, $endTime )->getFirst(); if (!$highlightedNews) { return; } /** @var Category $category */ $category = $this->categoryRepository->findByUid($highlightedNews->getPid()); $highlightedNewsMetaData = NULL; if ($category) { $highlightedNewsMetaData = $this->getMetaDataForNews($highlightedNews, $category); } if ($highlightedNewsMetaData['image']) { HeaderMetaDataService::addOgImageToHeader($highlightedNewsMetaData['image']); } elseif ($highlightedNewsMetaData['teaserImage']) { HeaderMetaDataService::addOgImageToHeader($highlightedNewsMetaData['teaserImage']); } } /** * Renders the news overview grouped by categories * * @param array $newsByCategory * @param array $allNews * @param array $newsFilter * @return void * @throws \InvalidArgumentException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ protected function overviewWithCategories(array $newsByCategory = [], array $allNews = [], array $newsFilter = []) { $newsLimitPerCategory = (int) $this->settings['newsLimit']; $this->categoryRepository->setDefaultOrderings(['sorting' => Query::ORDER_ASCENDING]); $offset = 0; $currentPageBrowserPage = (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage']; if ($currentPageBrowserPage && $newsLimitPerCategory) { $offset = $currentPageBrowserPage * $newsLimitPerCategory; } if ($this->settings['onlyNewsWithinThisPageSection']) { /** @noinspection PhpUndefinedMethodInspection */ $categories = $this->categoryRepository->findByPid($GLOBALS['TSFE']->id); } else { $categories = $this->categoryRepository->findAll(); } $startTime = (int) $this->settings['starttime']; $endTime = (int) $this->settings['endtime']; $categoryIds = []; $categoriesById = []; $newsMetaData = []; foreach ($categories as $category) { /** @var $category Category */ $categoryId = $category->getUid(); $categoryIds[] = $category->getUid(); $categoriesById[$categoryId] = $category; $tagIds = NULL; if ($newsFilter['tag']) { $tagIds = [(int) $newsFilter['tag']]; } $news = $this->newsRepository->findAllSortedNewsByCategories( [$categoryId], $newsLimitPerCategory, $offset, $this->settings['sortBy'], $tagIds, $startTime, $endTime ); $newsMetaData[$categoryId] = []; foreach ($news as $newsEntry) { /** @var News $newsEntry */ $categoryId = $newsEntry->getPid(); $category = $categoriesById[$categoryId]; if (!$category) { // Category isn't visible. continue; } $data = $this->getMetaDataForNews($newsEntry, $category); $newsMetaData[$categoryId][] = $data; } } $maxNewsPerCategory = 0; foreach ($categoriesById as $categoryId => $category) { if (\count($newsMetaData[$categoryId]) <= 0) { // Hide empty tags. continue; } /** @var $category Category */ if (isset($newsByCategory[$categoryId])) { /** @var $category Category */ $newsByCategory[$categoryId]['newsMetaData'] = array_merge($newsByCategory[$categoryId]['newsMetaData'], $newsMetaData[$categoryId], $newsFilter); } else { $newsByCategory[$categoryId] = [ 'record' => $category, 'recordId' => $categoryId, 'recordType' => 'category', 'newsMetaData' => $newsMetaData[$categoryId], 'newsCount' => \count($newsMetaData[$categoryId]) ]; } $maxNewsPerCategory = max($maxNewsPerCategory, count($newsByCategory[$categoryId]['newsMetaData'])); } $tagIds = NULL; if ($newsFilter['tag']) { $tagIds = [(int) $newsFilter['tag']]; } $news = $this->newsRepository->findAllSortedNewsByCategories( $categoryIds, $newsLimitPerCategory, $offset, $this->settings['sortBy'], $tagIds, $startTime, $endTime ); foreach ($news as $newsEntry) { /** @var News $newsEntry */ $categoryId = $newsEntry->getPid(); $category = $categoriesById[$categoryId]; if (!$category) { // Category isn't visible. continue; } $data = $this->getMetaDataForNews($newsEntry, $category); $allNews[] = $data; } $this->highlightBestFitNews($categoryIds); $newsCount = $this->newsRepository->newsCountByCategories($categoryIds, $tagIds, $startTime, $endTime); $numberOfPages = ($newsLimitPerCategory <= 0 ? 0 : ceil($newsCount / $newsLimitPerCategory)); // Redo this function, until one variable get the amount of newsLimitPerTag. Reduces the amount of ajax calls. Needed because of languagevisibility. if ($maxNewsPerCategory < $newsLimitPerCategory && count($allNews) < $newsLimitPerCategory) { $nextPage = $currentPageBrowserPage + 1; if ($nextPage <= $numberOfPages) { GeneralUtility::_GETset(['tx_sgnews_pagebrowser' => ['currentPage' => $nextPage]]); $this->overviewWithCategories($newsByCategory, $allNews, $newsFilter); return; } } // find all tags $tagPid = $GLOBALS['TSFE']->id; if ($this->settings['onlyNewsWithinThisPageSection']) { /** @noinspection PhpUndefinedMethodInspection */ $tags = $this->tagRepository->findByPid($tagPid); } else { $tags = $this->tagRepository->findAll(); } // 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('numberOfPages', $numberOfPages); $this->view->assign('newsItems', $newsByCategory); $this->view->assign('groupBy', 'category'); $this->view->assign('allNews', $allNews); $this->view->assign('categoryTabs', TRUE); } /** * Renders the news overview grouped by tags * * @param array $newsByTag * @param array $allNews * @param array $newsFilter * @return void * @throws \InvalidArgumentException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ protected function overviewWithTags(array $newsByTag = [], array $allNews = [], array $newsFilter = []) { $newsLimitPerTag = (int) $this->settings['newsLimit']; $this->tagRepository->setDefaultOrderings(['sorting' => Query::ORDER_ASCENDING]); $offset = 0; $currentPageBrowserPage = (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage']; if ($currentPageBrowserPage && $newsLimitPerTag) { $offset = $currentPageBrowserPage * $newsLimitPerTag; } $tagPid = (int) $this->settings['tagPid']; if (!$tagPid) { $tagPid = $GLOBALS['TSFE']->id; } if ($this->settings['onlyNewsWithinThisPageSection']) { /** @noinspection PhpUndefinedMethodInspection */ $tags = $this->tagRepository->findByPid($tagPid); } else { $tags = $this->tagRepository->findAll(); } $startTime = (int) $this->settings['starttime']; $endTime = (int) $this->settings['endtime']; $tagIds = []; $tagsById = []; $categoriesById = []; $newsMetaData = []; foreach ($tags as $tag) { /** @var $tag Tag */ $tagId = $tag->getUid(); $tagIds[] = $tagId; $tagsById[$tagId] = $tag; $categoryIds = NULL; if ($newsFilter['category']) { $categoryIds = [(int) $newsFilter['category']]; } $news = $this->newsRepository->findAllSortedNewsByCategories( $categoryIds, $newsLimitPerTag, $offset, $this->settings['sortBy'], [$tagId], $startTime, $endTime ); $newsMetaData[$tagId] = []; 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; } $data = $this->getMetaDataForNews($newsEntry, $category); $newsMetaData[$tagId][] = $data; } } $maxNewsPerTag = 0; foreach ($tagsById as $tagId => $tag) { if (\count($newsMetaData[$tagId]) <= 0) { // Hide empty tags. continue; } if (isset($newsByTag[$tagId])) { $newsByTag[$tagId]['newsMetaData'] = array_merge($newsByTag[$tagId]['newsMetaData'], $newsMetaData[$tagId]); } else { $newsByTag[$tagId] = [ 'record' => $tag, 'recordId' => $tagId, 'recordType' => 'tag', 'newsMetaData' => $newsMetaData[$tagId], 'newsCount' => \count($newsMetaData[$tagId]) ]; } $maxNewsPerTag = max($maxNewsPerTag, count($newsByTag[$tagId]['newsMetaData'])); } $categoryIds = NULL; if ($newsFilter['category']) { $categoryIds = [(int) $newsFilter['category']]; } $news = $this->newsRepository->findAllSortedNewsByCategories( $categoryIds, $newsLimitPerTag, $offset, $this->settings['sortBy'], $tagIds, $startTime, $endTime ); 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; } $data = $this->getMetaDataForNews($newsEntry, $category); $allNews[] = $data; } $this->highlightBestFitNews([], $tagIds); $newsCount = $this->newsRepository->newsCountByCategories([], $tagIds, $startTime, $endTime); $numberOfPages = ($newsLimitPerTag <= 0 ? 0 : ceil($newsCount / $newsLimitPerTag)); // Redo this function, until one variable get the amount of newsLimitPerTag. Reduces the amount of ajax calls. Needed because of languagevisibility. if ($maxNewsPerTag < $newsLimitPerTag && count($allNews) < $newsLimitPerTag) { $nextPage = $currentPageBrowserPage + 1; if ($nextPage <= $numberOfPages) { GeneralUtility::_GETset(['tx_sgnews_pagebrowser' => ['currentPage' => $nextPage]]); $this->overviewWithTags($newsByTag, $allNews, $newsFilter); return; } } if ($this->settings['onlyNewsWithinThisPageSection']) { /** @noinspection PhpUndefinedMethodInspection */ $categories = $this->categoryRepository->findByPid($GLOBALS['TSFE']->id); } else { $categories = $this->categoryRepository->findAll(); } // 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('numberOfPages', $numberOfPages); $this->view->assign('newsItems', $newsByTag); $this->view->assign('groupBy', 'tag'); $this->view->assign('allNews', $allNews); $this->view->assign('tagTabs', TRUE); } /** * Renders the news in a paginated list * * @param array $newsMetaData * @param array $newsFilter * @param boolean $isInitialCall * @return void * @throws \InvalidArgumentException * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException */ protected function overviewWithoutCategoriesAction( array $newsMetaData = [], array $newsFilter = NULL, $isInitialCall = TRUE ) { // 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('selectedTag', $selectedTag); $this->view->assign('selectedCategory', $selectedCategory); $offset = 0; $newsPerPage = (int) $this->settings['newsLimit']; $currentPageBrowserPage = (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage']; if ($currentPageBrowserPage && $newsPerPage) { // might be necessary for the recursive calling performance wise $offset = ($currentPageBrowserPage * $newsPerPage) - ($isInitialCall ? 0 : 1); } $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 */ $categoryId = $category->getUid(); $categoryIds[] = $categoryId; $categoriesById[$categoryId] = $category; } // 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); } else { $newsCount = $this->newsRepository->countAll($startTime, $endTime); $categoryIds = NULL; $categoriesById = []; $categories = $this->categoryRepository->findAll(); foreach ($categories as $category) { /** @var $category Category */ $categoriesById[$category->getUid()] = $category; } } // 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']]; } $news = $this->newsRepository->findAllSortedNewsByCategories( $categoryIds, $newsPerPage, $offset, $this->settings['sortBy'], $tagIds, $startTime, $endTime ); foreach ($news as $newsEntry) { /** @var News $newsEntry */ $data = $this->getMetaDataForNews($newsEntry, $categoriesById[$newsEntry->getPid()]); $newsMetaData[] = $data; } $this->highlightBestFitNews($categoryIds); $numberOfPages = ($newsPerPage <= 0 ? 0 : ceil($newsCount / $newsPerPage)); // Redo this function, until one variable get the amount of newsLimitPerTag. Reduces the amount of ajax calls. Needed because of languagevisibility. if (count($newsMetaData) < $newsPerPage) { $nextPage = $currentPageBrowserPage + 1; if ($nextPage <= $numberOfPages) { GeneralUtility::_GETset(['tx_sgnews_pagebrowser' => ['currentPage' => $nextPage]]); $this->overviewWithoutCategoriesAction($newsMetaData, $newsFilter, FALSE); return; } } // find all tags $currentPageId = $GLOBALS['TSFE']->id; if ($this->settings['onlyNewsWithinThisPageSection']) { /** @noinspection PhpUndefinedMethodInspection */ $tags = $this->tagRepository->findByPid($currentPageId); } else { $tags = $this->tagRepository->findAll(); } $this->view->assign('tags', $tags->toArray()); $this->view->assign('categories', $categories->toArray()); $this->view->assign('numberOfPages', $numberOfPages); $this->view->assign('newsMetaData', $newsMetaData); } }