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

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
craigh committed Jan 21, 2020
1 parent 827383b commit bb563c2
Show file tree
Hide file tree
Showing 8 changed files with 796 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/composer.lock
/vendor/
150 changes: 150 additions & 0 deletions Column.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Zikula package.
*
* Copyright Zikula Foundation - https://ziku.la/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Zikula\Component\SortableColumns;

/**
* Class Column
*
* A column defines a column of a data table that is used in conjunction with SortableColumns to
* assist in the display of column headers and links to facilitate resorting based on column and direction.
*/
class Column
{
public const DIRECTION_ASCENDING = 'ASC';

public const DIRECTION_DESCENDING = 'DESC';

public const CSS_CLASS_UNSORTED = 'unsorted';

public const CSS_CLASS_ASCENDING = 'sorted-asc';

public const CSS_CLASS_DESCENDING = 'sorted-desc';

/**
* @var string
*/
private $name;

/**
* @var string
*/
private $defaultSortDirection;

/**
* @var string
*/
private $currentSortDirection;

/**
* @var string
*/
private $reverseSortDirection;

/**
* @var string
*/
private $cssClassString;

/**
* @var bool
*/
private $isSortColumn = false;

public function __construct(string $name, string $currentSortDirection = null, string $defaultSortDirection = null)
{
$this->name = $name;
$this->currentSortDirection = !empty($currentSortDirection) ? $currentSortDirection : self::DIRECTION_ASCENDING;
$this->reverseSortDirection = $this->reverse($this->currentSortDirection);
$this->defaultSortDirection = !empty($defaultSortDirection) ? $defaultSortDirection : self::DIRECTION_ASCENDING;
$this->cssClassString = self::CSS_CLASS_UNSORTED;
}

public function getName(): string
{
return $this->name;
}

public function setName(string $name): void
{
$this->name = $name;
}

public function getDefaultSortDirection(): string
{
return $this->defaultSortDirection;
}

public function setDefaultSortDirection(string $defaultSortDirection): void
{
$this->defaultSortDirection = $defaultSortDirection;
}

public function getCurrentSortDirection(): string
{
return $this->currentSortDirection;
}

public function setCurrentSortDirection(string $currentSortDirection): void
{
$this->currentSortDirection = $currentSortDirection;
$this->setCssClassString($this->cssFromDirection($currentSortDirection));
$this->reverseSortDirection = $this->reverse($currentSortDirection);
}

public function getReverseSortDirection(): string
{
return $this->reverseSortDirection;
}

public function setReverseSortDirection(string $reverseSortDirection): void
{
$this->reverseSortDirection = $reverseSortDirection;
}

public function getCssClassString(): string
{
return $this->cssClassString;
}

public function setCssClassString(string $cssClassString): void
{
$this->cssClassString = $cssClassString;
}

public function isSortColumn(): bool
{
return $this->isSortColumn;
}

public function setSortColumn(bool $isSortColumn): void
{
$this->isSortColumn = $isSortColumn;
}

/**
* Reverse the direction constants.
*/
private function reverse(string $direction): string
{
return (self::DIRECTION_ASCENDING === $direction) ? self::DIRECTION_DESCENDING : self::DIRECTION_ASCENDING;
}

/**
* Determine a css class based on the direction.
*/
private function cssFromDirection(string $direction): string
{
return (self::DIRECTION_ASCENDING === $direction) ? self::CSS_CLASS_ASCENDING : self::CSS_CLASS_DESCENDING;
}
}
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# SortableColumns
SortableColumns is a zikula component to help manage data table column headings that can be clicked to sort the data
SortableColumns is a Zikula component to help manage data table column headings that can be clicked to sort the data.
The collection is an `Doctrine\Common\Collections\ArrayCollection` of `Zikula\Component\SortableColumns\Column` objects.
Use `SortableColumns::generateSortableColumns` to create an array of attributes (url, css class) indexed by column name
which can be used in the generation of table headings/links.
231 changes: 231 additions & 0 deletions SortableColumns.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Zikula package.
*
* Copyright Zikula Foundation - https://ziku.la/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Zikula\Component\SortableColumns;

use Doctrine\Common\Collections\ArrayCollection;
use InvalidArgumentException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;

/**
* Class SortableColumns
*
* SortableColumns is a zikula component to help manage data table column headings that can be clicked to sort the data.
* The collection is an ArrayCollection of Zikula\Component\SortableColumns\Column objects.
* Use the ::generateSortableColumns method to create an array of attributes (url, css class) indexed by column name
* which can be used in the generation of table headings/links.
*/
class SortableColumns
{
/**
* @var RouterInterface
*/
private $router;

/**
* The route name string to generate urls for column headers
* @var string
*/
private $routeName;

/**
* A collection of Columns to manage
* @var ArrayCollection
*/
private $columnCollection;

/**
* The default column (if unset, the first column add is used)
* @var Column
*/
private $defaultColumn;

/**
* The column used to sort the data
* @var Column
*/
private $sortColumn;

/**
* The direction to sorted (constant from Column class)
* @var string
*/
private $sortDirection = Column::DIRECTION_ASCENDING;

/**
* The name of the html field that holds the selected orderBy field (default: `sort-field`)
* @var string
*/
private $sortFieldName;

/**
* The name of the html field that holds the selected orderBy direction (default: `sort-direction`)
* @var string
*/
private $directionFieldName;

/**
* Additional url parameters that must be included in the generated urls
* @var array
*/
private $additionalUrlParameters = [];

public function __construct(
RouterInterface $router,
string $routeName,
string $sortFieldName = 'sort-field',
string $directionFieldName = 'sort-direction'
) {
$this->router = $router;
$this->routeName = $routeName;
$this->sortFieldName = $sortFieldName;
$this->directionFieldName = $directionFieldName;
$this->columnCollection = new ArrayCollection();
}

/**
* Create an array of column definitions indexed by column name
* <code>
* ['a' =>
* ['url' => '/foo?sort-direction=ASC&sort-field=a',
* 'class' => 'z-order-unsorted'
* ],
* ]
* </code>
*/
public function generateSortableColumns(): array
{
$resultArray = [];
/** @var Column $column */
foreach ($this->columnCollection as $column) {
$this->additionalUrlParameters[$this->directionFieldName] = $column->isSortColumn() ? $column->getReverseSortDirection() : $column->getCurrentSortDirection();
$this->additionalUrlParameters[$this->sortFieldName] = $column->getName();
$resultArray[$column->getName()] = [
'url' => $this->router->generate($this->routeName, $this->additionalUrlParameters),
'class' => $column->getCssClassString(),
];
}

return $resultArray;
}

/**
* Add one column.
*/
public function addColumn(Column $column): void
{
$this->columnCollection->set($column->getName(), $column);
}

/**
* Shortcut to add an array of columns.
*/
public function addColumns(array $columns = []): void
{
foreach ($columns as $column) {
if ($column instanceof Column) {
$this->addColumn($column);
} else {
throw new InvalidArgumentException('Columns must be an instance of \Zikula\Component\SortableColumns\Column.');
}
}
}

public function removeColumn(string $name): void
{
$this->columnCollection->remove($name);
}

public function getColumn(?string $name): ?Column
{
return $this->columnCollection->get($name);
}

/**
* Set the column to sort by and the sort direction.
*/
public function setOrderBy(Column $sortColumn = null, string $sortDirection = null): void
{
$sortColumn = $sortColumn ?: $this->getDefaultColumn();
if (null === $sortColumn) {
return;
}
$sortDirection = $sortDirection ?: Column::DIRECTION_ASCENDING;
$this->setSortDirection($sortDirection);
$this->setSortColumn($sortColumn);
}

/**
* Shortcut to set OrderBy using the Request object.
*/
public function setOrderByFromRequest(Request $request): void
{
if (null === $this->getDefaultColumn()) {
return;
}
$sortColumnName = $request->get($this->sortFieldName, $this->getDefaultColumn()->getName());
$sortDirection = $request->get($this->directionFieldName, Column::DIRECTION_ASCENDING);
$this->setOrderBy($this->getColumn($sortColumnName), $sortDirection);
}

public function getSortColumn(): ?Column
{
return $this->sortColumn ?? $this->getDefaultColumn();
}

private function setSortColumn(Column $sortColumn): void
{
if ($this->columnCollection->contains($sortColumn)) {
$this->sortColumn = $sortColumn;
$sortColumn->setSortColumn(true);
$sortColumn->setCurrentSortDirection($this->getSortDirection());
}
}

public function getSortDirection(): string
{
return $this->sortDirection;
}

private function setSortDirection(string $sortDirection): void
{
if (in_array($sortDirection, [Column::DIRECTION_ASCENDING, Column::DIRECTION_DESCENDING], true)) {
$this->sortDirection = $sortDirection;
}
}

public function getDefaultColumn(): ?Column
{
if (!empty($this->defaultColumn)) {
return $this->defaultColumn;
}

return $this->columnCollection->first();
}

public function setDefaultColumn(Column $defaultColumn): void
{
$this->defaultColumn = $defaultColumn;
}

public function getAdditionalUrlParameters(): array
{
return $this->additionalUrlParameters;
}

public function setAdditionalUrlParameters(array $additionalUrlParameters = []): void
{
$this->additionalUrlParameters = $additionalUrlParameters;
}
}
Loading

0 comments on commit bb563c2

Please sign in to comment.