2015-09-07 13:55:19 +02:00
|
|
|
<?php
|
|
|
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
|
|
|
|
|
|
|
namespace Icinga\Controllers;
|
|
|
|
|
2015-09-07 15:43:06 +02:00
|
|
|
use Exception;
|
2015-09-07 15:01:55 +02:00
|
|
|
use Icinga\Application\Config;
|
2015-09-16 15:05:43 +02:00
|
|
|
use Icinga\Application\Icinga;
|
2015-09-29 17:12:57 +02:00
|
|
|
use Icinga\Exception\IcingaException;
|
2015-09-07 15:21:21 +02:00
|
|
|
use Icinga\Exception\NotFoundError;
|
2015-09-18 08:53:05 +02:00
|
|
|
use Icinga\Data\DataArray\ArrayDatasource;
|
2015-09-07 16:02:12 +02:00
|
|
|
use Icinga\Forms\ConfirmRemovalForm;
|
2015-09-07 15:43:06 +02:00
|
|
|
use Icinga\Forms\Navigation\NavigationConfigForm;
|
2015-09-07 13:55:19 +02:00
|
|
|
use Icinga\Web\Controller;
|
2015-09-07 15:04:31 +02:00
|
|
|
use Icinga\Web\Form;
|
2015-09-07 16:02:12 +02:00
|
|
|
use Icinga\Web\Notification;
|
2015-09-07 15:04:31 +02:00
|
|
|
use Icinga\Web\Url;
|
2015-09-07 13:55:19 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Navigation configuration
|
|
|
|
*/
|
|
|
|
class NavigationController extends Controller
|
|
|
|
{
|
2015-09-16 15:05:43 +02:00
|
|
|
/**
|
|
|
|
* The default item types provided by Icinga Web 2
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $defaultItemTypes;
|
|
|
|
|
2015-09-29 17:12:57 +02:00
|
|
|
/**
|
|
|
|
* The item types provided by Icinga Web 2's modules
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $moduleItemTypes;
|
|
|
|
|
2015-09-16 15:05:43 +02:00
|
|
|
/**
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
|
|
|
public function init()
|
|
|
|
{
|
|
|
|
parent::init();
|
|
|
|
$this->defaultItemTypes = array(
|
2015-09-29 17:12:57 +02:00
|
|
|
'menu-item' => array(
|
|
|
|
'label' => $this->translate('Menu Entry'),
|
|
|
|
'config' => 'menu'
|
|
|
|
),
|
|
|
|
'dashlet' => array(
|
|
|
|
'label' => 'Dashlet',
|
|
|
|
'config' => 'dashboard'
|
|
|
|
)
|
2015-09-16 15:05:43 +02:00
|
|
|
);
|
2015-09-29 17:12:57 +02:00
|
|
|
|
|
|
|
$moduleItemTypes = array();
|
|
|
|
$moduleManager = Icinga::app()->getModuleManager();
|
|
|
|
foreach ($moduleManager->getLoadedModules() as $module) {
|
|
|
|
if ($this->hasPermission($moduleManager::MODULE_PERMISSION_NS . $module->getName())) {
|
|
|
|
foreach ($module->getNavigationItems() as $type => $options) {
|
|
|
|
if (! isset($moduleItemTypes[$type])) {
|
|
|
|
$moduleItemTypes[$type] = $options;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->moduleItemTypes = $moduleItemTypes;
|
2015-09-16 15:05:43 +02:00
|
|
|
}
|
|
|
|
|
2015-09-29 17:09:32 +02:00
|
|
|
/**
|
|
|
|
* Return the label for the given navigation item type
|
|
|
|
*
|
|
|
|
* @param string $type
|
|
|
|
*
|
|
|
|
* @return string It's $type if no label can be found
|
|
|
|
*/
|
|
|
|
protected function getItemLabel($type)
|
|
|
|
{
|
|
|
|
if (isset($this->moduleItemTypes[$type]['label'])) {
|
|
|
|
return $this->moduleItemTypes[$type]['label'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($this->defaultItemTypes[$type]['label'])) {
|
|
|
|
return $this->defaultItemTypes[$type]['label'];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $type;
|
|
|
|
}
|
|
|
|
|
2015-09-16 15:05:43 +02:00
|
|
|
/**
|
|
|
|
* Return a list of available navigation item types
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
protected function listItemTypes()
|
|
|
|
{
|
2015-09-29 17:12:57 +02:00
|
|
|
$types = array();
|
|
|
|
foreach ($this->defaultItemTypes as $type => $options) {
|
|
|
|
$types[$type] = isset($options['label']) ? $options['label'] : $type;
|
|
|
|
}
|
2015-09-21 08:59:36 +02:00
|
|
|
|
2015-09-29 17:12:57 +02:00
|
|
|
foreach ($this->moduleItemTypes as $type => $options) {
|
|
|
|
$types[$type] = isset($options['label']) ? $options['label'] : $type;
|
2015-09-16 15:05:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $types;
|
|
|
|
}
|
|
|
|
|
2015-09-07 13:55:19 +02:00
|
|
|
/**
|
2015-09-29 17:08:53 +02:00
|
|
|
* Return the path to the configuration file for the given navigation item type and user
|
|
|
|
*
|
|
|
|
* @param string $type
|
|
|
|
* @param string $username
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*
|
|
|
|
* @throws IcingaException In case the given type is unknown
|
|
|
|
*/
|
|
|
|
protected function getConfigPath($type, $username = null)
|
|
|
|
{
|
|
|
|
if (isset($this->defaultItemTypes[$type])) {
|
|
|
|
$options = $this->defaultItemTypes[$type];
|
|
|
|
} elseif (isset($this->moduleItemTypes[$type])) {
|
|
|
|
$options = $this->moduleItemTypes[$type];
|
|
|
|
} else {
|
|
|
|
throw new IcingaException('Invalid navigation item type %s provided', $type);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($options['config'])) {
|
|
|
|
$filename = $options['config'] . '.ini';
|
|
|
|
} else {
|
|
|
|
$filename = $type . 's.ini';
|
|
|
|
}
|
|
|
|
|
|
|
|
return Config::resolvePath(($username ? "preferences/$username/" : 'navigation/') . $filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-09-07 13:55:19 +02:00
|
|
|
* Show the current user a list of his/her navigation items
|
|
|
|
*/
|
|
|
|
public function indexAction()
|
|
|
|
{
|
2015-09-07 15:01:55 +02:00
|
|
|
$user = $this->Auth()->getUser();
|
2015-09-18 08:53:05 +02:00
|
|
|
|
|
|
|
$ds = new ArrayDatasource(array_merge(
|
|
|
|
Config::app('navigation')->select()->where('owner', $user->getUsername())->fetchAll(),
|
|
|
|
iterator_to_array($user->loadNavigationConfig())
|
|
|
|
));
|
|
|
|
$ds->setKeyColumn('name');
|
|
|
|
$query = $ds->select();
|
2015-09-07 15:01:55 +02:00
|
|
|
|
2015-09-16 15:09:56 +02:00
|
|
|
$this->view->types = $this->listItemTypes();
|
2015-09-18 08:53:05 +02:00
|
|
|
$this->view->items = $query;
|
2015-09-07 15:01:55 +02:00
|
|
|
|
|
|
|
$this->getTabs()->add(
|
|
|
|
'navigation',
|
|
|
|
array(
|
|
|
|
'title' => $this->translate('List and configure your own navigation items'),
|
|
|
|
'label' => $this->translate('Navigation'),
|
|
|
|
'url' => 'navigation'
|
|
|
|
)
|
|
|
|
)->activate('navigation');
|
2015-09-18 08:53:05 +02:00
|
|
|
$this->setupSortControl(
|
|
|
|
array(
|
2015-09-18 08:58:57 +02:00
|
|
|
'type' => $this->translate('Type'),
|
2015-09-18 15:51:00 +02:00
|
|
|
'owner' => $this->translate('Shared'),
|
2015-09-18 08:58:57 +02:00
|
|
|
'name' => $this->translate('Shared Navigation')
|
2015-09-18 08:53:05 +02:00
|
|
|
),
|
|
|
|
$query
|
|
|
|
);
|
2015-09-07 13:55:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* List all shared navigation items
|
|
|
|
*/
|
|
|
|
public function sharedAction()
|
|
|
|
{
|
|
|
|
$this->assertPermission('config/application/navigation');
|
2015-09-17 15:17:46 +02:00
|
|
|
$config = Config::app('navigation');
|
|
|
|
$config->getConfigObject()->setKeyColumn('name');
|
|
|
|
$query = $config->select();
|
2015-09-07 15:04:31 +02:00
|
|
|
|
|
|
|
$removeForm = new Form();
|
|
|
|
$removeForm->setUidDisabled();
|
|
|
|
$removeForm->setAction(Url::fromPath('navigation/unshare'));
|
|
|
|
$removeForm->addElement('hidden', 'name', array(
|
|
|
|
'decorators' => array('ViewHelper')
|
|
|
|
));
|
|
|
|
$removeForm->addElement('hidden', 'redirect', array(
|
|
|
|
'value' => Url::fromPath('navigation/shared'),
|
|
|
|
'decorators' => array('ViewHelper')
|
|
|
|
));
|
|
|
|
$removeForm->addElement('button', 'btn_submit', array(
|
|
|
|
'escape' => false,
|
|
|
|
'type' => 'submit',
|
|
|
|
'class' => 'link-like spinner',
|
|
|
|
'value' => 'btn_submit',
|
|
|
|
'decorators' => array('ViewHelper'),
|
|
|
|
'label' => $this->view->icon('trash'),
|
|
|
|
'title' => $this->translate('Unshare this navigation item')
|
|
|
|
));
|
2015-09-17 15:17:46 +02:00
|
|
|
|
2015-09-07 15:04:31 +02:00
|
|
|
$this->view->removeForm = $removeForm;
|
2015-09-17 15:17:46 +02:00
|
|
|
$this->view->types = $this->listItemTypes();
|
|
|
|
$this->view->items = $query;
|
2015-09-07 15:04:31 +02:00
|
|
|
|
|
|
|
$this->getTabs()->add(
|
|
|
|
'navigation/shared',
|
|
|
|
array(
|
|
|
|
'title' => $this->translate('List and configure shared navigation items'),
|
|
|
|
'label' => $this->translate('Shared Navigation'),
|
|
|
|
'url' => 'navigation/shared'
|
|
|
|
)
|
|
|
|
)->activate('navigation/shared');
|
2015-09-17 15:17:46 +02:00
|
|
|
$this->setupSortControl(
|
|
|
|
array(
|
|
|
|
'type' => $this->translate('Type'),
|
2015-09-18 08:58:57 +02:00
|
|
|
'owner' => $this->translate('Owner'),
|
|
|
|
'name' => $this->translate('Shared Navigation')
|
2015-09-17 15:17:46 +02:00
|
|
|
),
|
|
|
|
$query
|
|
|
|
);
|
2015-09-07 13:55:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a navigation item
|
|
|
|
*/
|
|
|
|
public function addAction()
|
|
|
|
{
|
2015-09-07 15:50:26 +02:00
|
|
|
$form = new NavigationConfigForm();
|
|
|
|
$form->setRedirectUrl('navigation');
|
|
|
|
$form->setTitle($this->translate('Create New Navigation Item'));
|
2015-09-29 17:12:57 +02:00
|
|
|
$form->setItemTypes(array_merge($this->defaultItemTypes, $this->moduleItemTypes));
|
2015-09-07 15:50:26 +02:00
|
|
|
$form->addDescription($this->translate('Create a new navigation item, such as a menu entry or dashlet.'));
|
2015-09-15 15:57:03 +02:00
|
|
|
$form->setUser($this->Auth()->getUser());
|
|
|
|
$form->setShareConfig(Config::app('navigation'));
|
2015-09-07 15:50:26 +02:00
|
|
|
$form->setOnSuccess(function (NavigationConfigForm $form) {
|
2015-09-24 14:05:28 +02:00
|
|
|
$data = array_filter($form->getValues());
|
|
|
|
|
2015-09-07 15:50:26 +02:00
|
|
|
try {
|
2015-09-24 14:05:28 +02:00
|
|
|
$form->add($data);
|
2015-09-07 15:50:26 +02:00
|
|
|
} catch (Exception $e) {
|
|
|
|
$form->error($e->getMessage());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($form->save()) {
|
2015-09-24 14:05:28 +02:00
|
|
|
if (isset($data['type']) && $data['type'] === 'menu-item') {
|
|
|
|
$form->getResponse()->setRerenderLayout();
|
|
|
|
}
|
|
|
|
|
2015-09-07 15:50:26 +02:00
|
|
|
Notification::success(t('Navigation item successfully created'));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
$form->handleRequest();
|
|
|
|
|
|
|
|
$this->view->form = $form;
|
|
|
|
$this->render('form');
|
2015-09-07 13:55:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Edit a navigation item
|
|
|
|
*/
|
|
|
|
public function editAction()
|
|
|
|
{
|
2015-09-07 15:43:06 +02:00
|
|
|
$itemName = $this->params->getRequired('name');
|
2015-09-23 14:21:04 +02:00
|
|
|
$referrer = $this->params->get('referrer', 'index');
|
2015-09-07 15:43:06 +02:00
|
|
|
|
|
|
|
$form = new NavigationConfigForm();
|
2015-09-23 14:21:04 +02:00
|
|
|
$form->setRedirectUrl($referrer === 'shared' ? 'navigation/shared' : 'navigation');
|
2015-09-16 15:05:43 +02:00
|
|
|
$form->setItemTypes($this->listItemTypes());
|
2015-09-07 15:43:06 +02:00
|
|
|
$form->setTitle(sprintf($this->translate('Edit Navigation Item %s'), $itemName));
|
2015-09-15 15:57:03 +02:00
|
|
|
$form->setUser($this->Auth()->getUser());
|
|
|
|
$form->setShareConfig(Config::app('navigation'));
|
2015-09-07 15:43:06 +02:00
|
|
|
$form->setOnSuccess(function (NavigationConfigForm $form) use ($itemName) {
|
2015-09-24 14:05:57 +02:00
|
|
|
$data = array_map(
|
|
|
|
function ($v) {
|
|
|
|
return $v !== '' ? $v : null;
|
|
|
|
},
|
|
|
|
$form->getValues()
|
|
|
|
);
|
|
|
|
|
2015-09-07 15:43:06 +02:00
|
|
|
try {
|
2015-09-24 14:05:57 +02:00
|
|
|
$form->edit($itemName, $data);
|
2015-09-07 15:43:06 +02:00
|
|
|
} catch (NotFoundError $e) {
|
|
|
|
throw $e;
|
|
|
|
} catch (Exception $e) {
|
|
|
|
$form->error($e->getMessage());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($form->save()) {
|
2015-09-24 14:05:57 +02:00
|
|
|
if (isset($data['type']) && $data['type'] === 'menu-item') {
|
|
|
|
$form->getResponse()->setRerenderLayout();
|
|
|
|
}
|
|
|
|
|
2015-09-07 15:43:06 +02:00
|
|
|
Notification::success(sprintf(t('Navigation item "%s" successfully updated'), $itemName));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
try {
|
|
|
|
$form->load($itemName);
|
|
|
|
$form->handleRequest();
|
|
|
|
} catch (NotFoundError $_) {
|
|
|
|
$this->httpNotFound(sprintf($this->translate('Navigation item "%s" not found'), $itemName));
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->view->form = $form;
|
|
|
|
$this->render('form');
|
2015-09-07 13:55:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove a navigation item
|
|
|
|
*/
|
|
|
|
public function removeAction()
|
|
|
|
{
|
2015-09-07 16:02:12 +02:00
|
|
|
$itemName = $this->params->getRequired('name');
|
|
|
|
|
|
|
|
$navigationConfigForm = new NavigationConfigForm();
|
2015-09-15 15:57:03 +02:00
|
|
|
$navigationConfigForm->setUser($this->Auth()->getUser());
|
|
|
|
$navigationConfigForm->setShareConfig(Config::app('navigation'));
|
2015-09-07 16:02:12 +02:00
|
|
|
$form = new ConfirmRemovalForm();
|
|
|
|
$form->setRedirectUrl('navigation');
|
|
|
|
$form->setTitle(sprintf($this->translate('Remove Navigation Item %s'), $itemName));
|
|
|
|
$form->setOnSuccess(function (ConfirmRemovalForm $form) use ($itemName, $navigationConfigForm) {
|
|
|
|
try {
|
2015-09-25 10:51:44 +02:00
|
|
|
$itemConfig = $navigationConfigForm->delete($itemName);
|
2015-09-15 15:57:03 +02:00
|
|
|
} catch (NotFoundError $e) {
|
|
|
|
Notification::success(sprintf(t('Navigation Item "%s" not found. No action required'), $itemName));
|
|
|
|
return true;
|
2015-09-07 16:02:12 +02:00
|
|
|
} catch (Exception $e) {
|
|
|
|
$form->error($e->getMessage());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($navigationConfigForm->save()) {
|
2015-09-25 10:51:44 +02:00
|
|
|
if ($itemConfig->type === 'menu-item') {
|
|
|
|
$form->getResponse()->setRerenderLayout();
|
|
|
|
}
|
|
|
|
|
2015-09-07 16:02:12 +02:00
|
|
|
Notification::success(sprintf(t('Navigation Item "%s" successfully removed'), $itemName));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
$form->handleRequest();
|
|
|
|
|
|
|
|
$this->view->form = $form;
|
|
|
|
$this->render('form');
|
2015-09-07 13:55:19 +02:00
|
|
|
}
|
2015-09-07 15:21:21 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Unshare a navigation item
|
|
|
|
*/
|
|
|
|
public function unshareAction()
|
|
|
|
{
|
|
|
|
$this->assertPermission('config/application/navigation');
|
|
|
|
$this->assertHttpMethod('POST');
|
|
|
|
|
2015-09-07 15:43:06 +02:00
|
|
|
$navigationConfigForm = new NavigationConfigForm();
|
2015-09-15 15:57:03 +02:00
|
|
|
$navigationConfigForm->setUser($this->Auth()->getUser());
|
|
|
|
$navigationConfigForm->setShareConfig(Config::app('navigation'));
|
2015-09-07 15:21:21 +02:00
|
|
|
|
|
|
|
$form = new Form(array(
|
2015-09-07 15:43:06 +02:00
|
|
|
'onSuccess' => function ($form) use ($navigationConfigForm) {
|
2015-09-25 10:51:16 +02:00
|
|
|
$itemName = $form->getValue('name');
|
|
|
|
|
2015-09-07 15:21:21 +02:00
|
|
|
try {
|
2015-09-25 10:51:16 +02:00
|
|
|
$newConfig = $navigationConfigForm->unshare($itemName);
|
2015-09-18 13:24:44 +02:00
|
|
|
if ($navigationConfigForm->save()) {
|
2015-09-25 10:51:16 +02:00
|
|
|
if ($newConfig->getSection($itemName)->type === 'menu-item') {
|
|
|
|
$form->getResponse()->setRerenderLayout();
|
|
|
|
}
|
|
|
|
|
2015-09-18 13:24:44 +02:00
|
|
|
Notification::success(sprintf(
|
|
|
|
t('Navigation item "%s" has been unshared'),
|
|
|
|
$form->getValue('name')
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
// TODO: It failed obviously to write one of the configs, so we're leaving the user in
|
|
|
|
// a inconsistent state. Luckily, it's nothing lost but possibly duplicated...
|
|
|
|
Notification::error(sprintf(
|
|
|
|
t('Failed to unshare navigation item "%s"'),
|
|
|
|
$form->getValue('name')
|
|
|
|
));
|
|
|
|
}
|
2015-09-07 15:21:21 +02:00
|
|
|
} catch (NotFoundError $e) {
|
|
|
|
throw $e;
|
|
|
|
} catch (Exception $e) {
|
|
|
|
Notification::error($e->getMessage());
|
|
|
|
}
|
|
|
|
|
|
|
|
$redirect = $form->getValue('redirect');
|
|
|
|
if (! empty($redirect)) {
|
|
|
|
$form->setRedirectUrl(htmlspecialchars_decode($redirect));
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
));
|
|
|
|
$form->setUidDisabled();
|
|
|
|
$form->setSubmitLabel('btn_submit'); // Required to ensure that isSubmitted() is called
|
|
|
|
$form->addElement('hidden', 'name', array('required' => true));
|
|
|
|
$form->addElement('hidden', 'redirect');
|
|
|
|
|
|
|
|
try {
|
|
|
|
$form->handleRequest();
|
|
|
|
} catch (NotFoundError $_) {
|
|
|
|
$this->httpNotFound(sprintf($this->translate('Navigation item "%s" not found'), $form->getValue('name')));
|
|
|
|
}
|
|
|
|
}
|
2015-09-07 13:55:19 +02:00
|
|
|
}
|