Initial xentral_oss_20.3.c9ffacf
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\Options\DataTableOptions;
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
use Xentral\Widgets\DataTable\Exception\FeatureNotImplementedException;
|
||||
|
||||
/**
|
||||
* @todo
|
||||
*
|
||||
* @example https://datatables.net/reference/api/columns().footer()#Example
|
||||
*/
|
||||
final class ColumnAggregateFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/**
|
||||
* @throws FeatureNotImplementedException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
throw new FeatureNotImplementedException('Feature is not implemented yet.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
$this->modifyOptions($table->getOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableOptions $options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function modifyOptions(DataTableOptions $options)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\Column\Column;
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
|
||||
/**
|
||||
* @todo Fertigstellen
|
||||
*/
|
||||
final class ColumnFilterFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/** @var string TYPE_NONE Filter deactivated */
|
||||
const TYPE_NONE = 'none'; // Filter deactivated
|
||||
|
||||
/** @var string TYPE_TEXT Default filter */
|
||||
const TYPE_TEXT = 'text'; // Default
|
||||
|
||||
/** @var string TYPE_TEXT_MULTI @todo Mehrere Wörter mit ODER suchen */
|
||||
const TYPE_TEXT_MULTI = 'text_multi';
|
||||
|
||||
/** @var string TYPE_SELECT @todo Dropdown */
|
||||
const TYPE_SELECT = 'select';
|
||||
|
||||
/** @var string TYPE_NUMBER */
|
||||
const TYPE_NUMBER = 'number';
|
||||
|
||||
/** @var string TYPE_NUMBER_RANGE */
|
||||
const TYPE_NUMBER_RANGE = 'number_range';
|
||||
|
||||
/** @var string TYPE_DATE @todo */
|
||||
const TYPE_DATE = 'date';
|
||||
|
||||
/** @var string TYPE_DATE_RANGE @todo */
|
||||
const TYPE_DATE_RANGE = 'date_range';
|
||||
|
||||
/** @var array $columnSettings */
|
||||
private $columnSettings = [];
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
$this->modifyOptions($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $columnName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addNumberRangeFilter($columnName)
|
||||
{
|
||||
$this->columnSettings[$columnName] = [
|
||||
'name' => $columnName,
|
||||
'type' => self::TYPE_NUMBER_RANGE,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo
|
||||
*
|
||||
* @param string $columnName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addMultiWordFilter($columnName)
|
||||
{
|
||||
$this->columnSettings[$columnName] = [
|
||||
'name' => $columnName,
|
||||
'type' => self::TYPE_TEXT,
|
||||
'multi_word' => true,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo
|
||||
*
|
||||
* @param string $columnName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
// public function addDropdownFilter($columnName)
|
||||
// {
|
||||
// $this->columnSettings[$columnName] = [
|
||||
// 'name' => $columnName,
|
||||
// 'type' => self::TYPE_SELECT,
|
||||
// ];
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function modifyOptions(DataTableInterface $table)
|
||||
{
|
||||
$result = [];
|
||||
/** @var Column $column */
|
||||
foreach ($table->getColumns() as $index => $column) {
|
||||
$columnName = $column->getName();
|
||||
if (isset($this->columnSettings[$columnName])) {
|
||||
$result[$index] = $this->columnSettings[$columnName];
|
||||
} else {
|
||||
// Default
|
||||
$defaultType = $column->isSearchable() ? self::TYPE_TEXT : self::TYPE_NONE;
|
||||
$result[$index] = [
|
||||
'name' => $column->getName(),
|
||||
'type' => $defaultType,
|
||||
];
|
||||
}
|
||||
if ($columnName === 'id' || $columnName === 'menu') {
|
||||
$result[$index] = [
|
||||
'name' => $column->getName(),
|
||||
'type' => self::TYPE_NONE, // Column filtering inactive on menu and id column
|
||||
];
|
||||
}
|
||||
if (strpos($columnName, '_') === 0) {
|
||||
$result[$index] = [
|
||||
'name' => $column->getName(),
|
||||
'type' => self::TYPE_NONE, // @todo Wird benötigt?
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$table->getOptions()->setOption('columnFilter', $result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\Options\DataTableOptions;
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
use Xentral\Widgets\DataTable\Exception\FeatureIncompatibleException;
|
||||
|
||||
/**
|
||||
* @deprecated Nicht verwenden; Momentan inkompatibel mit ColumnFilter! Filter-Eingabefelder werden falsch zugeordnet.
|
||||
*
|
||||
* @see https://datatables.net/extensions/colreorder/
|
||||
*/
|
||||
final class ColumnReorderFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/**
|
||||
* @throws FeatureIncompatibleException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
throw new FeatureIncompatibleException('DataTable feature "ColumnReorder" is incompatible.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
$this->modifyOptions($table->getOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableOptions $options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function modifyOptions(DataTableOptions $options)
|
||||
{
|
||||
/** @see https://datatables.net/reference/option/colReorder */
|
||||
$options->setOption('colReorder', ['enable' => true, 'realtime' => false]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
use Xentral\Widgets\DataTable\Exception\DataTableExceptionInterface;
|
||||
|
||||
interface DataTableFeatureInterface
|
||||
{
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @throws DataTableExceptionInterface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
|
||||
final class DebugFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/** @var bool $enabled */
|
||||
private $enabled;
|
||||
|
||||
/**
|
||||
* @param bool $enabled
|
||||
*/
|
||||
public function __construct($enabled = true)
|
||||
{
|
||||
$this->enabled = (bool)$enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
if ($this->enabled === true) {
|
||||
$table->getConfig()->addCssClass('datatable-debug');
|
||||
} else {
|
||||
$table->getConfig()->removeCssClass('datatable-debug');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
$this->enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
$this->enabled = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use ArrayIterator;
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
use Xentral\Widgets\DataTable\Exception\FeatureExistsException;
|
||||
use Xentral\Widgets\DataTable\Exception\FeatureNotFoundException;
|
||||
use Xentral\Widgets\DataTable\Exception\InvalidArgumentException;
|
||||
|
||||
class FeatureCollection implements IteratorAggregate
|
||||
{
|
||||
/** @var array $features */
|
||||
protected $features = [];
|
||||
|
||||
/**
|
||||
* @param array|DataTableFeatureInterface[] $features
|
||||
*/
|
||||
public function __construct(array $features = [])
|
||||
{
|
||||
foreach ($features as $feature) {
|
||||
$this->add($feature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className Full-qualified class name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($className)
|
||||
{
|
||||
$this->ensureClassNameParameter($className, __METHOD__);
|
||||
|
||||
foreach ($this->features as $feature) {
|
||||
if (get_class($feature) === $className) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className Full-qualified class name
|
||||
*
|
||||
* @throws FeatureNotFoundException
|
||||
*
|
||||
* @return DataTableFeatureInterface
|
||||
*/
|
||||
public function get($className)
|
||||
{
|
||||
$this->ensureClassNameParameter($className, __METHOD__);
|
||||
|
||||
foreach ($this->features as $feature) {
|
||||
if (get_class($feature) === $className) {
|
||||
return $feature;
|
||||
}
|
||||
}
|
||||
|
||||
throw new FeatureNotFoundException(sprintf('Feature class "%s" not found.', $className));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|DataTableFeatureInterface[]
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return $this->features;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new feature
|
||||
*
|
||||
* @param DataTableFeatureInterface $feature
|
||||
*
|
||||
* @throws FeatureExistsException If feature with same type already exists
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add(DataTableFeatureInterface $feature)
|
||||
{
|
||||
if ($this->has(get_class($feature))) {
|
||||
throw new FeatureExistsException(sprintf('Feature class "%s" already exists', get_class($feature)));
|
||||
}
|
||||
|
||||
$this->features[] = $feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a feature; If feature with same type exists, it will be overwritten.
|
||||
*
|
||||
* @param DataTableFeatureInterface $feature
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set(DataTableFeatureInterface $feature)
|
||||
{
|
||||
$this->remove(get_class($feature));
|
||||
$this->features[] = $feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|object $className Full-qualified class name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function remove($className)
|
||||
{
|
||||
$this->ensureClassNameParameter($className, __METHOD__);
|
||||
|
||||
foreach ($this->features as $index => $feature) {
|
||||
if (get_class($feature) === $className) {
|
||||
unset($this->features[$index]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function removeAll()
|
||||
{
|
||||
$this->features = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayIterator|Traversable
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->features);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep copy object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
foreach ($this->features as $index => $column) {
|
||||
$this->features[$index] = clone $column;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $className
|
||||
* @param string $callerName
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function ensureClassNameParameter($className, $callerName)
|
||||
{
|
||||
if (!is_string($className)) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Parameter "className" in method "%s" has to be a class name.', $callerName
|
||||
));
|
||||
}
|
||||
|
||||
if (!class_exists($className, true)) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'"%s" is not a valid class.', $className
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
use Xentral\Widgets\DataTable\Options\DataTableOptions;
|
||||
use Xentral\Widgets\DataTable\Exception\FeatureIncompatibleException;
|
||||
|
||||
/**
|
||||
* @see https://datatables.net/extensions/fixedheader/
|
||||
*/
|
||||
final class FixedHeaderFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/**
|
||||
* @throws FeatureIncompatibleException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
throw new FeatureIncompatibleException('Feature "FixedHeaderFeature" does not work currently.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
$this->modifyOptions($table->getOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableOptions $options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function modifyOptions(DataTableOptions $options)
|
||||
{
|
||||
/** @see https://datatables.net/reference/option/fixedHeader */
|
||||
$options->setOption('fixedHeader', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\Column\Column;
|
||||
use Xentral\Widgets\DataTable\Column\ColumnCollection;
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
use Xentral\Widgets\DataTable\Options\DataTableOptions;
|
||||
|
||||
/**
|
||||
* @see https://datatables.net/extensions/responsive/
|
||||
*/
|
||||
final class ResponsiveFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/** @var int PRIO_HIGHEST */
|
||||
const PRIO_HIGHEST = 1;
|
||||
|
||||
/** @var int PRIO_HIGHER */
|
||||
const PRIO_HIGHER = 10;
|
||||
|
||||
/** @var int PRIO_NORMAL */
|
||||
const PRIO_NORMAL = 100;
|
||||
|
||||
/** @var int PRIO_LOWER */
|
||||
const PRIO_LOWER = 1000;
|
||||
|
||||
/** @var int PRIO_LOWEST */
|
||||
const PRIO_LOWEST = 10000;
|
||||
|
||||
/** @var array $responsiveProperty */
|
||||
private $responsiveProperty = [
|
||||
'details' => false,
|
||||
];
|
||||
|
||||
/** @var array $columnPriorities */
|
||||
private $columnPriorities = [];
|
||||
|
||||
/** @var int $defaultPriority */
|
||||
private $defaultPriority = self::PRIO_NORMAL;
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
$this->modifyOptions($table->getOptions());
|
||||
$this->modifyColumns($table->getColumns());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $columnName
|
||||
* @param int $priority
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPriority($columnName, $priority)
|
||||
{
|
||||
$this->columnPriorities[$columnName] = (int)$priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $priority
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultPriority($priority)
|
||||
{
|
||||
$this->defaultPriority = (int)$priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableOptions $options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function modifyOptions(DataTableOptions $options)
|
||||
{
|
||||
$options->setOption('responsive', $this->responsiveProperty);
|
||||
$options->removeOption('scrollX');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ColumnCollection $columns
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function modifyColumns(ColumnCollection $columns)
|
||||
{
|
||||
/** @var Column $column */
|
||||
foreach ($columns as $column) {
|
||||
$name = $column->getName();
|
||||
if (isset($this->columnPriorities[$name])) {
|
||||
$column->set('responsivePriority', $this->columnPriorities[$name]);
|
||||
} else {
|
||||
if (!$column->has('responsivePriority')) {
|
||||
$column->set('responsivePriority', $this->defaultPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Closure;
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
|
||||
final class RowClassesFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/** @var array $colors */
|
||||
private static $availableColors = [
|
||||
'lightgray',
|
||||
'lightgreen',
|
||||
'lightteal',
|
||||
'lightcyan',
|
||||
'lightblue',
|
||||
'lightindigo',
|
||||
'lightviolet',
|
||||
'lightfuchsia',
|
||||
'lightpink',
|
||||
'lightred',
|
||||
'lightorange',
|
||||
'lightyellow',
|
||||
'lightlime',
|
||||
];
|
||||
|
||||
/** @var array|string[] $classes */
|
||||
private $classes;
|
||||
|
||||
/** @var array|Closure[] $customFormatter */
|
||||
private $customFormatter = [];
|
||||
|
||||
/**
|
||||
* @param array|string[] $classes
|
||||
* @param array|Closure $customFormatter
|
||||
*/
|
||||
public function __construct(array $classes = [], array $customFormatter = [])
|
||||
{
|
||||
foreach ($classes as $class) {
|
||||
$this->addClass($class);
|
||||
}
|
||||
foreach ($customFormatter as $formatter) {
|
||||
$this->addCustomFormatter($formatter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClass($className)
|
||||
{
|
||||
$this->classes[] = trim($className);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|string[]
|
||||
*/
|
||||
public function getClasses()
|
||||
{
|
||||
return $this->classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClassesString()
|
||||
{
|
||||
return implode(' ', $this->classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCustomFormatter()
|
||||
{
|
||||
return !empty($this->customFormatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|Closure[]
|
||||
*/
|
||||
public function getCustomFormatter()
|
||||
{
|
||||
return $this->customFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Closure $closure
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addCustomFormatter(Closure $closure)
|
||||
{
|
||||
$this->customFormatter[] = $closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
// @todo Logik steckt momentan in DataTableRenderer; muss aber hier rein
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRandomColor()
|
||||
{
|
||||
$count = count(self::$availableColors);
|
||||
$index = mt_rand() % $count;
|
||||
|
||||
return self::$availableColors[$index];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\Column\Column;
|
||||
use Xentral\Widgets\DataTable\Column\ColumnFormatter;
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
use Xentral\Widgets\DataTable\Exception\DataTableExceptionInterface;
|
||||
use Xentral\Widgets\DataTable\Exception\InvalidArgumentException;
|
||||
|
||||
final class RowDetailsFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/** @var string $ajaxUrl */
|
||||
private $ajaxUrl;
|
||||
|
||||
/** @var string $ajaxMethod */
|
||||
private $ajaxMethod;
|
||||
|
||||
/** @var array $ajaxParams @todo Additional AJAX parameter */
|
||||
private $ajaxParams = [];
|
||||
|
||||
/**
|
||||
* Der Wert aus der id-Spalte wird als POST-Parameter `id` übergeben
|
||||
*
|
||||
* @param string $ajaxUrl `./index.php?module=foo&action=bar`
|
||||
* @param string $ajaxMethod [GET|POST]
|
||||
* @param callable|null $customFormatter @todo
|
||||
*/
|
||||
public function __construct($ajaxUrl, $ajaxMethod = 'POST', $customFormatter = null)
|
||||
{
|
||||
$ajaxMethod = strtoupper($ajaxMethod);
|
||||
if (!in_array($ajaxMethod, ['GET', 'POST'])) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid method "%s".', $ajaxMethod));
|
||||
}
|
||||
|
||||
$this->ajaxUrl = $ajaxUrl;
|
||||
$this->ajaxMethod = $ajaxMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @throws DataTableExceptionInterface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
$table->getOptions()->setOption('rowDetails', [
|
||||
'ajax' => [
|
||||
'url' => $this->ajaxUrl,
|
||||
'method' => $this->ajaxMethod,
|
||||
'data' => $this->ajaxParams,
|
||||
],
|
||||
]);
|
||||
|
||||
// Detail-Spalte erzeugen
|
||||
$newCol = Column::fixed('details', '', 'center', '20px');
|
||||
$newCol->setFormatter(ColumnFormatter::template('<span class="details" data-id="{ID}"></span>'));
|
||||
$newCol->addCssClass('dt-details');
|
||||
|
||||
// Detail-Spalte vor erste Spalte einfügen
|
||||
/** @var Column $firstCol */
|
||||
$firstCol = $table->getColumns()->getByIndex(0);
|
||||
$table->getColumns()->addBefore($newCol, $firstCol->getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
use Xentral\Widgets\DataTable\Exception\ColumnNotFoundException;
|
||||
use Xentral\Widgets\DataTable\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @see https://datatables.net/extensions/rowgroup/
|
||||
*/
|
||||
final class RowGroupFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/** @var array $groupColumns */
|
||||
private $groupColumns;
|
||||
|
||||
/** @var bool $enabled */
|
||||
private $enabled;
|
||||
|
||||
/**
|
||||
* @param array $columnNames
|
||||
*/
|
||||
public function __construct(array $columnNames)
|
||||
{
|
||||
if (count($columnNames) === 0) {
|
||||
throw new InvalidArgumentException('Parameter "columnNames" is can not be empty.');
|
||||
}
|
||||
$this->groupColumns = $columnNames;
|
||||
$this->enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @throws ColumnNotFoundException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
foreach ($this->groupColumns as $columnName) {
|
||||
if (!$table->getColumns()->has($columnName)) {
|
||||
throw new ColumnNotFoundException(sprintf(
|
||||
'RowGroupFeature failed. Column "%s" not found.',
|
||||
$columnName
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($this->enabled === true) {
|
||||
$table->getOptions()->setOption('rowGroup', ['dataSrc' => $this->groupColumns]);
|
||||
}
|
||||
if ($this->enabled === false) {
|
||||
$table->getOptions()->setOption('rowGroup', false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $columnNames
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function groupBy(array $columnNames)
|
||||
{
|
||||
if (count($columnNames) === 0) {
|
||||
throw new InvalidArgumentException('Parameter "columnNames" is can not be empty.');
|
||||
}
|
||||
$this->groupColumns = $columnNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
$this->enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
$this->enabled = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
|
||||
final class StateSaveFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/** @var bool $enabled */
|
||||
private $enabled;
|
||||
|
||||
/** @var int $duration In seconds (0 = Forever) */
|
||||
private $duration;
|
||||
|
||||
/**
|
||||
* @param bool $enabled
|
||||
* @param int $duration
|
||||
*/
|
||||
public function __construct($enabled = true, $duration = 0)
|
||||
{
|
||||
$this->enabled = (bool)$enabled;
|
||||
$this->duration = (int)$duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
// $options = $table->getOptions()->toArray();
|
||||
// $options['columns'] = $table->getColumns()->toArray();
|
||||
// $table->getOptions()->setOption('revision', md5(json_encode($options)));
|
||||
|
||||
$table->getOptions()->setOption('stateSave', $this->enabled);
|
||||
$table->getOptions()->setOption('stateDuration', $this->duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
$this->enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
$this->enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getDuration()
|
||||
{
|
||||
return $this->duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $duration
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDuration($duration)
|
||||
{
|
||||
$this->duration = (int)$duration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
|
||||
final class TableControlFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/** @var array $buttonConfigCopy */
|
||||
private static $buttonConfigCopy = [
|
||||
'extend' => 'copy',
|
||||
'text' => 'Zwischenablage',
|
||||
];
|
||||
|
||||
/** @var array $buttonConfigCsv */
|
||||
private static $buttonConfigCsv = [
|
||||
'extend' => 'collection',
|
||||
'text' => 'CSV',
|
||||
'collectionTitle' => 'CSV-Export',
|
||||
'autoClose' => true,
|
||||
'buttons' => [
|
||||
[
|
||||
'text' => 'Alle Seiten',
|
||||
'action' => 'export-csv-all',
|
||||
],
|
||||
[
|
||||
'text' => 'Aktuelle Seite',
|
||||
'action' => 'export-csv-page',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/** @var array $buttonConfigExcel */
|
||||
private static $buttonConfigExcel = [
|
||||
'extend' => 'excel',
|
||||
'text' => 'Excel',
|
||||
];
|
||||
|
||||
/** @var array $buttonConfigPdf */
|
||||
private static $buttonConfigPdf = [
|
||||
'extend' => 'pdf',
|
||||
'text' => 'PDF',
|
||||
'orientation' => 'landscape',
|
||||
'pageSize' => 'A4',
|
||||
];
|
||||
|
||||
/** @var array $buttonConfigPrint */
|
||||
private static $buttonConfigPrint = [
|
||||
'extend' => 'print',
|
||||
'text' => 'Drucken',
|
||||
];
|
||||
|
||||
/** @var bool $info */
|
||||
private $info = true;
|
||||
|
||||
/** @var bool $paging */
|
||||
private $paging = true;
|
||||
|
||||
/** @var bool $searching */
|
||||
private $searching = true;
|
||||
|
||||
/** @var bool $lengthChange */
|
||||
private $lengthChange = true;
|
||||
|
||||
/** @var int|null $pageLength */
|
||||
private $pageLength;
|
||||
|
||||
/** @var bool $processing */
|
||||
private $processing = true;
|
||||
|
||||
/** @var bool $sorting */
|
||||
private $sorting = true;
|
||||
|
||||
/** @var array $buttons */
|
||||
private $buttons = [];
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->setFullMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
$table->getOptions()->setOption('info', $this->info);
|
||||
$table->getOptions()->setOption('paging', $this->paging);
|
||||
$table->getOptions()->setOption('buttons', $this->buttons);
|
||||
$table->getOptions()->setOption('searching', $this->searching);
|
||||
$table->getOptions()->setOption('lengthChange', $this->lengthChange);
|
||||
$table->getOptions()->setOption('processing', $this->processing);
|
||||
$table->getOptions()->setOption('ordering', $this->sorting);
|
||||
if ($this->pageLength !== null && $this->pageLength > 0) {
|
||||
$table->getOptions()->setOption('pageLength', $this->pageLength);
|
||||
$table->getOptions()->setOption('lengthChange', false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setFullMode()
|
||||
{
|
||||
$this->showInfo();
|
||||
$this->showButtons();
|
||||
$this->showLengthChange();
|
||||
$this->enableSearching();
|
||||
$this->enableSorting();
|
||||
$this->enablePaging();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setMinimalMode()
|
||||
{
|
||||
$this->showInfo();
|
||||
$this->enablePaging();
|
||||
$this->enableSorting();
|
||||
|
||||
$this->hideButtons();
|
||||
$this->hideLengthChange();
|
||||
$this->disableSearching();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function showInfo()
|
||||
{
|
||||
$this->info = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function hideInfo()
|
||||
{
|
||||
$this->info = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function showButtons()
|
||||
{
|
||||
$this->buttons = [
|
||||
'buttons' => [
|
||||
self::$buttonConfigCopy,
|
||||
self::$buttonConfigCsv,
|
||||
self::$buttonConfigExcel,
|
||||
self::$buttonConfigPdf,
|
||||
self::$buttonConfigPrint,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function hideButtons()
|
||||
{
|
||||
$this->buttons = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function showLengthChange()
|
||||
{
|
||||
$this->lengthChange = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function hideLengthChange()
|
||||
{
|
||||
$this->lengthChange = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $rowsPerPage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPageLength($rowsPerPage)
|
||||
{
|
||||
$this->pageLength = (int)$rowsPerPage;
|
||||
$this->hideLengthChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function showProcessingIndicator()
|
||||
{
|
||||
$this->processing = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function hideProcessingIndicator()
|
||||
{
|
||||
$this->processing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enableSearching()
|
||||
{
|
||||
// @todo ColumnFilter aktivieren
|
||||
$this->searching = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disableSearching()
|
||||
{
|
||||
// @todo ColumnFilter deaktivieren
|
||||
$this->searching = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enableSorting()
|
||||
{
|
||||
$this->sorting = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disableSorting()
|
||||
{
|
||||
$this->sorting = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enablePaging()
|
||||
{
|
||||
$this->paging = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disablePaging()
|
||||
{
|
||||
$this->paging = false;
|
||||
$this->lengthChange = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Widgets\DataTable\Feature;
|
||||
|
||||
use Xentral\Widgets\DataTable\DataTableInterface;
|
||||
|
||||
final class TableStylingFeature implements DataTableFeatureInterface
|
||||
{
|
||||
/** @var array $cssClasses */
|
||||
private $cssClasses = [];
|
||||
|
||||
/**
|
||||
* @param bool $compact
|
||||
* @param bool $disableLineWrapping
|
||||
*/
|
||||
public function __construct($compact = false, $disableLineWrapping = false)
|
||||
{
|
||||
$this->setDefaultStyle();
|
||||
if ($compact === true) {
|
||||
$this->setCompactStyle();
|
||||
}
|
||||
if ($disableLineWrapping === true) {
|
||||
$this->disableLineWrapping();
|
||||
} else {
|
||||
$this->enableLineWrapping();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataTableInterface $table
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function modifyTable(DataTableInterface $table)
|
||||
{
|
||||
foreach ($this->cssClasses as $cssClass) {
|
||||
$table->getConfig()->addCssClass($cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* display: Short-hand for stripe, hover, row-border and order-column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultStyle()
|
||||
{
|
||||
$this->removeCssClass('display');
|
||||
$this->removeCssClass('compact');
|
||||
$this->removeCssClass('order-column');
|
||||
|
||||
$this->enableHover();
|
||||
$this->disableRowBorder();
|
||||
$this->disableStripes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setCompactStyle()
|
||||
{
|
||||
$this->addCssClass('compact');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enableLineWrapping()
|
||||
{
|
||||
$this->removeCssClass('nowrap');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disableLineWrapping()
|
||||
{
|
||||
$this->addCssClass('nowrap');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enableHover()
|
||||
{
|
||||
$this->addCssClass('hover');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disableHover()
|
||||
{
|
||||
$this->removeCssClass('hover');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enableStripes()
|
||||
{
|
||||
$this->addCssClass('stripe');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disableStripes()
|
||||
{
|
||||
$this->removeCssClass('stripe');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function enableRowBorder()
|
||||
{
|
||||
$this->addCssClass('row-border');
|
||||
$this->removeCssClass('cell-border');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disableRowBorder()
|
||||
{
|
||||
$this->removeCssClass('row-border');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function hasCssClass($className)
|
||||
{
|
||||
return in_array($className, $this->cssClasses, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function addCssClass($className)
|
||||
{
|
||||
$this->cssClasses[] = trim($className);
|
||||
$this->cssClasses = array_unique($this->cssClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeCssClass($className)
|
||||
{
|
||||
$classKey = array_search($className, $this->cssClasses, true);
|
||||
if ($classKey !== false) {
|
||||
unset($this->cssClasses[$classKey]);
|
||||
$this->cssClasses = array_values($this->cssClasses);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user