Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 74 additions & 58 deletions Classes/EventListener/NewsListActionEventListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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);
}
Expand All @@ -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 = [];
Expand All @@ -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'];
Expand All @@ -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);
}
}
74 changes: 66 additions & 8 deletions Classes/Hooks/EnrichDemandObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
Expand All @@ -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;
}
}
11 changes: 11 additions & 0 deletions Configuration/FlexForms/flexform_newsfilter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@
</config>
</TCEforms>
</settings.filterTags>

<!-- Session Filter -->
<settings.keepFilterOnReload>
<TCEforms>
<label>LLL:EXT:news_filter/Resources/Private/Language/locallang_ff.xlf:settings.keepFilterOnReload</label>
<config>
<type>check</type>
<default>0</default>
</config>
</TCEforms>
</settings.keepFilterOnReload>
</el>
</ROOT>
</extra>
11 changes: 11 additions & 0 deletions Configuration/FlexForms/flexform_newsfilter12.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@
<minitems>0</minitems>
</config>
</settings.filterTags>

<!-- Session Filter -->
<settings.keepFilterOnReload>
<TCEforms>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cepheiVV, TCEforms isn't "compatible" (?) with TYPO3 12 that's why the other options in this file don't have it.

<label>LLL:EXT:news_filter/Resources/Private/Language/locallang_ff.xlf:settings.keepFilterOnReload</label>
<config>
<type>check</type>
<default>0</default>
</config>
</TCEforms>
</settings.keepFilterOnReload>
</el>
</ROOT>
</extra>
9 changes: 6 additions & 3 deletions Resources/Private/Language/locallang_ff.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
<file source-language="en" datatype="plaintext" original="messages" date="2023-11-29T13:15:00Z" product-name="news_filter">
<header/>
<body>
<trans-unit id="settings.enableFilter" xml:space="preserve">
<source>Enable filter</source>
</trans-unit>
<trans-unit id="settings.enableFilter" xml:space="preserve">
<source>Enable filter</source>
</trans-unit>
<trans-unit id="settings.keepFilterOnReload" xml:space="preserve">
<source>Keep filter on reload</source>
</trans-unit>
</body>
</file>
</xliff>