Skip to content

Commit

Permalink
[FEATURE] Extended filters
Browse files Browse the repository at this point in the history
Extended filters can be defined in UserTsConfig.

For demonstration there are examples that can be included with

@import 'EXT:pagetreefilter/Configuration/TsConfig/Examples/*.tsconfig'

Relates: #16
  • Loading branch information
Christoph Lehmann committed Feb 2, 2023
1 parent a15fe27 commit 7ae7e8c
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 14 deletions.
10 changes: 7 additions & 3 deletions Classes/Controller/TreeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ public function filterDataAction(ServerRequestInterface $request): ResponseInter
$rootElement['name'] = sprintf('❌ %s', $this->getLanguageService()->sL('LLL:EXT:pagetreefilter/Resources/Private/Language/locallang.xlf:filter_error'));
$elements = [$rootElement];
} else {
if (PageTreeRepository::$filteredPageUids !== []) {
foreach($elements as $key => $element) {
if (in_array($element['identifier'], PageTreeRepository::$filteredPageUids)) {
foreach ($elements as $key => $element) {
foreach (PageTreeRepository::$resultSets as $resultSet) {
if (in_array($element['identifier'], $resultSet['pageUids'])) {
if (isset($resultSet['description'])) {
$elements[$key]['tip'] .= sprintf(', %s', $resultSet['description']);
}
$elements[$key]['class'] = 'pagetreefilter-highlighted';
$elements[$key]['backgroundColor'] = $resultSet['backgroundColor'] ?? '#0078e6';
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions Classes/Controller/WizardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public function getWizards(): array
$wizards = $this->appendRecords($wizards);
$wizards = $this->appendPageTypes($wizards);
$wizards = $this->appendUnknownContentTypes($wizards);
$wizards = $this->appendExtended($wizards);


return $wizards;
}
Expand Down Expand Up @@ -241,6 +243,26 @@ protected function appendUnknownContentTypes(array $wizards): array
return $wizards;
}

protected function appendExtended($wizards)
{
$customWizardItems = ConfigurationUtility::getCustomWizardItems();
if ($customWizardItems !== []) {
$wizards['filters']['header'] =
$this->getLanguageService()->sL('LLL:EXT:pagetreefilter/Resources/Private/Language/locallang.xlf:wizard_tab_extended_filters');

foreach ($customWizardItems as $identifier => $wizardItem) {
$wizards['filters_' . $identifier] = [
'title' => $this->getLanguageService()->sL($wizardItem['title']),
'description' => $this->getLanguageService()->sL($wizardItem['description'] ?? ''),
'iconIdentifier' => $wizardItem['iconIdentifier'] ?? 'actions-filter',
'filter' => $wizardItem['filter']
];
}
}

return $wizards;
}

protected function areRecordsInTable($tableName): bool
{
/** @var QueryBuilder $queryBuilder */
Expand Down
53 changes: 45 additions & 8 deletions Classes/Domain/Repository/PageTreeRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@

class PageTreeRepository extends \TYPO3\CMS\Backend\Tree\Repository\PageTreeRepository
{
public static $filteredPageUids = [];
public static $resultSets = [];

public static $filterErrorneous = false;

protected $filterTable;

protected $filterConstraints = [];

// @todo: Use predefined list from core. Where is it?
protected $extendedFiltersThatShouldBeApplied = [];

protected const ALLOWED_TABLE_FIELDS = [
'tt_content:CType',
'tt_content:list_type',
Expand All @@ -35,19 +36,52 @@ public function fetchFilteredTree(string $searchFilter, array $allowedMountPoint
{
if (ConfigurationUtility::isWizardEnabled()) {
$newSearchFilter = $this->extractConstraints($searchFilter);
$searchFilter = $newSearchFilter;
$pages = [];

if ($this->filterTable) {
$this->validate();

if (!self::$filterErrorneous) {
self::$filteredPageUids = $this->getFilteredPageUids();
$pages = $this->getFilteredPageUids();
self::$resultSets['default'] = [
'pageUids' => $pages
];
}
}

if (self::$filteredPageUids !== []) {
$additionalWhereClause = sprintf('%s AND uid IN (%s)', $additionalWhereClause,
implode(',', self::$filteredPageUids));
$searchFilter = $newSearchFilter;
$extendedFilters = ConfigurationUtility::getExtendedFilters();
if ($this->extendedFiltersThatShouldBeApplied !== [] && $extendedFilters !== []) {
foreach($this->extendedFiltersThatShouldBeApplied as $extendedFilter) {
if (isset($extendedFilters[$extendedFilter])) {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($extendedFilters[$extendedFilter]['select.']['table']);
$filteredPages = $queryBuilder
->select($extendedFilters[$extendedFilter]['select.']['field'])
->from($extendedFilters[$extendedFilter]['select.']['table'])
->andWhere($extendedFilters[$extendedFilter]['select.']['where'])
->execute()
->fetchFirstColumn();

self::$resultSets[$extendedFilter] = array_merge(
$extendedFilters[$extendedFilter],
[
'pageUids' => $filteredPages
]
);

foreach ($filteredPages as $filteredPage) {
$pages[] = $filteredPage;
}
}
}
}


if ($pages !== []) {
$additionalWhereClause = sprintf('%s AND uid IN (%s)', $additionalWhereClause,
implode(',', array_unique($pages)));
}
}

return parent::fetchFilteredTree($searchFilter, $allowedMountPointPageIds, $additionalWhereClause);
Expand Down Expand Up @@ -117,6 +151,9 @@ protected function extractConstraints(string $searchFilter): string
case 'table':
$this->filterTable = $filter[1];
break;
case 'filter':
$this->extendedFiltersThatShouldBeApplied[] = $filter[1];
break;
default:
$this->filterConstraints[] = [
'field' => $filter[0],
Expand All @@ -140,7 +177,7 @@ protected function validate()
if (!$backendUser->isAdmin() && !$backendUser->check('tables_select', $this->filterTable)) {
self::$filterErrorneous = true;
}
$connection = $connection = GeneralUtility::makeInstance(ConnectionPool::class)
$connection = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable($this->filterTable);
foreach($this->filterConstraints as $constraint) {
if (!isset($GLOBALS['TCA'][$this->filterTable]['columns'][$constraint['field']])) {
Expand Down
22 changes: 22 additions & 0 deletions Classes/Utility/ConfigurationUtility.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,28 @@ public static function getPageId()
return GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('pagetreefilter', 'pageId');
}

public static function getExtendedFilters(): array
{
$backendUser = self::getBackendUser();
$filters = $backendUser->getTSConfig()['tx_pagetreefilter.']['filters.'] ?? [];
foreach ($filters as $name => $configuration) {
$filters[rtrim($name, '.')] = $configuration;
unset($filters[$name]);
}
return $filters;
}

public static function getCustomWizardItems(): array
{
$backendUser = self::getBackendUser();
$wizardItems = $backendUser->getTSConfig()['tx_pagetreefilter.']['wizardItems.'] ?? [];
foreach ($wizardItems as $name => $configuration) {
$wizardItems[rtrim($name, '.')] = $configuration;
unset($wizardItems[$name]);
}
return $wizardItems;
}

protected static function getBackendUser(): ?BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
Expand Down
40 changes: 40 additions & 0 deletions Configuration/TsConfig/Examples/Seo.tsconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
tx_pagetreefilter {
filters {
indexingEnabled {
description = Page will be indexed by search engines
select {
field = uid
table = pages
where = no_index=0 AND doktype < 199
}
backgroundColor = green
}
indexingDisabled {
description = Page will be not be indexed by search engines
select {
field = uid
table = pages
where = no_index=1 AND doktype < 199
}
backgroundColor = grey
}
noMetaDescription {
description = Page has no meta description, so the description in search engine results might be inaccurate
select {
field = uid
table = pages
where = no_index=0 AND doktype < 199 AND (description='' OR description IS NULL)
}
backgroundColor = red
}
}

wizardItems {
seoStatus {
title = SEO Status
description = Show pages with SEO issues
iconIdentifier = content-elements-searchform
filter = filter=indexingEnabled filter=indexingDisabled filter=noMetaDescription
}
}
}
75 changes: 75 additions & 0 deletions Configuration/TsConfig/Examples/SolrIndexQueue.tsconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
tx_pagetreefilter {
filters {
indexedInSolr {
# The description is visible when you hover over the page icon
description = Indexed in Solr

select {
field = item_uid
table = tx_solr_indexqueue_item
where = indexing_configuration = 'pages' AND indexed > changed AND errors = ''
}

# A CSS background color for pages matching the query
backgroundColor = darkgreen
}
solrIndexingErrors {
description = Has indexing error
select {
field = item_uid
table = tx_solr_indexqueue_item
where = indexing_configuration = 'pages' AND errors != ''
}
backgroundColor = red
}
solrNeedsIndexing {
description = Needs (re)indexing
select {
field = item_uid
table = tx_solr_indexqueue_item
where = indexing_configuration = 'pages' AND indexed = 0 AND errors = ''
}
backgroundColor = lightgreen
}
solrNotInQueue {
description = Not in Index Queue
select {
field = uid
table = pages
where = sys_language_uid = 0 AND uid NOT IN (SELECT item_uid FROM tx_solr_indexqueue_item)
}
backgroundColor = orange
}
solrNoSearch {
description = Indexing disabled
select {
field = uid
table = pages
where = no_search = 1
}
backgroundColor = lightgrey
}
solrNoSearchSubEntries {
description = Indexing disabled for sub entries
select {
field = uid
table = pages
where = no_search_sub_entries = 1
}
backgroundColor = #4b4b4b
}
}

wizardItems {
solrIndexQueueStatus {
title = Solr Index Queue Status
description = Show pages that are indexed, not in the queue or have errors

# Overview of icons in TYPO3: https://typo3.github.io/TYPO3.Icons/
iconIdentifier = content-elements-searchform

# Multiple filters can be combined. The order matters for overlapping queries with different background colors
filter = filter=indexedInSolr filter=solrIndexingErrors filter=solrNeedsIndexing filter=solrNotInQueue filter=solrNoSearch filter=solrNoSearchSubEntries
}
}
}
4 changes: 4 additions & 0 deletions Resources/Private/Language/de.locallang.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
<source>Records</source>
<target>Datensätze</target>
</trans-unit>
<trans-unit id="wizard_tab_extended_filters" resname="wizard_tab_extended_filters">
<source>Extended Filters</source>
<target>Erweiterte Filter</target>
</trans-unit>
<trans-unit id="wizard_error_message" resname="wizard_error_message">
<source>Nothing found. Probably the page id was configured incorrectly.</source>
<target>Nichts gefunden. Wahrscheinlich ist die Seiten-Id falsch konfiguriert.</target>
Expand Down
3 changes: 3 additions & 0 deletions Resources/Private/Language/locallang.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
<trans-unit id="wizard_tab_records" resname="wizard_tab_records">
<source>Records</source>
</trans-unit>
<trans-unit id="wizard_tab_extended_filters" resname="wizard_tab_extended_filters">
<source>Extended Filters</source>
</trans-unit>
<trans-unit id="wizard_error_message" resname="wizard_error_message">
<source>Nothing found. Probably the page id was configured incorrectly.</source>
</trans-unit>
Expand Down
5 changes: 2 additions & 3 deletions Resources/Public/Css/Backend/pagetreefilter.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
.pagetreefilter-highlighted {
fill: #0078e6 !important;
fill-opacity: 0.1;
fill-opacity: 0.3;
stroke-width: 1px;
stroke: #d7d7d7;
}

.pagetreefilter-highlighted.node-over,
.pagetreefilter-highlighted.node-selected {
fill-opacity: 0.3;
fill-opacity: 0.6;
}

.pagetreefilter-wizard .modal-body {
Expand Down

0 comments on commit 7ae7e8c

Please sign in to comment.