icingaweb2/library/Icinga/Application/Modules/Manager.php

250 lines
6.5 KiB
PHP
Raw Normal View History

<?php
namespace Icinga\Application\Modules;
use Icinga\Application\ApplicationBootstrap;
use Icinga\Data\ArrayDatasource;
use Icinga\Web\Notification;
use Icinga\Exception\ConfigurationError;
// TODO: show whether enabling/disabling modules is allowed by checking enableDir
// perms
class Manager
{
protected $installedBaseDirs;
protected $enabledDirs = array();
protected $loadedModules = array();
protected $index;
protected $app;
protected $enableDir;
public function __construct(ApplicationBootstrap $app)
{
$this->app = $app;
$this->prepareEssentials();
$this->detectEnabledModules();
}
protected function prepareEssentials()
{
$this->enableDir = $this->app->getConfig()->getConfigDir()
. '/enabledModules';
if (! file_exists($this->enableDir) || ! is_dir($this->enableDir)) {
throw new ProgrammingError(
sprintf(
'Missing module directory: %s',
$this->enableDir
)
);
}
}
protected function detectEnabledModules()
{
$fh = opendir($this->enableDir);
while (false !== ($file = readdir($fh))) {
if ($file[0] === '.') {
continue;
}
$link = $this->enableDir . '/' . $file;
if (! is_link($link)) {
continue;
}
$dir = realpath($link);
if (! file_exists($dir) || ! is_dir($dir)) {
continue;
}
$this->enabledDirs[$file] = $dir;
}
}
public function loadEnabledModules()
{
foreach ($this->listEnabledModules() as $name) {
$this->loadModule($name);
}
return $this;
}
public function loadModule($name)
{
if ($this->hasLoaded($name)) {
return $this;
}
$module = new Module($this->app, $name, $this->getModuleDir($name));
$module->register();
$this->loadedModules[$name] = $module;
return $this;
}
public function enableModule($name)
{
if (! $this->hasInstalled($name)) {
throw new ConfigurationError(
sprintf(
"Cannot enable module '%s' as it isn't installed",
$name
)
);
return $this;
}
$target = $this->installedBaseDirs[$name];
$link = $this->enableDir . '/' . $name;
if (! is_writable($this->enableDir)) {
Notification::error("I do not have permissions to enable modules");
return $this;
}
if (@symlink($target, $link)) {
Notification::success("The module $name has been enabled");
} else {
Notification::error("Enabling module $name failed");
}
return $this;
}
public function disableModule($name)
{
if (! $this->hasEnabled($name)) {
return $this;
}
if (! is_writable($this->enableDir)) {
Notification::error("I do not have permissions to disable modules");
return $this;
}
$link = $this->enableDir . '/' . $name;
if (file_exists($link) && is_link($link)) {
if (@unlink($link)) {
Notification::success("The module $name has been disabled");
} else {
Notification::error("Disabling module $name failed");
}
}
return $this;
}
public function getModuleConfigDir($name)
{
return $this->getModuleDir($name, '/config');
}
public function getModuleDir($name, $subdir = '')
{
if ($this->hasEnabled($name)) {
return $this->enabledDirs[$name]. $subdir;
}
if ($this->hasInstalled($name)) {
return $this->installedBaseDirs[$name] . $subdir;
}
throw new ProgrammingError(
sprintf(
'Trying to access uninstalled module dir: %s',
$name
)
);
}
public function hasInstalled($name)
{
if ($this->installedBaseDirs === null) {
$this->detectInstalledModules();
}
return array_key_exists($name, $this->installedBaseDirs);
}
public function hasEnabled($name)
{
return array_key_exists($name, $this->enabledDirs);
}
public function hasLoaded($name)
{
return array_key_exists($name, $this->loadedModules);
}
public function getLoadedModules()
{
return $this->loadedModules;
}
public function getModule($name)
{
if (! $this->hasLoaded($name)) {
throw new ProgrammingError(
sprintf(
'Cannot access module %s as it hasn\'t been loaded',
$name
)
);
}
return $this->loadedModules[$name];
}
public function getModuleInfo()
{
$installed = $this->listInstalledModules();
$info = array();
foreach ($installed as $name) {
$info[] = (object) array(
'name' => $name,
'path' => $this->installedBaseDirs[$name],
'enabled' => $this->hasEnabled($name),
'loaded' => $this->hasLoaded($name)
);
}
return $info;
}
public function select()
{
$ds = new ArrayDatasource($this->getModuleInfo());
return $ds->select();
}
public function listEnabledModules()
{
return array_keys($this->enabledDirs);
}
public function listLoadedModules()
{
return array_keys($this->loadedModules);
}
public function listInstalledModules()
{
if ($this->installedBaseDirs === null) {
$this->detectInstalledModules();
}
return array_keys($this->installedBaseDirs);
}
public function detectInstalledModules()
{
// TODO: Allow multiple paths for installed modules (e.g. web vs pkg)
$basedir = realpath(ICINGA_APPDIR . '/../modules');
$fh = @opendir($basedir);
if ($fh === false) {
return $this;
}
while ($name = readdir($fh)) {
if ($name[0] === '.') {
continue;
}
if (is_dir($basedir . '/' . $name)) {
$this->installedBaseDirs[$name] = $basedir . '/' . $name;
}
}
}
}