From 61c4dfe382f7cc159fdc19f3f318ff6b388f3139 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Thu, 1 Jan 2026 22:24:30 +0100 Subject: [PATCH] Allow positioning of additional grid view filters Closes #6536 --- .../gridView/AbstractGridView.class.php | 83 ++++++++++++++++--- 1 file changed, 72 insertions(+), 11 deletions(-) diff --git a/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php b/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php index dfeefc74e5..66a6de017c 100644 --- a/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php +++ b/wcfsetup/install/files/lib/system/gridView/AbstractGridView.class.php @@ -75,6 +75,15 @@ abstract class AbstractGridView */ private array $availableFilters = []; + /** + * @var array + */ + private array $extraFilters = []; + /** * Adds a new column to the grid view. */ @@ -683,22 +692,52 @@ protected function fireInitializedEvent(): void EventHandler::getInstance()->fire($event); } - /** - * Validates the configuration of this grid view. - */ - protected function validate(): void + private function buildAvailableFilters(): void { - $columnFilters = []; + $filters = []; foreach ($this->getColumns() as $column) { if ($column->getFilter() !== null) { - $columnFilters[$column->getID()] = $column->getFilter(); + $filters[] = $column->getFilter(); } } - $this->availableFilters = [ - ...$columnFilters, - ...$this->availableFilters, - ]; + foreach ($this->extraFilters as $filterData) { + $filter = $filterData['filter']; + + if ($filterData['target'] === null) { + if ($filterData['insertBefore']) { + \array_unshift($filters, $filter); + } else { + $filters[] = $filter; + } + } else { + $index = \array_find_key( + $filters, + static fn($filterObj) => $filterObj->getId() === $filterData['target'] + ); + if ($index === null) { + throw new \RuntimeException("Cannot find the target '{$filterData['target']}' for filter '{$filter->getId()}'."); + } + + if (!$filterData['insertBefore']) { + $index++; + } + + \array_splice($filters, $index, 0, [$filter]); + } + } + + foreach ($filters as $filter) { + $this->availableFilters[$filter->getId()] = $filter; + } + } + + /** + * Validates the configuration of this grid view. + */ + protected function validate(): void + { + $this->buildAvailableFilters(); if ($this->getDefaultSortField() === '') { throw new \InvalidArgumentException("Undefined default sort field."); @@ -863,7 +902,29 @@ protected function applyFilters(): void public function addAvailableFilter(IViewFilter $filter): void { - $this->availableFilters[$filter->getId()] = $filter; + $this->extraFilters[$filter->getId()] = [ + 'filter' => $filter, + 'target' => null, + 'insertBefore' => false, + ]; + } + + public function addAvailableFilterBefore(IViewFilter $filter, ?string $targetFilterID = null): void + { + $this->extraFilters[$filter->getId()] = [ + 'filter' => $filter, + 'target' => $targetFilterID, + 'insertBefore' => true, + ]; + } + + public function addAvailableFilterAfter(IViewFilter $filter, ?string $targetFilterID = null): void + { + $this->extraFilters[$filter->getId()] = [ + 'filter' => $filter, + 'target' => $targetFilterID, + 'insertBefore' => false, + ]; } /**