Merge branch 'bugfix/separate-configuration-files-for-navigation-items-10246'

fixes #10246
This commit is contained in:
Johannes Meyer 2015-09-30 12:38:45 +02:00
commit ff25c24825
9 changed files with 299 additions and 107 deletions

View File

@ -5,13 +5,13 @@ namespace Icinga\Controllers;
use Exception; use Exception;
use Icinga\Application\Config; use Icinga\Application\Config;
use Icinga\Application\Icinga;
use Icinga\Exception\NotFoundError; use Icinga\Exception\NotFoundError;
use Icinga\Data\DataArray\ArrayDatasource; use Icinga\Data\DataArray\ArrayDatasource;
use Icinga\Forms\ConfirmRemovalForm; use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Forms\Navigation\NavigationConfigForm; use Icinga\Forms\Navigation\NavigationConfigForm;
use Icinga\Web\Controller; use Icinga\Web\Controller;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Web\Navigation\Navigation;
use Icinga\Web\Notification; use Icinga\Web\Notification;
use Icinga\Web\Url; use Icinga\Web\Url;
@ -21,11 +21,11 @@ use Icinga\Web\Url;
class NavigationController extends Controller class NavigationController extends Controller
{ {
/** /**
* The default item types provided by Icinga Web 2 * The global navigation item type configuration
* *
* @var array * @var array
*/ */
protected $defaultItemTypes; protected $itemTypeConfig;
/** /**
* {@inheritdoc} * {@inheritdoc}
@ -33,11 +33,19 @@ class NavigationController extends Controller
public function init() public function init()
{ {
parent::init(); parent::init();
$this->itemTypeConfig = Navigation::getItemTypeConfiguration();
}
$this->defaultItemTypes = array( /**
'menu-item' => $this->translate('Menu Entry'), * Return the label for the given navigation item type
'dashlet' => 'Dashlet' *
); * @param string $type
*
* @return string $type if no label can be found
*/
protected function getItemLabel($type)
{
return isset($this->itemTypeConfig[$type]['label']) ? $this->itemTypeConfig[$type]['label'] : $type;
} }
/** /**
@ -47,33 +55,71 @@ class NavigationController extends Controller
*/ */
protected function listItemTypes() protected function listItemTypes()
{ {
$moduleManager = Icinga::app()->getModuleManager(); $types = array();
foreach ($this->itemTypeConfig as $type => $options) {
$types = $this->defaultItemTypes; $types[$type] = isset($options['label']) ? $options['label'] : $type;
foreach ($moduleManager->getLoadedModules() as $module) {
if ($this->hasPermission($moduleManager::MODULE_PERMISSION_NS . $module->getName())) {
$moduleTypes = $module->getNavigationItems();
if (! empty($moduleTypes)) {
$types = array_merge($types, $moduleTypes);
}
}
} }
return $types; return $types;
} }
/**
* Return all shared navigation item configurations
*
* @param string $owner A username if only items shared by a specific user are desired
*
* @return array
*/
protected function fetchSharedNavigationItemConfigs($owner = null)
{
$configs = array();
foreach ($this->itemTypeConfig as $type => $_) {
$config = Config::navigation($type);
$config->getConfigObject()->setKeyColumn('name');
$query = $config->select();
if ($owner !== null) {
$query->where('owner', $owner);
}
foreach ($query as $itemConfig) {
$configs[] = $itemConfig;
}
}
return $configs;
}
/**
* Return all user navigation item configurations
*
* @param string $username
*
* @return array
*/
protected function fetchUserNavigationItemConfigs($username)
{
$configs = array();
foreach ($this->itemTypeConfig as $type => $_) {
$config = Config::navigation($type, $username);
$config->getConfigObject()->setKeyColumn('name');
foreach ($config->select() as $itemConfig) {
$configs[] = $itemConfig;
}
}
return $configs;
}
/** /**
* Show the current user a list of his/her navigation items * Show the current user a list of his/her navigation items
*/ */
public function indexAction() public function indexAction()
{ {
$user = $this->Auth()->getUser(); $user = $this->Auth()->getUser();
$ds = new ArrayDatasource(array_merge( $ds = new ArrayDatasource(array_merge(
Config::app('navigation')->select()->where('owner', $user->getUsername())->fetchAll(), $this->fetchSharedNavigationItemConfigs($user->getUsername()),
iterator_to_array($user->loadNavigationConfig()) $this->fetchUserNavigationItemConfigs($user->getUsername())
)); ));
$ds->setKeyColumn('name');
$query = $ds->select(); $query = $ds->select();
$this->view->types = $this->listItemTypes(); $this->view->types = $this->listItemTypes();
@ -91,7 +137,7 @@ class NavigationController extends Controller
array( array(
'type' => $this->translate('Type'), 'type' => $this->translate('Type'),
'owner' => $this->translate('Shared'), 'owner' => $this->translate('Shared'),
'name' => $this->translate('Shared Navigation') 'name' => $this->translate('Navigation')
), ),
$query $query
); );
@ -103,13 +149,11 @@ class NavigationController extends Controller
public function sharedAction() public function sharedAction()
{ {
$this->assertPermission('config/application/navigation'); $this->assertPermission('config/application/navigation');
$config = Config::app('navigation'); $ds = new ArrayDatasource($this->fetchSharedNavigationItemConfigs());
$config->getConfigObject()->setKeyColumn('name'); $query = $ds->select();
$query = $config->select();
$removeForm = new Form(); $removeForm = new Form();
$removeForm->setUidDisabled(); $removeForm->setUidDisabled();
$removeForm->setAction(Url::fromPath('navigation/unshare'));
$removeForm->addElement('hidden', 'name', array( $removeForm->addElement('hidden', 'name', array(
'decorators' => array('ViewHelper') 'decorators' => array('ViewHelper')
)); ));
@ -156,11 +200,10 @@ class NavigationController extends Controller
{ {
$form = new NavigationConfigForm(); $form = new NavigationConfigForm();
$form->setRedirectUrl('navigation'); $form->setRedirectUrl('navigation');
$form->setUser($this->Auth()->getUser());
$form->setItemTypes($this->listItemTypes()); $form->setItemTypes($this->listItemTypes());
$form->setTitle($this->translate('Create New Navigation Item')); $form->setTitle($this->translate('Create New Navigation Item'));
$form->addDescription($this->translate('Create a new navigation item, such as a menu entry or dashlet.')); $form->addDescription($this->translate('Create a new navigation item, such as a menu entry or dashlet.'));
$form->setUser($this->Auth()->getUser());
$form->setShareConfig(Config::app('navigation'));
$form->setOnSuccess(function (NavigationConfigForm $form) { $form->setOnSuccess(function (NavigationConfigForm $form) {
$data = array_filter($form->getValues()); $data = array_filter($form->getValues());
@ -172,7 +215,7 @@ class NavigationController extends Controller
} }
if ($form->save()) { if ($form->save()) {
if (isset($data['type']) && $data['type'] === 'menu-item') { if ($data['type'] === 'menu-item') {
$form->getResponse()->setRerenderLayout(); $form->getResponse()->setRerenderLayout();
} }
@ -194,14 +237,22 @@ class NavigationController extends Controller
public function editAction() public function editAction()
{ {
$itemName = $this->params->getRequired('name'); $itemName = $this->params->getRequired('name');
$itemType = $this->params->getRequired('type');
$referrer = $this->params->get('referrer', 'index'); $referrer = $this->params->get('referrer', 'index');
$user = $this->Auth()->getUser();
if ($user->can('config/application/navigation')) {
$itemOwner = $this->params->get('owner', $user->getUsername());
} else {
$itemOwner = $user->getUsername();
}
$form = new NavigationConfigForm(); $form = new NavigationConfigForm();
$form->setUser($user);
$form->setShareConfig(Config::navigation($itemType));
$form->setUserConfig(Config::navigation($itemType, $itemOwner));
$form->setRedirectUrl($referrer === 'shared' ? 'navigation/shared' : 'navigation'); $form->setRedirectUrl($referrer === 'shared' ? 'navigation/shared' : 'navigation');
$form->setItemTypes($this->listItemTypes()); $form->setTitle(sprintf($this->translate('Edit %s %s'), $this->getItemLabel($itemType), $itemName));
$form->setTitle(sprintf($this->translate('Edit Navigation Item %s'), $itemName));
$form->setUser($this->Auth()->getUser());
$form->setShareConfig(Config::app('navigation'));
$form->setOnSuccess(function (NavigationConfigForm $form) use ($itemName) { $form->setOnSuccess(function (NavigationConfigForm $form) use ($itemName) {
$data = array_map( $data = array_map(
function ($v) { function ($v) {
@ -248,13 +299,17 @@ class NavigationController extends Controller
public function removeAction() public function removeAction()
{ {
$itemName = $this->params->getRequired('name'); $itemName = $this->params->getRequired('name');
$itemType = $this->params->getRequired('type');
$user = $this->Auth()->getUser();
$navigationConfigForm = new NavigationConfigForm(); $navigationConfigForm = new NavigationConfigForm();
$navigationConfigForm->setUser($this->Auth()->getUser()); $navigationConfigForm->setUser($user);
$navigationConfigForm->setShareConfig(Config::app('navigation')); $navigationConfigForm->setShareConfig(Config::navigation($itemType));
$navigationConfigForm->setUserConfig(Config::navigation($itemType, $user->getUsername()));
$form = new ConfirmRemovalForm(); $form = new ConfirmRemovalForm();
$form->setRedirectUrl('navigation'); $form->setRedirectUrl('navigation');
$form->setTitle(sprintf($this->translate('Remove Navigation Item %s'), $itemName)); $form->setTitle(sprintf($this->translate('Remove %s %s'), $this->getItemLabel($itemType), $itemName));
$form->setOnSuccess(function (ConfirmRemovalForm $form) use ($itemName, $navigationConfigForm) { $form->setOnSuccess(function (ConfirmRemovalForm $form) use ($itemName, $navigationConfigForm) {
try { try {
$itemConfig = $navigationConfigForm->delete($itemName); $itemConfig = $navigationConfigForm->delete($itemName);
@ -291,9 +346,14 @@ class NavigationController extends Controller
$this->assertPermission('config/application/navigation'); $this->assertPermission('config/application/navigation');
$this->assertHttpMethod('POST'); $this->assertHttpMethod('POST');
// TODO: I'd like these being form fields
$itemType = $this->params->getRequired('type');
$itemOwner = $this->params->getRequired('owner');
$navigationConfigForm = new NavigationConfigForm(); $navigationConfigForm = new NavigationConfigForm();
$navigationConfigForm->setUser($this->Auth()->getUser()); $navigationConfigForm->setUser($this->Auth()->getUser());
$navigationConfigForm->setShareConfig(Config::app('navigation')); $navigationConfigForm->setShareConfig(Config::navigation($itemType));
$navigationConfigForm->setUserConfig(Config::navigation($itemType, $itemOwner));
$form = new Form(array( $form = new Form(array(
'onSuccess' => function ($form) use ($navigationConfigForm) { 'onSuccess' => function ($form) use ($navigationConfigForm) {

View File

@ -123,12 +123,18 @@ class NavigationConfigForm extends ConfigForm
/** /**
* Return the user's navigation configuration * Return the user's navigation configuration
* *
* @param string $type
*
* @return Config * @return Config
*/ */
public function getUserConfig() public function getUserConfig($type = null)
{ {
if ($this->userConfig === null) { if ($this->userConfig === null) {
$this->setUserConfig($this->getUser()->loadNavigationConfig()); if ($type === null) {
throw new ProgrammingError('You need to pass a type if no user configuration is set');
}
$this->setUserConfig(Config::navigation($type, $this->getUser()->getUsername()));
} }
return $this->userConfig; return $this->userConfig;
@ -151,10 +157,20 @@ class NavigationConfigForm extends ConfigForm
/** /**
* Return the shared navigation configuration * Return the shared navigation configuration
* *
* @param string $type
*
* @return Config * @return Config
*/ */
public function getShareConfig() public function getShareConfig($type = null)
{ {
if ($this->shareConfig === null) {
if ($type === null) {
throw new ProgrammingError('You need to pass a type if no share configuration is set');
}
$this->setShareConfig(Config::navigation($type));
}
return $this->shareConfig; return $this->shareConfig;
} }
@ -194,10 +210,9 @@ class NavigationConfigForm extends ConfigForm
$children = $this->itemToLoad ? $this->getFlattenedChildren($this->itemToLoad) : array(); $children = $this->itemToLoad ? $this->getFlattenedChildren($this->itemToLoad) : array();
$names = array(); $names = array();
foreach ($this->getShareConfig() as $sectionName => $sectionConfig) { foreach ($this->getShareConfig($type) as $sectionName => $sectionConfig) {
if ( if (
$sectionName !== $this->itemToLoad $sectionName !== $this->itemToLoad
&& $sectionConfig->type === $type
&& $sectionConfig->owner === ($owner ?: $this->getUser()->getUsername()) && $sectionConfig->owner === ($owner ?: $this->getUser()->getUsername())
&& !in_array($sectionName, $children, true) && !in_array($sectionName, $children, true)
) { ) {
@ -205,10 +220,9 @@ class NavigationConfigForm extends ConfigForm
} }
} }
foreach ($this->getUserConfig() as $sectionName => $sectionConfig) { foreach ($this->getUserConfig($type) as $sectionName => $sectionConfig) {
if ( if (
$sectionName !== $this->itemToLoad $sectionName !== $this->itemToLoad
&& $sectionConfig->type === $type
&& !in_array($sectionName, $children, true) && !in_array($sectionName, $children, true)
) { ) {
$names[] = $sectionName; $names[] = $sectionName;
@ -271,29 +285,31 @@ class NavigationConfigForm extends ConfigForm
* *
* @return $this * @return $this
* *
* @throws InvalidArgumentException In case $data does not contain a navigation item name * @throws InvalidArgumentException In case $data does not contain a navigation item name or type
* @throws IcingaException In case a navigation item with the same name already exists * @throws IcingaException In case a navigation item with the same name already exists
*/ */
public function add(array $data) public function add(array $data)
{ {
if (! isset($data['name'])) { if (! isset($data['name'])) {
throw new InvalidArgumentException('Key \'name\' missing'); throw new InvalidArgumentException('Key \'name\' missing');
} elseif (! isset($data['type'])) {
throw new InvalidArgumentException('Key \'type\' missing');
} }
$shared = false; $shared = false;
$config = $this->getUserConfig(); $config = $this->getUserConfig($data['type']);
if ((isset($data['users']) && $data['users']) || (isset($data['groups']) && $data['groups'])) { if ((isset($data['users']) && $data['users']) || (isset($data['groups']) && $data['groups'])) {
if ($this->getUser()->can('application/share/navigation')) { if ($this->getUser()->can('application/share/navigation')) {
$data['owner'] = $this->getUser()->getUsername(); $data['owner'] = $this->getUser()->getUsername();
$config = $this->getShareConfig(); $config = $this->getShareConfig($data['type']);
$shared = true; $shared = true;
} else { } else {
unset($data['users']); unset($data['users']);
unset($data['groups']); unset($data['groups']);
} }
} elseif (isset($data['parent']) && $data['parent'] && $this->hasBeenShared($data['parent'])) { } elseif (isset($data['parent']) && $data['parent'] && $this->hasBeenShared($data['parent'], $data['type'])) {
$data['owner'] = $this->getUser()->getUsername(); $data['owner'] = $this->getUser()->getUsername();
$config = $this->getShareConfig(); $config = $this->getShareConfig($data['type']);
$shared = true; $shared = true;
} }
@ -301,9 +317,9 @@ class NavigationConfigForm extends ConfigForm
$exists = $config->hasSection($itemName); $exists = $config->hasSection($itemName);
if (! $exists) { if (! $exists) {
if ($shared) { if ($shared) {
$exists = $this->getUserConfig()->hasSection($itemName); $exists = $this->getUserConfig($data['type'])->hasSection($itemName);
} else { } else {
$exists = (bool) $this->getShareConfig() $exists = (bool) $this->getShareConfig($data['type'])
->select() ->select()
->where('name', $itemName) ->where('name', $itemName)
->where('owner', $this->getUser()->getUsername()) ->where('owner', $this->getUser()->getUsername())
@ -385,8 +401,7 @@ class NavigationConfigForm extends ConfigForm
if ($ownerName === $this->getUser()->getUsername()) { if ($ownerName === $this->getUser()->getUsername()) {
$exists = $this->getUserConfig()->hasSection($name); $exists = $this->getUserConfig()->hasSection($name);
} else { } else {
$owner = new User($ownerName); $exists = Config::navigation($itemConfig->type, $ownerName)->hasSection($name);
$exists = $owner->loadNavigationConfig()->hasSection($name);
} }
} else { } else {
$exists = (bool) $this->getShareConfig() $exists = (bool) $this->getShareConfig()
@ -521,8 +536,7 @@ class NavigationConfigForm extends ConfigForm
if (! $itemConfig->owner || $itemConfig->owner === $this->getUser()->getUsername()) { if (! $itemConfig->owner || $itemConfig->owner === $this->getUser()->getUsername()) {
$config = $this->getUserConfig(); $config = $this->getUserConfig();
} else { } else {
$owner = new User($itemConfig->owner); $config = Config::navigation($itemConfig->type, $itemConfig->owner);
$config = $owner->loadNavigationConfig();
} }
foreach ($children as $child) { foreach ($children as $child) {
@ -549,6 +563,13 @@ class NavigationConfigForm extends ConfigForm
$shared = false; $shared = false;
$itemTypes = $this->getItemTypes(); $itemTypes = $this->getItemTypes();
$itemType = isset($formData['type']) ? $formData['type'] : key($itemTypes); $itemType = isset($formData['type']) ? $formData['type'] : key($itemTypes);
if ($itemType === null) {
throw new ProgrammingError(
'This should actually not happen. Create a bug report at dev.icinga.org'
. ' or remove this assertion if you know what you\'re doing'
);
}
$itemForm = $this->getItemForm($itemType); $itemForm = $this->getItemForm($itemType);
$this->addElement( $this->addElement(
@ -606,17 +627,27 @@ class NavigationConfigForm extends ConfigForm
} }
} }
$this->addElement( if (empty($itemTypes) || count($itemTypes) === 1) {
'select', $this->addElement(
'type', 'hidden',
array( 'type',
'required' => true, array(
'autosubmit' => true, 'value' => $itemType
'label' => $this->translate('Type'), )
'description' => $this->translate('The type of this navigation item'), );
'multiOptions' => $itemTypes } else {
) $this->addElement(
); 'select',
'type',
array(
'required' => true,
'autosubmit' => true,
'label' => $this->translate('Type'),
'description' => $this->translate('The type of this navigation item'),
'multiOptions' => $itemTypes
)
);
}
if (! $shared && $itemForm->requiresParentSelection()) { if (! $shared && $itemForm->requiresParentSelection()) {
if ($this->itemToLoad && $this->hasBeenShared($this->itemToLoad)) { if ($this->itemToLoad && $this->hasBeenShared($this->itemToLoad)) {
@ -767,12 +798,13 @@ class NavigationConfigForm extends ConfigForm
* Return whether the given navigation item has been shared * Return whether the given navigation item has been shared
* *
* @param string $name * @param string $name
* @param string $type
* *
* @return bool * @return bool
*/ */
protected function hasBeenShared($name) protected function hasBeenShared($name, $type = null)
{ {
return $this->getConfigForItem($name) === $this->getShareConfig(); return $this->getShareConfig($type) === $this->getConfigForItem($name);
} }
/** /**

View File

@ -22,14 +22,17 @@
<th style="width: 5em"><?= $this->translate('Remove'); ?></th> <th style="width: 5em"><?= $this->translate('Remove'); ?></th>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($items as $name => $item): ?> <?php foreach ($items as $item): ?>
<tr> <tr>
<td><?= $this->qlink( <td><?= $this->qlink(
$name, $item->name,
'navigation/edit', 'navigation/edit',
array('name' => $name),
array( array(
'title' => sprintf($this->translate('Edit navigation item %s'), $name) 'name' => $item->name,
'type' => $item->type
),
array(
'title' => sprintf($this->translate('Edit navigation item %s'), $item->name)
) )
); ?></td> ); ?></td>
<td><?= $item->type && isset($types[$item->type]) <td><?= $item->type && isset($types[$item->type])
@ -39,10 +42,13 @@
<td><?= $this->qlink( <td><?= $this->qlink(
'', '',
'navigation/remove', 'navigation/remove',
array('name' => $name), array(
'name' => $item->name,
'type' => $item->type
),
array( array(
'icon' => 'trash', 'icon' => 'trash',
'title' => sprintf($this->translate('Remove navigation item %s'), $name) 'title' => sprintf($this->translate('Remove navigation item %s'), $item->name)
) )
); ?></td> ); ?></td>
</tr> </tr>

View File

@ -1,4 +1,8 @@
<?php if (! $this->compact): ?> <?php
use Icinga\Web\Url;
if (! $this->compact): ?>
<div class="controls"> <div class="controls">
<?= $this->tabs; ?> <?= $this->tabs; ?>
<?= $this->sortBox; ?> <?= $this->sortBox; ?>
@ -19,17 +23,19 @@
<th style="width: 5em"><?= $this->translate('Unshare'); ?></th> <th style="width: 5em"><?= $this->translate('Unshare'); ?></th>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($items as $name => $item): ?> <?php foreach ($items as $item): ?>
<tr> <tr>
<td><?= $this->qlink( <td><?= $this->qlink(
$name, $item->name,
'navigation/edit', 'navigation/edit',
array( array(
'name' => $name, 'name' => $item->name,
'type' => $item->type,
'owner' => $item->owner,
'referrer' => 'shared' 'referrer' => 'shared'
), ),
array( array(
'title' => sprintf($this->translate('Edit shared navigation item %s'), $name) 'title' => sprintf($this->translate('Edit shared navigation item %s'), $item->name)
) )
); ?></td> ); ?></td>
<td><?= $item->type && isset($types[$item->type]) <td><?= $item->type && isset($types[$item->type])
@ -48,7 +54,12 @@
) )
); ?></td> ); ?></td>
<?php else: ?> <?php else: ?>
<td data-base-target="_self"><?= $removeForm->setDefault('name', $name); ?></td> <td data-base-target="_self"><?= $removeForm
->setDefault('name', $item->name)
->setAction(Url::fromPath(
'navigation/unshare',
array('type' => $item->type, 'owner' => $item->owner)
)); ?></td>
<?php endif ?> <?php endif ?>
</tr> </tr>
<?php endforeach ?> <?php endforeach ?>

View File

@ -13,7 +13,9 @@ use Icinga\Data\Selectable;
use Icinga\Data\SimpleQuery; use Icinga\Data\SimpleQuery;
use Icinga\File\Ini\IniWriter; use Icinga\File\Ini\IniWriter;
use Icinga\File\Ini\IniParser; use Icinga\File\Ini\IniParser;
use Icinga\Exception\IcingaException;
use Icinga\Exception\NotReadableError; use Icinga\Exception\NotReadableError;
use Icinga\Web\Navigation\Navigation;
/** /**
* Container for INI like configuration and global registry of application and module related configuration. * Container for INI like configuration and global registry of application and module related configuration.
@ -41,6 +43,13 @@ class Config implements Countable, Iterator, Selectable
*/ */
protected static $modules = array(); protected static $modules = array();
/**
* Navigation config instances per type
*
* @var array
*/
protected static $navigation = array();
/** /**
* The internal ConfigObject * The internal ConfigObject
* *
@ -416,6 +425,60 @@ class Config implements Countable, Iterator, Selectable
return $moduleConfigs[$configname]; return $moduleConfigs[$configname];
} }
/**
* Retrieve a navigation config
*
* @param string $type The type identifier of the navigation item for which to return its config
* @param string $username A user's name or null if the shared config is desired
* @param bool $fromDisk If true, the configuration will be read from disk
*
* @return Config The requested configuration
*/
public static function navigation($type, $username = null, $fromDisk = false)
{
if (! isset(self::$navigation[$type])) {
self::$navigation[$type] = array();
}
$branch = $username ?: 'shared';
$typeConfigs = self::$navigation[$type];
if (! isset($typeConfigs[$branch]) || $fromDisk) {
$typeConfigs[$branch] = static::fromIni(static::getNavigationConfigPath($type, $username));
}
return $typeConfigs[$branch];
}
/**
* 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 static function getNavigationConfigPath($type, $username = null)
{
$itemTypeConfig = Navigation::getItemTypeConfiguration();
if (! isset($itemTypeConfig[$type])) {
throw new IcingaException('Invalid navigation item type %s provided', $type);
}
if (isset($itemTypeConfig[$type]['config'])) {
$filename = $itemTypeConfig[$type]['config'] . '.ini';
} else {
$filename = $type . 's.ini';
}
return static::resolvePath(
($username ? 'preferences' . DIRECTORY_SEPARATOR . $username : 'navigation')
. DIRECTORY_SEPARATOR
. $filename
);
}
/** /**
* Return this config rendered as a INI structured string * Return this config rendered as a INI structured string
* *

View File

@ -1014,16 +1014,21 @@ class Module
} }
/** /**
* Provide a new type of configurable navigation item with a optional label * Provide a new type of configurable navigation item with a optional label and config filename
* *
* @param string $type * @param string $type
* @param string $label * @param string $label
* @param string $config
* *
* @return $this * @return $this
*/ */
protected function provideNavigationItem($type, $label = null) protected function provideNavigationItem($type, $label = null, $config = null)
{ {
$this->navigationItems[$type] = $label ?: $type; $this->navigationItems[$type] = array(
'label' => $label,
'config' => $config
);
return $this; return $this;
} }

View File

@ -179,12 +179,11 @@ class Web extends EmbeddedWeb
*/ */
public function getSharedNavigation($type) public function getSharedNavigation($type)
{ {
$config = Config::app('navigation')->getConfigObject(); $config = Config::navigation($type === 'dashboard-pane' ? 'dashlet' : $type);
$config->setKeyColumn('name');
if ($type === 'dashboard-pane') { if ($type === 'dashboard-pane') {
$panes = array(); $panes = array();
foreach ($config->select()->where('type', 'dashlet') as $dashletName => $dashletConfig) { foreach ($config as $dashletName => $dashletConfig) {
if ($this->hasAccessToSharedNavigationItem($dashletConfig)) { if ($this->hasAccessToSharedNavigationItem($dashletConfig)) {
// TODO: Throw ConfigurationError if pane or url is missing // TODO: Throw ConfigurationError if pane or url is missing
$panes[$dashletConfig->pane][$dashletName] = $dashletConfig->url; $panes[$dashletConfig->pane][$dashletName] = $dashletConfig->url;
@ -203,7 +202,7 @@ class Web extends EmbeddedWeb
} }
} else { } else {
$items = array(); $items = array();
foreach ($config->select()->where('type', $type) as $name => $typeConfig) { foreach ($config as $name => $typeConfig) {
if ($this->hasAccessToSharedNavigationItem($typeConfig)) { if ($this->hasAccessToSharedNavigationItem($typeConfig)) {
$items[$name] = $typeConfig; $items[$name] = $typeConfig;
} }

View File

@ -479,22 +479,6 @@ class User
return false; return false;
} }
/**
* Load and return this user's navigation configuration
*
* @return Config
*/
public function loadNavigationConfig()
{
return Config::fromIni(
Config::resolvePath('preferences')
. DIRECTORY_SEPARATOR
. $this->getUsername()
. DIRECTORY_SEPARATOR
. 'navigation.ini'
);
}
/** /**
* Load and return this user's configured navigation of the given type * Load and return this user's configured navigation of the given type
* *
@ -504,12 +488,11 @@ class User
*/ */
public function getNavigation($type) public function getNavigation($type)
{ {
$config = $this->loadNavigationConfig(); $config = Config::navigation($type === 'dashboard-pane' ? 'dashlet' : $type, $this->getUsername());
$config->getConfigObject()->setKeyColumn('name');
if ($type === 'dashboard-pane') { if ($type === 'dashboard-pane') {
$panes = array(); $panes = array();
foreach ($config->select()->where('type', 'dashlet') as $dashletName => $dashletConfig) { foreach ($config as $dashletName => $dashletConfig) {
// TODO: Throw ConfigurationError if pane or url is missing // TODO: Throw ConfigurationError if pane or url is missing
$panes[$dashletConfig->pane][$dashletName] = $dashletConfig->url; $panes[$dashletConfig->pane][$dashletName] = $dashletConfig->url;
} }
@ -525,7 +508,7 @@ class User
); );
} }
} else { } else {
$navigation = Navigation::fromConfig($config->select()->where('type', $type)); $navigation = Navigation::fromConfig($config);
} }
return $navigation; return $navigation;

View File

@ -451,6 +451,39 @@ class Navigation implements ArrayAccess, Countable, IteratorAggregate
return $this; return $this;
} }
/**
* Return the global navigation item type configuration
*
* @return array
*/
public static function getItemTypeConfiguration()
{
$defaultItemTypes = array(
'menu-item' => array(
'label' => t('Menu Entry'),
'config' => 'menu'
),
'dashlet' => array(
'label' => 'Dashlet',
'config' => 'dashboard'
)
);
$moduleItemTypes = array();
$moduleManager = Icinga::app()->getModuleManager();
foreach ($moduleManager->getLoadedModules() as $module) {
if (Auth::getInstance()->hasPermission($moduleManager::MODULE_PERMISSION_NS . $module->getName())) {
foreach ($module->getNavigationItems() as $type => $options) {
if (! isset($moduleItemTypes[$type])) {
$moduleItemTypes[$type] = $options;
}
}
}
}
return array_merge($defaultItemTypes, $moduleItemTypes);
}
/** /**
* Create and return a new set of navigation items for the given configuration * Create and return a new set of navigation items for the given configuration
* *