Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add filters #167

Merged
merged 19 commits into from
Feb 21, 2024
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"yiisoft/router": "^3.0",
"yiisoft/strings": "^2.0",
"yiisoft/translator": "^3.0",
"yiisoft/validator": "^1.1",
"yiisoft/view": "^8.0",
"yiisoft/widget": "^2.0"
},
Expand Down
11 changes: 11 additions & 0 deletions config/widgets-themes.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
declare(strict_types=1);

use Yiisoft\Yii\DataView\Column\ActionColumnRenderer;
use Yiisoft\Yii\DataView\Filter\Widget\DropdownFilter;
use Yiisoft\Yii\DataView\Filter\Widget\TextInputFilter;
use Yiisoft\Yii\DataView\GridView;
use Yiisoft\Yii\DataView\KeysetPagination;
use Yiisoft\Yii\DataView\OffsetPagination;
Expand All @@ -17,6 +19,9 @@
'sortableHeaderPrepend()' => ['<div class="float-end text-secondary text-opacity-50">⭥</div>'],
'sortableHeaderAscPrepend()' => ['<div class="float-end fw-bold">⭡</div>'],
'sortableHeaderDescPrepend()' => ['<div class="float-end fw-bold">⭣</div>'],
'filterCellAttributes()' => [['class' => 'align-top']],
'filterCellInvalidClass()' => ['bg-danger bg-opacity-10'],
'filterErrorsContainerAttributes()' => [['class' => 'text-danger mt-1']],

Check warning on line 24 in config/widgets-themes.php

View check run for this annotation

Codecov / codecov/patch

config/widgets-themes.php#L22-L24

Added lines #L22 - L24 were not covered by tests
'addColumnRendererConfigs()' => [
[
ActionColumnRenderer::class => [
Expand All @@ -25,6 +30,12 @@
],
],
],
DropdownFilter::class => [
'attributes()' => [['class' => 'form-select']],
],
TextInputFilter::class => [
'attributes()' => [['class' => 'form-control']],
],

Check warning on line 38 in config/widgets-themes.php

View check run for this annotation

Codecov / codecov/patch

config/widgets-themes.php#L33-L38

Added lines #L33 - L38 were not covered by tests
OffsetPagination::class => [
'listTag()' => ['ul'],
'listAttributes()' => [['class' => 'pagination']],
Expand Down
38 changes: 30 additions & 8 deletions src/BaseListView.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
use Yiisoft\Data\Paginator\PageToken;
use Yiisoft\Data\Paginator\PaginatorInterface;
use Yiisoft\Data\Reader\CountableDataInterface;
use Yiisoft\Data\Reader\Filter\All;
use Yiisoft\Data\Reader\FilterableDataInterface;
use Yiisoft\Data\Reader\FilterInterface;
use Yiisoft\Data\Reader\LimitableDataInterface;
use Yiisoft\Data\Reader\OffsetableDataInterface;
use Yiisoft\Data\Reader\ReadableDataInterface;
Expand All @@ -26,6 +28,7 @@
use Yiisoft\Translator\SimpleMessageFormatter;
use Yiisoft\Translator\Translator;
use Yiisoft\Translator\TranslatorInterface;
use Yiisoft\Validator\Result as ValidationResult;
use Yiisoft\Widget\Widget;
use Yiisoft\Yii\DataView\Exception\DataReaderNotSetException;

Expand Down Expand Up @@ -83,7 +86,7 @@
protected array $urlArguments = [];
protected array $urlQueryParameters = [];

private UrlParameterProviderInterface|null $urlParameterProvider = null;
protected UrlParameterProviderInterface|null $urlParameterProvider = null;

private bool $ignoreMissingPage = true;

Expand Down Expand Up @@ -170,11 +173,11 @@
/**
* Renders the data models.
*
* @return string the rendering result.
* @return string The rendering result.
*
* @psalm-param array<array-key, array|object> $items
*/
abstract protected function renderItems(array $items): string;
abstract protected function renderItems(array $items, ValidationResult $filterValidationResult): string;

final public function containerTag(?string $tag): static
{
Expand Down Expand Up @@ -240,11 +243,21 @@
}

/**
* @psalm-return list{FilterInterface[],ValidationResult}
*/
protected function makeFilters(): array

Check warning on line 248 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "ProtectedVisibility": --- Original +++ New @@ @@ /** * @psalm-return list{FilterInterface[],ValidationResult} */ - protected function makeFilters() : array + private function makeFilters() : array { return [[], new ValidationResult()]; }
{
return [[], new ValidationResult()];
}

/**
* @param FilterInterface[] $filters
*
* @throws PageNotFoundException
*
* @psalm-return array<array-key, array|object>
*/
private function prepareDataReaderAndGetItems(): array
private function prepareDataReaderAndGetItems(array $filters): array
{
$page = $this->urlParameterProvider?->get(
$this->urlConfig->getPageParameterName(),
Expand All @@ -263,15 +276,15 @@
$this->urlConfig->getSortParameterType(),
);

$this->preparedDataReader = $this->prepareDataReaderByParams($page, $previousPage, $pageSize, $sort);
$this->preparedDataReader = $this->prepareDataReaderByParams($page, $previousPage, $pageSize, $sort, $filters);

try {
return $this->getItems($this->preparedDataReader);
} catch (PageNotFoundException $exception) {
}

if ($this->ignoreMissingPage) {
$this->preparedDataReader = $this->prepareDataReaderByParams(null, null, $pageSize, $sort);
$this->preparedDataReader = $this->prepareDataReaderByParams(null, null, $pageSize, $sort, $filters);

Check warning on line 287 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L287

Added line #L287 was not covered by tests
try {
return $this->getItems($this->preparedDataReader);
} catch (PageNotFoundException $exception) {
Expand All @@ -296,17 +309,21 @@
return is_array($items) ? $items : iterator_to_array($items);
}

/**
* @param FilterInterface[] $filters
*/
private function prepareDataReaderByParams(
?string $page,
?string $previousPage,
?string $pageSize,
?string $sort,
array $filters,
): ReadableDataInterface {
$dataReader = $this->getDataReader();

if (!$dataReader instanceof PaginatorInterface) {
if (
$dataReader instanceof OffsetableDataInterface

Check warning on line 326 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "LogicalAnd": --- Original +++ New @@ @@ { $dataReader = $this->getDataReader(); if (!$dataReader instanceof PaginatorInterface) { - if ($dataReader instanceof OffsetableDataInterface && $dataReader instanceof CountableDataInterface && $dataReader instanceof LimitableDataInterface) { + if (($dataReader instanceof OffsetableDataInterface || $dataReader instanceof CountableDataInterface) && $dataReader instanceof LimitableDataInterface) { $dataReader = new OffsetPaginator($dataReader); } elseif ($dataReader instanceof FilterableDataInterface && $dataReader instanceof SortableDataInterface && $dataReader instanceof LimitableDataInterface) { if ($dataReader->getSort() !== null) {
&& $dataReader instanceof CountableDataInterface
&& $dataReader instanceof LimitableDataInterface
) {
Expand All @@ -326,7 +343,7 @@
}
}

if ($dataReader->isPaginationRequired()) {

Check warning on line 346 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "IfNegation": --- Original +++ New @@ @@ return $dataReader; } } - if ($dataReader->isPaginationRequired()) { + if (!$dataReader->isPaginationRequired()) { if ($pageSize !== null) { $dataReader = $dataReader->withPageSize((int) $pageSize); }
if ($pageSize !== null) {
$dataReader = $dataReader->withPageSize((int) $pageSize);
}
Expand All @@ -338,13 +355,17 @@
}
}

if ($dataReader->isSortable() && !empty($sort)) {

Check warning on line 358 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndSingleSubExprNegation": --- Original +++ New @@ @@ $dataReader = $dataReader->withToken(PageToken::previous($previousPage)); } } - if ($dataReader->isSortable() && !empty($sort)) { + if (!$dataReader->isSortable() && !empty($sort)) { $sortObject = $dataReader->getSort(); if ($sortObject !== null) { $dataReader = $dataReader->withSort($sortObject->withOrderString($sort));
$sortObject = $dataReader->getSort();
if ($sortObject !== null) {
$dataReader = $dataReader->withSort($sortObject->withOrderString($sort));
}
}

if ($dataReader->isFilterable() && !empty($filters)) {

Check warning on line 365 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "LogicalAnd": --- Original +++ New @@ @@ $dataReader = $dataReader->withSort($sortObject->withOrderString($sort)); } } - if ($dataReader->isFilterable() && !empty($filters)) { + if ($dataReader->isFilterable() || !empty($filters)) { $dataReader = $dataReader->withFilter(new All(...$filters)); } return $dataReader;

Check warning on line 365 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndNegation": --- Original +++ New @@ @@ $dataReader = $dataReader->withSort($sortObject->withOrderString($sort)); } } - if ($dataReader->isFilterable() && !empty($filters)) { + if (!($dataReader->isFilterable() && !empty($filters))) { $dataReader = $dataReader->withFilter(new All(...$filters)); } return $dataReader;

Check warning on line 365 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndSingleSubExprNegation": --- Original +++ New @@ @@ $dataReader = $dataReader->withSort($sortObject->withOrderString($sort)); } } - if ($dataReader->isFilterable() && !empty($filters)) { + if (!$dataReader->isFilterable() && !empty($filters)) { $dataReader = $dataReader->withFilter(new All(...$filters)); } return $dataReader;
$dataReader = $dataReader->withFilter(new All(...$filters));

Check warning on line 366 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L366

Added line #L366 was not covered by tests
}

return $dataReader;
}

Expand Down Expand Up @@ -528,15 +549,16 @@

public function render(): string
{
$items = $this->prepareDataReaderAndGetItems();
[$filters, $filterValidationResult] = $this->makeFilters();
$items = $this->prepareDataReaderAndGetItems($filters);

$content = trim(
strtr(
$this->layout,
[
'{header}' => $this->renderHeader(),
'{toolbar}' => $this->toolbar,
'{items}' => $this->renderItems($items),
'{items}' => $this->renderItems($items, $filterValidationResult),
'{summary}' => $this->renderSummary(),
'{pager}' => $this->renderPagination(),
],
Expand Down Expand Up @@ -622,7 +644,7 @@
$currentPage = $dataReader->getCurrentPage();

// The starting row number (1-based) currently being displayed
$begin = ($currentPage - 1) * $dataReader->getPageSize() + 1;

Check warning on line 647 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "DecrementInteger": --- Original +++ New @@ @@ // The page number (1-based) current being displayed $currentPage = $dataReader->getCurrentPage(); // The starting row number (1-based) currently being displayed - $begin = ($currentPage - 1) * $dataReader->getPageSize() + 1; + $begin = ($currentPage - 0) * $dataReader->getPageSize() + 1; // The number of rows currently being displayed $count = $dataReader->getCurrentPageSize(); // The ending row number (1-based) currently being displayed

Check warning on line 647 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "IncrementInteger": --- Original +++ New @@ @@ // The page number (1-based) current being displayed $currentPage = $dataReader->getCurrentPage(); // The starting row number (1-based) currently being displayed - $begin = ($currentPage - 1) * $dataReader->getPageSize() + 1; + $begin = ($currentPage - 2) * $dataReader->getPageSize() + 1; // The number of rows currently being displayed $count = $dataReader->getCurrentPageSize(); // The ending row number (1-based) currently being displayed

Check warning on line 647 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "Minus": --- Original +++ New @@ @@ // The page number (1-based) current being displayed $currentPage = $dataReader->getCurrentPage(); // The starting row number (1-based) currently being displayed - $begin = ($currentPage - 1) * $dataReader->getPageSize() + 1; + $begin = ($currentPage + 1) * $dataReader->getPageSize() + 1; // The number of rows currently being displayed $count = $dataReader->getCurrentPageSize(); // The ending row number (1-based) currently being displayed

// The number of rows currently being displayed
$count = $dataReader->getCurrentPageSize();
Expand Down
25 changes: 22 additions & 3 deletions src/Column/Base/Cell.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ final class Cell
{
private bool $doubleEncode = true;

/**
* @psalm-var array<array-key,string|Stringable>
*/
private array $content;

public function __construct(
private array $attributes = [],
private ?bool $encode = null,
private string|Stringable $content = '',
string|Stringable ...$content,
) {
$this->content = $content;
}

/**
Expand Down Expand Up @@ -48,7 +54,7 @@ public function doubleEncode(bool $doubleEncode): self
/**
* @param string|Stringable $content Tag content.
*/
public function content(string|Stringable $content): self
public function content(string|Stringable ...$content): self
{
$new = clone $this;
$new->content = $content;
Expand Down Expand Up @@ -115,8 +121,21 @@ public function isDoubleEncode(): bool
return $this->doubleEncode;
}

public function getContent(): string|Stringable
/**
* @psalm-return array<array-key,string|Stringable>
*/
public function getContent(): array
{
return $this->content;
}

public function isEmptyContent(): bool
{
foreach ($this->content as $content) {
if (!empty((string) $content)) {
return false;
}
}
return true;
}
}
26 changes: 26 additions & 0 deletions src/Column/Base/FilterContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\DataView\Column\Base;

use Yiisoft\Validator\Result;
use Yiisoft\Yii\DataView\UrlParameterProviderInterface;
use Yiisoft\Yii\DataView\UrlParameterType;

final class FilterContext
{
public function __construct(
public readonly string $formId,
public readonly Result $validationResult,
public readonly ?string $cellInvalidClass,
public readonly array $errorsContainerAttributes,
private readonly ?UrlParameterProviderInterface $urlParameterProvider,
) {
}

public function getQueryValue(string $name): ?string

Check warning on line 22 in src/Column/Base/FilterContext.php

View check run for this annotation

Codecov / codecov/patch

src/Column/Base/FilterContext.php#L22

Added line #L22 was not covered by tests
{
return $this->urlParameterProvider?->get($name, UrlParameterType::QUERY);

Check warning on line 24 in src/Column/Base/FilterContext.php

View check run for this annotation

Codecov / codecov/patch

src/Column/Base/FilterContext.php#L24

Added line #L24 was not covered by tests
}
}
23 changes: 23 additions & 0 deletions src/Column/Base/MakeFilterContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\DataView\Column\Base;

use Yiisoft\Validator\Result;
use Yiisoft\Yii\DataView\UrlParameterProviderInterface;
use Yiisoft\Yii\DataView\UrlParameterType;

final class MakeFilterContext
{
public function __construct(
public readonly Result $validationResult,
private readonly ?UrlParameterProviderInterface $urlParameterProvider,
) {
}

public function getQueryValue(string $name): ?string
{
return $this->urlParameterProvider?->get($name, UrlParameterType::QUERY);
}
}
11 changes: 11 additions & 0 deletions src/Column/DataColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

namespace Yiisoft\Yii\DataView\Column;

use Yiisoft\Validator\RuleInterface;
use Yiisoft\Yii\DataView\Filter\Factory\FilterFactoryInterface;
use Yiisoft\Yii\DataView\Filter\Widget\FilterWidget;

/**
* DetailColumn is the default column type for the {@see GridView} widget.
*
Expand All @@ -20,6 +24,10 @@ final class DataColumn implements ColumnInterface
{
public readonly ?string $queryProperty;

/**
* @psalm-param bool|array<array-key,string|array<array-key,string>>|FilterWidget $filter
* @psalm-param RuleInterface[]|RuleInterface|null $filterValidation
*/
public function __construct(
public readonly ?string $property = null,
?string $queryProperty = null,
Expand All @@ -32,6 +40,9 @@ public function __construct(
public readonly bool $withSorting = true,
public readonly mixed $content = null,
public readonly ?string $dateTimeFormat = null,
public readonly bool|array|FilterWidget $filter = false,
public readonly string|FilterFactoryInterface|null $filterFactory = null,
public readonly array|RuleInterface|null $filterValidation = null,
private readonly bool $visible = true,
) {
$this->queryProperty = $queryProperty ?? $this->property;
Expand Down
Loading
Loading