Skip to content
This repository was archived by the owner on Aug 18, 2022. It is now read-only.

Commit bb563c2

Browse files
committed
initial commit
1 parent 827383b commit bb563c2

File tree

8 files changed

+796
-1
lines changed

8 files changed

+796
-1
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/composer.lock
2+
/vendor/

Column.php

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Zikula package.
7+
*
8+
* Copyright Zikula Foundation - https://ziku.la/
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Zikula\Component\SortableColumns;
15+
16+
/**
17+
* Class Column
18+
*
19+
* A column defines a column of a data table that is used in conjunction with SortableColumns to
20+
* assist in the display of column headers and links to facilitate resorting based on column and direction.
21+
*/
22+
class Column
23+
{
24+
public const DIRECTION_ASCENDING = 'ASC';
25+
26+
public const DIRECTION_DESCENDING = 'DESC';
27+
28+
public const CSS_CLASS_UNSORTED = 'unsorted';
29+
30+
public const CSS_CLASS_ASCENDING = 'sorted-asc';
31+
32+
public const CSS_CLASS_DESCENDING = 'sorted-desc';
33+
34+
/**
35+
* @var string
36+
*/
37+
private $name;
38+
39+
/**
40+
* @var string
41+
*/
42+
private $defaultSortDirection;
43+
44+
/**
45+
* @var string
46+
*/
47+
private $currentSortDirection;
48+
49+
/**
50+
* @var string
51+
*/
52+
private $reverseSortDirection;
53+
54+
/**
55+
* @var string
56+
*/
57+
private $cssClassString;
58+
59+
/**
60+
* @var bool
61+
*/
62+
private $isSortColumn = false;
63+
64+
public function __construct(string $name, string $currentSortDirection = null, string $defaultSortDirection = null)
65+
{
66+
$this->name = $name;
67+
$this->currentSortDirection = !empty($currentSortDirection) ? $currentSortDirection : self::DIRECTION_ASCENDING;
68+
$this->reverseSortDirection = $this->reverse($this->currentSortDirection);
69+
$this->defaultSortDirection = !empty($defaultSortDirection) ? $defaultSortDirection : self::DIRECTION_ASCENDING;
70+
$this->cssClassString = self::CSS_CLASS_UNSORTED;
71+
}
72+
73+
public function getName(): string
74+
{
75+
return $this->name;
76+
}
77+
78+
public function setName(string $name): void
79+
{
80+
$this->name = $name;
81+
}
82+
83+
public function getDefaultSortDirection(): string
84+
{
85+
return $this->defaultSortDirection;
86+
}
87+
88+
public function setDefaultSortDirection(string $defaultSortDirection): void
89+
{
90+
$this->defaultSortDirection = $defaultSortDirection;
91+
}
92+
93+
public function getCurrentSortDirection(): string
94+
{
95+
return $this->currentSortDirection;
96+
}
97+
98+
public function setCurrentSortDirection(string $currentSortDirection): void
99+
{
100+
$this->currentSortDirection = $currentSortDirection;
101+
$this->setCssClassString($this->cssFromDirection($currentSortDirection));
102+
$this->reverseSortDirection = $this->reverse($currentSortDirection);
103+
}
104+
105+
public function getReverseSortDirection(): string
106+
{
107+
return $this->reverseSortDirection;
108+
}
109+
110+
public function setReverseSortDirection(string $reverseSortDirection): void
111+
{
112+
$this->reverseSortDirection = $reverseSortDirection;
113+
}
114+
115+
public function getCssClassString(): string
116+
{
117+
return $this->cssClassString;
118+
}
119+
120+
public function setCssClassString(string $cssClassString): void
121+
{
122+
$this->cssClassString = $cssClassString;
123+
}
124+
125+
public function isSortColumn(): bool
126+
{
127+
return $this->isSortColumn;
128+
}
129+
130+
public function setSortColumn(bool $isSortColumn): void
131+
{
132+
$this->isSortColumn = $isSortColumn;
133+
}
134+
135+
/**
136+
* Reverse the direction constants.
137+
*/
138+
private function reverse(string $direction): string
139+
{
140+
return (self::DIRECTION_ASCENDING === $direction) ? self::DIRECTION_DESCENDING : self::DIRECTION_ASCENDING;
141+
}
142+
143+
/**
144+
* Determine a css class based on the direction.
145+
*/
146+
private function cssFromDirection(string $direction): string
147+
{
148+
return (self::DIRECTION_ASCENDING === $direction) ? self::CSS_CLASS_ASCENDING : self::CSS_CLASS_DESCENDING;
149+
}
150+
}

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
# SortableColumns
2-
SortableColumns is a zikula component to help manage data table column headings that can be clicked to sort the data
2+
SortableColumns is a Zikula component to help manage data table column headings that can be clicked to sort the data.
3+
The collection is an `Doctrine\Common\Collections\ArrayCollection` of `Zikula\Component\SortableColumns\Column` objects.
4+
Use `SortableColumns::generateSortableColumns` to create an array of attributes (url, css class) indexed by column name
5+
which can be used in the generation of table headings/links.

SortableColumns.php

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Zikula package.
7+
*
8+
* Copyright Zikula Foundation - https://ziku.la/
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Zikula\Component\SortableColumns;
15+
16+
use Doctrine\Common\Collections\ArrayCollection;
17+
use InvalidArgumentException;
18+
use Symfony\Component\HttpFoundation\Request;
19+
use Symfony\Component\Routing\RouterInterface;
20+
21+
/**
22+
* Class SortableColumns
23+
*
24+
* SortableColumns is a zikula component to help manage data table column headings that can be clicked to sort the data.
25+
* The collection is an ArrayCollection of Zikula\Component\SortableColumns\Column objects.
26+
* Use the ::generateSortableColumns method to create an array of attributes (url, css class) indexed by column name
27+
* which can be used in the generation of table headings/links.
28+
*/
29+
class SortableColumns
30+
{
31+
/**
32+
* @var RouterInterface
33+
*/
34+
private $router;
35+
36+
/**
37+
* The route name string to generate urls for column headers
38+
* @var string
39+
*/
40+
private $routeName;
41+
42+
/**
43+
* A collection of Columns to manage
44+
* @var ArrayCollection
45+
*/
46+
private $columnCollection;
47+
48+
/**
49+
* The default column (if unset, the first column add is used)
50+
* @var Column
51+
*/
52+
private $defaultColumn;
53+
54+
/**
55+
* The column used to sort the data
56+
* @var Column
57+
*/
58+
private $sortColumn;
59+
60+
/**
61+
* The direction to sorted (constant from Column class)
62+
* @var string
63+
*/
64+
private $sortDirection = Column::DIRECTION_ASCENDING;
65+
66+
/**
67+
* The name of the html field that holds the selected orderBy field (default: `sort-field`)
68+
* @var string
69+
*/
70+
private $sortFieldName;
71+
72+
/**
73+
* The name of the html field that holds the selected orderBy direction (default: `sort-direction`)
74+
* @var string
75+
*/
76+
private $directionFieldName;
77+
78+
/**
79+
* Additional url parameters that must be included in the generated urls
80+
* @var array
81+
*/
82+
private $additionalUrlParameters = [];
83+
84+
public function __construct(
85+
RouterInterface $router,
86+
string $routeName,
87+
string $sortFieldName = 'sort-field',
88+
string $directionFieldName = 'sort-direction'
89+
) {
90+
$this->router = $router;
91+
$this->routeName = $routeName;
92+
$this->sortFieldName = $sortFieldName;
93+
$this->directionFieldName = $directionFieldName;
94+
$this->columnCollection = new ArrayCollection();
95+
}
96+
97+
/**
98+
* Create an array of column definitions indexed by column name
99+
* <code>
100+
* ['a' =>
101+
* ['url' => '/foo?sort-direction=ASC&sort-field=a',
102+
* 'class' => 'z-order-unsorted'
103+
* ],
104+
* ]
105+
* </code>
106+
*/
107+
public function generateSortableColumns(): array
108+
{
109+
$resultArray = [];
110+
/** @var Column $column */
111+
foreach ($this->columnCollection as $column) {
112+
$this->additionalUrlParameters[$this->directionFieldName] = $column->isSortColumn() ? $column->getReverseSortDirection() : $column->getCurrentSortDirection();
113+
$this->additionalUrlParameters[$this->sortFieldName] = $column->getName();
114+
$resultArray[$column->getName()] = [
115+
'url' => $this->router->generate($this->routeName, $this->additionalUrlParameters),
116+
'class' => $column->getCssClassString(),
117+
];
118+
}
119+
120+
return $resultArray;
121+
}
122+
123+
/**
124+
* Add one column.
125+
*/
126+
public function addColumn(Column $column): void
127+
{
128+
$this->columnCollection->set($column->getName(), $column);
129+
}
130+
131+
/**
132+
* Shortcut to add an array of columns.
133+
*/
134+
public function addColumns(array $columns = []): void
135+
{
136+
foreach ($columns as $column) {
137+
if ($column instanceof Column) {
138+
$this->addColumn($column);
139+
} else {
140+
throw new InvalidArgumentException('Columns must be an instance of \Zikula\Component\SortableColumns\Column.');
141+
}
142+
}
143+
}
144+
145+
public function removeColumn(string $name): void
146+
{
147+
$this->columnCollection->remove($name);
148+
}
149+
150+
public function getColumn(?string $name): ?Column
151+
{
152+
return $this->columnCollection->get($name);
153+
}
154+
155+
/**
156+
* Set the column to sort by and the sort direction.
157+
*/
158+
public function setOrderBy(Column $sortColumn = null, string $sortDirection = null): void
159+
{
160+
$sortColumn = $sortColumn ?: $this->getDefaultColumn();
161+
if (null === $sortColumn) {
162+
return;
163+
}
164+
$sortDirection = $sortDirection ?: Column::DIRECTION_ASCENDING;
165+
$this->setSortDirection($sortDirection);
166+
$this->setSortColumn($sortColumn);
167+
}
168+
169+
/**
170+
* Shortcut to set OrderBy using the Request object.
171+
*/
172+
public function setOrderByFromRequest(Request $request): void
173+
{
174+
if (null === $this->getDefaultColumn()) {
175+
return;
176+
}
177+
$sortColumnName = $request->get($this->sortFieldName, $this->getDefaultColumn()->getName());
178+
$sortDirection = $request->get($this->directionFieldName, Column::DIRECTION_ASCENDING);
179+
$this->setOrderBy($this->getColumn($sortColumnName), $sortDirection);
180+
}
181+
182+
public function getSortColumn(): ?Column
183+
{
184+
return $this->sortColumn ?? $this->getDefaultColumn();
185+
}
186+
187+
private function setSortColumn(Column $sortColumn): void
188+
{
189+
if ($this->columnCollection->contains($sortColumn)) {
190+
$this->sortColumn = $sortColumn;
191+
$sortColumn->setSortColumn(true);
192+
$sortColumn->setCurrentSortDirection($this->getSortDirection());
193+
}
194+
}
195+
196+
public function getSortDirection(): string
197+
{
198+
return $this->sortDirection;
199+
}
200+
201+
private function setSortDirection(string $sortDirection): void
202+
{
203+
if (in_array($sortDirection, [Column::DIRECTION_ASCENDING, Column::DIRECTION_DESCENDING], true)) {
204+
$this->sortDirection = $sortDirection;
205+
}
206+
}
207+
208+
public function getDefaultColumn(): ?Column
209+
{
210+
if (!empty($this->defaultColumn)) {
211+
return $this->defaultColumn;
212+
}
213+
214+
return $this->columnCollection->first();
215+
}
216+
217+
public function setDefaultColumn(Column $defaultColumn): void
218+
{
219+
$this->defaultColumn = $defaultColumn;
220+
}
221+
222+
public function getAdditionalUrlParameters(): array
223+
{
224+
return $this->additionalUrlParameters;
225+
}
226+
227+
public function setAdditionalUrlParameters(array $additionalUrlParameters = []): void
228+
{
229+
$this->additionalUrlParameters = $additionalUrlParameters;
230+
}
231+
}

0 commit comments

Comments
 (0)