+
-
+
\ No newline at end of file
diff --git a/modules/setup/library/Setup/Requirement.php b/modules/setup/library/Setup/Requirement.php
new file mode 100644
index 000000000..37bb5663e
--- /dev/null
+++ b/modules/setup/library/Setup/Requirement.php
@@ -0,0 +1,279 @@
+optional = false;
+ $this->descriptions = array();
+
+ foreach ($options as $key => $value) {
+ $setMethod = 'set' . ucfirst($key);
+ $addMethod = 'add' . ucfirst($key);
+ if (method_exists($this, $setMethod)) {
+ $this->$setMethod($value);
+ } elseif (method_exists($this, $addMethod)) {
+ $this->$addMethod($value);
+ } else {
+ throw LogicException('No setter found for option key: ' . $key);
+ }
+ }
+ }
+
+ /**
+ * Set the state of this requirement
+ *
+ * @param bool $state
+ *
+ * @return Requirement
+ */
+ public function setState($state)
+ {
+ $this->state = (bool) $state;
+ return $this;
+ }
+
+ /**
+ * Return the state of this requirement
+ *
+ * Evaluates the requirement in case there is no state set yet.
+ *
+ * @return int
+ */
+ public function getState()
+ {
+ if ($this->state === null) {
+ $this->state = $this->evaluate();
+ }
+
+ return $this->state;
+ }
+
+ /**
+ * Set a descriptive text for this requirement's current state
+ *
+ * @param string $text
+ *
+ * @return Requirement
+ */
+ public function setStateText($text)
+ {
+ $this->stateText = $text;
+ return $this;
+ }
+
+ /**
+ * Return a descriptive text for this requirement's current state
+ *
+ * @return string
+ */
+ public function getStateText()
+ {
+ return $this->stateText;
+ }
+
+ /**
+ * Add a description for this requirement
+ *
+ * @param string $description
+ *
+ * @return Requirement
+ */
+ public function addDescription($description)
+ {
+ $this->descriptions[] = $description;
+ return $this;
+ }
+
+ /**
+ * Return the descriptions of this wizard
+ *
+ * @return array
+ */
+ public function getDescriptions()
+ {
+ return $this->descriptions;
+ }
+
+ /**
+ * Set the title for this requirement
+ *
+ * @param string $title
+ *
+ * @return Requirement
+ */
+ public function setTitle($title)
+ {
+ $this->title = $title;
+ return $this;
+ }
+
+ /**
+ * Return the title of this requirement
+ *
+ * In case there is no title set the alias is returned instead.
+ *
+ * @return string
+ */
+ public function getTitle()
+ {
+ if ($this->title === null) {
+ return $this->getAlias();
+ }
+
+ return $this->title;
+ }
+
+ /**
+ * Set the condition for this requirement
+ *
+ * @param mixed $condition
+ *
+ * @return Requirement
+ */
+ public function setCondition($condition)
+ {
+ $this->condition = $condition;
+ return $this;
+ }
+
+ /**
+ * Return the condition of this requirement
+ *
+ * @return mixed
+ */
+ public function getCondition()
+ {
+ return $this->condition;
+ }
+
+ /**
+ * Set whether this requirement is optional
+ *
+ * @param bool $state
+ *
+ * @return Requirement
+ */
+ public function setOptional($state = true)
+ {
+ $this->optional = (bool) $state;
+ return $this;
+ }
+
+ /**
+ * Return whether this requirement is optional
+ *
+ * @return bool
+ */
+ public function isOptional()
+ {
+ return $this->optional;
+ }
+
+ /**
+ * Set the alias to display the condition with in a human readable way
+ *
+ * @param string $alias
+ *
+ * @return Requirement
+ */
+ public function setAlias($alias)
+ {
+ $this->alias = $alias;
+ return $this;
+ }
+
+ /**
+ * Return the alias to display the condition with in a human readable way
+ *
+ * @return string
+ */
+ public function getAlias()
+ {
+ return $this->alias;
+ }
+
+ /**
+ * Evaluate this requirement and return whether it is fulfilled
+ *
+ * @return bool
+ */
+ abstract protected function evaluate();
+
+ /**
+ * Return whether the given requirement equals this one
+ *
+ * @param Requirement $requirement
+ *
+ * @return bool
+ */
+ public function equals(Requirement $requirement)
+ {
+ if ($requirement instanceof static) {
+ return $this->getCondition() === $requirement->getCondition();
+ }
+
+ return false;
+ }
+}
diff --git a/modules/setup/library/Setup/Requirement/ClassRequirement.php b/modules/setup/library/Setup/Requirement/ClassRequirement.php
new file mode 100644
index 000000000..e0f25cf4e
--- /dev/null
+++ b/modules/setup/library/Setup/Requirement/ClassRequirement.php
@@ -0,0 +1,28 @@
+getCondition();
+ if (Platform::classExists($classNameOrPath)) {
+ $this->setStateText(sprintf(
+ mt('setup', 'The %s is available.', 'setup.requirement.class'),
+ $this->getAlias() ?: $classNameOrPath . ' ' . mt('setup', 'class', 'setup.requirement.class')
+ ));
+ return true;
+ } else {
+ $this->setStateText(sprintf(
+ mt('setup', 'The %s is missing.', 'setup.requirement.class'),
+ $this->getAlias() ?: $classNameOrPath . ' ' . mt('setup', 'class', 'setup.requirement.class')
+ ));
+ return false;
+ }
+ }
+}
diff --git a/modules/setup/library/Setup/Requirement/ConfigDirectoryRequirement.php b/modules/setup/library/Setup/Requirement/ConfigDirectoryRequirement.php
new file mode 100644
index 000000000..3404717db
--- /dev/null
+++ b/modules/setup/library/Setup/Requirement/ConfigDirectoryRequirement.php
@@ -0,0 +1,42 @@
+getCondition();
+ if (file_exists($path)) {
+ $readable = is_readable($path);
+ if ($readable && is_writable($path)) {
+ $this->setStateText(sprintf(mt('setup', 'The directory %s is read- and writable.'), $path));
+ return true;
+ } else {
+ $this->setStateText(sprintf(
+ $readable
+ ? mt('setup', 'The directory %s is not writable.')
+ : mt('setup', 'The directory %s is not readable.'),
+ $path
+ ));
+ return false;
+ }
+ } else {
+ $this->setStateText(sprintf(mt('setup', 'The directory %s does not exist.'), $path));
+ return false;
+ }
+ }
+}
diff --git a/modules/setup/library/Setup/Requirement/OSRequirement.php b/modules/setup/library/Setup/Requirement/OSRequirement.php
new file mode 100644
index 000000000..ff185bb3c
--- /dev/null
+++ b/modules/setup/library/Setup/Requirement/OSRequirement.php
@@ -0,0 +1,27 @@
+getCondition()));
+ }
+
+ return $title;
+ }
+
+ protected function evaluate()
+ {
+ $phpOS = Platform::getOperatingSystemName();
+ $this->setStateText(sprintf(mt('setup', 'You are running PHP on a %s system.'), ucfirst($phpOS)));
+ return strtolower($phpOS) === strtolower($this->getCondition());
+ }
+}
diff --git a/modules/setup/library/Setup/Requirement/PhpConfigRequirement.php b/modules/setup/library/Setup/Requirement/PhpConfigRequirement.php
new file mode 100644
index 000000000..670c988e4
--- /dev/null
+++ b/modules/setup/library/Setup/Requirement/PhpConfigRequirement.php
@@ -0,0 +1,22 @@
+getCondition();
+ $configValue = Platform::getPhpConfig($configDirective);
+ $this->setStateText(
+ $configValue
+ ? sprintf(mt('setup', 'The PHP config `%s\' is set to "%s".'), $configDirective, $configValue)
+ : sprintf(mt('setup', 'The PHP config `%s\' is not defined.'), $configDirective)
+ );
+ return is_bool($value) ? $configValue == $value : $configValue === $value;
+ }
+}
diff --git a/modules/setup/library/Setup/Requirement/PhpModuleRequirement.php b/modules/setup/library/Setup/Requirement/PhpModuleRequirement.php
new file mode 100644
index 000000000..6581797ce
--- /dev/null
+++ b/modules/setup/library/Setup/Requirement/PhpModuleRequirement.php
@@ -0,0 +1,42 @@
+getAlias()) {
+ if ($title === null) {
+ $title = $this->getCondition();
+ }
+
+ return sprintf(mt('setup', 'PHP Module: %s'), $title);
+ }
+
+ return $title;
+ }
+
+ protected function evaluate()
+ {
+ $moduleName = $this->getCondition();
+ if (Platform::extensionLoaded($moduleName)) {
+ $this->setStateText(sprintf(
+ mt('setup', 'The PHP module %s is available.'),
+ $this->getAlias() ?: $moduleName
+ ));
+ return true;
+ } else {
+ $this->setStateText(sprintf(
+ mt('setup', 'The PHP module %s is missing.'),
+ $this->getAlias() ?: $moduleName
+ ));
+ return false;
+ }
+ }
+}
diff --git a/modules/setup/library/Setup/Requirement/PhpVersionRequirement.php b/modules/setup/library/Setup/Requirement/PhpVersionRequirement.php
new file mode 100644
index 000000000..d6ca5f189
--- /dev/null
+++ b/modules/setup/library/Setup/Requirement/PhpVersionRequirement.php
@@ -0,0 +1,28 @@
+setStateText(sprintf(mt('setup', 'You are running PHP version %s.'), $phpVersion));
+ list($operator, $requiredVersion) = $this->getCondition();
+ return version_compare($phpVersion, $requiredVersion, $operator);
+ }
+}
diff --git a/modules/setup/library/Setup/RequirementSet.php b/modules/setup/library/Setup/RequirementSet.php
new file mode 100644
index 000000000..8bb018d7b
--- /dev/null
+++ b/modules/setup/library/Setup/RequirementSet.php
@@ -0,0 +1,333 @@
+optional = $optional;
+ $this->requirements = array();
+ $this->setMode($mode ?: static::MODE_AND);
+ }
+
+ /**
+ * Set the state of this set
+ *
+ * @param bool $state
+ *
+ * @return RequirementSet
+ */
+ public function setState($state)
+ {
+ $this->state = (bool) $state;
+ return $this;
+ }
+
+ /**
+ * Return the state of this set
+ *
+ * Alias for RequirementSet::fulfilled(true).
+ *
+ * @return bool
+ */
+ public function getState()
+ {
+ return $this->fulfilled(true);
+ }
+
+ /**
+ * Set whether this set of requirements should be optional
+ *
+ * @param bool $state
+ *
+ * @return RequirementSet
+ */
+ public function setOptional($state = true)
+ {
+ $this->optional = (bool) $state;
+ return $this;
+ }
+
+ /**
+ * Return whether this set of requirements is optional
+ *
+ * @return bool
+ */
+ public function isOptional()
+ {
+ return $this->optional;
+ }
+
+ /**
+ * Set the mode by which to evaluate the requirements
+ *
+ * @param int $mode
+ *
+ * @return RequirementSet
+ *
+ * @throws LogicException In case the given mode is invalid
+ */
+ public function setMode($mode)
+ {
+ if ($mode !== static::MODE_AND && $mode !== static::MODE_OR) {
+ throw new LogicException(sprintf('Invalid mode %u given.'), $mode);
+ }
+
+ $this->mode = $mode;
+ return $this;
+ }
+
+ /**
+ * Return the mode by which the requirements are evaluated
+ *
+ * @return int
+ */
+ public function getMode()
+ {
+ return $this->mode;
+ }
+
+ /**
+ * Register a requirement
+ *
+ * @param Requirement $requirement The requirement to add
+ *
+ * @return RequirementSet
+ */
+ public function add(Requirement $requirement)
+ {
+ $merged = false;
+ foreach ($this->requirements as $knownRequirement) {
+ if ($knownRequirement instanceof Requirement && $requirement->equals($knownRequirement)) {
+ $knownRequirement->setOptional($requirement->isOptional());
+ foreach ($requirement->getDescriptions() as $description) {
+ $knownRequirement->addDescription($description);
+ }
+
+ $merged = true;
+ break;
+ }
+ }
+
+ if (! $merged) {
+ $this->requirements[] = $requirement;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Return all registered requirements
+ *
+ * @return array
+ */
+ public function getAll()
+ {
+ return $this->requirements;
+ }
+
+ /**
+ * Register the given set of requirements
+ *
+ * @param RequirementSet $set The set to register
+ *
+ * @return RequirementSet
+ */
+ public function merge(RequirementSet $set)
+ {
+ if ($this->getMode() === $set->getMode() && $this->isOptional() === $set->isOptional()) {
+ foreach ($set->getAll() as $requirement) {
+ if ($requirement instanceof static) {
+ $this->merge($requirement);
+ } else {
+ $this->add($requirement);
+ }
+ }
+ } else {
+ $this->requirements[] = $set;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Return whether all requirements can successfully be evaluated based on the current mode
+ *
+ * In case this is a optional set of requirements (and $force is false), true is returned immediately.
+ *
+ * @param bool $force Whether to ignore the optionality of a set or single requirement
+ *
+ * @return bool
+ */
+ public function fulfilled($force = false)
+ {
+ $state = $this->isOptional();
+ if (! $force && $state) {
+ return true;
+ }
+
+ if (! $force && $this->state !== null) {
+ return $this->state;
+ } elseif ($force && $this->forcedState !== null) {
+ return $this->forcedState;
+ }
+
+ $self = $this->requirements;
+ foreach ($self as $requirement) {
+ if ($requirement->getState()) {
+ $state = true;
+ if ($this->getMode() === static::MODE_OR) {
+ break;
+ }
+ } elseif ($force || !$requirement->isOptional()) {
+ $state = false;
+ if ($this->getMode() === static::MODE_AND) {
+ break;
+ }
+ }
+ }
+
+ if ($force) {
+ return $this->forcedState = $state;
+ }
+
+ return $this->state = $state;
+ }
+
+ /**
+ * Return whether the current element represents a nested set of requirements
+ *
+ * @return bool
+ */
+ public function hasChildren()
+ {
+ $current = $this->current();
+ return $current instanceof static;
+ }
+
+ /**
+ * Return a iterator for the current nested set of requirements
+ *
+ * @return RecursiveIterator
+ */
+ public function getChildren()
+ {
+ return $this->current();
+ }
+
+ /**
+ * Rewind the iterator to its first element
+ */
+ public function rewind()
+ {
+ reset($this->requirements);
+ }
+
+ /**
+ * Return whether the current iterator position is valid
+ *
+ * @return bool
+ */
+ public function valid()
+ {
+ return $this->key() !== null;
+ }
+
+ /**
+ * Return the current element in the iteration
+ *
+ * @return Requirement|RequirementSet
+ */
+ public function current()
+ {
+ return current($this->requirements);
+ }
+
+ /**
+ * Return the position of the current element in the iteration
+ *
+ * @return int
+ */
+ public function key()
+ {
+ return key($this->requirements);
+ }
+
+ /**
+ * Advance the iterator to the next element
+ */
+ public function next()
+ {
+ next($this->requirements);
+ }
+
+ /**
+ * Return this set of requirements rendered as HTML
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $renderer = new RequirementsRenderer($this);
+ return (string) $renderer;
+ }
+}
diff --git a/modules/setup/library/Setup/Requirements.php b/modules/setup/library/Setup/Requirements.php
deleted file mode 100644
index bede70aa0..000000000
--- a/modules/setup/library/Setup/Requirements.php
+++ /dev/null
@@ -1,197 +0,0 @@
-requirements[$name] = array_key_exists($name, $this->requirements)
- ? $this->combine($this->requirements[$name], $requirement)
- : $requirement;
- return $this;
- }
-
- /**
- * Combine the two given requirements
- *
- * Returns the most important requirement with the description from the other one being added.
- *
- * @param object $oldRequirement
- * @param object $newRequirement
- *
- * @return object
- */
- protected function combine($oldRequirement, $newRequirement)
- {
- if ($newRequirement->state === static::STATE_MANDATORY && $oldRequirement->state === static::STATE_OPTIONAL) {
- $tempRequirement = $oldRequirement;
- $oldRequirement = $newRequirement;
- $newRequirement = $tempRequirement;
- }
-
- if (! is_array($oldRequirement->description)) {
- $oldRequirement->description = array($oldRequirement->description);
- }
-
- $oldRequirement->description[] = $newRequirement->description;
- return $oldRequirement;
- }
-
- /**
- * Return all registered requirements
- *
- * @return array
- */
- public function getAll()
- {
- return $this->requirements;
- }
-
- /**
- * Return an iterator of all registered requirements
- *
- * @return ArrayIterator
- */
- public function getIterator()
- {
- return new ArrayIterator($this->getAll());
- }
-
- /**
- * Register an optional requirement
- *
- * @param string $name
- * @param string $title
- * @param string $description
- * @param bool $state
- * @param string $message
- *
- * @return self
- */
- public function addOptional($name, $title, $description, $state, $message)
- {
- $this->add(
- $name,
- (object) array(
- 'title' => $title,
- 'message' => $message,
- 'description' => $description,
- 'state' => (bool) $state ? static::STATE_OK : static::STATE_OPTIONAL
- )
- );
- return $this;
- }
-
- /**
- * Register a mandatory requirement
- *
- * @param string $name
- * @param string $title
- * @param string $description
- * @param bool $state
- * @param string $message
- *
- * @return self
- */
- public function addMandatory($name, $title, $description, $state, $message)
- {
- $this->add(
- $name,
- (object) array(
- 'title' => $title,
- 'message' => $message,
- 'description' => $description,
- 'state' => (bool) $state ? static::STATE_OK : static::STATE_MANDATORY
- )
- );
- return $this;
- }
-
- /**
- * Register the given requirements
- *
- * @param Requirements $requirements The requirements to register
- *
- * @return self
- */
- public function merge(Requirements $requirements)
- {
- foreach ($requirements->getAll() as $name => $requirement) {
- $this->add($name, $requirement);
- }
-
- return $this;
- }
-
- /**
- * Make all registered requirements being optional
- *
- * @return self
- */
- public function allOptional()
- {
- foreach ($this->getAll() as $requirement) {
- if ($requirement->state === static::STATE_MANDATORY) {
- $requirement->state = static::STATE_OPTIONAL;
- }
- }
-
- return $this;
- }
-
- /**
- * Return whether all mandatory requirements are fulfilled
- *
- * @return bool
- */
- public function fulfilled()
- {
- foreach ($this->getAll() as $requirement) {
- if ($requirement->state === static::STATE_MANDATORY) {
- return false;
- }
- }
-
- return true;
- }
-}
diff --git a/modules/setup/library/Setup/RequirementsRenderer.php b/modules/setup/library/Setup/RequirementsRenderer.php
new file mode 100644
index 000000000..b768a1e86
--- /dev/null
+++ b/modules/setup/library/Setup/RequirementsRenderer.php
@@ -0,0 +1,83 @@
+tags[] = '
';
+ $this->tags[] = '';
+ }
+
+ public function endIteration()
+ {
+ $this->tags[] = '';
+ $this->tags[] = '
';
+ }
+
+ public function beginChildren()
+ {
+ $this->tags[] = '
';
+ $currentSet = $this->getSubIterator();
+ $state = $currentSet->getState() ? 'fulfilled' : (
+ $currentSet->isOptional() ? 'not-available' : 'missing'
+ );
+ $colSpanRequired = $this->hasSingleRequirements($this->getSubIterator($this->getDepth() - 1));
+ $this->tags[] = '';
+ $this->beginIteration();
+ }
+
+ public function endChildren()
+ {
+ $this->endIteration();
+ $this->tags[] = ' | ';
+ $this->tags[] = '
';
+ }
+
+ protected function hasSingleRequirements(RequirementSet $requirements)
+ {
+ $set = $requirements->getAll();
+ foreach ($set as $entry) {
+ if ($entry instanceof Requirement) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function render()
+ {
+ foreach ($this as $requirement) {
+ $this->tags[] = '
';
+ $this->tags[] = '' . $requirement->getTitle() . ' | ';
+ $this->tags[] = '';
+ $descriptions = $requirement->getDescriptions();
+ if (count($descriptions) > 1) {
+ $this->tags[] = '';
+ foreach ($descriptions as $d) {
+ $this->tags[] = '- ' . $d . '
';
+ }
+ $this->tags[] = ' ';
+ } elseif (! empty($descriptions)) {
+ $this->tags[] = $descriptions[0];
+ }
+ $this->tags[] = ' | ';
+ $this->tags[] = '' . $requirement->getStateText() . ' | ';
+ $this->tags[] = '
';
+ }
+
+ return implode("\n", $this->tags);
+ }
+
+ public function __toString()
+ {
+ return $this->render();
+ }
+}
diff --git a/modules/setup/library/Setup/SetupWizard.php b/modules/setup/library/Setup/SetupWizard.php
index 9e7b45174..1ce948dc1 100644
--- a/modules/setup/library/Setup/SetupWizard.php
+++ b/modules/setup/library/Setup/SetupWizard.php
@@ -18,7 +18,7 @@ interface SetupWizard
/**
* Return the requirements of this wizard
*
- * @return Requirements
+ * @return RequirementSet
*/
public function getRequirements();
}
diff --git a/modules/setup/library/Setup/WebWizard.php b/modules/setup/library/Setup/WebWizard.php
index 0bf575033..d16b614f5 100644
--- a/modules/setup/library/Setup/WebWizard.php
+++ b/modules/setup/library/Setup/WebWizard.php
@@ -9,7 +9,6 @@ use Icinga\Web\Wizard;
use Icinga\Web\Request;
use Icinga\Application\Config;
use Icinga\Application\Icinga;
-use Icinga\Application\Platform;
use Icinga\Module\Setup\Forms\ModulePage;
use Icinga\Module\Setup\Forms\WelcomePage;
use Icinga\Module\Setup\Forms\SummaryPage;
@@ -29,8 +28,13 @@ use Icinga\Module\Setup\Steps\GeneralConfigStep;
use Icinga\Module\Setup\Steps\ResourceStep;
use Icinga\Module\Setup\Steps\AuthenticationStep;
use Icinga\Module\Setup\Utils\EnableModuleStep;
-use Icinga\Module\Setup\Utils\MakeDirStep;
use Icinga\Module\Setup\Utils\DbTool;
+use Icinga\Module\Setup\Requirement\OSRequirement;
+use Icinga\Module\Setup\Requirement\ClassRequirement;
+use Icinga\Module\Setup\Requirement\PhpConfigRequirement;
+use Icinga\Module\Setup\Requirement\PhpModuleRequirement;
+use Icinga\Module\Setup\Requirement\PhpVersionRequirement;
+use Icinga\Module\Setup\Requirement\ConfigDirectoryRequirement;
/**
* Icinga Web 2 Setup Wizard
@@ -111,7 +115,7 @@ class WebWizard extends Wizard implements SetupWizard
public function setupPage(Form $page, Request $request)
{
if ($page->getName() === 'setup_requirements') {
- $page->setRequirements($this->getRequirements());
+ $page->setWizard($this);
} elseif ($page->getName() === 'setup_preferences_type') {
$authData = $this->getPageData('setup_authentication_type');
if ($authData['type'] === 'db') {
@@ -351,203 +355,159 @@ class WebWizard extends Wizard implements SetupWizard
/**
* @see SetupWizard::getRequirements()
*/
- public function getRequirements()
+ public function getRequirements($skipModules = false)
{
- $requirements = new Requirements();
+ $set = new RequirementSet();
- $phpVersion = Platform::getPhpVersion();
- $requirements->addMandatory(
- 'php_version_>=_5_3_2',
- mt('setup', 'PHP Version'),
- mt(
+ $set->add(new PhpVersionRequirement(array(
+ 'condition' => array('>=', '5.3.2'),
+ 'description' => mt(
'setup',
'Running Icinga Web 2 requires PHP version 5.3.2. Advanced features'
. ' like the built-in web server require PHP version 5.4.'
- ),
- version_compare($phpVersion, '5.3.2', '>='),
- sprintf(mt('setup', 'You are running PHP version %s.'), $phpVersion)
- );
+ )
+ )));
- $defaultTimezone = Platform::getPhpConfig('date.timezone');
- $requirements->addMandatory(
- 'existing_default_timezone',
- mt('setup', 'Default Timezone'),
- sprintf(
+ $set->add(new PhpConfigRequirement(array(
+ 'condition' => array('date.timezone', true),
+ 'title' => mt('setup', 'Default Timezone'),
+ 'description' => sprintf(
mt('setup', 'It is required that a default timezone has been set using date.timezone in %s.'),
php_ini_loaded_file() ?: 'php.ini'
),
- $defaultTimezone,
- $defaultTimezone ? sprintf(mt('setup', 'Your default timezone is: %s'), $defaultTimezone) : (
- mt('setup', 'You did not define a default timezone.')
- )
- );
+ )));
- $requirements->addOptional(
- 'platform=linux',
- mt('setup', 'Linux Platform'),
- mt(
+ $set->add(new OSRequirement(array(
+ 'optional' => true,
+ 'condition' => 'linux',
+ 'description' => mt(
'setup',
'Icinga Web 2 is developed for and tested on Linux. While we cannot'
. ' guarantee they will, other platforms may also perform as well.'
- ),
- Platform::isLinux(),
- sprintf(mt('setup', 'You are running PHP on a %s system.'), Platform::getOperatingSystemName())
- );
-
- $requirements->addMandatory(
- 'existing_php_mod_openssl',
- mt('setup', 'PHP Module: OpenSSL'),
- mt('setup', 'The PHP module for OpenSSL is required to generate cryptographically safe password salts.'),
- Platform::extensionLoaded('openssl'),
- Platform::extensionLoaded('openssl') ? mt('setup', 'The PHP module for OpenSSL is available.') : (
- mt('setup', 'The PHP module for OpenSSL is missing.')
)
- );
+ )));
- $requirements->addOptional(
- 'existing_php_mod_json',
- mt('setup', 'PHP Module: JSON'),
- mt('setup', 'The JSON module for PHP is required for various export functionalities as well as APIs.'),
- Platform::extensionLoaded('json'),
- Platform::extensionLoaded('json') ? mt('setup', 'The PHP module JSON is available.') : (
- mt('setup', 'The PHP module JSON is missing.')
+ $set->add(new PhpModuleRequirement(array(
+ 'condition' => 'OpenSSL',
+ 'description' => mt(
+ 'setup',
+ 'The PHP module for OpenSSL is required to generate cryptographically safe password salts.'
)
- );
+ )));
- $requirements->addOptional(
- 'existing_php_mod_ldap',
- mt('setup', 'PHP Module: LDAP'),
- mt('setup', 'If you\'d like to authenticate users using LDAP the corresponding PHP module is required'),
- Platform::extensionLoaded('ldap'),
- Platform::extensionLoaded('ldap') ? mt('setup', 'The PHP module LDAP is available') : (
- mt('setup', 'The PHP module LDAP is missing')
+ $set->add(new PhpModuleRequirement(array(
+ 'optional' => true,
+ 'condition' => 'JSON',
+ 'description' => mt(
+ 'setup',
+ 'The JSON module for PHP is required for various export functionalities as well as APIs.'
)
- );
+ )));
- $requirements->addOptional(
- 'existing_php_mod_intl',
- mt('setup', 'PHP Module: INTL'),
- mt(
+ $set->add(new PhpModuleRequirement(array(
+ 'optional' => true,
+ 'condition' => 'LDAP',
+ 'description' => mt(
+ 'setup',
+ 'If you\'d like to authenticate users using LDAP the corresponding PHP module is required.'
+ )
+ )));
+
+ $set->add(new PhpModuleRequirement(array(
+ 'optional' => true,
+ 'condition' => 'INTL',
+ 'description' => mt(
'setup',
'If you want your users to benefit from language, timezone and date/time'
. ' format negotiation, the INTL module for PHP is required.'
- ),
- Platform::extensionLoaded('intl'),
- Platform::extensionLoaded('intl') ? mt('setup', 'The PHP module INTL is available') : (
- mt('setup', 'The PHP module INTL is missing')
)
- );
+ )));
// TODO(6172): Remove this requirement once we do not ship dompdf with Icinga Web 2 anymore
- $requirements->addOptional(
- 'existing_php_mod_dom',
- mt('setup', 'PHP Module: DOM'),
- mt('setup', 'To be able to export views and reports to PDF, the DOM module for PHP is required.'),
- Platform::extensionLoaded('dom'),
- Platform::extensionLoaded('dom') ? mt('setup', 'The PHP module DOM is available') : (
- mt('setup', 'The PHP module DOM is missing')
- )
- );
-
- $requirements->addOptional(
- 'existing_php_mod_gd',
- mt('setup', 'PHP Module: GD'),
- mt(
+ $set->add(new PhpModuleRequirement(array(
+ 'optional' => true,
+ 'condition' => 'DOM',
+ 'description' => mt(
'setup',
- 'In case you want views being exported to PDF,'
- . ' you\'ll need the GD extension for PHP.'
- ),
- Platform::extensionLoaded('gd'),
- Platform::extensionLoaded('gd') ? mt('setup', 'The PHP module GD is available') : (
- mt('setup', 'The PHP module GD is missing')
+ 'To be able to export views and reports to PDF, the DOM module for PHP is required.'
)
- );
+ )));
- $requirements->addOptional(
- 'existing_php_mod_imagick',
- mt('setup', 'PHP Module: Imagick'),
- mt(
+ $set->add(new PhpModuleRequirement(array(
+ 'optional' => true,
+ 'condition' => 'GD',
+ 'description' => mt(
'setup',
- 'In case you want graphs being exported to PDF as well'
- . ', you\'ll need the ImageMagick extension for PHP.'
- ),
- Platform::extensionLoaded('imagick'),
- Platform::extensionLoaded('imagick') ? mt('setup', 'The PHP module Imagick is available') : (
- mt('setup', 'The PHP module Imagick is missing')
+ 'In case you want views being exported to PDF, you\'ll need the GD extension for PHP.'
)
- );
+ )));
- $requirements->addOptional(
- 'existing_php_mod_pdo_mysql',
- mt('setup', 'PHP Module: PDO-MySQL'),
- mt(
+ $set->add(new PhpModuleRequirement(array(
+ 'optional' => true,
+ 'condition' => 'Imagick',
+ 'description' => mt(
'setup',
- 'Is Icinga Web 2 supposed to access a MySQL database the PDO-MySQL module for PHP is required.'
- ),
- Platform::extensionLoaded('mysql'),
- Platform::extensionLoaded('mysql') ? mt('setup', 'The PHP module PDO-MySQL is available.') : (
- mt('setup', 'The PHP module PDO-MySQL is missing.')
+ 'In case you want graphs being exported to PDF as well, you\'ll need the ImageMagick extension for PHP.'
)
- );
+ )));
- $requirements->addOptional(
- 'existing_php_mod_pdo_pgsql',
- mt('setup', 'PHP Module: PDO-PostgreSQL'),
- mt(
+ $mysqlSet = new RequirementSet(true);
+ $mysqlSet->add(new PhpModuleRequirement(array(
+ 'optional' => true,
+ 'condition' => 'mysql',
+ 'alias' => 'PDO-MySQL',
+ 'description' => mt(
'setup',
- 'Is Icinga Web 2 supposed to access a PostgreSQL database'
- . ' the PDO-PostgreSQL module for PHP is required.'
- ),
- Platform::extensionLoaded('pgsql'),
- Platform::extensionLoaded('pgsql') ? mt('setup', 'The PHP module PDO-PostgreSQL is available.') : (
- mt('setup', 'The PHP module PDO-PostgreSQL is missing.')
+ 'To store users or preferences in a MySQL database the PDO-MySQL module for PHP is required.'
)
- );
-
- $mysqlAdapterFound = Platform::zendClassExists('Zend_Db_Adapter_Pdo_Mysql');
- $requirements->addOptional(
- 'existing_class_Zend_Db_Adapter_Pdo_Mysql',
- mt('setup', 'Zend Database Adapter For MySQL'),
- mt('setup', 'The Zend database adapter for MySQL is required to access a MySQL database.'),
- $mysqlAdapterFound,
- $mysqlAdapterFound ? mt('setup', 'The Zend database adapter for MySQL is available.') : (
- mt('setup', 'The Zend database adapter for MySQL is missing.')
+ )));
+ $mysqlSet->add(new ClassRequirement(array(
+ 'optional' => true,
+ 'condition' => 'Zend_Db_Adapter_Pdo_Mysql',
+ 'alias' => mt('setup', 'Zend database adapter for MySQL'),
+ 'description' => mt(
+ 'setup',
+ 'The Zend database adapter for MySQL is required to access a MySQL database.'
)
- );
+ )));
+ $set->merge($mysqlSet);
- $pgsqlAdapterFound = Platform::zendClassExists('Zend_Db_Adapter_Pdo_Pgsql');
- $requirements->addOptional(
- 'existing_class_Zend_Db_Adapter_Pdo_Pgsql',
- mt('setup', 'Zend Database Adapter For PostgreSQL'),
- mt('setup', 'The Zend database adapter for PostgreSQL is required to access a PostgreSQL database.'),
- $pgsqlAdapterFound,
- $pgsqlAdapterFound ? mt('setup', 'The Zend database adapter for PostgreSQL is available.') : (
- mt('setup', 'The Zend database adapter for PostgreSQL is missing.')
+ $pgsqlSet = new RequirementSet(true);
+ $pgsqlSet->add(new PhpModuleRequirement(array(
+ 'optional' => true,
+ 'condition' => 'pgsql',
+ 'alias' => 'PDO-PostgreSQL',
+ 'description' => mt(
+ 'setup',
+ 'To store users or preferences in a PostgreSQL database the PDO-PostgreSQL module for PHP is required.'
)
- );
+ )));
+ $pgsqlSet->add(new ClassRequirement(array(
+ 'optional' => true,
+ 'condition' => 'Zend_Db_Adapter_Pdo_Pgsql',
+ 'alias' => mt('setup', 'Zend database adapter for PostgreSQL'),
+ 'description' => mt(
+ 'setup',
+ 'The Zend database adapter for PostgreSQL is required to access a PostgreSQL database.'
+ )
+ )));
+ $set->merge($pgsqlSet);
- $configDir = Icinga::app()->getConfigDir();
- $requirements->addMandatory(
- 'writable_directory_' . $configDir,
- mt('setup', 'Writable Config Directory'),
- mt(
+ $set->add(new ConfigDirectoryRequirement(array(
+ 'condition' => Icinga::app()->getConfigDir(),
+ 'description' => mt(
'setup',
'The Icinga Web 2 configuration directory defaults to "/etc/icingaweb2", if' .
' not explicitly set in the environment variable "ICINGAWEB_CONFIGDIR".'
- ),
- is_writable($configDir),
- sprintf(
- is_writable($configDir) ? mt('setup', 'The current configuration directory is writable: %s') : (
- mt('setup', 'The current configuration directory is not writable: %s')
- ),
- $configDir
)
- );
+ )));
- foreach ($this->getWizards() as $wizard) {
- $requirements->merge($wizard->getRequirements());
+ if (! $skipModules) {
+ foreach ($this->getWizards() as $wizard) {
+ $set->merge($wizard->getRequirements());
+ }
}
- return $requirements;
+ return $set;
}
}
diff --git a/modules/setup/test/php/library/Setup/RequirementSetTest.php b/modules/setup/test/php/library/Setup/RequirementSetTest.php
new file mode 100644
index 000000000..d2c4d2029
--- /dev/null
+++ b/modules/setup/test/php/library/Setup/RequirementSetTest.php
@@ -0,0 +1,496 @@
+assertFalse($emptySet->fulfilled(), 'A empty mandatory set of type and is fulfilled');
+
+ $singleTrueSet = new RequirementSet();
+ $singleTrueSet->add(new TrueRequirement());
+ $this->assertTrue(
+ $singleTrueSet->fulfilled(),
+ 'A mandatory set of type and with a single TrueRequirement is not fulfilled'
+ );
+
+ $singleFalseSet = new RequirementSet();
+ $singleFalseSet->add(new FalseRequirement());
+ $this->assertFalse(
+ $singleFalseSet->fulfilled(),
+ 'A mandatory set of type and with a single FalseRequirement is fulfilled'
+ );
+
+ $mixedSet = new RequirementSet();
+ $mixedSet->add(new TrueRequirement());
+ $mixedSet->add(new FalseRequirement());
+ $this->assertFalse(
+ $mixedSet->fulfilled(),
+ 'A mandatory set of type and with one True- and one FalseRequirement is fulfilled'
+ );
+ }
+
+ public function testFlatOptionalRequirementsOfTypeAnd()
+ {
+ $emptySet = new RequirementSet(true);
+ $this->assertTrue($emptySet->fulfilled(), 'A empty optional set of type and is not fulfilled');
+
+ $singleTrueSet = new RequirementSet(true);
+ $singleTrueSet->add(new TrueRequirement());
+ $this->assertTrue(
+ $singleTrueSet->fulfilled(),
+ 'A optional set of type and with a single TrueRequirement is not fulfilled'
+ );
+
+ $singleFalseSet = new RequirementSet(true);
+ $singleFalseSet->add(new FalseRequirement());
+ $this->assertTrue(
+ $singleFalseSet->fulfilled(),
+ 'A optional set of type and with a single FalseRequirement is not fulfilled'
+ );
+
+ $mixedSet = new RequirementSet(true);
+ $mixedSet->add(new TrueRequirement());
+ $mixedSet->add(new FalseRequirement());
+ $this->assertTrue(
+ $mixedSet->fulfilled(),
+ 'A optional set of type and with one True- and one FalseRequirement is not fulfilled'
+ );
+ }
+
+ public function testFlatMixedRequirementsOfTypeAnd()
+ {
+ $mandatoryOptionalTrueSet = new RequirementSet();
+ $mandatoryOptionalTrueSet->add(new TrueRequirement(array('optional' => true)));
+ $mandatoryOptionalTrueSet->add(new FalseRequirement());
+ $this->assertFalse(
+ $mandatoryOptionalTrueSet->fulfilled(),
+ 'A mandatory set of type and with one optional True- and one mandatory FalseRequirement is fulfilled'
+ );
+
+ $mandatoryOptionalFalseSet = new RequirementSet();
+ $mandatoryOptionalFalseSet->add(new TrueRequirement());
+ $mandatoryOptionalFalseSet->add(new FalseRequirement(array('optional' => true)));
+ $this->assertTrue(
+ $mandatoryOptionalFalseSet->fulfilled(),
+ 'A mandatory set of type and with one mandatory True- and one optional FalseRequirement is not fulfilled'
+ );
+
+ $optionalOptionalTrueSet = new RequirementSet(true);
+ $optionalOptionalTrueSet->add(new TrueRequirement(array('optional' => true)));
+ $optionalOptionalTrueSet->add(new FalseRequirement());
+ $this->assertTrue(
+ $optionalOptionalTrueSet->fulfilled(),
+ 'A optional set of type and with one optional True- and one mandatory FalseRequirement is not fulfilled'
+ );
+
+ $optionalOptionalFalseSet = new RequirementSet(true);
+ $optionalOptionalFalseSet->add(new TrueRequirement());
+ $optionalOptionalFalseSet->add(new FalseRequirement(array('optional' => true)));
+ $this->assertTrue(
+ $optionalOptionalFalseSet->fulfilled(),
+ 'A optional set of type and with one mandatory True- and one optional FalseRequirement is not fulfilled'
+ );
+ }
+
+ public function testFlatMandatoryRequirementsOfTypeOr()
+ {
+ $emptySet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $this->assertFalse($emptySet->fulfilled(), 'A empty mandatory set of type or is fulfilled');
+
+ $singleTrueSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $singleTrueSet->add(new TrueRequirement());
+ $this->assertTrue(
+ $singleTrueSet->fulfilled(),
+ 'A mandatory set of type or with a single TrueRequirement is not fulfilled'
+ );
+
+ $singleFalseSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $singleFalseSet->add(new FalseRequirement());
+ $this->assertFalse(
+ $singleFalseSet->fulfilled(),
+ 'A mandatory set of type or with a single FalseRequirement is fulfilled'
+ );
+
+ $mixedSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $mixedSet->add(new TrueRequirement());
+ $mixedSet->add(new FalseRequirement());
+ $this->assertTrue(
+ $mixedSet->fulfilled(),
+ 'A mandatory set of type or with one True- and one FalseRequirement is not fulfilled'
+ );
+ }
+
+ public function testFlatOptionalRequirementsOfTypeOr()
+ {
+ $emptySet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $this->assertTrue($emptySet->fulfilled(), 'A empty optional set of type or is not fulfilled');
+
+ $singleTrueSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $singleTrueSet->add(new TrueRequirement());
+ $this->assertTrue(
+ $singleTrueSet->fulfilled(),
+ 'A optional set of type or with a single TrueRequirement is not fulfilled'
+ );
+
+ $singleFalseSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $singleFalseSet->add(new FalseRequirement());
+ $this->assertTrue(
+ $singleFalseSet->fulfilled(),
+ 'A optional set of type or with a single FalseRequirement is not fulfilled'
+ );
+
+ $mixedSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $mixedSet->add(new TrueRequirement());
+ $mixedSet->add(new FalseRequirement());
+ $this->assertTrue(
+ $mixedSet->fulfilled(),
+ 'A optional set of type or with one True- and one FalseRequirement is not fulfilled'
+ );
+ }
+
+ public function testFlatMixedRequirementsOfTypeOr()
+ {
+ $mandatoryOptionalTrueSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $mandatoryOptionalTrueSet->add(new TrueRequirement(array('optional' => true)));
+ $mandatoryOptionalTrueSet->add(new FalseRequirement());
+ $this->assertTrue(
+ $mandatoryOptionalTrueSet->fulfilled(),
+ 'A mandatory set of type or with one optional True- and one mandatory FalseRequirement is not fulfilled'
+ );
+
+ $mandatoryOptionalFalseSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $mandatoryOptionalFalseSet->add(new TrueRequirement());
+ $mandatoryOptionalFalseSet->add(new FalseRequirement(array('optional' => true)));
+ $this->assertTrue(
+ $mandatoryOptionalFalseSet->fulfilled(),
+ 'A mandatory set of type or with one mandatory True- and one optional FalseRequirement is not fulfilled'
+ );
+
+ $optionalOptionalTrueSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $optionalOptionalTrueSet->add(new TrueRequirement(array('optional' => true)));
+ $optionalOptionalTrueSet->add(new FalseRequirement());
+ $this->assertTrue(
+ $optionalOptionalTrueSet->fulfilled(),
+ 'A optional set of type or with one optional True- and one mandatory FalseRequirement is not fulfilled'
+ );
+
+ $optionalOptionalFalseSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $optionalOptionalFalseSet->add(new TrueRequirement());
+ $optionalOptionalFalseSet->add(new FalseRequirement(array('optional' => true)));
+ $this->assertTrue(
+ $optionalOptionalFalseSet->fulfilled(),
+ 'A optional set of type or with one mandatory True- and one optional FalseRequirement is not fulfilled'
+ );
+ }
+
+ public function testNestedMandatoryRequirementsOfTypeAnd()
+ {
+ $trueSet = new RequirementSet();
+ $trueSet->add(new TrueRequirement());
+ $falseSet = new RequirementSet();
+ $falseSet->add(new FalseRequirement());
+
+ $nestedTrueSet = new RequirementSet();
+ $nestedTrueSet->merge($trueSet);
+ $this->assertTrue(
+ $nestedTrueSet->fulfilled(),
+ 'A nested mandatory set of type and with one mandatory TrueRequirement is not fulfilled'
+ );
+
+ $nestedFalseSet = new RequirementSet();
+ $nestedFalseSet->merge($falseSet);
+ $this->assertFalse(
+ $nestedFalseSet->fulfilled(),
+ 'A nested mandatory set of type and with one mandatory FalseRequirement is fulfilled'
+ );
+
+ $nestedMixedSet = new RequirementSet();
+ $nestedMixedSet->merge($trueSet);
+ $nestedMixedSet->merge($falseSet);
+ $this->assertFalse(
+ $nestedMixedSet->fulfilled(),
+ 'Two nested mandatory sets of type and with one mandatory True- and'
+ . ' one mandatory FalseRequirement respectively are fulfilled'
+ );
+ }
+
+ public function testNestedOptionalRequirementsOfTypeAnd()
+ {
+ $trueSet = new RequirementSet(true);
+ $trueSet->add(new TrueRequirement());
+ $falseSet = new RequirementSet(true);
+ $falseSet->add(new FalseRequirement());
+
+ $nestedTrueSet = new RequirementSet(true);
+ $nestedTrueSet->merge($trueSet);
+ $this->assertTrue(
+ $nestedTrueSet->fulfilled(),
+ 'A nested optional set of type and with one mandatory TrueRequirement is not fulfilled'
+ );
+
+ $nestedFalseSet = new RequirementSet(true);
+ $nestedFalseSet->merge($falseSet);
+ $this->assertTrue(
+ $nestedFalseSet->fulfilled(),
+ 'A nested optional set of type and with one mandatory FalseRequirement is not fulfilled'
+ );
+
+ $nestedMixedSet = new RequirementSet(true);
+ $nestedMixedSet->merge($trueSet);
+ $nestedMixedSet->merge($falseSet);
+ $this->assertTrue(
+ $nestedMixedSet->fulfilled(),
+ 'Two nested optional sets of type and with one mandatory True- and'
+ . ' one mandatory FalseRequirement respectively are not fulfilled'
+ );
+ }
+
+ public function testNestedMixedRequirementsOfTypeAnd()
+ {
+ $mandatoryMandatoryTrueSet = new RequirementSet();
+ $mandatoryMandatoryTrueSet->add(new TrueRequirement());
+ $mandatoryOptionalTrueSet = new RequirementSet();
+ $mandatoryOptionalTrueSet->add(new TrueRequirement(array('optional' => true)));
+ $mandatoryMandatoryFalseSet = new RequirementSet();
+ $mandatoryMandatoryFalseSet->add(new FalseRequirement());
+ $mandatoryOptionalFalseSet = new RequirementSet();
+ $mandatoryOptionalFalseSet->add(new FalseRequirement(array('optional' => true)));
+ $optionalMandatoryTrueSet = new RequirementSet(true);
+ $optionalMandatoryTrueSet->add(new TrueRequirement());
+ $optionalOptionalTrueSet = new RequirementSet(true);
+ $optionalOptionalTrueSet->add(new TrueRequirement(array('optional' => true)));
+ $optionalMandatoryFalseSet = new RequirementSet(true);
+ $optionalMandatoryFalseSet->add(new FalseRequirement());
+ $optionalOptionalFalseSet = new RequirementSet(true);
+ $optionalOptionalFalseSet->add(new FalseRequirement(array('optional' => true)));
+
+ $mandatoryMandatoryOptionalTrueSet = new RequirementSet();
+ $mandatoryMandatoryOptionalTrueSet->merge($mandatoryOptionalTrueSet);
+ $mandatoryMandatoryOptionalTrueSet->merge($mandatoryMandatoryFalseSet);
+ $this->assertFalse(
+ $mandatoryMandatoryOptionalTrueSet->fulfilled(),
+ 'A mandatory set of type and with two nested mandatory sets of type and where one has a optional'
+ . ' TrueRequirement and the other one has a mandatory FalseRequirement is fulfilled'
+ );
+
+ $mandatoryMandatoryOptionalFalseSet = new RequirementSet();
+ $mandatoryMandatoryOptionalFalseSet->merge($mandatoryOptionalFalseSet);
+ $mandatoryMandatoryOptionalFalseSet->merge($mandatoryMandatoryTrueSet);
+ $this->assertTrue(
+ $mandatoryMandatoryOptionalFalseSet->fulfilled(),
+ 'A mandatory set of type and with two nested mandatory sets of type and where one has a mandatory'
+ . ' TrueRequirement and the other one has a optional FalseRequirement is not fulfilled'
+ );
+
+ $optionalOptionalOptionalTrueSet = new RequirementSet(true);
+ $optionalOptionalOptionalTrueSet->merge($optionalOptionalTrueSet);
+ $optionalOptionalOptionalTrueSet->merge($optionalMandatoryFalseSet);
+ $this->assertTrue(
+ $optionalOptionalOptionalTrueSet->fulfilled(),
+ 'A optional set of type and with two nested optional sets of type and where one has a optional'
+ . ' TrueRequirement and the other one has a mandatory FalseRequirement is not fulfilled'
+ );
+
+ $optionalOptionalOptionalFalseSet = new RequirementSet(true);
+ $optionalOptionalOptionalFalseSet->merge($optionalOptionalFalseSet);
+ $optionalOptionalOptionalFalseSet->merge($optionalMandatoryTrueSet);
+ $this->assertTrue(
+ $optionalOptionalOptionalFalseSet->fulfilled(),
+ 'A optional set of type and with two nested optional sets of type and where one has a mandatory'
+ . ' TrueRequirement and the other one has a optional FalseRequirement is not fulfilled'
+ );
+ }
+
+ public function testNestedMandatoryRequirementsOfTypeOr()
+ {
+ $trueSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $trueSet->add(new TrueRequirement());
+ $falseSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $falseSet->add(new FalseRequirement());
+
+ $nestedTrueSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $nestedTrueSet->merge($trueSet);
+ $this->assertTrue(
+ $nestedTrueSet->fulfilled(),
+ 'A nested mandatory set of type or with one mandatory TrueRequirement is not fulfilled'
+ );
+
+ $nestedFalseSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $nestedFalseSet->merge($falseSet);
+ $this->assertFalse(
+ $nestedFalseSet->fulfilled(),
+ 'A nested mandatory set of type or with one mandatory FalseRequirement is fulfilled'
+ );
+
+ $nestedMixedSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $nestedMixedSet->merge($trueSet);
+ $nestedMixedSet->merge($falseSet);
+ $this->assertTrue(
+ $nestedMixedSet->fulfilled(),
+ 'Two nested mandatory sets of type or with one mandatory True- and'
+ . ' one mandatory FalseRequirement respectively are not fulfilled'
+ );
+ }
+
+ public function testNestedOptionalRequirementsOfTypeOr()
+ {
+ $trueSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $trueSet->add(new TrueRequirement());
+ $falseSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $falseSet->add(new FalseRequirement());
+
+ $nestedTrueSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $nestedTrueSet->merge($trueSet);
+ $this->assertTrue(
+ $nestedTrueSet->fulfilled(),
+ 'A nested optional set of type or with one mandatory TrueRequirement is not fulfilled'
+ );
+
+ $nestedFalseSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $nestedFalseSet->merge($falseSet);
+ $this->assertTrue(
+ $nestedFalseSet->fulfilled(),
+ 'A nested optional set of type or with one mandatory FalseRequirement is not fulfilled'
+ );
+
+ $nestedMixedSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $nestedMixedSet->merge($trueSet);
+ $nestedMixedSet->merge($falseSet);
+ $this->assertTrue(
+ $nestedMixedSet->fulfilled(),
+ 'Two nested optional sets of type or with one mandatory True- and'
+ . ' one mandatory FalseRequirement respectively are not fulfilled'
+ );
+ }
+
+ public function testNestedMixedRequirementsOfTypeOr()
+ {
+ $mandatoryMandatoryTrueSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $mandatoryMandatoryTrueSet->add(new TrueRequirement());
+ $mandatoryOptionalTrueSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $mandatoryOptionalTrueSet->add(new TrueRequirement(array('optional' => true)));
+ $mandatoryMandatoryFalseSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $mandatoryMandatoryFalseSet->add(new FalseRequirement());
+ $mandatoryOptionalFalseSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $mandatoryOptionalFalseSet->add(new FalseRequirement(array('optional' => true)));
+ $optionalMandatoryTrueSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $optionalMandatoryTrueSet->add(new TrueRequirement());
+ $optionalOptionalTrueSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $optionalOptionalTrueSet->add(new TrueRequirement(array('optional' => true)));
+ $optionalMandatoryFalseSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $optionalMandatoryFalseSet->add(new FalseRequirement());
+ $optionalOptionalFalseSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $optionalOptionalFalseSet->add(new FalseRequirement(array('optional' => true)));
+
+ $mandatoryMandatoryOptionalTrueSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $mandatoryMandatoryOptionalTrueSet->merge($mandatoryOptionalTrueSet);
+ $mandatoryMandatoryOptionalTrueSet->merge($mandatoryMandatoryFalseSet);
+ $this->assertTrue($mandatoryMandatoryOptionalTrueSet->fulfilled());
+
+ $mandatoryMandatoryOptionalFalseSet = new RequirementSet(false, RequirementSet::MODE_OR);
+ $mandatoryMandatoryOptionalFalseSet->merge($mandatoryOptionalFalseSet);
+ $mandatoryMandatoryOptionalFalseSet->merge($mandatoryMandatoryTrueSet);
+ $this->assertTrue($mandatoryMandatoryOptionalFalseSet->fulfilled());
+
+ $optionalOptionalOptionalTrueSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $optionalOptionalOptionalTrueSet->merge($optionalOptionalTrueSet);
+ $optionalOptionalOptionalTrueSet->merge($optionalMandatoryFalseSet);
+ $this->assertTrue($optionalOptionalOptionalTrueSet->fulfilled());
+
+ $optionalOptionalOptionalFalseSet = new RequirementSet(true, RequirementSet::MODE_OR);
+ $optionalOptionalOptionalFalseSet->merge($optionalOptionalFalseSet);
+ $optionalOptionalOptionalFalseSet->merge($optionalMandatoryTrueSet);
+ $this->assertTrue($optionalOptionalOptionalFalseSet->fulfilled());
+ }
+
+ public function testNestedMandatoryRequirementsOfDifferentTypes()
+ {
+ $true = new TrueRequirement();
+ $false = new FalseRequirement();
+
+ $level1And = new RequirementSet();
+ $level2FirstOr = new RequirementSet(false, RequirementSet::MODE_OR);
+ $level2SecondOr = new RequirementSet(false, RequirementSet::MODE_OR);
+ $level1And->merge($level2FirstOr)->merge($level2SecondOr);
+ $level3FirstAnd = new RequirementSet();
+ $level3SecondAnd = new RequirementSet();
+ $level2FirstOr->merge($level3FirstAnd)->merge($level3SecondAnd);
+ $level2SecondOr->merge($level3FirstAnd)->merge($level3SecondAnd);
+ $level3FirstAnd->add($true)->add($true);
+ $level3SecondAnd->add($false)->add($true);
+ $this->assertTrue($level1And->fulfilled());
+
+ $level1Or = new RequirementSet(false, RequirementSet::MODE_OR);
+ $level2FirstAnd = new RequirementSet();
+ $level2SecondAnd = new RequirementSet();
+ $level1Or->merge($level2FirstAnd)->merge($level2SecondAnd);
+ $level3FirstOr = new RequirementSet(false, RequirementSet::MODE_OR);
+ $level3SecondOr = new RequirementSet(false, RequirementSet::MODE_OR);
+ $level2FirstAnd->merge($level3FirstOr)->merge($level3SecondOr);
+ $level2SecondAnd->merge($level3FirstOr)->merge($level3SecondOr);
+ $level3FirstOr->add($false);
+ $level3SecondOr->add($true);
+ $this->assertFalse($level1Or->fulfilled());
+ }
+
+ public function testNestedOptionalRequirementsOfDifferentTypes()
+ {
+ $true = new TrueRequirement();
+ $false = new FalseRequirement();
+
+ $level1And = new RequirementSet();
+ $level2FirstAnd = new RequirementSet(true);
+ $level2SecondAnd = new RequirementSet(true);
+ $level1And->merge($level2FirstAnd)->merge($level2SecondAnd);
+ $level3FirstOr = new RequirementSet(true, RequirementSet::MODE_OR);
+ $level3SecondOr = new RequirementSet(true, RequirementSet::MODE_OR);
+ $level2FirstAnd->merge($level3FirstOr)->merge($level3SecondOr);
+ $level2SecondAnd->merge($level3FirstOr)->merge($level3SecondOr);
+ $level3FirstOr->add($false);
+ $level3SecondOr->add($false);
+ $this->assertFalse($level1And->fulfilled());
+ $this->assertTrue($level2FirstAnd->fulfilled());
+ $this->assertTrue($level2SecondAnd->fulfilled());
+
+ $level1Or = new RequirementSet(false, RequirementSet::MODE_OR);
+ $level2FirstOr = new RequirementSet(true, RequirementSet::MODE_OR);
+ $level2SecondOr = new RequirementSet(true, RequirementSet::MODE_OR);
+ $level1Or->merge($level2FirstOr)->merge($level2SecondOr);
+ $level3FirstAnd = new RequirementSet(true);
+ $level3SecondAnd = new RequirementSet(true);
+ $level2FirstOr->merge($level3FirstAnd)->merge($level3SecondAnd);
+ $level2SecondOr->merge($level3FirstAnd)->merge($level3SecondAnd);
+ $level3FirstAnd->add($true)->add($true);
+ $level3SecondAnd->add($false)->add($true);
+ $this->assertTrue($level1Or->fulfilled());
+ }
+
+ public function testNestedMixedRequirementsOfDifferentTypes()
+ {
+ $this->markTestIncomplete();
+ }
+}
diff --git a/public/css/icinga/setup.less b/public/css/icinga/setup.less
index 66b08417e..26c4b4e64 100644
--- a/public/css/icinga/setup.less
+++ b/public/css/icinga/setup.less
@@ -110,7 +110,8 @@
}
#setup div.buttons {
- margin: 1.5em 0;
+ margin-top: 1.5em; // Yes, -top and -bottom, keep it like that...
+ margin-bottom: 1.5em;
.double {
position: absolute;
@@ -166,25 +167,58 @@
}
}
-#setup table.requirements {
+form#setup_requirements {
+ margin-top: 2em;
+ padding-top: 0.5em;
+ border-top: 2px solid @colorPetrol;
+
+ div.buttons div.requirements-refresh {
+ width: 25%;
+ float: right;
+ text-align: center;
+
+ a.button-like {
+ padding: 0.1em 0.4em;
+ }
+ }
+}
+
+#setup > table.requirements {
font-size: 0.9em;
- margin: -1em -1em 2em;
+}
+
+#setup table.requirements {
+ margin: -1em;
border-spacing: 1em;
border-collapse: separate;
- border-bottom: 2px solid @colorPetrol;
td {
+ padding: 0;
+
h2 {
margin: 0 1em 0 0;
}
+ table {
+ font-size: 102%; // Just a hack for webkit, remove this in case you can't see any difference or make it work without it
+ }
+
ul {
margin: 0;
padding-left: 1em;
list-style-type: square;
}
+ &.title {
+ width: 25%;
+ }
+
+ &.desc {
+ width: 50%;
+ }
+
&.state {
+ width: 25%;
color: white;
padding: 0.4em;
@@ -201,24 +235,6 @@
background-color: @colorCritical;
}
}
-
- &.btn-update {
- padding-top: 0.3em;
- text-align: center;
-
- div.buttons {
- margin: 0;
-
- a.button-like {
- padding: 0.2em 0.5em;
- background-color: @colorPetro;
-
- &:hover, &:focus {
- background-color: #666;
- }
- }
- }
- }
}
}