* Tim Klein-Hitpass * Kai Ratzeburg * * 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 2 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 TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; use TYPO3\CMS\Extbase\Persistence\QueryInterface; /** * Controller for the teaser object * * @copyright Copyright belongs to the respective authors * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later */ class TeaserController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController { /** * @var array */ protected $settings = []; /** * @var integer */ protected $currentPageUid = null; /** * @var \PwTeaserTeam\PwTeaser\Domain\Repository\PageRepository * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $pageRepository; /** * @var \PwTeaserTeam\PwTeaser\Domain\Repository\ContentRepository * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $contentRepository; /** * @var \TYPO3\CMS\Extbase\Domain\Repository\CategoryRepository * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $categoryRepository; /** * @var \PwTeaserTeam\PwTeaser\Utility\Settings * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $settingsUtility; /** * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer */ protected $contentObject = null; /** * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher * @TYPO3\CMS\Extbase\Annotation\Inject */ protected $signalSlotDispatcher; /** * @var \TYPO3\CMS\Fluid\View\TemplateView */ protected $view; /** * @var array */ protected $viewSettings = []; /** * Initialize Action will performed before each action will be executed * * @return void */ public function initializeAction() { $this->settings = $this->settingsUtility->renderConfigurationArray($this->settings); $frameworkSettings = $this->configurationManager->getConfiguration( ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK ); $viewSettings = $frameworkSettings['view']; $presets = $viewSettings['presets']; unset($viewSettings['presets']); $this->viewSettings = $this->settingsUtility->renderConfigurationArray($viewSettings, 'view.'); $this->viewSettings['presets'] = $presets; } /** * Displays teasers * * @return void */ public function indexAction() { $this->currentPageUid = $GLOBALS['TSFE']->id; $this->performTemplatePathAndFilename(); $this->setOrderingAndLimitation(); $this->performPluginConfigurations(); switch ($this->settings['source']) { default: case 'thisChildren': $rootPageUids = $this->currentPageUid; $pages = $this->pageRepository->findByPid($this->currentPageUid); break; case 'thisChildrenRecursively': $rootPageUids = $this->currentPageUid; $pages = $this->pageRepository->findByPidRecursively( $this->currentPageUid, (int)$this->settings['recursionDepthFrom'], (int)$this->settings['recursionDepth'] ); break; case 'custom': $rootPageUids = $this->settings['customPages']; $pages = $this->pageRepository->findByPidList( $this->settings['customPages'], $this->settings['orderByPlugin'] ); break; case 'customChildren': $rootPageUids = $this->settings['customPages']; $pages = $this->pageRepository->findChildrenByPidList($this->settings['customPages']); break; case 'customChildrenRecursively': $rootPageUids = $this->settings['customPages']; $pages = $this->pageRepository->findChildrenRecursivelyByPidList( $this->settings['customPages'], (int)$this->settings['recursionDepthFrom'], (int)$this->settings['recursionDepth'] ); break; } if ($this->settings['pageMode'] !== 'nested') { $pages = $this->performSpecialOrderings($pages); } /** @var $page \PwTeaserTeam\PwTeaser\Domain\Model\Page */ foreach ($pages as $page) { if ($page->getUid() === $this->currentPageUid) { $page->setIsCurrentPage(true); } // Load contents if enabled in configuration if ($this->settings['loadContents'] == '1') { $page->setContents($this->contentRepository->findByPid($page->getUid())); } } if ($this->settings['pageMode'] === 'nested') { $pages = $this->convertFlatToNestedPagesArray($pages, $rootPageUids); } $this->signalSlotDispatcher->dispatch(__CLASS__, __FUNCTION__ . 'ModifyPages', [&$pages, $this]); $this->view->assign('pages', $pages); } /** * Function to sort given pages by recursiveRootLineOrdering string * * @param \PwTeaserTeam\PwTeaser\Domain\Model\Page $a * @param \PwTeaserTeam\PwTeaser\Domain\Model\Page $b * @return integer */ protected function sortByRecursivelySorting( \PwTeaserTeam\PwTeaser\Domain\Model\Page $a, \PwTeaserTeam\PwTeaser\Domain\Model\Page $b ) { if ($a->getRecursiveRootLineOrdering() == $b->getRecursiveRootLineOrdering()) { return 0; } return ($a->getRecursiveRootLineOrdering() < $b->getRecursiveRootLineOrdering()) ? -1 : 1; } /** * Sets ordering and limitation settings from $this->settings * * @return void */ protected function setOrderingAndLimitation() { if (!empty($this->settings['orderBy'])) { if ($this->settings['orderBy'] === 'customField') { $this->pageRepository->setOrderBy($this->settings['orderByCustomField']); } else { $this->pageRepository->setOrderBy($this->settings['orderBy']); } } if (!empty($this->settings['orderDirection'])) { $this->pageRepository->setOrderDirection($this->settings['orderDirection']); } if (!empty($this->settings['limit']) && $this->settings['orderBy'] !== 'random') { $this->pageRepository->setLimit(intval($this->settings['limit'])); } } /** * Sets the fluid template to file if file is selected in flexform * configuration and file exists * * @return boolean Returns TRUE if templateType is file and exists, * otherwise returns FALSE */ protected function performTemplatePathAndFilename() { $templateType = $this->viewSettings['templateType']; $templateFile = $this->viewSettings['templateRootFile']; $layoutRootPaths = $this->viewSettings['layoutRootPaths'] ?: [$this->viewSettings['layoutRootPath'] ?: null]; $partialRootPaths = $this->viewSettings['partialRootPaths'] ?: [$this->viewSettings['partialRootPath'] ?: null]; $templateRootPaths = $this->viewSettings['templateRootPaths'] ?: [$this->viewSettings['templateRootPath'] ?: null]; $preset = $this->viewSettings['templatePreset'] ?? null; if ($templateType === 'preset' && !empty($preset)) { $currentPreset = $this->viewSettings['presets'][$preset]; if (array_key_exists('partialRootPaths', $currentPreset) && !empty($currentPreset['partialRootPaths'])) { $partialRootPaths = $currentPreset['partialRootPaths']; } if (array_key_exists('layoutRootPaths', $currentPreset) && !empty($currentPreset['layoutRootPaths'])) { $layoutRootPaths = $currentPreset['layoutRootPaths']; } $templateType = 'file'; $templateFile = $currentPreset['templateRootFile']; } if ($templateType !== 'preset' && $templateRootPaths !== [null] && !empty($templateRootPaths)) { if (!file_exists(GeneralUtility::getFileAbsFileName(reset($templateRootPaths)))) { throw new \Exception('Template folder "' . reset($templateRootPaths) . '" not found!'); } $this->view->setTemplateRootPaths($templateRootPaths); } if ($layoutRootPaths !== [null] && !empty($layoutRootPaths)) { if (!file_exists(GeneralUtility::getFileAbsFileName(reset($layoutRootPaths)))) { throw new \Exception('Layout folder "' . reset($layoutRootPaths) . '" not found!'); } $this->view->setLayoutRootPaths($layoutRootPaths); } if ($partialRootPaths !== [null] && !empty($partialRootPaths)) { if (!file_exists(GeneralUtility::getFileAbsFileName(reset($partialRootPaths)))) { throw new \Exception('Partial folder "' . reset($partialRootPaths) . '" not found!'); } $this->view->setPartialRootPaths($partialRootPaths); } if ($templateType === 'file' && !empty($templateFile) && file_exists(GeneralUtility::getFileAbsFileName($templateFile)) ) { $this->view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateFile)); return true; } $templatePathAndFilename = $this->viewSettings['templatePathAndFilename'] ?? ''; if ($templateType === null && !empty($templatePathAndFilename) && file_exists(GeneralUtility::getFileAbsFileName($templatePathAndFilename))) { $this->view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePathAndFilename)); return true; } return false; } /** * Performs configurations from plugin settings (flexform) * * @return void */ protected function performPluginConfigurations() { // Set ShowNavHiddenItems to TRUE $this->pageRepository->setShowNavHiddenItems(($this->settings['showNavHiddenItems'] == '1')); $this->pageRepository->setFilteredDokType( GeneralUtility::trimExplode( ',', $this->settings['showDoktypes'], true ) ); if ($this->settings['hideCurrentPage'] == '1') { $this->pageRepository->setIgnoreOfUid($this->currentPageUid); } if ($this->settings['ignoreUids']) { $ignoringUids = GeneralUtility::trimExplode(',', $this->settings['ignoreUids'], true); array_map([$this->pageRepository, 'setIgnoreOfUid'], $ignoringUids); } if ($this->settings['categoriesList'] && $this->settings['categoryMode']) { $categories = []; foreach (GeneralUtility::intExplode(',', $this->settings['categoriesList'], true) as $categoryUid) { $categories[] = $this->categoryRepository->findByUid($categoryUid); } switch ((int)$this->settings['categoryMode']) { case \PwTeaserTeam\PwTeaser\Domain\Repository\PageRepository::CATEGORY_MODE_OR: case \PwTeaserTeam\PwTeaser\Domain\Repository\PageRepository::CATEGORY_MODE_OR_NOT: $isAnd = false; break; default: $isAnd = true; } switch ((int)$this->settings['categoryMode']) { case \PwTeaserTeam\PwTeaser\Domain\Repository\PageRepository::CATEGORY_MODE_AND_NOT: case \PwTeaserTeam\PwTeaser\Domain\Repository\PageRepository::CATEGORY_MODE_OR_NOT: $isNot = true; break; default: $isNot = false; } $this->pageRepository->addCategoryConstraint($categories, $isAnd, $isNot); } if ($this->settings['source'] === 'custom') { $this->settings['pageMode'] = 'flat'; } if ($this->settings['pageMode'] === 'nested') { $this->settings['recursionDepthFrom'] = 0; $this->settings['orderBy'] = 'uid'; $this->settings['limit'] = 0; } } /** * Performs special orderings like "random" or "sorting" * * @param array $pages * @return array */ protected function performSpecialOrderings(array $pages) { // Make random if selected on queryResult, cause Extbase doesn't support it if ($this->settings['orderBy'] === 'random') { shuffle($pages); if (!empty($this->settings['limit'])) { $pages = array_slice($pages, 0, $this->settings['limit']); } } if ($this->settings['orderBy'] === 'sorting' && strpos($this->settings['source'], 'Recursively') !== false) { usort($pages, [$this, 'sortByRecursivelySorting']); if (strtolower($this->settings['orderDirection']) === strtolower(QueryInterface::ORDER_DESCENDING)) { $pages = array_reverse($pages); } if (!empty($this->settings['limit'])) { $pages = array_slice($pages, 0, $this->settings['limit']); return $pages; } return $pages; } return $pages; } /** * Converts given pages array (flat) to nested one * * @param array $pages * @param string $rootPageUids Comma separated list of page uids * @return array */ protected function convertFlatToNestedPagesArray($pages, $rootPageUids) { $rootPageUidArray = GeneralUtility::intExplode(',', $rootPageUids); $rootPages = []; foreach ($rootPageUidArray as $rootPageUid) { $page = $this->pageRepository->findByUid($rootPageUid); $this->fillChildPagesRecursivley($page, $pages); $rootPages[] = $page; } return $rootPages; } /** * Fills given parentPage's childPages attribute recursively with pages * * @param \PwTeaserTeam\PwTeaser\Domain\Model\Page $parentPage * @param array $pages * @return \PwTeaserTeam\PwTeaser\Domain\Model\Page */ protected function fillChildPagesRecursivley($parentPage, array $pages) { $childPages = []; /** @var $page \PwTeaserTeam\PwTeaser\Domain\Model\Page */ foreach ($pages as $page) { if ($page->getPid() === $parentPage->getUid()) { $this->fillChildPagesRecursivley($page, $pages); $childPages[$page->getSorting()] = $page; } } ksort($childPages); $parentPage->setChildPages(array_values($childPages)); return $parentPage; } }