'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); } }