summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Web/Controller.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/Icinga/Web/Controller.php')
-rw-r--r--library/Icinga/Web/Controller.php264
1 files changed, 264 insertions, 0 deletions
diff --git a/library/Icinga/Web/Controller.php b/library/Icinga/Web/Controller.php
new file mode 100644
index 0000000..008fbf6
--- /dev/null
+++ b/library/Icinga/Web/Controller.php
@@ -0,0 +1,264 @@
+<?php
+/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Web;
+
+use Icinga\Data\Filterable;
+use Icinga\Data\Sortable;
+use Icinga\Data\QueryInterface;
+use Icinga\Exception\Http\HttpBadRequestException;
+use Icinga\Exception\Http\HttpNotFoundException;
+use Icinga\Web\Controller\ModuleActionController;
+use Icinga\Web\Widget\Limiter;
+use Icinga\Web\Widget\Paginator;
+use Icinga\Web\Widget\SortBox;
+
+/**
+ * This is the controller all modules should inherit from
+ * We will flip code with the ModuleActionController as soon as a couple
+ * of pending feature branches are merged back to the master.
+ *
+ * @property View $view
+ */
+class Controller extends ModuleActionController
+{
+ /**
+ * Cache for page size configured via user preferences
+ *
+ * @var false|int
+ */
+ protected $userPageSize;
+
+ /**
+ * @see ActionController::init
+ */
+ public function init()
+ {
+ parent::init();
+ $this->handleSortControlSubmit();
+ }
+
+ /**
+ * Check whether the sort control has been submitted and redirect using GET parameters
+ */
+ protected function handleSortControlSubmit()
+ {
+ $request = $this->getRequest();
+ if (! $request->isPost()) {
+ return;
+ }
+
+ if (($sort = $request->getPost('sort')) || ($direction = $request->getPost('dir'))) {
+ $url = Url::fromRequest();
+ if ($sort) {
+ $url->setParam('sort', $sort);
+ $url->remove('dir');
+ } else {
+ $url->setParam('dir', $direction);
+ }
+
+ $this->redirectNow($url);
+ }
+ }
+
+ /**
+ * Immediately respond w/ HTTP 400
+ *
+ * @param string $message Exception message or exception format string
+ * @param mixed ...$arg Format string argument
+ *
+ * @throws HttpBadRequestException
+ */
+ public function httpBadRequest($message)
+ {
+ throw HttpBadRequestException::create(func_get_args());
+ }
+
+ /**
+ * Immediately respond w/ HTTP 404
+ *
+ * @param string $message Exception message or exception format string
+ * @param mixed ...$arg Format string argument
+ *
+ * @throws HttpNotFoundException
+ */
+ public function httpNotFound($message)
+ {
+ throw HttpNotFoundException::create(func_get_args());
+ }
+
+ /**
+ * Render the given form using a simple view script
+ *
+ * @param Form $form
+ * @param string $tab
+ */
+ public function renderForm(Form $form, $tab)
+ {
+ $this->getTabs()->add(uniqid(), array(
+ 'active' => true,
+ 'label' => $tab,
+ 'url' => Url::fromRequest()
+ ));
+ $this->view->form = $form;
+ $this->render('simple-form', null, true);
+ }
+
+ /**
+ * Create a SortBox widget and apply its sort rules on the given query
+ *
+ * The widget is set on the `sortBox' view property only if the current view has not been requested as compact
+ *
+ * @param array $columns An array containing the sort columns, with the
+ * submit value as the key and the label as the value
+ * @param Sortable $query Query to apply the user chosen sort rules on
+ * @param array $defaults An array containing default sort directions for specific columns
+ *
+ * @return $this
+ */
+ protected function setupSortControl(array $columns, Sortable $query = null, array $defaults = null)
+ {
+ $request = $this->getRequest();
+ $sortBox = SortBox::create('sortbox-' . $request->getActionName(), $columns, $defaults);
+ $sortBox->setRequest($request);
+
+ if ($query) {
+ $sortBox->setQuery($query);
+ $sortBox->handleRequest($request);
+ }
+
+ if (! $this->view->compact) {
+ $this->view->sortBox = $sortBox;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Create a Limiter widget at the `limiter' view property
+ *
+ * In case the current view has been requested as compact this method does nothing.
+ *
+ * @param int $itemsPerPage Default number of items per page
+ *
+ * @return $this
+ */
+ protected function setupLimitControl($itemsPerPage = 25)
+ {
+ if (! $this->view->compact) {
+ $this->view->limiter = new Limiter();
+ $this->view->limiter->setDefaultLimit($this->getPageSize($itemsPerPage));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the page size configured via user preferences or return the default value
+ *
+ * @param ?int $default
+ *
+ * @return int
+ */
+ protected function getPageSize($default)
+ {
+ if ($this->userPageSize === null) {
+ $user = $this->Auth()->getUser();
+ if ($user !== null) {
+ $pageSize = $user->getPreferences()->getValue('icingaweb', 'default_page_size');
+ $this->userPageSize = $pageSize ? (int) $pageSize : false;
+ } else {
+ $this->userPageSize = false;
+ }
+ }
+
+ return $this->userPageSize !== false ? $this->userPageSize : $default;
+ }
+
+ /**
+ * Apply the given page limit and number on the given query and setup a paginator for it
+ *
+ * The $itemsPerPage and $pageNumber parameters are only applied if not available in the current request.
+ * The paginator is set on the `paginator' view property only if the current view has not been requested as compact.
+ *
+ * @param QueryInterface $query The query to create a paginator for
+ * @param int $itemsPerPage Default number of items per page
+ * @param int $pageNumber Default page number
+ *
+ * @return $this
+ */
+ protected function setupPaginationControl(QueryInterface $query, $itemsPerPage = 25, $pageNumber = 0)
+ {
+ $request = $this->getRequest();
+ $limit = $request->getParam('limit', $this->getPageSize($itemsPerPage));
+ $page = $request->getParam('page', $pageNumber);
+ $query->limit($limit, $page > 0 ? ($page - 1) * $limit : 0);
+
+ if (! $this->view->compact) {
+ $paginator = new Paginator();
+ $paginator->setQuery($query);
+ $this->view->paginator = $paginator;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Create a FilterEditor widget and apply the user's chosen filter options on the given filterable
+ *
+ * The widget is set on the `filterEditor' view property only if the current view has not been requested as compact.
+ * The optional $filterColumns parameter should be an array of key-value pairs where the key is the name of the
+ * column and the value the label to show to the user. The optional $searchColumns parameter should be an array
+ * of column names to be used to handle quick searches.
+ *
+ * If the given filterable is an instance of Icinga\Data\FilterColumns, $filterable->getFilterColumns() and
+ * $filterable->getSearchColumns() is called to provide the respective columns if $filterColumns or $searchColumns
+ * is not given.
+ *
+ * @param Filterable $filterable The filterable to create a filter editor for
+ * @param array $filterColumns The filter columns to offer to the user
+ * @param array $searchColumns The search columns to utilize for quick searches
+ * @param array $preserveParams The url parameters to preserve
+ *
+ * @return $this
+ *
+ * @todo Preserving and ignoring parameters should be configurable (another two method params? property magic?)
+ */
+ protected function setupFilterControl(
+ Filterable $filterable,
+ array $filterColumns = null,
+ array $searchColumns = null,
+ array $preserveParams = null
+ ) {
+ $defaultPreservedParams = array(
+ 'limit', // setupPaginationControl()
+ 'sort', // setupSortControl()
+ 'dir', // setupSortControl()
+ 'backend', // Framework
+ 'showCompact', // Framework
+ '_dev' // Framework
+ );
+
+ $editor = Widget::create('filterEditor');
+ /** @var \Icinga\Web\Widget\FilterEditor $editor */
+ call_user_func_array(
+ array($editor, 'preserveParams'),
+ array_merge($defaultPreservedParams, $preserveParams ?: array())
+ );
+
+ $editor
+ ->setQuery($filterable)
+ ->ignoreParams('page') // setupPaginationControl()
+ ->setColumns($filterColumns)
+ ->setSearchColumns($searchColumns)
+ ->handleRequest($this->getRequest());
+
+ if ($this->view->compact) {
+ $editor->setVisible(false);
+ }
+
+ $this->view->filterEditor = $editor;
+
+ return $this;
+ }
+}