Skip to content

Commit

Permalink
Generate and display category filters for search
Browse files Browse the repository at this point in the history
  • Loading branch information
okmiim committed May 17, 2022
1 parent bfdc722 commit 77bbe92
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 4 deletions.
114 changes: 114 additions & 0 deletions Classes/EventListener/CategoryFilterEventListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

declare(strict_types=1);

namespace HDNET\Calendarize\EventListener;

use Doctrine\DBAL\Connection;
use HDNET\Calendarize\Controller\CalendarController;
use HDNET\Calendarize\Event\GenericActionAssignmentEvent;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* Gets all used categories from the default Event and assigns it to extended.categories in fluid.
* This is only active for search actions!
*/
class CategoryFilterEventListener
{
protected string $itemTableName = 'tx_calendarize_domain_model_event';
protected string $itemFieldName = 'categories';

public function __invoke(GenericActionAssignmentEvent $event)
{
if (CalendarController::class !== $event->getClassName() || 'searchAction' !== $event->getEventName()) {
return;
}
if (!$this->checkConfiguration($event->getVariables()['configurations'] ?? [], $this->itemTableName)) {
return;
}
$variables = $event->getVariables();
$variables['extended']['categories'] = array_merge(
$variables['extended']['categories'] ?? [],
$this->getCategories($this->itemTableName, $this->itemFieldName)
);

$event->setVariables($variables);
}

/**
* Check if the event configuration is active.
*
* @param array $configurations
* @param string $tableName
*
* @return bool
*/
protected function checkConfiguration(array $configurations, string $tableName): bool
{
foreach ($configurations as $config) {
if (($config['tableName'] ?? '') === $tableName) {
return true;
}
}

return false;
}

/**
* Gets all used categories of the default Event (self::itemTableName).
*
* @param string $tableName
* @param string $fieldName
*
* @return array
*
* @throws \Doctrine\DBAL\DBALException
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
*/
protected function getCategories(string $tableName, string $fieldName): array
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('sys_category');

$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));

$languageUid = GeneralUtility::makeInstance(Context::class)->getAspect('language')->getId();

$queryBuilder->select('sys_category.*')
->distinct()
->from('sys_category')
->join(
'sys_category',
'sys_category_record_mm',
'sys_category_record_mm',
$queryBuilder->expr()->eq(
'sys_category_record_mm.uid_local',
$queryBuilder->quoteIdentifier('sys_category.uid')
)
)
->where(
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq(
'sys_category_record_mm.tablenames',
$queryBuilder->createNamedParameter($tableName, \PDO::PARAM_STR)
),
$queryBuilder->expr()->eq(
'sys_category_record_mm.fieldname',
$queryBuilder->createNamedParameter($fieldName, \PDO::PARAM_STR)
),
$queryBuilder->expr()->in(
'sys_category.sys_language_uid',
$queryBuilder->createNamedParameter([-1, $languageUid], Connection::PARAM_INT_ARRAY)
)
)
)
->orderBy('sys_category.title', 'ASC');

return $queryBuilder->execute()->fetchAll();
}
}
35 changes: 35 additions & 0 deletions Classes/ViewHelpers/InArrayViewHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace HDNET\Calendarize\ViewHelpers;

use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;

/**
* Checks if an element (needle) is in an array (haystack).
*/
class InArrayViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;

public function initializeArguments()
{
$this->registerArgument('needle', 'mixed', 'The searched value.', true);
$this->registerArgument('haystack', 'array', 'The array.', true);
$this->registerArgument('strict', 'boolean', 'If true then the function will also check the types.', false, false);
}

public static function renderStatic(
array $arguments,
\Closure $renderChildrenClosure,
RenderingContextInterface $renderingContext
) {
if (!\is_array($arguments['haystack'])) {
return false;
}

return \in_array($arguments['needle'], $arguments['haystack'], $arguments['strict']);
}
}
6 changes: 6 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ services:
identifier: 'bookingCountries'
event: HDNET\Calendarize\Event\GenericActionAssignmentEvent

HDNET\Calendarize\EventListener\CategoryFilterEventListener:
tags:
- name: event.listener
identifier: 'categoryFilter'
event: HDNET\Calendarize\Event\GenericActionAssignmentEvent

HDNET\Calendarize\EventListener\DefaultEventSearchListener:
tags:
- name: event.listener
Expand Down
14 changes: 10 additions & 4 deletions Resources/Private/Partials/Event/Search.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
{namespace c=HDNET\Calendarize\ViewHelpers}
<!-- move to extension partial -->
<div class="form-group">
<label for="calendarizeFullText"><f:translate key="search.text" extensionName="Calendarize" /></label>
<f:form.textfield id="calendarizeFullText" name="customSearch[fullText]" value="{customSearch.fullText}" class="form-control" />
</div>

<f:comment>
<label for="calendarizeCategories">Category</label>
<f:form.select options="--- add categories here ---" id="calendarizeCategories" name="customSearch[category]" value="{customSearch.category}" class="form-control" />
</f:comment>
<f:if condition="{extended.categories}">
Categories:
<f:for each="{extended.categories}" as="category">
<div class="form-check">
<f:form.checkbox name="customSearch[categories][]" value="{category.uid}" id="categoryFilter-{category.uid}" class="form-check-input" checked="{c:inArray(needle: category.uid, haystack:customSearch.categories)}"/>
<label for="categoryFilter-{category.uid}" class="form-check-label">{category.title}</label>
</div>
</f:for>
</f:if>

0 comments on commit 77bbe92

Please sign in to comment.