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

Improve pagination #151

Merged
merged 25 commits into from
Jan 10, 2024
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
159 changes: 143 additions & 16 deletions src/BaseListView.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@
use Yiisoft\Data\Paginator\KeysetPaginator;
use Yiisoft\Data\Paginator\OffsetPaginator;
use Yiisoft\Data\Paginator\PaginatorInterface;
use Yiisoft\Data\Reader\CountableDataInterface;
use Yiisoft\Data\Reader\FilterableDataInterface;
use Yiisoft\Data\Reader\LimitableDataInterface;
use Yiisoft\Data\Reader\OffsetableDataInterface;
use Yiisoft\Data\Reader\ReadableDataInterface;
use Yiisoft\Data\Reader\SortableDataInterface;
use Yiisoft\Definitions\Exception\CircularReferenceException;
use Yiisoft\Definitions\Exception\InvalidConfigException;
use Yiisoft\Definitions\Exception\NotInstantiableException;
use Yiisoft\Factory\NotFoundException;
use Yiisoft\Html\Html;
use Yiisoft\Html\Tag\Div;
use Yiisoft\Html\Tag\Td;
use Yiisoft\Router\UrlGeneratorInterface;
use Yiisoft\Translator\CategorySource;
use Yiisoft\Translator\IdMessageReader;
use Yiisoft\Translator\IntlMessageFormatter;
Expand All @@ -27,8 +31,28 @@
use Yiisoft\Widget\Widget;
use Yiisoft\Yii\DataView\Exception\DataReaderNotSetException;

/**
* @psalm-import-type UrlCreator from BasePagination
*/
abstract class BaseListView extends Widget
{
/**
* @psalm-var UrlCreator|null
*/
private $paginationUrlCreator = null;
private string $pageParameterName = 'page';
private string $pageSizeParameterName = 'pagesize';

/**
* @psalm-var UrlParameterType::*
*/
private int $pageParameterType = UrlParameterType::QUERY;

/**
* @psalm-var UrlParameterType::*
*/
private int $pageSizeParameterType = UrlParameterType::QUERY;

/**
* A name for {@see CategorySource} used with translator ({@see TranslatorInterface}) by default.
*/
Expand All @@ -51,7 +75,7 @@
private string $header = '';
private array $headerAttributes = [];
private string $layout = "{header}\n{toolbar}\n{items}\n{summary}\n{pager}";
private string $pagination = '';
private string|BasePagination|null $pagination = null;
protected ?ReadableDataInterface $dataReader = null;
protected array $sortLinkAttributes = [];
private ?string $summary = null;
Expand All @@ -64,14 +88,56 @@
protected array $urlArguments = [];
protected array $urlQueryParameters = [];

private UrlParameterProviderInterface|null $urlParameterProvider = null;

public function __construct(
TranslatorInterface|null $translator = null,
private UrlGeneratorInterface|null $urlGenerator = null,
protected readonly string $translationCategory = self::DEFAULT_TRANSLATION_CATEGORY,
) {
$this->translator = $translator ?? $this->createDefaultTranslator();
}

/**
* @psalm-param UrlCreator|null $urlCreator
*/
final public function paginationUrlCreator(?callable $urlCreator): static

Check warning on line 103 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L103

Added line #L103 was not covered by tests
{
$new = clone $this;
$new->paginationUrlCreator = $urlCreator;
return $new;

Check warning on line 107 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L105-L107

Added lines #L105 - L107 were not covered by tests
}

/**
* Return a new instance with name of argument or query parameter for page.
*
* @param string $name The name of argument or query parameter for page.
*/
final public function pageParameterName(string $name): static

Check warning on line 115 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L115

Added line #L115 was not covered by tests
{
$new = clone $this;
$new->pageParameterName = $name;
return $new;

Check warning on line 119 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L117-L119

Added lines #L117 - L119 were not covered by tests
}

/**
* Return a new instance with name of argument or query parameter for page size.
*
* @param string $name The name of argument or query parameter for page size.
*/
final public function pageSizeParameterName(string $name): static

Check warning on line 127 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L127

Added line #L127 was not covered by tests
{
$new = clone $this;
$new->pageSizeParameterName = $name;
return $new;

Check warning on line 131 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L129-L131

Added lines #L129 - L131 were not covered by tests
}

final public function urlParameterProvider(?UrlParameterProviderInterface $provider): static

Check warning on line 134 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L134

Added line #L134 was not covered by tests
{
$new = clone $this;
$new->urlParameterProvider = $provider;
return $new;

Check warning on line 138 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L136-L138

Added lines #L136 - L138 were not covered by tests
}

/**
* Renders the data models.
*
Expand Down Expand Up @@ -142,13 +208,47 @@
return $this->dataReader;
}

public function getUrlGenerator(): UrlGeneratorInterface
private function getPreparedDataReader(): ReadableDataInterface
{
if ($this->urlGenerator === null) {
throw new Exception\UrlGeneratorNotSetException();
$dataReader = $this->getDataReader();

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

Check warning on line 217 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) { $dataReader = new KeysetPaginator($dataReader);
&& $dataReader instanceof CountableDataInterface
&& $dataReader instanceof LimitableDataInterface
) {
$dataReader = new OffsetPaginator($dataReader);
} elseif (
$dataReader instanceof FilterableDataInterface
&& $dataReader instanceof SortableDataInterface
&& $dataReader instanceof LimitableDataInterface

Check warning on line 225 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L223-L225

Added lines #L223 - L225 were not covered by tests
) {
$dataReader = new KeysetPaginator($dataReader);

Check warning on line 227 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L227

Added line #L227 was not covered by tests
} else {
return $dataReader;

Check warning on line 229 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L229

Added line #L229 was not covered by tests
}
}

return $this->urlGenerator;
if ($dataReader->isPaginationRequired()) {

Check warning on line 233 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()) { $pageSize = $this->urlParameterProvider?->get($this->pageSizeParameterName, $this->pageSizeParameterType); if ($pageSize !== null) { $dataReader = $dataReader->withPageSize((int) $pageSize);
$pageSize = $this->urlParameterProvider?->get(
$this->pageSizeParameterName,
$this->pageSizeParameterType,
);
if ($pageSize !== null) {
$dataReader = $dataReader->withPageSize((int)$pageSize);

Check warning on line 239 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L239

Added line #L239 was not covered by tests
}

$page = $this->urlParameterProvider?->get(
$this->pageParameterName,
$this->pageParameterType,
);
if ($page !== null) {
$dataReader = $dataReader->withNextPageToken($page);

Check warning on line 247 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L247

Added line #L247 was not covered by tests
}
}

return $dataReader;
}

/**
Expand Down Expand Up @@ -213,13 +313,12 @@
/**
* Returns a new instance with the pagination of the grid view, detail view, or list view.
*
* @param string $value The pagination of the grid view, detail view, or list view.
* @param BasePagination|string|null $pagination The pagination of the grid view, detail view, or list view.
*/
public function pagination(string $value): static
public function pagination(string|BasePagination|null $pagination): static
{
$new = clone $this;
$new->pagination = $value;

$new->pagination = $pagination;
return $new;
}

Expand Down Expand Up @@ -383,7 +482,7 @@
public function render(): string
{
if ($this->dataReader === null) {
throw new DataReaderNotSetException();

Check warning on line 485 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "Throw_": --- Original +++ New @@ @@ public function render() : string { if ($this->dataReader === null) { - throw new DataReaderNotSetException(); + new DataReaderNotSetException(); } $content = trim(strtr($this->layout, ['{header}' => $this->renderHeader(), '{toolbar}' => $this->toolbar, '{items}' => $this->renderItems(), '{summary}' => $this->renderSummary(), '{pager}' => $this->renderPagination()])); return $this->containerTag === null ? $content : Html::div("\n" . $content . "\n", $this->containerAttributes)->encode(false)->render();
}

$content = trim(
Expand All @@ -409,23 +508,51 @@
*/
protected function getItems(): array
{
$data = $this->getDataReader()->read();
$data = $this->getPreparedDataReader()->read();
return is_array($data) ? $data : iterator_to_array($data);
}

private function renderPagination(): string
{
$dataReader = $this->getDataReader();
if (!$dataReader instanceof PaginatorInterface) {
$preparedDataReader = $this->getPreparedDataReader();
if (!$preparedDataReader instanceof PaginatorInterface || !$preparedDataReader->isPaginationRequired()) {
return '';
}

return $dataReader->isPaginationRequired() ? $this->pagination : '';
if (is_string($this->pagination)) {
return $this->pagination;
}

if ($this->pagination === null) {
if ($preparedDataReader instanceof OffsetPaginator) {
$pagination = OffsetPagination::widget();
} elseif ($preparedDataReader instanceof KeysetPaginator) {
$pagination = KeysetPagination::widget();

Check warning on line 530 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L526-L530

Added lines #L526 - L530 were not covered by tests
} else {
return '';

Check warning on line 532 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L532

Added line #L532 was not covered by tests
}
} else {
$pagination = $this->pagination;

Check warning on line 535 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L535

Added line #L535 was not covered by tests
}

if ($this->paginationUrlCreator !== null) {
$pagination = $pagination->urlCreator($this->paginationUrlCreator);

Check warning on line 539 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L538-L539

Added lines #L538 - L539 were not covered by tests
}

$dataReader = $this->getDataReader();
if ($dataReader instanceof PaginatorInterface) {
$pagination = $pagination->defaultPageSize($dataReader->getPageSize());

Check warning on line 544 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L542-L544

Added lines #L542 - L544 were not covered by tests
}

return $pagination
->paginator($preparedDataReader)
->pageParameterName($this->pageParameterName)
->render();

Check warning on line 550 in src/BaseListView.php

View check run for this annotation

Codecov / codecov/patch

src/BaseListView.php#L547-L550

Added lines #L547 - L550 were not covered by tests
}

private function renderSummary(): string
{
$dataReader = $this->getDataReader();
$dataReader = $this->getPreparedDataReader();
if (!$dataReader instanceof OffsetPaginator) {
return '';
}
Expand Down Expand Up @@ -456,7 +583,7 @@
default => Div::tag()
->attributes($this->headerAttributes)
->content($this->header)
->encode(false)

Check warning on line 586 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "FalseValue": --- Original +++ New @@ @@ { return match ($this->header) { '' => '', - default => Div::tag()->attributes($this->headerAttributes)->content($this->header)->encode(false)->render(), + default => Div::tag()->attributes($this->headerAttributes)->content($this->header)->encode(true)->render(), }; } /**
->render(),
};
}
Expand All @@ -473,7 +600,7 @@
$categorySource = new CategorySource(
$this->translationCategory,
new IdMessageReader(),
extension_loaded('intl') ? new IntlMessageFormatter() : new SimpleMessageFormatter(),

Check warning on line 603 in src/BaseListView.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.2-ubuntu-latest

Escaped Mutant for Mutator "Ternary": --- Original +++ New @@ @@ */ private function createDefaultTranslator() : Translator { - $categorySource = new CategorySource($this->translationCategory, new IdMessageReader(), extension_loaded('intl') ? new IntlMessageFormatter() : new SimpleMessageFormatter()); + $categorySource = new CategorySource($this->translationCategory, new IdMessageReader(), extension_loaded('intl') ? new SimpleMessageFormatter() : new IntlMessageFormatter()); $translator = new Translator(); $translator->addCategorySources($categorySource); return $translator; } }
);
$translator = new Translator();
$translator->addCategorySources($categorySource);
Expand Down
Loading
Loading