diff --git a/Classes/EventListener/NewsListActionEventListener.php b/Classes/EventListener/NewsListActionEventListener.php index 808c25a..cd53f4b 100644 --- a/Classes/EventListener/NewsListActionEventListener.php +++ b/Classes/EventListener/NewsListActionEventListener.php @@ -4,18 +4,24 @@ namespace GeorgRinger\NewsFilter\EventListener; -use GeorgRinger\News\Domain\Model\Dto\NewsDemand; +use Doctrine\DBAL\DBALException; use GeorgRinger\News\Domain\Repository\CategoryRepository; use GeorgRinger\News\Domain\Repository\TagRepository; use GeorgRinger\News\Event\NewsListActionEvent; use GeorgRinger\News\Utility\Page; use GeorgRinger\NewsFilter\Domain\Model\Dto\Search; use TYPO3\CMS\Core\Context\Context; +use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Property\Exception; use TYPO3\CMS\Extbase\Property\PropertyMapper; +use TYPO3\CMS\Extbase\Service\CacheService; +/** + * NewsListActionEventListener + */ class NewsListActionEventListener { /** @var CategoryRepository */ @@ -27,26 +33,51 @@ class NewsListActionEventListener /** @var PropertyMapper */ protected $propertyMapper; + /** @var CacheService */ + protected $cacheService; + public function __construct( CategoryRepository $categoryRepository, TagRepository $tagRepository, - PropertyMapper $propertyMapper + PropertyMapper $propertyMapper, + CacheService $cacheService ) { $this->categoryRepository = $categoryRepository; $this->tagRepository = $tagRepository; $this->propertyMapper = $propertyMapper; + $this->cacheService = $cacheService; } - public function __invoke(NewsListActionEvent $event) + /** + * @throws Exception + * @throws AspectNotFoundException + */ + public function __invoke(NewsListActionEvent $event): void { $data = $event->getAssignedValues(); $settings = $data['settings']; if ($settings['enableFilter'] ?? false) { - $search = GeneralUtility::makeInstance(Search::class); + $search = $settings['keepFilterOnReload'] ? + $this->getSearchFromSession($event) : + GeneralUtility::makeInstance(Search::class); + + // set a new search if a new search was submitted $vars = GeneralUtility::_POST('tx_news_pi1'); - if (isset($vars['search']) && is_array($vars['search'])) { + $hasPostData = isset($vars['search']) && is_array($vars['search']); + if ($hasPostData) { + + if ($settings['keepFilterOnReload']) { + $this->saveSearchInSession($event, $vars['search']); + + // clear teh cache for the current page when a + // new filter is saved to the session in order + // to get the new filter after reloading the page + $currentPage = $GLOBALS['TSFE']->id; + $this->cacheService->clearPageCache([$currentPage]); + } + /** @var Search $search */ $search = $this->propertyMapper->convert($vars['search'], Search::class); } @@ -72,6 +103,13 @@ public function __invoke(NewsListActionEvent $event) $event->setAssignedValues($data); } + /** + * @param string $tableName + * @param string $pidList + * @return array + * @throws \Doctrine\DBAL\Driver\Exception + * @throws DBALException + */ protected function getAllRecordsByPid(string $tableName, string $pidList): array { $list = []; @@ -86,8 +124,8 @@ protected function getAllRecordsByPid(string $tableName, string $pidList): array $queryBuilder->createNamedParameter(explode(',', $pidList), Connection::PARAM_INT_ARRAY) ) ) - ->execute() - ->fetchAll(); + ->executeQuery() + ->fetchAllAssociative(); foreach ($rows as $row) { $list[] = $row['uid']; @@ -96,61 +134,39 @@ protected function getAllRecordsByPid(string $tableName, string $pidList): array } /** - * Create the demand object which define which records will get shown + * Load filter from session or create a new empty search * - * @param array $settings - * @param string $class optional class which must be an instance of \GeorgRinger\News\Domain\Model\Dto\NewsDemand - * @return NewsDemand + * @param NewsListActionEvent $event + * @return Search + * @throws Exception */ - protected function createDemandObjectFromSettings( - $settings, - $class = 'GeorgRinger\\News\\Domain\\Model\\Dto\\NewsDemand' - ) { - $class = isset($settings['demandClass']) && !empty($settings['demandClass']) ? $settings['demandClass'] : $class; - - /* @var $demand \GeorgRinger\News\Domain\Model\Dto\NewsDemand */ - $demand = GeneralUtility::makeInstance($class, $settings); - if (!$demand instanceof NewsDemand) { - throw new \UnexpectedValueException( - sprintf( - 'The demand object must be an instance of \GeorgRinger\\News\\Domain\\Model\\Dto\\NewsDemand, but %s given!', - $class - ), - 1423157953 - ); - } - - $demand->setCategories(GeneralUtility::trimExplode(',', $settings['categories'], true)); - $demand->setCategoryConjunction($settings['categoryConjunction']); - $demand->setIncludeSubCategories((bool)$settings['includeSubCategories']); - $demand->setTags($settings['tags']); - - $demand->setTopNewsRestriction((int)$settings['topNewsRestriction']); - $demand->setTimeRestriction($settings['timeRestriction']); - $demand->setTimeRestrictionHigh($settings['timeRestrictionHigh']); - $demand->setArchiveRestriction($settings['archiveRestriction']); - $demand->setExcludeAlreadyDisplayedNews((bool)$settings['excludeAlreadyDisplayedNews']); - $demand->setHideIdList((string)($settings['hideIdList'] ?? '')); - - if ($settings['orderBy']) { - $demand->setOrder($settings['orderBy'] . ' ' . $settings['orderDirection']); + protected function getSearchFromSession(NewsListActionEvent $event): Search + { + $request = $event->getRequest(); + $frontendUser = $request->getAttribute('frontend.user'); + $sessionFilter = $frontendUser->getKey('ses', 'tx_news_filter'); + if ($sessionFilter) { + $sessionFilter = unserialize($sessionFilter); + $search = $this->propertyMapper->convert($sessionFilter, Search::class); + } else { + $search = GeneralUtility::makeInstance(Search::class); } - $demand->setOrderByAllowed($settings['orderByAllowed']); - - $demand->setTopNewsFirst((bool)$settings['topNewsFirst']); - $demand->setLimit((int)$settings['limit']); - $demand->setOffset((int)$settings['offset']); - - $demand->setSearchFields($settings['search']['fields']); - $demand->setDateField($settings['dateField']); - $demand->setMonth((int)$settings['month']); - $demand->setYear((int)$settings['year']); + return $search; + } - $demand->setStoragePage(Page::extendPidListByChildren( - $settings['startingpoint'], - $settings['recursive'] - )); - return $demand; + /** + * serialize and save search in session + * + * @param NewsListActionEvent $event + * @param array $search + * @return void + */ + protected function saveSearchInSession(NewsListActionEvent $event, array $search): void + { + $request = $event->getRequest(); + $frontendUser = $request->getAttribute('frontend.user'); + $sessionData = serialize($search); + $frontendUser->setKey('ses', 'tx_news_filter', $sessionData); } } diff --git a/Classes/Hooks/EnrichDemandObject.php b/Classes/Hooks/EnrichDemandObject.php index 874b32f..85fe12a 100644 --- a/Classes/Hooks/EnrichDemandObject.php +++ b/Classes/Hooks/EnrichDemandObject.php @@ -4,21 +4,34 @@ namespace GeorgRinger\NewsFilter\Hooks; +use GeorgRinger\News\Event\NewsListActionEvent; use GeorgRinger\NewsFilter\Domain\Model\Dto\Demand; use GeorgRinger\NewsFilter\Domain\Model\Dto\Search; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Property\Exception; use TYPO3\CMS\Extbase\Property\PropertyMapper; +/** + * EnrichDemandObject + */ class EnrichDemandObject { /** @var PropertyMapper */ protected $propertyMapper; + /** + * @param PropertyMapper $propertyMapper + */ public function __construct(PropertyMapper $propertyMapper) { $this->propertyMapper = $propertyMapper; } + /** + * @param array $params + * @return void + * @throws Exception + */ public function run(array &$params): void { $demand = $params['demand']; @@ -28,18 +41,63 @@ public function run(array &$params): void $settings = $params['settings']; if ($settings['enableFilter'] ?? false) { + $vars = GeneralUtility::_POST('tx_news_pi1'); - if (isset($vars['search']) && is_array($vars['search'])) { + $hasPostData = isset($vars['search']) && is_array($vars['search']); + if ($hasPostData) { + // set the demand based on POST data + /** @var Search $search */ $search = $this->propertyMapper->convert($vars['search'], Search::class); - $search->setFields($settings['search']['fields']); - $search->setSplitSubjectWords((bool)$settings['search']['splitSearchWord']); - $demand->setSearch($search); - $demand->setFilteredCategories($search->getFilteredCategories()); - $demand->setFilteredTags($search->getFilteredTags()); - $demand->setFromDate($search->getFromDate()); - $demand->setToDate($search->getToDate()); + $this->setSearchDemand($settings, $search, $demand); + } else { + // set the demand based on session data + if ($settings['keepFilterOnReload']) { + $search = $this->getSearchFromSession(); + $this->setSearchDemand($settings, $search, $demand); + } } } } + + /** + * Load filter from session or create a new empty search + * + * @param NewsListActionEvent $event + * @return Search + * @throws Exception + */ + protected function getSearchFromSession(): Search + { + $request = $GLOBALS['TYPO3_REQUEST']; + $frontendUser = $request->getAttribute('frontend.user'); + $sessionFilter = $frontendUser->getKey('ses', 'tx_news_filter'); + if ($sessionFilter) { + $sessionFilter = unserialize($sessionFilter); + $search = $this->propertyMapper->convert($sessionFilter, Search::class); + } else { + $search = GeneralUtility::makeInstance(Search::class); + } + + return $search; + } + + /** + * @param array $settings + * @param Search $search + * @param Demand $demand + * @return Demand + */ + protected function setSearchDemand(array $settings, Search $search, Demand $demand): Demand + { + $search->setFields($settings['search']['fields']); + $search->setSplitSubjectWords((bool)$settings['search']['splitSearchWord']); + $demand->setSearch($search); + $demand->setFilteredCategories($search->getFilteredCategories()); + $demand->setFilteredTags($search->getFilteredTags()); + $demand->setFromDate($search->getFromDate()); + $demand->setToDate($search->getToDate()); + + return $demand; + } } diff --git a/Configuration/FlexForms/flexform_newsfilter.xml b/Configuration/FlexForms/flexform_newsfilter.xml index f78c96b..d1fe7c8 100644 --- a/Configuration/FlexForms/flexform_newsfilter.xml +++ b/Configuration/FlexForms/flexform_newsfilter.xml @@ -44,6 +44,17 @@ + + + + + + + check + 0 + + + diff --git a/Configuration/FlexForms/flexform_newsfilter12.xml b/Configuration/FlexForms/flexform_newsfilter12.xml index 4704605..3c56b1a 100644 --- a/Configuration/FlexForms/flexform_newsfilter12.xml +++ b/Configuration/FlexForms/flexform_newsfilter12.xml @@ -36,6 +36,17 @@ 0 + + + + + + + check + 0 + + + diff --git a/Resources/Private/Language/locallang_ff.xlf b/Resources/Private/Language/locallang_ff.xlf index 8924d3b..370985e 100644 --- a/Resources/Private/Language/locallang_ff.xlf +++ b/Resources/Private/Language/locallang_ff.xlf @@ -3,9 +3,12 @@
- - Enable filter - + + Enable filter + + + Keep filter on reload +