Skip to content

Commit

Permalink
add method getSortParam(). (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
terabytesoftw committed May 16, 2023
1 parent d818507 commit c4140be
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 52 deletions.
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -18,7 +18,7 @@
"require-dev": {
"maglnet/composer-require-checker": "^4.3",
"phpunit/phpunit": "^10.0",
"roave/infection-static-analysis-plugin": "^1.29",
"roave/infection-static-analysis-plugin": "^1.31",
"vimeo/psalm": "^5.8",
"yiisoft/cache": "^3.0",
"yiisoft/db-sqlite": "^1.0"
Expand Down
5 changes: 4 additions & 1 deletion src/AbstractIteratorDataDataProvider.php
Expand Up @@ -9,6 +9,10 @@

use function ceil;

/**
* The basic implementation of the {@see teratorDataProviderInterface} and can be used as a base class for data
* providers that retrieve data from an array or an iterator object.
*/
abstract class AbstractIteratorDataDataProvider implements IteratorDataProviderInterface
{
protected int $limit = self::DEFAULT_LIMIT;
Expand Down Expand Up @@ -39,7 +43,6 @@ public function getTotalPages(): int

public function withLimit(int $value): static
{
// validate limit
if ($value < 0) {
$value = self::DEFAULT_LIMIT;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ActiveIteratorDataProvider.php
Expand Up @@ -7,7 +7,7 @@
use Yiisoft\ActiveRecord\ActiveQueryInterface;

/**
* Provides a way to iterate over the results of an Active Query with support for pagination.
* Provides a way to iterate over the results of an active query with support for pagination.
*/
final class ActiveIteratorDataProvider extends AbstractIteratorDataDataProvider
{
Expand Down
3 changes: 3 additions & 0 deletions src/QueryIteratorDataProvider.php
Expand Up @@ -6,6 +6,9 @@

use Yiisoft\Db\Query\QueryInterface;

/**
* Provides a way to iterate over the results of {@see \Yiisoft\Db\Query\QueryInterface} in terms of data items.
*/
final class QueryIteratorDataProvider extends AbstractIteratorDataDataProvider
{
public function __construct(private QueryInterface $query)
Expand Down
94 changes: 63 additions & 31 deletions src/Sort.php
Expand Up @@ -15,7 +15,7 @@
use function substr;

/**
* Sort represents information relevant to sorting.
* Represents information relevant to sorting.
*
* When data needs to be sorted according to one or several columns, we can use Sort to represent the sorting
* information and generate appropriate hyperlinks that can lead to sort actions.
Expand All @@ -32,7 +32,7 @@
* 'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
* ],
* ],
* )->params(['sort' => 'age,-name'])->multisort();
* )->params(['sort' => 'age,-name'])->multiSort();
* ```
*
* In the above, we declare two {@see columns} that support sorting: `name` and `age`.
Expand All @@ -46,7 +46,7 @@ final class Sort
private array $params = [];
/** @psalm-var non-empty-string */
private string $separator = ',';
private string $sortParam = 'sort';
private string $sortParamName = 'sort';

/**
* @param array $values List of columns that are allowed to be sorted.
Expand All @@ -59,8 +59,6 @@ final class Sort
* 'name' => [
* 'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
* 'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
* 'default' => SORT_DESC,
* 'label' => 'Name',
* ],
* ]
* ```
Expand All @@ -74,8 +72,6 @@ final class Sort
* 'asc' => ['age' => SORT_ASC],
* 'desc' => ['age' => SORT_DESC],
* ],
* 'default' => SORT_ASC,
* 'label' => 'age',
* ]
* ```
*
Expand All @@ -92,12 +88,6 @@ final class Sort
* - The `asc` and `desc` elements specify how to sort by the column in ascending and descending orders,
* respectively. Their values represent the actual columns and the directions by which the data should be sorted
* by.
* - The `default` element specifies by which direction the column should be sorted if it is not currently sorted
* (the default value is ascending order).
* - The `label` element specifies what label should be used to create a sort link.
*
* Note that if the Sort object is already created, you can only use the full format to configure every column.
* Each column must include these elements: `asc` and `desc`.
*/
public function columns(array $values = []): self
{
Expand Down Expand Up @@ -170,8 +160,6 @@ public function defaultColumnOrder(array $values): self
}

/**
* Returns the sort direction of the specified column in the current request.
*
* @param string $vale The column name.
*
* @return int|null Sort direction of the column.
Expand All @@ -187,8 +175,6 @@ public function getColumnOrder(string $value): int|null
}

/**
* Returns the currently requested sort information.
*
* @param bool $value Whether to recalculate the sort directions.
*
* @return array Sort directions indexed by column names.
Expand All @@ -200,13 +186,13 @@ public function getColumnOrders(bool $value = false): array
return $this->columnOrders;
}

if (isset($this->params[$this->sortParam])) {
if (isset($this->params[$this->sortParamName])) {
$this->columnOrders = [];

$sortParam = $this->parseSortParam((string) $this->params[$this->sortParam]);
$sortParamName = $this->parseSortParam((string) $this->params[$this->sortParamName]);

/** @var array<array-key,string> $sortParam */
foreach ($sortParam as $column) {
/** @var array<array-key,string> $sortParamName */
foreach ($sortParamName as $column) {
$descending = strncmp($column, '-', 1) === 0;
$column = $descending ? substr($column, 1) : $column;

Expand All @@ -226,8 +212,6 @@ public function getColumnOrders(bool $value = false): array
}

/**
* Returns the columns and their corresponding sort directions.
*
* @param bool $value whether to recalculate the sort directions. Defaults to `false`.
*
* @return array The columns (`keys`) and their corresponding sort directions (`values`).
Expand Down Expand Up @@ -257,7 +241,14 @@ public function getOrders(): array
return $columns;
}

public function getSortParams(string $column): array
/**
* @param string $column The name of the column.
*
* @throws InvalidArgumentException if the specified column is unknown.
*
* @return array The sort parameter value for the specified column.
*/
public function getSortParam(string $column): array
{
if ($this->hasColumn($column) === false) {
throw new InvalidArgumentException("Unknown attribute: $column");
Expand All @@ -280,7 +271,48 @@ public function getSortParams(string $column): array
$sorts[] = $direction === SORT_DESC ? '-' . $attribute : $attribute;
}

return [$this->sortParam => implode($this->separator, $sorts)];
return [$this->sortParamName => implode($this->separator, $sorts)];
}

/**
* Returns an array of sort parameter values for all columns.
*
* @return array An array of sort parameter values for all columns.
*/
public function getSortParams(): array
{
$sortParams = [];
$columnOrders = $this->getColumnOrders(true);

/** @psalm-var array<string,int> $columnOrders */
foreach ($columnOrders as $column => $direction) {
$directions = $columnOrders;
$direction = $direction === SORT_DESC ? SORT_ASC : SORT_DESC;
unset($directions[$column]);

$directions = match ($this->multiSort) {
true => array_merge([$column => $direction], $directions),
default => [$column => $direction],
};

$sorts = [];

foreach ($directions as $attribute => $direction) {
$sorts[] = $direction === SORT_DESC ? '-' . $attribute : $attribute;
}

$sortParams[$column][$this->sortParamName] = implode($this->separator, $sorts);
}

return $sortParams;
}

/**
* @return string The parameter name for specifying sort information in a URL.
*/
public function getSortParamName(): string
{
return $this->sortParamName;
}

/**
Expand All @@ -301,10 +333,10 @@ public function multiSort(bool $value = true): self
*
* In order to add hash to all links use `\array_merge($_GET, ['#' => 'my-hash'])`.
*
* The array element indexed by {@see sortParam} is considered to be the current sort directions.
* The array element indexed by {@see sortParamName} is considered to be the current sort directions.
* If the element does not exist, the {@see defaultColumnOrder} will be used.
*
* @see sortParam
* @see sortParamName
* @see defaultColumnOrder
*/
public function params(array $value): self
Expand All @@ -330,9 +362,9 @@ public function separator(string $value): self
*
* @see params
*/
public function sortParam(string $value): self
public function sortParamName(string $value): self
{
$this->sortParam = $value;
$this->sortParamName = $value;

return $this;
}
Expand All @@ -350,7 +382,7 @@ private function hasColumn(string $value): bool
}

/**
* Parses the value of {@see sortParam} into an array of sort column.
* Parses the value of {@see sortParamName} into an array of sort column.
*
* The format must be the column name only for ascending or the column name prefixed with `-` for descending.
*
Expand All @@ -364,7 +396,7 @@ private function hasColumn(string $value): bool
* ]
* ```
*
* @param string $param the value of the {@see sortParam}.
* @param string $param the value of the {@see sortParamName}.
*
* @return array The valid sort attributes.
*/
Expand Down
69 changes: 51 additions & 18 deletions tests/DataProvider/SortTest.php
Expand Up @@ -165,7 +165,7 @@ public function testGetOrders(): void
$this->assertSame(SORT_DESC, $orders['age']);
}

public function testGetSortParams(): void
public function testGetSortParam(): void
{
$this->sort
->columns(
Expand All @@ -180,22 +180,22 @@ public function testGetSortParams(): void
->multiSort()
->params(['sort' => 'age,-name']);

$this->assertSame(['sort' => '-age,-name'], $this->sort->getSortParams('age'));
$this->assertSame(['sort' => 'name,age'], $this->sort->getSortParams('name'));
$this->assertSame(['sort' => '-age,-name'], $this->sort->getSortParam('age'));
$this->assertSame(['sort' => 'name,age'], $this->sort->getSortParam('name'));

$this->sort->multiSort(false);

$this->assertSame(['sort' => '-age'], $this->sort->getSortParams('age'));
$this->assertSame(['sort' => '-age'], $this->sort->getSortParam('age'));

$this->sort
->defaultColumnOrder(['age' => SORT_DESC, 'name' => SORT_ASC])
->multiSort()
->params(['sort' => 'age,name']);

$this->assertSame(['sort' => '-age,name'], $this->sort->getSortParams('age'));
$this->assertSame(['sort' => '-age,name'], $this->sort->getSortParam('age'));
}

public function testGetSortParamsWithException(): void
public function testGetSortParamWithException(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Unknown attribute: unexistingAttribute');
Expand All @@ -206,7 +206,48 @@ public function testGetSortParamsWithException(): void
]
)->params(['sort' => 'age,-name'])->multiSort();

$this->sort->getSortParams('unexistingAttribute');
$this->sort->getSortParam('unexistingAttribute');
}

public function testGetSortParams(): void
{
$this->sort
->columns(
[
'age',
'name' => [
'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
],
],
)
->multiSort()
->params(['sort' => 'age,-name']);

$this->assertSame(
[
'age' => ['sort' => '-age,-name'],
'name' => ['sort' => 'name,age'],
],
$this->sort->getSortParams(),
);

$this->sort->multiSort(false);

$this->assertSame(['age' => ['sort' => '-age']], $this->sort->getSortParams());

$this->sort
->defaultColumnOrder(['age' => SORT_DESC, 'name' => SORT_ASC])
->multiSort()
->params(['sort' => 'age,name']);

$this->assertSame(
[
'age' => ['sort' => '-age,name'],
'name' => ['sort' => '-name,age'],
],
$this->sort->getSortParams(),
);
}

public function testSeparator(): void
Expand All @@ -229,18 +270,10 @@ public function testSeparator(): void
$this->assertSame(['age' => SORT_ASC, 'name' => SORT_ASC], $this->sort->getColumnOrders(true));
}

public function testSortParam(): void
public function testSortParamNamme(): void
{
$this->sort->columns(
[
'age',
'name' => [
'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
],
]
)->params(['order' => 'age,-name'])->sortParam('order')->multiSort(true);
$this->sort->sortParamName('order');

$this->assertSame(['age' => SORT_ASC, 'name' => SORT_DESC], $this->sort->getColumnOrders());
$this->assertSame('order', $this->sort->getSortParamName());
}
}

0 comments on commit c4140be

Please sign in to comment.