diff options
Diffstat (limited to 'library/Icinga/Web/Controller.php')
-rw-r--r-- | library/Icinga/Web/Controller.php | 264 |
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..a2730d5 --- /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; + } +} |