Merge pull request #3837 from Icinga/fix/dont-translate-pane-and-dashlet-names-in-configs-3542
Don't translate pane and dashlet names in configs
This commit is contained in:
commit
8d09279e15
|
@ -106,29 +106,22 @@ class DashboardController extends ActionController
|
|||
$action = $this;
|
||||
$form->setOnSuccess(function (Form $form) use ($dashboard, $action) {
|
||||
try {
|
||||
$pane = $dashboard->getPane($form->getValue('pane'));
|
||||
$pane = $dashboard->getPane($form->getValue('org_pane'));
|
||||
$pane->setTitle($form->getValue('pane'));
|
||||
} catch (ProgrammingError $e) {
|
||||
$pane = new Dashboard\Pane($form->getValue('pane'));
|
||||
$pane->setUserWidget();
|
||||
$dashboard->addPane($pane);
|
||||
}
|
||||
try {
|
||||
$dashlet = $pane->getDashlet($form->getValue('dashlet'));
|
||||
$dashlet = $pane->getDashlet($form->getValue('org_dashlet'));
|
||||
$dashlet->setTitle($form->getValue('dashlet'));
|
||||
$dashlet->setUrl($form->getValue('url'));
|
||||
} catch (ProgrammingError $e) {
|
||||
$dashlet = new Dashboard\Dashlet($form->getValue('dashlet'), $form->getValue('url'), $pane);
|
||||
$pane->addDashlet($dashlet);
|
||||
}
|
||||
$dashlet->setUserWidget();
|
||||
// Rename dashlet
|
||||
if ($form->getValue('org_dashlet') && $form->getValue('org_dashlet') !== $dashlet->getTitle()) {
|
||||
$pane->removeDashlet($form->getValue('org_dashlet'));
|
||||
}
|
||||
// Move
|
||||
if ($form->getValue('org_pane') && $form->getValue('org_pane') !== $pane->getTitle()) {
|
||||
$oldPane = $dashboard->getPane($form->getValue('org_pane'));
|
||||
$oldPane->removeDashlet($dashlet->getTitle());
|
||||
}
|
||||
$dashboardConfig = $dashboard->getConfig();
|
||||
try {
|
||||
$dashboardConfig->saveIni();
|
||||
|
@ -269,7 +262,7 @@ class DashboardController extends ActionController
|
|||
$action = $this;
|
||||
$form->setOnSuccess(function (Form $form) use ($dashboard, $pane, $action) {
|
||||
$pane = $dashboard->getPane($pane);
|
||||
$dashboard->removePane($pane->getTitle());
|
||||
$dashboard->removePane($pane->getName());
|
||||
$dashboardConfig = $dashboard->getConfig();
|
||||
try {
|
||||
$dashboardConfig->saveIni();
|
||||
|
|
|
@ -161,10 +161,10 @@ class DashletForm extends Form
|
|||
public function load(Dashlet $dashlet)
|
||||
{
|
||||
$this->populate(array(
|
||||
'pane' => $dashlet->getPane()->getName(),
|
||||
'pane' => $dashlet->getPane()->getTitle(),
|
||||
'org_pane' => $dashlet->getPane()->getName(),
|
||||
'dashlet' => $dashlet->getTitle(),
|
||||
'org_dashlet' => $dashlet->getTitle(),
|
||||
'org_dashlet' => $dashlet->getName(),
|
||||
'url' => $dashlet->getUrl()->getRelativeUrl()
|
||||
));
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<?= $this->qlink(
|
||||
$dashlet->getTitle(),
|
||||
'dashboard/update-dashlet',
|
||||
array('pane' => $pane->getName(), 'dashlet' => $dashlet->getTitle()),
|
||||
array('pane' => $pane->getName(), 'dashlet' => $dashlet->getName()),
|
||||
array('title' => sprintf($this->translate('Edit dashlet %s'), $dashlet->getTitle()))
|
||||
); ?>
|
||||
</td>
|
||||
|
@ -75,10 +75,10 @@
|
|||
<?= $this->qlink(
|
||||
'',
|
||||
'dashboard/remove-dashlet',
|
||||
array('pane' => $pane->getName(), 'dashlet' => $dashlet->getTitle()),
|
||||
array('pane' => $pane->getName(), 'dashlet' => $dashlet->getName()),
|
||||
array(
|
||||
'icon' => 'trash',
|
||||
'title' => sprintf($this->translate('Remove dashlet %s from pane %s'), $dashlet->getTitle(), $pane->getName())
|
||||
'title' => sprintf($this->translate('Remove dashlet %s from pane %s'), $dashlet->getTitle(), $pane->getTitle())
|
||||
)
|
||||
); ?>
|
||||
</td>
|
||||
|
|
|
@ -14,6 +14,9 @@ v2.3 to v2.5 requires to follow the instructions for v2.4 too.
|
|||
for log messages emitted by jquery-migrate. (https://github.com/jquery/jquery-migrate) Your javascript code will still
|
||||
work, though jquery-migrate will notify you if you're utilizing deprecated/removed functions. jquery-migrate will be
|
||||
removed with Icinga Web v2.8 and code not adjusted accordingly will stop working.
|
||||
* If you're using a language other than english and you've adjusted or disabled module dashboards, you'll need to
|
||||
update all of your `dashboard.ini` files. A CLI command exists to assist you with this task. Enable the `migrate`
|
||||
module and run the following on the host where these files exist: `icingacli migrate dashboard sections --verbose`
|
||||
|
||||
## Upgrading to Icinga Web 2 2.6.x <a id="upgrading-to-2.6.x"></a>
|
||||
|
||||
|
|
|
@ -314,9 +314,12 @@ class Module
|
|||
$navigation = new Navigation();
|
||||
foreach ($panes as $pane) {
|
||||
/** @var DashboardContainer $pane */
|
||||
$dashlets = array();
|
||||
$dashlets = [];
|
||||
foreach ($pane->getDashlets() as $dashletName => $dashletUrl) {
|
||||
$dashlets[$this->translate($dashletName)] = $dashletUrl;
|
||||
$dashlets[$dashletName] = [
|
||||
'label' => $this->translate($dashletName),
|
||||
'url' => $dashletUrl
|
||||
];
|
||||
}
|
||||
|
||||
$navigation->addItem(
|
||||
|
@ -326,7 +329,7 @@ class Module
|
|||
array(
|
||||
'label' => $this->translate($pane->getName()),
|
||||
'type' => 'dashboard-pane',
|
||||
'dashlets' => $dashlets
|
||||
'children' => $dashlets
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -5,6 +5,9 @@ namespace Icinga\Legacy;
|
|||
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\User;
|
||||
use Icinga\Web\Navigation\DashboardPane;
|
||||
use Icinga\Web\Navigation\Navigation;
|
||||
use Icinga\Web\Navigation\NavigationItem;
|
||||
|
||||
/**
|
||||
* Legacy dashboard config class for case insensitive interpretation of dashboard config files
|
||||
|
@ -76,6 +79,51 @@ class DashboardConfig extends Config
|
|||
*/
|
||||
public function saveIni($filePath = null, $fileMode = 0660)
|
||||
{
|
||||
// Preprocessing start, ensures that the non-translated names are used to save module dashboard changes
|
||||
// TODO: This MUST NOT survive the new dashboard implementation (yes, it's still a thing..)
|
||||
$dashboardNavigation = new Navigation();
|
||||
$dashboardNavigation->load('dashboard-pane');
|
||||
$getDashboardPane = function ($label) use ($dashboardNavigation) {
|
||||
foreach ($dashboardNavigation as $dashboardPane) {
|
||||
/** @var DashboardPane $dashboardPane */
|
||||
if ($dashboardPane->getLabel() === $label) {
|
||||
return $dashboardPane;
|
||||
}
|
||||
|
||||
foreach ($dashboardPane->getChildren() as $dashlet) {
|
||||
/** @var NavigationItem $dashlet */
|
||||
if ($dashlet->getLabel() === $label) {
|
||||
return $dashlet;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
foreach (clone $this->config as $name => $options) {
|
||||
if (strpos($name, '.') !== false) {
|
||||
list($dashboardLabel, $dashletLabel) = explode('.', $name, 2);
|
||||
} else {
|
||||
$dashboardLabel = $name;
|
||||
$dashletLabel = null;
|
||||
}
|
||||
|
||||
$dashboardPane = $getDashboardPane($dashboardLabel);
|
||||
if ($dashboardPane !== null) {
|
||||
$dashboardLabel = $dashboardPane->getName();
|
||||
}
|
||||
|
||||
if ($dashletLabel !== null) {
|
||||
$dashletItem = $getDashboardPane($dashletLabel);
|
||||
if ($dashletItem !== null) {
|
||||
$dashletLabel = $dashletItem->getName();
|
||||
}
|
||||
}
|
||||
|
||||
unset($this->config[$name]);
|
||||
$this->config[$dashboardLabel . ($dashletLabel ? '.' . $dashletLabel : '')] = $options;
|
||||
}
|
||||
// Preprocessing end
|
||||
|
||||
parent::saveIni($filePath, $fileMode);
|
||||
if ($filePath === null) {
|
||||
$filePath = $this->configFile;
|
||||
|
|
|
@ -62,19 +62,6 @@ class DashboardPane extends NavigationItem
|
|||
$this->setUrl(Url::fromPath('dashboard', array('pane' => $this->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function merge(NavigationItem $item)
|
||||
{
|
||||
parent::merge($item);
|
||||
|
||||
$this->setDashlets(array_merge(
|
||||
$this->getDashlets(false),
|
||||
$item->getDashlets(false)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set disabled state for pane
|
||||
*
|
||||
|
|
|
@ -77,15 +77,15 @@ class Dashboard extends AbstractWidget
|
|||
foreach ($navigation as $dashboardPane) {
|
||||
/** @var DashboardPane $dashboardPane */
|
||||
$pane = new Pane($dashboardPane->getLabel());
|
||||
foreach ($dashboardPane->getDashlets(false) as $title => $url) {
|
||||
$pane->addDashlet($title, $url);
|
||||
foreach ($dashboardPane->getChildren() as $dashlet) {
|
||||
$pane->addDashlet($dashlet->getLabel(), $dashlet->getUrl());
|
||||
}
|
||||
|
||||
$panes[] = $pane;
|
||||
}
|
||||
|
||||
$this->mergePanes($panes);
|
||||
$this->loadUserDashboards();
|
||||
$this->loadUserDashboards($navigation);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ class Dashboard extends AbstractWidget
|
|||
}
|
||||
foreach ($pane->getDashlets() as $dashlet) {
|
||||
if ($dashlet->isUserWidget()) {
|
||||
$output[$pane->getName() . '.' . $dashlet->getTitle()] = $dashlet->toArray();
|
||||
$output[$pane->getName() . '.' . $dashlet->getName()] = $dashlet->toArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,10 +114,10 @@ class Dashboard extends AbstractWidget
|
|||
/**
|
||||
* Load user dashboards from all config files that match the username
|
||||
*/
|
||||
protected function loadUserDashboards()
|
||||
protected function loadUserDashboards(Navigation $navigation)
|
||||
{
|
||||
foreach (DashboardConfig::listConfigFilesForUser($this->user) as $file) {
|
||||
$this->loadUserDashboardsFromFile($file);
|
||||
$this->loadUserDashboardsFromFile($file, $navigation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ class Dashboard extends AbstractWidget
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function loadUserDashboardsFromFile($file)
|
||||
protected function loadUserDashboardsFromFile($file, Navigation $dashboardNavigation)
|
||||
{
|
||||
try {
|
||||
$config = Config::fromIni($file);
|
||||
|
@ -143,8 +143,12 @@ class Dashboard extends AbstractWidget
|
|||
$dashlets = array();
|
||||
foreach ($config as $key => $part) {
|
||||
if (strpos($key, '.') === false) {
|
||||
if ($this->hasPane($part->title)) {
|
||||
$panes[$key] = $this->getPane($part->title);
|
||||
$dashboardPane = $dashboardNavigation->getItem($key);
|
||||
if ($dashboardPane !== null) {
|
||||
$key = $dashboardPane->getLabel();
|
||||
}
|
||||
if ($this->hasPane($key)) {
|
||||
$panes[$key] = $this->getPane($key);
|
||||
} else {
|
||||
$panes[$key] = new Pane($key);
|
||||
$panes[$key]->setTitle($part->title);
|
||||
|
@ -155,6 +159,14 @@ class Dashboard extends AbstractWidget
|
|||
}
|
||||
} else {
|
||||
list($paneName, $dashletName) = explode('.', $key, 2);
|
||||
$dashboardPane = $dashboardNavigation->getItem($paneName);
|
||||
if ($dashboardPane !== null) {
|
||||
$paneName = $dashboardPane->getLabel();
|
||||
$dashletItem = $dashboardPane->getChildren()->getItem($dashletName);
|
||||
if ($dashletItem !== null) {
|
||||
$dashletName = $dashletItem->getLabel();
|
||||
}
|
||||
}
|
||||
$part->pane = $paneName;
|
||||
$part->dashlet = $dashletName;
|
||||
$dashlets[] = $part;
|
||||
|
@ -175,6 +187,7 @@ class Dashboard extends AbstractWidget
|
|||
$dashletData->url,
|
||||
$pane
|
||||
);
|
||||
$dashlet->setName($dashletData->dashlet);
|
||||
|
||||
if ((bool) $dashletData->get('disabled', false) === true) {
|
||||
$dashlet->setDisabled(true);
|
||||
|
@ -200,7 +213,7 @@ class Dashboard extends AbstractWidget
|
|||
{
|
||||
/** @var $pane Pane */
|
||||
foreach ($panes as $pane) {
|
||||
if ($this->hasPane($pane->getTitle()) === true) {
|
||||
if ($this->hasPane($pane->getName()) === true) {
|
||||
/** @var $current Pane */
|
||||
$current = $this->panes[$pane->getName()];
|
||||
$current->addDashlets($pane->getDashlets());
|
||||
|
|
|
@ -22,6 +22,8 @@ class Dashlet extends UserWidget
|
|||
*/
|
||||
private $url;
|
||||
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* The title being displayed on top of the dashlet
|
||||
* @var
|
||||
|
@ -91,11 +93,23 @@ EOD;
|
|||
*/
|
||||
public function __construct($title, $url, Pane $pane)
|
||||
{
|
||||
$this->name = $title;
|
||||
$this->title = $title;
|
||||
$this->pane = $pane;
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the dashlets title
|
||||
*
|
||||
|
|
|
@ -22,7 +22,6 @@ class Pane extends UserWidget
|
|||
|
||||
/**
|
||||
* The title of this pane, as displayed in the dashboard tabs
|
||||
* @TODO: Currently the same as $name, evaluate if distinguishing is needed
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
@ -229,7 +228,7 @@ class Pane extends UserWidget
|
|||
public function addDashlet($dashlet, $url = null)
|
||||
{
|
||||
if ($dashlet instanceof Dashlet) {
|
||||
$this->dashlets[$dashlet->getTitle()] = $dashlet;
|
||||
$this->dashlets[$dashlet->getName()] = $dashlet;
|
||||
} elseif (is_string($dashlet) && $url !== null) {
|
||||
$this->createDashlet($dashlet, $url);
|
||||
} else {
|
||||
|
@ -248,15 +247,15 @@ class Pane extends UserWidget
|
|||
{
|
||||
/* @var $dashlet Dashlet */
|
||||
foreach ($dashlets as $dashlet) {
|
||||
if (array_key_exists($dashlet->getTitle(), $this->dashlets)) {
|
||||
if (preg_match('/_(\d+)$/', $dashlet->getTitle(), $m)) {
|
||||
$name = preg_replace('/_\d+$/', $m[1]++, $dashlet->getTitle());
|
||||
if (array_key_exists($dashlet->getName(), $this->dashlets)) {
|
||||
if (preg_match('/_(\d+)$/', $dashlet->getName(), $m)) {
|
||||
$name = preg_replace('/_\d+$/', $m[1]++, $dashlet->getName());
|
||||
} else {
|
||||
$name = $dashlet->getTitle() . '_2';
|
||||
$name = $dashlet->getName() . '_2';
|
||||
}
|
||||
$this->dashlets[$name] = $dashlet;
|
||||
} else {
|
||||
$this->dashlets[$dashlet->getTitle()] = $dashlet;
|
||||
$this->dashlets[$dashlet->getName()] = $dashlet;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2019 Icinga GmbH | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Migrate\Clicommands;
|
||||
|
||||
use Exception;
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Application\Modules\DashboardContainer;
|
||||
use Icinga\Cli\Command;
|
||||
use Icinga\Application\Logger;
|
||||
use Icinga\Util\Translator;
|
||||
use ReflectionClass;
|
||||
|
||||
class DashboardCommand extends Command
|
||||
{
|
||||
/**
|
||||
* Rename translated dashboard sections
|
||||
*
|
||||
* Migrates all locally found dashboard configurations so that the effects of
|
||||
* https://github.com/Icinga/icingaweb2/issues/3542 are reversed.
|
||||
*
|
||||
* USAGE
|
||||
*
|
||||
* icingacli migrate dashboard sections
|
||||
*/
|
||||
public function sectionsAction()
|
||||
{
|
||||
$moduleReflection = new ReflectionClass('Icinga\Application\Modules\Module');
|
||||
// There's no direct way to invoke this method
|
||||
$launchConfigScriptMethod = $moduleReflection->getMethod('launchConfigScript');
|
||||
$launchConfigScriptMethod->setAccessible(true);
|
||||
// Calling getDashboard() results in Url::fromPath() getting called as well == the CLI's death
|
||||
$paneItemsProperty = $moduleReflection->getProperty('paneItems');
|
||||
$paneItemsProperty->setAccessible(true);
|
||||
// Again, no direct way to access this nor to let the module setup its own translation domain
|
||||
$localeDirProperty = $moduleReflection->getProperty('localedir');
|
||||
$localeDirProperty->setAccessible(true);
|
||||
|
||||
$locales = Translator::getAvailableLocaleCodes();
|
||||
$modules = Icinga::app()->getModuleManager()->loadEnabledModules()->getLoadedModules();
|
||||
foreach ($this->listDashboardConfigs() as $path) {
|
||||
Logger::info('Migrating dashboard config: %s', $path);
|
||||
|
||||
$config = Config::fromIni($path);
|
||||
foreach ($modules as $module) {
|
||||
$localePath = $localeDirProperty->getValue($module);
|
||||
if (! is_dir($localePath)) {
|
||||
// Modules without any translations are not affected
|
||||
continue;
|
||||
}
|
||||
|
||||
$launchConfigScriptMethod->invoke($module);
|
||||
Translator::registerDomain($module->getName(), $localePath);
|
||||
|
||||
foreach ($locales as $locale) {
|
||||
if ($locale === 'en_US') {
|
||||
continue;
|
||||
}
|
||||
|
||||
Translator::setupLocale($locale);
|
||||
|
||||
foreach ($paneItemsProperty->getValue($module) as $paneName => $container) {
|
||||
/** @var DashboardContainer $container */
|
||||
foreach ($config->toArray() as $section => $options) {
|
||||
if (strpos($section, '.') !== false) {
|
||||
list($paneTitle, $dashletTitle) = explode('.', $section, 2);
|
||||
} else {
|
||||
$paneTitle = $section;
|
||||
$dashletTitle = null;
|
||||
}
|
||||
|
||||
if (isset($options['disabled']) && mt($module->getName(), $paneName) !== $paneTitle) {
|
||||
// `disabled` is checked because if it's a module's pane that's the only reason
|
||||
// why it's in there. If a user utilized the same label though for a custom pane,
|
||||
// it remains as is.
|
||||
continue;
|
||||
}
|
||||
|
||||
$dashletName = null;
|
||||
if ($dashletTitle !== null) {
|
||||
foreach ($container->getDashlets() as $name => $url) {
|
||||
if (mt($module->getName(), $name) === $dashletTitle) {
|
||||
$dashletName = $name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$newSection = $paneName . ($dashletName ? '.' . $dashletName : '');
|
||||
$config->removeSection($section);
|
||||
$config->setSection($newSection, $options);
|
||||
|
||||
Logger::info('Migrated section "%s" to "%s"', $section, $newSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$config->saveIni();
|
||||
}
|
||||
}
|
||||
|
||||
protected function listDashboardConfigs()
|
||||
{
|
||||
$dashboardConfigPath = Config::resolvePath('dashboards');
|
||||
|
||||
try {
|
||||
$dashboardConfigDir = opendir($dashboardConfigPath);
|
||||
} catch (Exception $e) {
|
||||
Logger::error('Cannot access dashboard configuration: %s', $e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while ($entry = readdir($dashboardConfigDir)) {
|
||||
$userDashboardPath = join(DIRECTORY_SEPARATOR, [$dashboardConfigPath, $entry, 'dashboard.ini']);
|
||||
if (is_file($userDashboardPath)) {
|
||||
yield $userDashboardPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue