Newer
Older
<?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\Repository\CategoryRepository;
use SGalinski\SgNews\Domain\Repository\NewsRepository;
use SGalinski\SgNews\Domain\Repository\TagRepository;
use SGalinski\SgNews\Service\ConfigurationService;
use SGalinski\SgNews\Service\HeaderMetaDataService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
Fabian Galinski
committed
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
/**
* Controller that handles the overview page of categories and their news
*/
class OverviewController extends AbstractController {
/**
/**
* Initialize the overviewAction to set the currentPageBrowserPage parameter
*
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException
*/
public function initializeOverviewAction(){
$currentPageBrowserPage = (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage'];
if($currentPageBrowserPage > 0){
$this->request->setArgument('currentPageBrowserPage', $currentPageBrowserPage);
}
}
* @param array $newsFilter
* @param int $currentPageBrowserPage
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
public function overviewAction(array $newsFilter = [], $currentPageBrowserPage = 0) {
switch ((int) $this->settings['groupBy']) {
case 1:
$this->overviewWithCategories([], [], $newsFilter, $currentPageBrowserPage);
$this->overviewWithTags([], [], $newsFilter, $currentPageBrowserPage);
$this->forward('overviewWithoutCategories', NULL, NULL, $this->request->getArguments());
/**
* 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
*/
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 int $currentPageBrowserPage
* @return void
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
protected function overviewWithCategories(
array $newsByCategory = [], array $allNews = [], array $newsFilter = [], $currentPageBrowserPage = 0
$newsLimitPerCategory = (int) $this->settings['newsLimit'];
$this->categoryRepository->setDefaultOrderings(['sorting' => Query::ORDER_ASCENDING]);
$offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsLimitPerCategory);
if ($this->settings['onlyNewsWithinThisPageSection']) {
$categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id);
} else {
$categories = $this->categoryRepository->findAll()->toArray();
}
if (count($categories) <= 0) {
return;
}
$startTime = (int) $this->settings['starttime'];
$endTime = (int) $this->settings['endtime'];
$configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
$sortBy = $configurationService->getConfiguration('sortBy', $this->settings);
$sortDirection = $configurationService->getConfiguration('sortDirection', $this->settings);
$categoryIds = [];
$categoriesById = [];
$newsMetaData = [];
/** @var $category Category */
$categoryIdsForSelect = [$categoryId];
$categoryIds[] = $category->getUid();
$categoriesById[$categoryId] = $category;
if ($category->_getProperty('_languageUid') > 0) {
Kevin Ditscheid
committed
$originalLangCategory = $this->categoryRepository->findOriginalLanguageById($category->getUid());
if ($originalLangCategory) {
$originalLangCategoryId = $originalLangCategory->getUid();
$categoryIdsForSelect[] = $originalLangCategoryId;
$categoryIds[] = $originalLangCategoryId;
$categoriesById[$originalLangCategoryId] = $originalLangCategory;
Kevin Ditscheid
committed
}
}
$tagIds = NULL;
if ($newsFilter['tag']) {
$tagIds = [(int) $newsFilter['tag']];
}
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[$categoryIdsForSelectId][] = $data;
}
$maxNewsPerCategory = 0;
foreach ($categoriesById as $categoryId => $category) {
if (!isset($newsMetaData[$categoryId]) || count($newsMetaData[$categoryId]) <= 0) {
// Hide empty categories.
/** @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])
Fabian Galinski
committed
$maxNewsPerCategory = \max($maxNewsPerCategory, \count($newsByCategory[$categoryId]['newsMetaData']));
$tagIds = NULL;
if ($newsFilter['tag']) {
$tagIds = [(int) $newsFilter['tag']];
}
$news = $this->newsRepository->findAllSortedNewsByCategories(
$categoryIds, $newsLimitPerCategory, $offset, $sortBy, $tagIds, $startTime, $endTime, $sortDirection
);
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.
Fabian Galinski
committed
if ($maxNewsPerCategory < $newsLimitPerCategory && \count($allNews) < $newsLimitPerCategory) {
$nextPage = $currentPageBrowserPage + 1;
if ($nextPage <= $numberOfPages) {
Fabian Galinski
committed
$this->setPageBrowserPage($nextPage);
$this->overviewWithCategories($newsByCategory, $allNews, $newsFilter, $nextPage);
return;
}
}
// find all tags
$tagPid = $GLOBALS['TSFE']->id;
if ($this->settings['onlyNewsWithinThisPageSection']) {
$tags = $this->tagRepository->findTagsInRootLine($tagPid);
$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);
$this->view->assign('categories', $categories);
$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 int $currentPageBrowserPage
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
protected function overviewWithTags(
array $newsByTag = [], array $allNews = [], array $newsFilter = [], $currentPageBrowserPage = 0
Fabian Galinski
committed
$startTime = (int) $this->settings['starttime'];
$endTime = (int) $this->settings['endtime'];
$newsLimitPerTag = (int) $this->settings['newsLimit'];
$offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsLimitPerTag);
Fabian Galinski
committed
$configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
$sortBy = $configurationService->getConfiguration('sortBy', $this->settings);
$sortDirection = $configurationService->getConfiguration('sortDirection', $this->settings);
Fabian Galinski
committed
$categoryIds = NULL;
if ($newsFilter['category']) {
$categoryIds = [(int) $newsFilter['category']];
}
$this->tagRepository->setDefaultOrderings(['sorting' => QueryInterface::ORDER_ASCENDING]);
if ($this->settings['onlyNewsWithinThisPageSection']) {
$tags = $this->tagRepository->findTagsInRootLine($tagPid);
$tags = $this->tagRepository->findAll()->toArray();
Fabian Galinski
committed
// Get news by tag id
$tagIds = [];
$tagsById = [];
$categoriesById = [];
$newsMetaData = [];
foreach ($tags as $tag) {
/** @var $tag Tag */
$tagId = $tag->getUid();
$tagIds[] = $tagId;
$tagsById[$tagId] = $tag;
$news = $this->newsRepository->findAllSortedNewsByCategories(
$categoryIds, $newsLimitPerTag, $offset, $sortBy, [$tagId], $startTime, $endTime, $sortDirection
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;
}
Fabian Galinski
committed
$newsMetaData[$tagId][] = $this->getMetaDataForNews($newsEntry, $category);
Fabian Galinski
committed
// Process news by tag id
$maxNewsPerTag = 0;
// Hide empty tags.
continue;
}
if (isset($newsByTag[$tagId])) {
$newsByTag[$tagId]['newsMetaData'] =
Fabian Galinski
committed
\array_merge($newsByTag[$tagId]['newsMetaData'], $newsMetaData[$tagId]);
} else {
$newsByTag[$tagId] = [
'record' => $tag,
'recordId' => $tagId,
'recordType' => 'tag',
'newsMetaData' => $newsMetaData[$tagId],
'newsCount' => \count($newsMetaData[$tagId])
Fabian Galinski
committed
$maxNewsPerTag = \max($maxNewsPerTag, \count($newsByTag[$tagId]['newsMetaData']));
Fabian Galinski
committed
// Get all news by tags.
$news = $this->newsRepository->findAllSortedNewsByCategories(
$categoryIds, $newsLimitPerTag, $offset, $sortBy, $tagIds, $startTime, $endTime, $sortDirection
);
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;
}
Fabian Galinski
committed
$allNews[] = $this->getMetaDataForNews($newsEntry, $category);
}
$this->highlightBestFitNews([], $tagIds);
Fabian Galinski
committed
// Check to achieve less Ajax calls.
$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.
Fabian Galinski
committed
if ($maxNewsPerTag < $newsLimitPerTag && \count($allNews) < $newsLimitPerTag) {
$nextPage = $currentPageBrowserPage + 1;
if ($nextPage <= $numberOfPages) {
Fabian Galinski
committed
$this->setPageBrowserPage($nextPage);
$this->overviewWithTags($newsByTag, $allNews, $newsFilter, $nextPage);
return;
}
}
if ($this->settings['onlyNewsWithinThisPageSection']) {
$categories = $this->categoryRepository->findCategoriesInRootLine($GLOBALS['TSFE']->id);
$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);
$this->view->assign('categories', $categories);
$this->view->assign('numberOfPages', $numberOfPages);
$this->view->assign('newsItems', $newsByTag);
$this->view->assign('groupBy', 'tag');
$this->view->assign('allNews', $allNews);
/**
* Initialize the overviewWithoutCategoriesAction to set the currentPageBrowserPage parameter
*
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException
*/
public function initializeOverviewWithoutCategoriesAction(){
$currentPageBrowserPage = (int) GeneralUtility::_GP('tx_sgnews_pagebrowser')['currentPage'];
if($currentPageBrowserPage > 0){
$this->request->setArgument('currentPageBrowserPage', $currentPageBrowserPage);
}
}
/**
* @param CategoryRepository $categoryRepository
*/
public function injectCategoryRepository(CategoryRepository $categoryRepository
) {
$this->categoryRepository = $categoryRepository;
}
/**
* @param NewsRepository $newsRepository
*/
public function injectNewsRepository(NewsRepository $newsRepository) {
$this->newsRepository = $newsRepository;
}
/**
* @param TagRepository $tagRepository
*/
public function injectTagRepository(TagRepository $tagRepository) {
$this->tagRepository = $tagRepository;
}
/**
* Renders the news in a paginated list
*
* @param array $newsMetaData
* @param int $currentPageBrowserPage
* @return void
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
protected function overviewWithoutCategoriesAction(
array $newsMetaData = [], array $newsFilter = NULL, $currentPageBrowserPage = 0
// 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);
$configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
$sortBy = $configurationService->getConfiguration('sortBy', $this->settings);
$sortDirection = $configurationService->getConfiguration('sortDirection', $this->settings);
$newsPerPage = (int) $this->settings['newsLimit'];
Fabian Galinski
committed
$offset = $this->calculatePaginationOffset($currentPageBrowserPage, $newsPerPage);
$newsCount = 0;
$startTime = (int) $this->settings['starttime'];
$endTime = (int) $this->settings['endtime'];
if ($this->settings['onlyNewsWithinThisPageSection']) {
$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;
}
Kevin Ditscheid
committed
}
}
// 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);
$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']];
}
$news = $this->newsRepository->findAllSortedNewsByCategories(
$categoryIds, $newsPerPage, $offset, $sortBy, $tagIds, $startTime, $endTime, $sortDirection
);
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.
Fabian Galinski
committed
if (\count($newsMetaData) < ($newsPerPage - 1)) {
$nextPage = $currentPageBrowserPage + 1;
if ($nextPage <= $numberOfPages) {
Fabian Galinski
committed
$this->setPageBrowserPage($nextPage);
$this->overviewWithoutCategoriesAction($newsMetaData, $newsFilter, $nextPage);
return;
}
}
if ($this->settings['onlyNewsWithinThisPageSection']) {
$tags = $this->tagRepository->findTagsInRootLine($currentPageId);
$tags = $this->tagRepository->findAll()->toArray();
$this->view->assign('tags', $tags);
$this->view->assign('categories', $categories);
$this->view->assign('numberOfPages', $numberOfPages);
$this->view->assign('newsMetaData', $newsMetaData);
Fabian Galinski
committed
}
/**
* Sets the pagebrowser page to the given new page.
*
* @param int $newPage
* @return void
*/
protected function setPageBrowserPage($newPage) {
$_GET['tx_sgnews_pagebrowser']['currentPage'] = $newPage;