diff --git a/application/controllers/PhperrorController.php b/application/controllers/PhperrorController.php
index f434b6c0e..40a32c1a7 100644
--- a/application/controllers/PhperrorController.php
+++ b/application/controllers/PhperrorController.php
@@ -3,7 +3,8 @@
namespace Icinga\Module\Director\Controllers;
use Icinga\Application\Icinga;
-use Icinga\Application\Modules\Manager;
+use Icinga\Module\Director\Application\DependencyChecker;
+use Icinga\Module\Director\Web\Table\Dependency\DependencyInfoTable;
use Icinga\Web\Controller;
class PhperrorController extends Controller
@@ -24,39 +25,19 @@ public function errorAction()
public function dependenciesAction()
{
- $dependencies = $this->view->dependencies = $this->Module()->getDependencies();
- $modules = $this->view->modules = Icinga::app()->getModuleManager();
- // Hint: we're duplicating some code here
- $satisfied = true;
- foreach ($dependencies as $module => $required) {
- /** @var Manager $this ->modules */
- if ($modules->hasEnabled($module)) {
- $installed = $modules->getModule($module, false)->getVersion();
- $installed = \ltrim($installed, 'v'); // v0.6.0 VS 0.6.0
- if (\preg_match('/^([<>=]+)\s*v?(\d+\.\d+\.\d+)$/', $required, $match)) {
- $operator = $match[1];
- $vRequired = $match[2];
- if (\version_compare($installed, $vRequired, $operator)) {
- continue;
- }
- }
- }
- $satisfied = false;
- }
-
- if ($satisfied) {
+ $checker = new DependencyChecker(Icinga::app());
+ if ($checker->satisfiesDependencies($this->Module())) {
$this->redirectNow('director');
}
-
$this->setAutorefreshInterval(15);
- $this->getTabs()->add('error', array(
+ $this->getTabs()->add('error', [
'label' => $this->translate('Error'),
'url' => $this->getRequest()->getUrl()
- ))->activate('error');
- $msg = $this->translate(
+ ])->activate('error');
+ $this->view->title = $this->translate('Unsatisfied dependencies');
+ $this->view->table = (new DependencyInfoTable($checker, $this->Module()))->render();
+ $this->view->message = $this->translate(
"Icinga Director depends on the following modules, please install/upgrade as required"
);
- $this->view->title = $this->translate('Unsatisfied dependencies');
- $this->view->message = sprintf($msg, PHP_VERSION);
}
}
diff --git a/application/views/scripts/phperror/dependencies.phtml b/application/views/scripts/phperror/dependencies.phtml
index c8d4c143c..7492a1445 100644
--- a/application/views/scripts/phperror/dependencies.phtml
+++ b/application/views/scripts/phperror/dependencies.phtml
@@ -10,62 +10,5 @@ use Icinga\Application\Modules\Manager;
= $this->escape($this->message) ?>
-
-
-
- = $this->translate('Module name') ?> |
- = $this->translate('Required') ?> |
- = $this->translate('Installed') ?> |
-
-
-
-dependencies as $module => $required) {
- /** @var Manager $this->modules */
- if ($modules->hasEnabled($module)) {
- $installed = $modules->getModule($module, false)->getVersion();
- $installed = \ltrim($installed, 'v'); // v0.6.0 VS 0.6.0
- if (\preg_match('/^([<>=]+)\s*v?(\d+\.\d+\.\d+)$/', $required, $match)) {
- $operator = $match[1];
- $vRequired = $match[2];
- if (\version_compare($installed, $vRequired, $operator)) {
- $icon = 'ok';
- } else {
- $icon = 'cancel';
- }
- } else {
- $icon = 'cancel';
- }
- $link = $this->qlink(
- $module,
- 'config/module',
- ['name' => $module],
- ['class' => "icon-$icon"]
- );
- } elseif ($modules->hasInstalled($module)) {
- $installed = $this->translate('disabled');
- $link = $this->qlink($module, 'config/module', ['name' => $module], ['class' => 'icon-cancel']);
- } else {
- $installed = $this->translate('missing');
- $link = sprintf(
- '%s (%s)',
- $this->escape($module),
- $this->escape($module),
- $this->translate('more')
- );
- }
-
- \printf(
- '%s | %s | %s |
',
- $link,
- $this->escape($required),
- $this->escape($installed)
- );
-}
-
-?>
-
-
+= $this->table ?>
diff --git a/doc/82-Changelog.md b/doc/82-Changelog.md
index 76bb240a0..656ea5fb9 100644
--- a/doc/82-Changelog.md
+++ b/doc/82-Changelog.md
@@ -48,6 +48,7 @@ next patch release (will be 1.8.1)
* FIX: show "deactivated" services as such also for read-only users (#2344)
* FIX: Overrides for Services belonging to Sets on root Host Templates (#2333)
* FIX: show no header tabs for search result in web 2.8+ (#2141)
+* FIX: show and link dependencies for web 2.9+ (#2354)
### Icinga Configuration
* FIX: rare race condition, where generated config might miss some files (#2351)
diff --git a/library/Director/Application/Dependency.php b/library/Director/Application/Dependency.php
new file mode 100644
index 000000000..0100e69fa
--- /dev/null
+++ b/library/Director/Application/Dependency.php
@@ -0,0 +1,113 @@
+=1.7.0
+ * @param string $installedVersion
+ * @param bool $enabled
+ */
+ public function __construct($name, $requirement, $installedVersion = null, $enabled = null)
+ {
+ $this->name = $name;
+ $this->setRequirement($requirement);
+ if ($installedVersion !== null) {
+ $this->setInstalledVersion($installedVersion);
+ }
+ if ($enabled !== null) {
+ $this->setEnabled($enabled);
+ }
+ }
+
+ public function setRequirement($requirement)
+ {
+ if (preg_match('/^([<>=]+)\s*v?(\d+\.\d+\.\d+)$/', $requirement, $match)) {
+ $this->operator = $match[1];
+ $this->requiredVersion = $match[2];
+ $this->requirement = $requirement;
+ } else {
+ throw new \InvalidArgumentException("'$requirement' is not a valid version constraint");
+ }
+ }
+
+ /**
+ * @return bool
+ */
+ public function isInstalled()
+ {
+ return $this->installedVersion !== null;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getInstalledVersion()
+ {
+ return $this->installedVersion;
+ }
+
+ /**
+ * @param string $version
+ */
+ public function setInstalledVersion($version)
+ {
+ $this->installedVersion = ltrim($version, 'v'); // v0.6.0 VS 0.6.0
+ }
+
+ /**
+ * @return bool
+ */
+ public function isEnabled()
+ {
+ return $this->enabled === true;
+ }
+
+ /**
+ * @param bool $enabled
+ */
+ public function setEnabled($enabled = true)
+ {
+ $this->enabled = $enabled;
+ }
+
+ public function isSatisfied()
+ {
+ if (! $this->isInstalled() || ! $this->isEnabled()) {
+ return false;
+ }
+
+ return version_compare($this->installedVersion, $this->requiredVersion, $this->operator);
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function getRequirement()
+ {
+ return $this->requirement;
+ }
+}
diff --git a/library/Director/Application/DependencyChecker.php b/library/Director/Application/DependencyChecker.php
new file mode 100644
index 000000000..d726b0b6a
--- /dev/null
+++ b/library/Director/Application/DependencyChecker.php
@@ -0,0 +1,73 @@
+app = $app;
+ $this->modules = $app->getModuleManager();
+ }
+
+ /**
+ * @param Module $module
+ * @return Dependency[]
+ */
+ public function getDependencies(Module $module)
+ {
+ $dependencies = [];
+ $isV290 = version_compare(Version::VERSION, '2.9.0', '>=');
+ foreach ($module->getDependencies() as $moduleName => $required) {
+ if ($isV290 && in_array($moduleName, ['ipl', 'reactbundle'], true)) {
+ continue;
+ }
+ $dependency = new Dependency($moduleName, $required);
+ $dependency->setEnabled($this->modules->hasEnabled($moduleName));
+ if ($this->modules->hasInstalled($moduleName)) {
+ $dependency->setInstalledVersion($this->modules->getModule($moduleName, false)->getVersion());
+ }
+ $dependencies[] = $dependency;
+ }
+ if ($isV290) {
+ $libs = $this->app->getLibraries();
+ foreach ($module->getRequiredLibraries() as $libraryName => $required) {
+ $dependency = new Dependency($libraryName, $required);
+ if ($libs->has($libraryName)) {
+ $dependency->setInstalledVersion($libs->get($libraryName)->getVersion());
+ $dependency->setEnabled();
+ }
+ $dependencies[] = $dependency;
+ }
+ }
+
+ return $dependencies;
+ }
+
+ // if (version_compare(Version::VERSION, '2.9.0', 'ge')) {
+ // }
+ /**
+ * @param Module $module
+ * @return bool
+ */
+ public function satisfiesDependencies(Module $module)
+ {
+ foreach ($this->getDependencies($module) as $dependency) {
+ if (! $dependency->isSatisfied()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/library/Director/Web/Table/Dependency/DependencyInfoTable.php b/library/Director/Web/Table/Dependency/DependencyInfoTable.php
new file mode 100644
index 000000000..28aa856d9
--- /dev/null
+++ b/library/Director/Web/Table/Dependency/DependencyInfoTable.php
@@ -0,0 +1,101 @@
+module = $module;
+ $this->checker = $checker;
+ }
+
+ protected function linkToModule($name, $icon)
+ {
+ return Html::link(
+ Html::escape($name),
+ Html::webUrl('config/module', ['name' => $name]),
+ [
+ 'class' => "icon-$icon"
+ ]
+ );
+ }
+
+ public function render()
+ {
+ $html = '