Skip to content
Merged
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
17 changes: 14 additions & 3 deletions wcfsetup/install/files/lib/action/GridViewFilterAction.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,19 @@ public function handle(ServerRequestInterface $request): ResponseInterface
return $response;
}

$data = $form->getData()['data'];
$rawData = $form->getData();
$data = $rawData['data'];

foreach ($view->getAvailableFilters() as $filter) {
if (!isset($rawData[$filter->getFormDataId()])) {
continue;
}

$data[$filter->getId()] = $filter->serializeValue($rawData[$filter->getFormDataId()]);
}

foreach ($data as $key => $value) {
if ($value === '' || $value === null) {
if ($value === '' || $value === null || $value === 0) {
unset($data[$key]);
}
}
Expand Down Expand Up @@ -95,7 +105,8 @@ private function getForm(AbstractGridView $gridView, array $values): Psr15Dialog
$formField = $filter->getFormField();

if (isset($values[$filter->getID()])) {
$formField->value($values[$filter->getID()]);
$value = $filter->unserializeValue($values[$filter->getID()]);
$formField->value($value);
}

$form->appendChild($formField);
Expand Down
14 changes: 9 additions & 5 deletions wcfsetup/install/files/lib/action/ListViewFilterAction.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,16 @@ public function handle(ServerRequestInterface $request): ResponseInterface
if ($response !== null) {
return $response;
}

$rawData = $form->getData();
$data = $rawData['data'];
// This code is required to bypass the strange behavior of the LabelFormField.
if (!empty($rawData['labelIDs'])) {
foreach ($rawData['labelIDs'] as $groupID => $value) {
$data['labelIDs' . $groupID] = $value;

foreach ($view->getAvailableFilters() as $filter) {
if (!isset($rawData[$filter->getFormDataId()])) {
continue;
}

$data[$filter->getId()] = $filter->serializeValue($rawData[$filter->getFormDataId()]);
}

foreach ($data as $key => $value) {
Expand Down Expand Up @@ -102,7 +105,8 @@ private function getForm(AbstractListView $listView, array $values): Psr15Dialog
$formField = $filter->getFormField();

if (isset($values[$filter->getID()])) {
$formField->value($values[$filter->getID()]);
$value = $filter->unserializeValue($values[$filter->getID()]);
$formField->value($value);
}

$form->appendChild($formField);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use wcf\system\interaction\EditInteraction;
use wcf\system\view\filter\BooleanFilter;
use wcf\system\view\filter\CategoryFilter;
use wcf\system\view\filter\MultipleSelectFilter;
use wcf\system\view\filter\SelectFilter;
use wcf\system\view\filter\TextFilter;
use wcf\system\view\filter\TimeFilter;
Expand Down Expand Up @@ -192,7 +193,7 @@ public function applyFilter(DatabaseObjectList $list, string $value): void
);
}
},
new SelectFilter(
new MultipleSelectFilter(
[
0 => 'wcf.acp.article.publicationStatus.unpublished',
1 => 'wcf.acp.article.publicationStatus.published',
Expand All @@ -201,7 +202,7 @@ public function applyFilter(DatabaseObjectList $list, string $value): void
'publicationStatus',
'wcf.acp.article.publicationStatus'
),
new BooleanFilter('isDeleted', 'wcf.acp.article.isDeleted')
new BooleanFilter('isDeleted', 'wcf.acp.article.isDeleted'),
]);
$provider = new ArticleInteractions();
$provider->addInteractions([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,22 @@ protected function getDatabaseColumnName(DatabaseObjectList $list): string
{
return ($this->databaseColumn ?: $list->getDatabaseTableAlias() . '.' . $this->id);
}

#[\Override]
public function serializeValue(mixed $value): string
{
return (string)$value;
}

#[\Override]
public function unserializeValue(string $value): mixed
{
return $value;
}

#[\Override]
public function getFormDataId(): string
{
return $this->getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,19 @@ public function getId(): string;
* Returns the label of this filter.
*/
public function getLabel(): string;

/**
* Serializes the given form field value to a string that can be passed in a URL.
*/
public function serializeValue(mixed $value): string;

/**
* Unserializes the given string to a value that can be passed to the form field.
*/
public function unserializeValue(string $value): mixed;

/**
* Returns the id of the form field used by this filter.
*/
public function getFormDataId(): string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,21 @@ public function renderValue(string $value): string
{
return $this->labelGroup->getLabel((int)$value)->getTitle();
}

#[\Override]
public function serializeValue(mixed $value): string
{
if (\is_array($value) && isset($value[$this->labelGroup->groupID])) {
return $value[$this->labelGroup->groupID];
}

return '';
}

#[\Override]
public function getFormDataId(): string
{
// `LabelFormField` stores form data values always under the key `labelIDs`.
return 'labelIDs';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

namespace wcf\system\view\filter;

use wcf\data\DatabaseObjectList;
use wcf\system\form\builder\field\AbstractFormField;
use wcf\system\form\builder\field\MultipleSelectionFormField;
use wcf\system\view\filter\exception\InvalidFilterValue;
use wcf\system\WCF;

/**
* Allows a column to be filtered on the basis of multiple selected values.
*
* @author Marcel Werk
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
class MultipleSelectFilter extends AbstractFilter
{
/**
* @param array<string|int, mixed> $options
*/
public function __construct(
protected readonly array $options,
string $id,
string $languageItem,
string $databaseColumn = '',
protected readonly bool $labelLanguageItems = true
) {
parent::__construct($id, $languageItem, $databaseColumn);
}

#[\Override]
public function getFormField(): AbstractFormField
{
return MultipleSelectionFormField::create($this->id)
->label($this->languageItem)
->options($this->options, labelLanguageItems: $this->labelLanguageItems);
}

#[\Override]
public function applyFilter(DatabaseObjectList $list, string $value): void
{
$filterValues = $this->unserializeValue($value);
foreach ($filterValues as $filterValue) {
if (!isset($this->options[$filterValue])) {
throw new InvalidFilterValue("Invalid value '{$filterValue}' for filter '{$this->id}' given.");
}
}

$columnName = $this->getDatabaseColumnName($list);

$list->getConditionBuilder()->add("{$columnName} IN (?)", [$filterValues]);
}

#[\Override]
public function renderValue(string $value): string
{
$renderedValues = \array_map(function ($filterValue): string {
if ($this->labelLanguageItems) {
return WCF::getLanguage()->get($this->options[$filterValue]);
} else {
return $this->options[$filterValue];
}
}, $this->unserializeValue($value));

return \implode(', ', $renderedValues);
}

#[\Override]
public function serializeValue(mixed $value): string
{
return \implode(',', $value);
}

/**
* @return array<string|int>
*/
#[\Override]
public function unserializeValue(string $value): array
{
return \explode(',', $value);
}
}