summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Web/Widget/SortBox.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/Icinga/Web/Widget/SortBox.php')
-rw-r--r--library/Icinga/Web/Widget/SortBox.php260
1 files changed, 260 insertions, 0 deletions
diff --git a/library/Icinga/Web/Widget/SortBox.php b/library/Icinga/Web/Widget/SortBox.php
new file mode 100644
index 0000000..72b6f58
--- /dev/null
+++ b/library/Icinga/Web/Widget/SortBox.php
@@ -0,0 +1,260 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Web\Widget;
+
+use Icinga\Application\Icinga;
+use Icinga\Data\Sortable;
+use Icinga\Data\SortRules;
+use Icinga\Web\Form;
+use Icinga\Web\Request;
+
+/**
+ * SortBox widget
+ *
+ * The "SortBox" Widget allows you to create a generic sort input for sortable views. It automatically creates a select
+ * box with all sort options and a dropbox with the sort direction. It also handles automatic submission of sorting
+ * changes and draws an additional submit button when JavaScript is disabled.
+ *
+ * The constructor takes a string for the component name and an array containing the select options, where the key is
+ * the value to be submitted and the value is the label that will be shown. You then should call setRequest in order
+ * to make sure the form is correctly populated when a request with a sort parameter is being made.
+ *
+ * Call setQuery in case you'll do not want to handle URL parameters manually, but to automatically apply the user's
+ * chosen sort rules on the given sortable query. This will also allow the SortBox to display the user the correct
+ * default sort rules if the given query provides already some sort rules.
+ */
+class SortBox extends AbstractWidget
+{
+ /**
+ * An array containing all sort columns with their associated labels
+ *
+ * @var array
+ */
+ protected $sortFields;
+
+ /**
+ * An array containing default sort directions for specific columns
+ *
+ * The first entry will be used as default sort column.
+ *
+ * @var array
+ */
+ protected $sortDefaults;
+
+ /**
+ * The name used to uniquely identfy the forms being created
+ *
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * The request to fetch sort rules from
+ *
+ * @var Request
+ */
+ protected $request;
+
+ /**
+ * The query to apply sort rules on
+ *
+ * @var Sortable
+ */
+ protected $query;
+
+ /**
+ * Create a SortBox with the entries from $sortFields
+ *
+ * @param string $name The name for the SortBox
+ * @param array $sortFields An array containing the columns and their labels to be displayed in the SortBox
+ * @param array $sortDefaults An array containing default sort directions for specific columns
+ */
+ public function __construct($name, array $sortFields, array $sortDefaults = null)
+ {
+ $this->name = $name;
+ $this->sortFields = $sortFields;
+ $this->sortDefaults = $sortDefaults;
+ }
+
+ /**
+ * Create a SortBox
+ *
+ * @param string $name The name for the SortBox
+ * @param array $sortFields An array containing the columns and their labels to be displayed in the SortBox
+ * @param array $sortDefaults An array containing default sort directions for specific columns
+ *
+ * @return SortBox
+ */
+ public static function create($name, array $sortFields, array $sortDefaults = null)
+ {
+ return new static($name, $sortFields, $sortDefaults);
+ }
+
+ /**
+ * Set the request to fetch sort rules from
+ *
+ * @param Request $request
+ *
+ * @return $this
+ */
+ public function setRequest($request)
+ {
+ $this->request = $request;
+ return $this;
+ }
+
+ /**
+ * Set the query to apply sort rules on
+ *
+ * @param Sortable $query
+ *
+ * @return $this
+ */
+ public function setQuery(Sortable $query)
+ {
+ $this->query = $query;
+ return $this;
+ }
+
+ /**
+ * Return the default sort rule for the query
+ *
+ * @param string $column An optional column
+ *
+ * @return array An array of two values: $column, $direction
+ */
+ protected function getSortDefaults($column = null)
+ {
+ $direction = null;
+ if (! empty($this->sortDefaults) && ($column === null || isset($this->sortDefaults[$column]))) {
+ if ($column === null) {
+ reset($this->sortDefaults);
+ $column = key($this->sortDefaults);
+ }
+
+ $direction = $this->sortDefaults[$column];
+ } elseif ($this->query !== null && $this->query instanceof SortRules) {
+ $sortRules = $this->query->getSortRules();
+ if ($column === null) {
+ $column = key($sortRules);
+ }
+
+ if ($column !== null && isset($sortRules[$column]['order'])) {
+ $direction = strtoupper($sortRules[$column]['order']) === Sortable::SORT_DESC ? 'desc' : 'asc';
+ }
+ } elseif ($column === null) {
+ reset($this->sortFields);
+ $column = key($this->sortFields);
+ }
+
+ return array($column, $direction);
+ }
+
+ /**
+ * Apply the sort rules from the given or current request on the query
+ *
+ * @param Request $request
+ *
+ * @return $this
+ */
+ public function handleRequest(Request $request = null)
+ {
+ if ($this->query !== null) {
+ if ($request === null) {
+ $request = Icinga::app()->getRequest();
+ }
+
+ if (! ($sort = $request->getParam('sort'))) {
+ list($sort, $dir) = $this->getSortDefaults();
+ } else {
+ list($_, $dir) = $this->getSortDefaults($sort);
+ }
+
+ $this->query->order($sort, $request->getParam('dir', $dir));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Render this SortBox as HTML
+ *
+ * @return string
+ */
+ public function render()
+ {
+ $columnForm = new Form();
+ $columnForm->setTokenDisabled();
+ $columnForm->setName($this->name . '-column');
+ $columnForm->setAttrib('class', 'icinga-controls inline');
+ $columnForm->addElement(
+ 'select',
+ 'sort',
+ array(
+ 'autosubmit' => true,
+ 'label' => $this->view()->translate('Sort by'),
+ 'multiOptions' => $this->sortFields,
+ 'decorators' => array(
+ array('ViewHelper'),
+ array('Label')
+ )
+ )
+ );
+
+ $column = null;
+ if ($this->request) {
+ $url = $this->request->getUrl();
+ if ($url->hasParam('sort')) {
+ $column = $url->getParam('sort');
+
+ if ($url->hasParam('dir')) {
+ $direction = $url->getParam('dir');
+ } else {
+ list($_, $direction) = $this->getSortDefaults($column);
+ }
+ } elseif ($url->hasParam('dir')) {
+ $direction = $url->getParam('dir');
+ list($column, $_) = $this->getSortDefaults();
+ }
+ }
+
+ if ($column === null) {
+ list($column, $direction) = $this->getSortDefaults();
+ }
+
+ // TODO(el): ToggleButton :)
+ $toggle = array('asc' => 'sort-name-down', 'desc' => 'sort-name-up');
+ unset($toggle[isset($direction) ? strtolower($direction) : 'asc']);
+ $newDirection = key($toggle);
+ $icon = current($toggle);
+
+ $orderForm = new Form();
+ $orderForm->setTokenDisabled();
+ $orderForm->setName($this->name . '-order');
+ $orderForm->setAttrib('class', 'inline sort-direction-control');
+ $orderForm->addElement(
+ 'hidden',
+ 'dir'
+ );
+ $orderForm->addElement(
+ 'button',
+ 'btn_submit',
+ array(
+ 'ignore' => true,
+ 'type' => 'submit',
+ 'label' => $this->view()->icon($icon),
+ 'decorators' => array('ViewHelper'),
+ 'escape' => false,
+ 'class' => 'link-button spinner',
+ 'value' => 'submit',
+ 'title' => t('Change sort direction'),
+ )
+ );
+
+
+ $columnForm->populate(array('sort' => $column));
+ $orderForm->populate(array('dir' => $newDirection));
+ return '<div class="sort-control">' . $columnForm . $orderForm . '</div>';
+ }
+}