'icinga-form inline sort-control'];
/** @var string Name of the URL parameter which stores the sort column */
protected $sortParam = self::DEFAULT_SORT_PARAM;
/** @var Url Request URL */
protected $url;
/** @var array Possible sort columns as sort string-value pairs */
private $columns;
/** @var string Default sort string */
private $default;
protected $method = 'GET';
/**
* Create a new sort control
*
* @param Url $url Request URL
*/
public function __construct(Url $url)
{
$this->url = $url;
}
/**
* Create a new sort control with the given options
*
* @param array $options A sort spec to label map
*
* @return static
*/
public static function create(array $options)
{
$normalized = [];
foreach ($options as $spec => $label) {
$normalized[SortUtil::normalizeSortSpec($spec)] = $label;
}
return (new static(Url::fromRequest()))
->setColumns($normalized);
}
/**
* Get the possible sort columns
*
* @return array Sort string-value pairs
*/
public function getColumns()
{
return $this->columns;
}
/**
* Set the possible sort columns
*
* @param array $columns Sort string-value pairs
*
* @return $this
*/
public function setColumns(array $columns)
{
// We're working with lowercase keys throughout the sort control
$this->columns = array_change_key_case($columns, CASE_LOWER);
return $this;
}
/**
* Get the default sort string
*
* @return string
*/
public function getDefault()
{
return $this->default;
}
/**
* Set the default sort string
*
* @param array|string $default
*
* @return $this
*/
public function setDefault($default)
{
// We're working with lowercase keys throughout the sort control
$this->default = strtolower($default);
return $this;
}
/**
* Get the name of the URL parameter which stores the sort
*
* @return string
*/
public function getSortParam()
{
return $this->sortParam;
}
/**
* Set the name of the URL parameter which stores the sort
*
* @param string $sortParam
*
* @return $this
*/
public function setSortParam($sortParam)
{
$this->sortParam = $sortParam;
return $this;
}
/**
* Get the sort string
*
* @return string|null
*/
public function getSort()
{
$sort = $this->url->getParam($this->getSortParam(), $this->getDefault());
if (! empty($sort)) {
$columns = $this->getColumns();
if (! isset($columns[$sort])) {
// Choose sort string based on the first closest match
foreach (array_keys($columns) as $key) {
if (Str::startsWith($key, $sort)) {
$sort = $key;
break;
}
}
}
}
return $sort;
}
/**
* Sort the given query according to the request
*
* @param Query $query
*
* @return $this
*/
public function apply(Query $query)
{
$default = (array) $query->getModel()->getDefaultSort();
if (! empty($default)) {
$this->setDefault(SortUtil::normalizeSortSpec($default));
}
$sort = $this->getSort();
if (! empty($sort)) {
$query->orderBy(SortUtil::createOrderBy($sort));
}
return $this;
}
protected function assemble()
{
$columns = $this->getColumns();
$sort = $this->getSort();
if (empty($sort)) {
reset($columns);
$sort = key($columns);
}
$sort = explode(',', $sort, 2);
list($column, $direction) = Str::symmetricSplit(array_shift($sort), ' ', 2);
if (! $direction || strtolower($direction) === 'asc') {
$toggleIcon = 'sort-alpha-down';
$toggleDirection = 'desc';
} else {
$toggleIcon = 'sort-alpha-down-alt';
$toggleDirection = 'asc';
}
if ($direction !== null) {
$value = implode(',', array_merge(["{$column} {$direction}"], $sort));
if (! isset($columns[$value])) {
foreach ([$column, "{$column} {$toggleDirection}"] as $key) {
$key = implode(',', array_merge([$key], $sort));
if (isset($columns[$key])) {
$columns[$value] = $columns[$key];
unset($columns[$key]);
break;
}
}
}
} else {
$value = implode(',', array_merge([$column], $sort));
}
if (! isset($columns[$value])) {
$columns[$value] = 'Custom';
}
$this->addElement('select', $this->getSortParam(), [
'class' => 'autosubmit',
'label' => 'Sort By',
'options' => $columns,
'value' => $value
])
->getElement($this->getSortParam())
->getWrapper()
->getAttributes()
->add('class', 'icinga-controls');
$toggleButton = new ButtonElement($this->getSortParam(), [
'class' => 'control-button spinner',
'title' => t('Change sort direction'),
'type' => 'submit',
'value' => implode(',', array_merge(["{$column} {$toggleDirection}"], $sort))
]);
$toggleButton->add(new Icon($toggleIcon));
$this->addElement($toggleButton);
}
}