commit
b978fdb115
|
@ -182,19 +182,24 @@ class Platform
|
|||
}
|
||||
|
||||
/**
|
||||
* Return whether the given Zend framework class exists
|
||||
* Return whether the given class exists
|
||||
*
|
||||
* @param string $name The name of the class to check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function zendClassExists($name)
|
||||
public static function classExists($name)
|
||||
{
|
||||
if (@class_exists($name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (@include str_replace('_', '/', $name) . '.php') !== false;
|
||||
if (strpos($name, '_') !== false) {
|
||||
// Assume it's a Zend-Framework class
|
||||
return (@include str_replace('_', '/', $name) . '.php') !== false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -206,7 +211,7 @@ class Platform
|
|||
*/
|
||||
public static function hasMysqlSupport()
|
||||
{
|
||||
return static::extensionLoaded('mysql') && static::zendClassExists('Zend_Db_Adapter_Pdo_Mysql');
|
||||
return static::extensionLoaded('mysql') && static::classExists('Zend_Db_Adapter_Pdo_Mysql');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -218,6 +223,6 @@ class Platform
|
|||
*/
|
||||
public static function hasPostgresqlSupport()
|
||||
{
|
||||
return static::extensionLoaded('pgsql') && static::zendClassExists('Zend_Db_Adapter_Pdo_Pgsql');
|
||||
return static::extensionLoaded('pgsql') && static::classExists('Zend_Db_Adapter_Pdo_Pgsql');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,12 @@
|
|||
|
||||
namespace Icinga\Module\Monitoring;
|
||||
|
||||
use Icinga\Application\Platform;
|
||||
use Icinga\Web\Form;
|
||||
use Icinga\Web\Wizard;
|
||||
use Icinga\Web\Request;
|
||||
use Icinga\Module\Setup\Setup;
|
||||
use Icinga\Module\Setup\SetupWizard;
|
||||
use Icinga\Module\Setup\Requirements;
|
||||
use Icinga\Module\Setup\RequirementSet;
|
||||
use Icinga\Module\Setup\Forms\SummaryPage;
|
||||
use Icinga\Module\Monitoring\Forms\Setup\WelcomePage;
|
||||
use Icinga\Module\Monitoring\Forms\Setup\BackendPage;
|
||||
|
@ -17,6 +16,8 @@ use Icinga\Module\Monitoring\Forms\Setup\InstancePage;
|
|||
use Icinga\Module\Monitoring\Forms\Setup\SecurityPage;
|
||||
use Icinga\Module\Monitoring\Forms\Setup\IdoResourcePage;
|
||||
use Icinga\Module\Monitoring\Forms\Setup\LivestatusResourcePage;
|
||||
use Icinga\Module\Setup\Requirement\ClassRequirement;
|
||||
use Icinga\Module\Setup\Requirement\PhpModuleRequirement;
|
||||
|
||||
/**
|
||||
* Monitoring Module Setup Wizard
|
||||
|
@ -135,22 +136,62 @@ class MonitoringWizard extends Wizard implements SetupWizard
|
|||
*/
|
||||
public function getRequirements()
|
||||
{
|
||||
$requirements = new Requirements();
|
||||
$set = new RequirementSet();
|
||||
|
||||
$requirements->addOptional(
|
||||
'existing_php_mod_sockets',
|
||||
mt('monitoring', 'PHP Module: Sockets'),
|
||||
mt(
|
||||
// TODO(8254): Add this to the $backendSet
|
||||
$set->add(new PhpModuleRequirement(array(
|
||||
'optional' => true,
|
||||
'condition' => 'Sockets',
|
||||
'description' => mt(
|
||||
'monitoring',
|
||||
'In case it\'s desired that a TCP connection is being used by Icinga Web 2 to'
|
||||
. ' access a Livestatus interface, the Sockets module for PHP is required.'
|
||||
),
|
||||
Platform::extensionLoaded('sockets'),
|
||||
Platform::extensionLoaded('sockets') ? mt('monitoring', 'The PHP Module sockets is available.') : (
|
||||
mt('monitoring', 'The PHP Module sockets is not available.')
|
||||
)
|
||||
);
|
||||
)));
|
||||
|
||||
return $requirements;
|
||||
$backendSet = new RequirementSet(false, RequirementSet::MODE_OR);
|
||||
$mysqlSet = new RequirementSet(true);
|
||||
$mysqlSet->add(new PhpModuleRequirement(array(
|
||||
'optional' => true,
|
||||
'condition' => 'mysql',
|
||||
'alias' => 'PDO-MySQL',
|
||||
'description' => mt(
|
||||
'monitoring',
|
||||
'To access the IDO stored in a MySQL database the PDO-MySQL module for PHP is required.'
|
||||
)
|
||||
)));
|
||||
$mysqlSet->add(new ClassRequirement(array(
|
||||
'optional' => true,
|
||||
'condition' => 'Zend_Db_Adapter_Pdo_Mysql',
|
||||
'alias' => mt('monitoring', 'Zend database adapter for MySQL'),
|
||||
'description' => mt(
|
||||
'monitoring',
|
||||
'The Zend database adapter for MySQL is required to access a MySQL database.'
|
||||
)
|
||||
)));
|
||||
$backendSet->merge($mysqlSet);
|
||||
$pgsqlSet = new RequirementSet(true);
|
||||
$pgsqlSet->add(new PhpModuleRequirement(array(
|
||||
'optional' => true,
|
||||
'condition' => 'pgsql',
|
||||
'alias' => 'PDO-PostgreSQL',
|
||||
'description' => mt(
|
||||
'monitoring',
|
||||
'To access the IDO stored 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('monitoring', 'Zend database adapter for PostgreSQL'),
|
||||
'description' => mt(
|
||||
'monitoring',
|
||||
'The Zend database adapter for PostgreSQL is required to access a PostgreSQL database.'
|
||||
)
|
||||
)));
|
||||
$backendSet->merge($pgsqlSet);
|
||||
$set->merge($backendSet);
|
||||
|
||||
return $set;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
namespace Icinga\Module\Setup\Forms;
|
||||
|
||||
use Icinga\Web\Form;
|
||||
use Icinga\Module\Setup\Requirements;
|
||||
use Icinga\Module\Setup\SetupWizard;
|
||||
|
||||
/**
|
||||
* Wizard page to list setup requirements
|
||||
|
@ -12,11 +12,11 @@ use Icinga\Module\Setup\Requirements;
|
|||
class RequirementsPage extends Form
|
||||
{
|
||||
/**
|
||||
* The requirements to list
|
||||
* The wizard
|
||||
*
|
||||
* @var Requirements
|
||||
* @var SetupWizard
|
||||
*/
|
||||
protected $requirements;
|
||||
protected $wizard;
|
||||
|
||||
/**
|
||||
* Initialize this page
|
||||
|
@ -28,30 +28,30 @@ class RequirementsPage extends Form
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the requirements to list
|
||||
* Set the wizard
|
||||
*
|
||||
* @param Requirements $requirements
|
||||
* @param SetupWizard $wizard
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setRequirements(Requirements $requirements)
|
||||
public function setWizard(SetupWizard $wizard)
|
||||
{
|
||||
$this->requirements = $requirements;
|
||||
$this->wizard = $wizard;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the requirements to list
|
||||
* Return the wizard
|
||||
*
|
||||
* @return Requirements
|
||||
* @return SetupWizard
|
||||
*/
|
||||
public function getRequirements()
|
||||
public function getWizard()
|
||||
{
|
||||
return $this->requirements;
|
||||
return $this->wizard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the given form data and check whether the requirements are fulfilled
|
||||
* Validate the given form data and check whether the wizard's requirements are fulfilled
|
||||
*
|
||||
* @param array $data The data to validate
|
||||
*
|
||||
|
@ -63,6 +63,6 @@ class RequirementsPage extends Form
|
|||
return false;
|
||||
}
|
||||
|
||||
return $this->requirements->fulfilled();
|
||||
return $this->wizard->getRequirements()->fulfilled();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,64 +1,38 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Web\Wizard;
|
||||
use Icinga\Module\Setup\Requirements;
|
||||
|
||||
$requirements = $form->getRequirements();
|
||||
|
||||
?>
|
||||
<table class="requirements">
|
||||
<tbody>
|
||||
<?php foreach ($requirements as $requirement): ?>
|
||||
<tr>
|
||||
<td><h2><?= $requirement->title; ?></h2></td>
|
||||
<td style="width: 50%">
|
||||
<?php if (is_array($requirement->description)): ?>
|
||||
<ul>
|
||||
<?php foreach ($requirement->description as $desc): ?>
|
||||
<li><?= $desc; ?></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php else: ?>
|
||||
<?= $requirement->description; ?>
|
||||
<?php endif ?>
|
||||
</td>
|
||||
<td class="state <?= $requirement->state === Requirements::STATE_OK ? 'fulfilled' : (
|
||||
$requirement->state === Requirements::STATE_OPTIONAL ? 'not-available' : 'missing'
|
||||
); ?>"><?= $requirement->message; ?></td>
|
||||
</tr>
|
||||
<h1>Icinga Web 2</h1>
|
||||
<?= $form->getWizard()->getRequirements(true); ?>
|
||||
<?php foreach ($form->getWizard()->getPage('setup_modules')->getModuleWizards() as $moduleName => $wizard): ?>
|
||||
<h1><?= ucwords($moduleName) . ' ' . $this->translate('Module'); ?></h1>
|
||||
<?= $wizard->getRequirements(); ?>
|
||||
<?php endforeach ?>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="btn-update">
|
||||
<div class="buttons">
|
||||
<?php $title = $this->translate('You may also need to restart the web-server for the changes to take effect!'); ?>
|
||||
<?= $this->qlink(
|
||||
$this->translate('Refresh'),
|
||||
null,
|
||||
null,
|
||||
array(
|
||||
'class' => 'button-like',
|
||||
'title' => $title,
|
||||
'aria-label' => sprintf($this->translate('Refresh the page; %s'), $title)
|
||||
)
|
||||
); ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<form id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>" action="<?= $form->getAction(); ?>">
|
||||
<?= $form->getElement($form->getTokenElementName()); ?>
|
||||
<?= $form->getElement($form->getUidElementName()); ?>
|
||||
<div class="buttons" style="margin: 0 0 1.5em;">
|
||||
<div class="buttons">
|
||||
<?= $form->getElement(Wizard::BTN_PREV); ?>
|
||||
<?php
|
||||
$btn = $form->getElement(Wizard::BTN_NEXT);
|
||||
if (false === $requirements->fulfilled()) {
|
||||
if (! $form->getWizard()->getRequirements()->fulfilled()) {
|
||||
$btn->setAttrib('disabled', 1);
|
||||
}
|
||||
echo $btn;
|
||||
?>
|
||||
<div class="requirements-refresh">
|
||||
<?php $title = $this->translate('You may also need to restart the web-server for the changes to take effect!'); ?>
|
||||
<?= $this->qlink(
|
||||
$this->translate('Refresh'),
|
||||
null,
|
||||
null,
|
||||
array(
|
||||
'class' => 'button-like',
|
||||
'title' => $title,
|
||||
'aria-label' => sprintf($this->translate('Refresh the page; %s'), $title)
|
||||
)
|
||||
); ?>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
|
@ -0,0 +1,279 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup;
|
||||
|
||||
use LogicException;
|
||||
|
||||
abstract class Requirement
|
||||
{
|
||||
/**
|
||||
* The state of this requirement
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* A descriptive text representing the current state of this requirement
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $stateText;
|
||||
|
||||
/**
|
||||
* The descriptions of this requirement
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $descriptions;
|
||||
|
||||
/**
|
||||
* The title of this requirement
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* The condition of this requirement
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $condition;
|
||||
|
||||
/**
|
||||
* Whether this requirement is optional
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $optional;
|
||||
|
||||
/**
|
||||
* The alias to display the condition with in a human readable way
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $alias;
|
||||
|
||||
/**
|
||||
* Create a new requirement
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @throws LogicException In case there exists no setter for an option's key
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup\Requirement;
|
||||
|
||||
use Icinga\Application\Platform;
|
||||
use Icinga\Module\Setup\Requirement;
|
||||
|
||||
class ClassRequirement extends Requirement
|
||||
{
|
||||
protected function evaluate()
|
||||
{
|
||||
$classNameOrPath = $this->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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup\Requirement;
|
||||
|
||||
use Icinga\Module\Setup\Requirement;
|
||||
|
||||
class ConfigDirectoryRequirement extends Requirement
|
||||
{
|
||||
public function getTitle()
|
||||
{
|
||||
$title = parent::getTitle();
|
||||
if ($title === null) {
|
||||
return mt('setup', 'Read- and writable configuration directory');
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
protected function evaluate()
|
||||
{
|
||||
$path = $this->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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup\Requirement;
|
||||
|
||||
use Icinga\Application\Platform;
|
||||
use Icinga\Module\Setup\Requirement;
|
||||
|
||||
class OSRequirement extends Requirement
|
||||
{
|
||||
public function getTitle()
|
||||
{
|
||||
$title = parent::getTitle();
|
||||
if ($title === null) {
|
||||
return sprintf(mt('setup', '%s Platform'), ucfirst($this->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());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup\Requirement;
|
||||
|
||||
use Icinga\Application\Platform;
|
||||
use Icinga\Module\Setup\Requirement;
|
||||
|
||||
class PhpConfigRequirement extends Requirement
|
||||
{
|
||||
protected function evaluate()
|
||||
{
|
||||
list($configDirective, $value) = $this->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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup\Requirement;
|
||||
|
||||
use Icinga\Application\Platform;
|
||||
use Icinga\Module\Setup\Requirement;
|
||||
|
||||
class PhpModuleRequirement extends Requirement
|
||||
{
|
||||
public function getTitle()
|
||||
{
|
||||
$title = parent::getTitle();
|
||||
if ($title === $this->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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup\Requirement;
|
||||
|
||||
use Icinga\Application\Platform;
|
||||
use Icinga\Module\Setup\Requirement;
|
||||
|
||||
class PhpVersionRequirement extends Requirement
|
||||
{
|
||||
public function getTitle()
|
||||
{
|
||||
$title = parent::getTitle();
|
||||
if ($title === null) {
|
||||
return mt('setup', 'PHP Version');
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
protected function evaluate()
|
||||
{
|
||||
$phpVersion = Platform::getPhpVersion();
|
||||
$this->setStateText(sprintf(mt('setup', 'You are running PHP version %s.'), $phpVersion));
|
||||
list($operator, $requiredVersion) = $this->getCondition();
|
||||
return version_compare($phpVersion, $requiredVersion, $operator);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,333 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup;
|
||||
|
||||
use LogicException;
|
||||
use RecursiveIterator;
|
||||
|
||||
/**
|
||||
* Container to store and handle requirements
|
||||
*/
|
||||
class RequirementSet implements RecursiveIterator
|
||||
{
|
||||
/**
|
||||
* Mode AND (all requirements must be met)
|
||||
*/
|
||||
const MODE_AND = 0;
|
||||
|
||||
/**
|
||||
* Mode OR (at least one requirement must be met)
|
||||
*/
|
||||
const MODE_OR = 1;
|
||||
|
||||
/**
|
||||
* Whether all requirements meet their condition
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Whether this set is optional
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $optional;
|
||||
|
||||
/**
|
||||
* The mode by which the requirements are evaluated
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $mode;
|
||||
|
||||
/**
|
||||
* The registered requirements
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $requirements;
|
||||
|
||||
/**
|
||||
* The raw state of this set's requirements
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $forcedState;
|
||||
|
||||
/**
|
||||
* Initialize a new set of requirements
|
||||
*
|
||||
* @param bool $optional Whether this set is optional
|
||||
* @param int $mode The mode by which to evaluate this set
|
||||
*/
|
||||
public function __construct($optional = false, $mode = null)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup;
|
||||
|
||||
use ArrayIterator;
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* Container to store and handle requirements
|
||||
*
|
||||
* TODO: Requirements should be registered as objects with a specific purpose (PhpModRequirement, PhpIniRequirement, ..)
|
||||
* so that it's not necessary to define unique identifiers which may differ between different modules.
|
||||
*/
|
||||
class Requirements implements IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Identifier representing the state OK
|
||||
*/
|
||||
const STATE_OK = 2;
|
||||
|
||||
/**
|
||||
* Identifier representing the state OPTIONAL
|
||||
*/
|
||||
const STATE_OPTIONAL = 1;
|
||||
|
||||
/**
|
||||
* Identifier representing the state MANDATORY
|
||||
*/
|
||||
const STATE_MANDATORY = 0;
|
||||
|
||||
/**
|
||||
* The registered requirements
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $requirements = array();
|
||||
|
||||
/**
|
||||
* Register a requirement
|
||||
*
|
||||
* @param object $requirement The requirement to add
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function add($name, $requirement)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Module\Setup;
|
||||
|
||||
use RecursiveIteratorIterator;
|
||||
|
||||
class RequirementsRenderer extends RecursiveIteratorIterator
|
||||
{
|
||||
public function beginIteration()
|
||||
{
|
||||
$this->tags[] = '<table class="requirements">';
|
||||
$this->tags[] = '<tbody>';
|
||||
}
|
||||
|
||||
public function endIteration()
|
||||
{
|
||||
$this->tags[] = '</tbody>';
|
||||
$this->tags[] = '</table>';
|
||||
}
|
||||
|
||||
public function beginChildren()
|
||||
{
|
||||
$this->tags[] = '<tr>';
|
||||
$currentSet = $this->getSubIterator();
|
||||
$state = $currentSet->getState() ? 'fulfilled' : (
|
||||
$currentSet->isOptional() ? 'not-available' : 'missing'
|
||||
);
|
||||
$colSpanRequired = $this->hasSingleRequirements($this->getSubIterator($this->getDepth() - 1));
|
||||
$this->tags[] = '<td class="set-state ' . $state . '"' . ($colSpanRequired ? ' colspan=3' : '') . '>';
|
||||
$this->beginIteration();
|
||||
}
|
||||
|
||||
public function endChildren()
|
||||
{
|
||||
$this->endIteration();
|
||||
$this->tags[] = '</td>';
|
||||
$this->tags[] = '</tr>';
|
||||
}
|
||||
|
||||
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[] = '<tr>';
|
||||
$this->tags[] = '<td class="title"><h2>' . $requirement->getTitle() . '</h2></td>';
|
||||
$this->tags[] = '<td class="desc">';
|
||||
$descriptions = $requirement->getDescriptions();
|
||||
if (count($descriptions) > 1) {
|
||||
$this->tags[] = '<ul>';
|
||||
foreach ($descriptions as $d) {
|
||||
$this->tags[] = '<li>' . $d . '</li>';
|
||||
}
|
||||
$this->tags[] = '</ul>';
|
||||
} elseif (! empty($descriptions)) {
|
||||
$this->tags[] = $descriptions[0];
|
||||
}
|
||||
$this->tags[] = '</td>';
|
||||
$this->tags[] = '<td class="state ' . ($requirement->getState() ? 'fulfilled' : (
|
||||
$requirement->isOptional() ? 'not-available' : 'missing'
|
||||
)) . '">' . $requirement->getStateText() . '</td>';
|
||||
$this->tags[] = '</tr>';
|
||||
}
|
||||
|
||||
return implode("\n", $this->tags);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->render();
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ interface SetupWizard
|
|||
/**
|
||||
* Return the requirements of this wizard
|
||||
*
|
||||
* @return Requirements
|
||||
* @return RequirementSet
|
||||
*/
|
||||
public function getRequirements();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,496 @@
|
|||
<?php
|
||||
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Tests\Icinga\Module\Setup;
|
||||
|
||||
use Icinga\Test\BaseTestCase;
|
||||
use Icinga\Module\Setup\Requirement;
|
||||
use Icinga\Module\Setup\RequirementSet;
|
||||
|
||||
class TrueRequirement extends Requirement
|
||||
{
|
||||
protected function evaluate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class FalseRequirement extends Requirement
|
||||
{
|
||||
protected function evaluate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class RequirementSetTest extends BaseTestCase
|
||||
{
|
||||
public function testFlatMandatoryRequirementsOfTypeAnd()
|
||||
{
|
||||
$emptySet = new RequirementSet();
|
||||
$this->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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue