Skip to content
Snippets Groups Projects
OverviewController.php 15.1 KiB
Newer Older
Stefan Galinski's avatar
Stefan Galinski committed
<?php

namespace SGalinski\SgNews\Controller;

/***************************************************************
 *  Copyright notice
 *
 *  (c) sgalinski Internet Services (https://www.sgalinski.de)
Stefan Galinski's avatar
Stefan Galinski committed
 *
 *  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;
Stefan Galinski's avatar
Stefan Galinski committed
use SGalinski\SgNews\Domain\Model\News;
use SGalinski\SgNews\Service\HeaderMetaDataService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
Stefan Galinski's avatar
Stefan Galinski committed
use TYPO3\CMS\Extbase\Persistence\Generic\Query;
use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
Stefan Galinski's avatar
Stefan Galinski committed

/**
 * 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;

Stefan Galinski's avatar
Stefan Galinski committed
	/**
	 * @inject
	 * @var \SGalinski\SgNews\Domain\Repository\NewsRepository
	 */
	protected $newsRepository;

	/**
	 * Renders the news overview
	 *
	 * @return void
	 * @throws \InvalidArgumentException
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
Stefan Galinski's avatar
Stefan Galinski committed
	 */
	public function overviewAction() {
		switch ((int) $this->settings['groupBy']) {
			case 1:
				$this->overviewWithCategories();
				break;
			case 2:
				$this->overviewWithTags();
				break;
			default:
				$this->forward('overviewWithoutCategories');
				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
		/** @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
	 * @throws \InvalidArgumentException
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	protected function overviewWithCategories(array $newsByCategory = [], array $allNews = []) {
		$newsLimitPerCategory = (int) $this->settings['newsLimit'];
Stefan Galinski's avatar
Stefan Galinski committed
		$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'];

		$categoriesById = [];
		$newsMetaData = [];
Stefan Galinski's avatar
Stefan Galinski committed
		foreach ($categories as $category) {
			/** @var $category Category */
Stefan Galinski's avatar
Stefan Galinski committed
			$categoryId = $category->getUid();
			$categoryIds[] = $category->getUid();
			$categoriesById[$categoryId] = $category;
Stefan Galinski's avatar
Stefan Galinski committed

			$news = $this->newsRepository->findAllSortedNewsByCategories(
				[$categoryId], $newsLimitPerCategory, $offset, $this->settings['sortBy'], NULL, $startTime, $endTime
			$newsMetaData[$categoryId] = [];
Stefan Galinski's avatar
Stefan Galinski committed
			foreach ($news as $newsEntry) {
				/** @var News $newsEntry */
				$categoryId = $newsEntry->getPid();
				$category = $categoriesById[$categoryId];
				if (!$category) {
					// Category isn't visible.
					continue;
				}
Stefan Galinski's avatar
Stefan Galinski committed
				$data = $this->getMetaDataForNews($newsEntry, $category);
				$newsMetaData[$categoryId][] = $data;
Stefan Galinski's avatar
Stefan Galinski committed
			}
Stefan Galinski's avatar
Stefan Galinski committed

		$maxNewsPerCategory = 0;
		foreach ($categoriesById as $categoryId => $category) {
			/** @var $category Category */
			if (isset($newsByCategory[$categoryId])) {
				/** @var $category Category */
				$newsByCategory[$categoryId]['newsMetaData'] =
					array_merge($newsByCategory[$categoryId]['newsMetaData'], $newsMetaData[$categoryId]);
			} else {
				$newsByCategory[$categoryId] = [
					'record' => $category,
					'recordId' => $categoryId,
					'recordType' => 'category',
					'newsMetaData' => $newsMetaData[$categoryId]
				];
			}

			$maxNewsPerCategory = max($maxNewsPerCategory, count($newsByCategory[$categoryId]['newsMetaData']));
Stefan Galinski's avatar
Stefan Galinski committed
		}

		$news = $this->newsRepository->findAllSortedNewsByCategories(
			$categoryIds, $newsLimitPerCategory, $offset, $this->settings['sortBy'], NULL, $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, NULL, $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);
				return;
			}
		}

		// find all tags
		$tagPid = $GLOBALS['TSFE']->id;
		if ($this->settings['onlyNewsWithinThisPageSection']) {
			/** @noinspection PhpUndefinedMethodInspection */
			$tags = $this->tagRepository->findByPid($tagPid);
		} 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('newsItems', $newsByCategory);
		$this->view->assign('groupBy', 'category');
		$this->view->assign('allNews', $allNews);
	}

	/**
	 * Renders the news overview grouped by tags
	 *
	 * @param array $newsByTag
	 * @param array $allNews
	 * @return void
	 * @throws \InvalidArgumentException
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	 */
	protected function overviewWithTags(array $newsByTag = [], array $allNews = []) {
		$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'];
			$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;

			$news = $this->newsRepository->findAllSortedNewsByCategories(
				NULL, $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;
			}
		}

		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]
				];
			}

			$maxNewsPerTag = max($maxNewsPerTag, count($newsByTag[$tagId]['newsMetaData']));
		}

		$news = $this->newsRepository->findAllSortedNewsByCategories(
			NULL, $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);
				return;
			}
		}

		if ($this->settings['onlyNewsWithinThisPageSection']) {
			/** @noinspection PhpUndefinedMethodInspection */
			$categories = $this->categoryRepository->findByPid($GLOBALS['TSFE']->id);
		} else {
			$categories = $this->categoryRepository->findAll();
		}

		$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);
Stefan Galinski's avatar
Stefan Galinski committed
	}

	/**
	 * Renders the news in a paginated list
	 *
	 * @param array $newsMetaData
	 * @throws \InvalidArgumentException
	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
	protected function overviewWithoutCategoriesAction(array $newsMetaData = []) {
		$offset = 0;
		$newsPerPage = (int) $this->settings['newsLimit'];
		$currentPageBrowserPage = (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage'];
		if ($currentPageBrowserPage && $newsPerPage) {
			$offset = ($currentPageBrowserPage * $newsPerPage) - 1;
		$startTime = (int) $this->settings['starttime'];
		$endTime = (int) $this->settings['endtime'];

		if ($this->settings['onlyNewsWithinThisPageSection']) {
			/** @noinspection PhpUndefinedMethodInspection */
			$categories = $this->categoryRepository->findByPid($GLOBALS['TSFE']->id);
			$categoriesById = [];
			/** @var QueryResult $categories */
			foreach ($categories as $category) {
				/** @var $category Category */
				$categoryId = $category->getUid();
				$categoryIds[] = $categoryId;
				$categoriesById[$categoryId] = $category;
			$newsCount = $this->newsRepository->newsCountByCategories($categoryIds, NULL, $startTime, $endTime);
			$newsCount = $this->newsRepository->countAll($startTime, $endTime);
			$categoryIds = NULL;
			$categoriesById = [];
			$categories = $this->categoryRepository->findAll();
			foreach ($categories as $category) {
				/** @var $category Category */
				$categoriesById[$category->getUid()] = $category;
			}
		$news = $this->newsRepository->findAllSortedNewsByCategories(
			$categoryIds, $newsPerPage, $offset, $this->settings['sortBy'], NULL, $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);
				return;
			}
		}

		// find all tags
		$tagPid = $GLOBALS['TSFE']->id;
		if ($this->settings['onlyNewsWithinThisPageSection']) {
			/** @noinspection PhpUndefinedMethodInspection */
			$tags = $this->tagRepository->findByPid($tagPid);
		} 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);