Merge branch 'master' into bugfix/unnecessary-joins-8614

This commit is contained in:
Eric Lippmann 2015-03-11 13:38:07 +01:00
commit 2286ab1846
78 changed files with 1989 additions and 715 deletions

View File

@ -1,5 +1,6 @@
Alexander Fuhr <alexander.fuhr@netways.de>
Alexander Klimov <alexander.klimov@netways.de>
ayoubabid <ayoubabid@users.noreply.github.com>
baufrecht <baufrecht@users.noreply.github.com>
Bernd Erk <bernd.erk@icinga.org>
Boden Garman <boden.garman@spintel.net.au>
@ -11,8 +12,9 @@ Goran Rakic <grakic@devbase.net>
Gunnar Beutner <gunnar.beutner@netways.de>
Jannis Moßhammer <jannis.mosshammer@netways.de>
Johannes Meyer <johannes.meyer@netways.de>
Marius Hein <marius.hein@netways.de>
Louis Sautier <sautier.louis@gmail.com>
Marcus Cobden <marcus@marcuscobden.co.uk>
Marius Hein <marius.hein@netways.de>
Markus Frosch <markus@lazyfrosch.de>
Matthias Jentsch <matthias.jentsch@netways.de>
Michael Friedrich <michael.friedrich@netways.de>
@ -22,4 +24,3 @@ Sylph Lin <sylph.lin@gmail.com>
Thomas Gelf <thomas.gelf@netways.de>
Tom Ford <exptom@users.noreply.github.com>
Ulf Lange <mopp@gmx.net>
ayoubabid <ayoubabid@users.noreply.github.com>

View File

@ -135,22 +135,23 @@ class ConfigController extends ActionController
public function moduleAction()
{
$name = $this->getParam('name');
$app = Icinga::app();
$manager = $app->getModuleManager();
$name = $this->getParam('name');
if ($manager->hasInstalled($name)) {
$this->view->moduleData = Icinga::app()
->getModuleManager()
->select()
->from('modules')
->where('name', $name)
->fetchRow();
$module = new Module($app, $name, $manager->getModuleDir($name));
$this->view->moduleData = $manager->select()->from('modules')->where('name', $name)->fetchRow();
if ($manager->hasLoaded($name)) {
$module = $manager->getModule($name);
} else {
$module = new Module($app, $name, $manager->getModuleDir($name));
}
$this->view->module = $module;
$this->view->tabs = $module->getConfigTabs()->activate('info');
} else {
$this->view->module = false;
$this->view->tabs = null;
}
$this->view->tabs = $module->getConfigTabs()->activate('info');
}
/**
@ -163,7 +164,6 @@ class ConfigController extends ActionController
$manager = Icinga::app()->getModuleManager();
try {
$manager->enableModule($module);
$manager->loadModule($module);
Notification::success(sprintf($this->translate('Module "%s" enabled'), $module));
$this->rerenderLayout()->reloadCss()->redirectNow('config/modules');
} catch (Exception $e) {

View File

@ -53,7 +53,7 @@ class ExternalBackendForm extends Form
return @preg_match($value, '') !== false;
});
$callbackValidator->setMessage(
$this->translate('"%value%" is not a valid regular expression'),
$this->translate('"%value%" is not a valid regular expression.'),
Zend_Validate_Callback::INVALID_VALUE
);
$this->addElement(
@ -62,9 +62,10 @@ class ExternalBackendForm extends Form
array(
'label' => $this->translate('Filter Pattern'),
'description' => $this->translate(
'The regular expression to use to strip specific parts off from usernames.'
. ' Leave empty if you do not want to strip off anything'
'The filter to use to strip specific parts off from usernames.'
. ' Leave empty if you do not want to strip off anything.'
),
'requirement' => $this->translate('The filter pattern must be a valid regular expression.'),
'validators' => array($callbackValidator)
)
);

View File

@ -55,7 +55,7 @@ class LdapBackendForm extends Form
'required' => true,
'label' => $this->translate('Backend Name'),
'description' => $this->translate(
'The name of this authentication provider that is used to differentiate it from others'
'The name of this authentication provider that is used to differentiate it from others.'
)
)
);
@ -64,8 +64,10 @@ class LdapBackendForm extends Form
'resource',
array(
'required' => true,
'label' => $this->translate('LDAP Resource'),
'description' => $this->translate('The resource to use for authenticating with this provider'),
'label' => $this->translate('LDAP Connection'),
'description' => $this->translate(
'The LDAP connection to use for authenticating with this provider.'
),
'multiOptions' => false === empty($this->resources)
? array_combine($this->resources, $this->resources)
: array()
@ -77,10 +79,40 @@ class LdapBackendForm extends Form
array(
'required' => true,
'label' => $this->translate('LDAP User Object Class'),
'description' => $this->translate('The object class used for storing users on the ldap server'),
'description' => $this->translate('The object class used for storing users on the LDAP server.'),
'value' => 'inetOrgPerson'
)
);
$this->addElement(
'text',
'filter',
array(
'allowEmpty' => true,
'label' => $this->translate('LDAP Filter'),
'description' => $this->translate(
'An additional filter to use when looking up users using the specified connection. '
. 'Leave empty to not to use any additional filter rules.'
),
'requirement' => $this->translate(
'The filter needs to be expressed as standard LDAP expression, without'
. ' outer parentheses. (e.g. &(foo=bar)(bar=foo) or foo=bar)'
),
'validators' => array(
array(
'Callback',
false,
array(
'callback' => function ($v) {
return strpos($v, '(') !== 0;
},
'messages' => array(
'callbackValue' => $this->translate('The filter must not be wrapped in parantheses.')
)
)
)
)
)
);
$this->addElement(
'text',
'user_name_attribute',
@ -88,7 +120,7 @@ class LdapBackendForm extends Form
'required' => true,
'label' => $this->translate('LDAP User Name Attribute'),
'description' => $this->translate(
'The attribute name used for storing the user name on the ldap server'
'The attribute name used for storing the user name on the LDAP server.'
),
'value' => 'uid'
)
@ -106,10 +138,10 @@ class LdapBackendForm extends Form
'base_dn',
array(
'required' => false,
'label' => $this->translate('Base DN'),
'label' => $this->translate('LDAP Base DN'),
'description' => $this->translate(
'The path where users can be found on the ldap server. Leave ' .
'empty to select all users available on the specified resource.'
'The path where users can be found on the LDAP server. Leave ' .
'empty to select all users available using the specified connection.'
)
)
);
@ -142,11 +174,17 @@ class LdapBackendForm extends Form
ResourceFactory::createResource($form->getResourceConfig()),
$form->getElement('user_class')->getValue(),
$form->getElement('user_name_attribute')->getValue(),
$form->getElement('base_dn')->getValue()
$form->getElement('base_dn')->getValue(),
$form->getElement('filter')->getValue()
);
$ldapUserBackend->assertAuthenticationPossible();
} catch (AuthenticationException $e) {
$form->addError($e->getMessage());
if (($previous = $e->getPrevious()) !== null) {
$form->addError($previous->getMessage());
} else {
$form->addError($e->getMessage());
}
return false;
} catch (Exception $e) {
$form->addError(sprintf($form->translate('Unable to validate authentication: %s'), $e->getMessage()));

View File

@ -66,6 +66,7 @@ class LoggingConfigForm extends Form
'description' => $this->translate(
'The name of the application by which to prefix syslog messages.'
),
'requirement' => $this->translate('The application prefix must not contain whitespace.'),
'value' => 'icingaweb2',
'validators' => array(
array(

View File

@ -3,6 +3,7 @@
namespace Icinga\Forms\Config\Resource;
use Zend_Validate_Callback;
use Icinga\Web\Form;
/**
@ -42,13 +43,22 @@ class FileResourceForm extends Form
'validators' => array('ReadablePathValidator')
)
);
$callbackValidator = new Zend_Validate_Callback(function ($value) {
return @preg_match($value, '') !== false;
});
$callbackValidator->setMessage(
$this->translate('"%value%" is not a valid regular expression.'),
Zend_Validate_Callback::INVALID_VALUE
);
$this->addElement(
'text',
'fields',
array(
'required' => true,
'label' => $this->translate('Pattern'),
'description' => $this->translate('The regular expression by which to identify columns')
'description' => $this->translate('The pattern by which to identify columns.'),
'requirement' => $this->translate('The column pattern must be a valid regular expression.'),
'validators' => array($callbackValidator)
)
);

View File

@ -29,7 +29,16 @@ if ($notifications->hasMessages()) {
}
?></ul>
<div id="logo" data-base-target="_main">
<img aria-hidden="true" src="<?= $this->href('img/logo_icinga-inv.png') ?>" class="logo" alt="<?= t('Dashboard') ?>" />
<?= $this->qlink(
'',
'/dashboard',
null,
array(
'icon' => '../logo_icinga-inv.png',
'aria-hidden' => 'true',
'tabindex' => -1
)
); ?>
</div>
</div>

View File

@ -2,9 +2,6 @@
<?= $this->tabs ?>
</div>
<div class="content">
<h1 tabindex="-1">
<?= $this->escape($module->getTitle()) ?>
</h1>
<?php if (! $module): ?>
<?= $this->translate('There is no such module installed.') ?>
<?php return; endif ?>
@ -14,6 +11,9 @@
$permissions = $module->getProvidedPermissions();
$state = $moduleData->enabled ? ($moduleData->loaded ? 'enabled' : 'failed') : 'disabled'
?>
<h1 tabindex="-1">
<?= $this->escape($module->getTitle()) ?>
</h1>
<table class="avp">
<tr>
<th><?= $this->escape($this->translate('Name')) ?></th>

View File

@ -252,7 +252,7 @@ class Manager
}
/**
* Disable the given module and remove it's enabled state
* Disable the given module and remove its enabled state
*
* @param string $name The name of the module to disable
*

View File

@ -113,6 +113,13 @@ class Module
*/
private $triedToLaunchConfigScript = false;
/**
* Whether this module has been registered
*
* @var bool
*/
private $registered = false;
/**
* Provided permissions
*
@ -279,6 +286,10 @@ class Module
*/
public function register()
{
if ($this->registered) {
return true;
}
$this->registerAutoloader();
try {
$this->launchRunScript();
@ -291,10 +302,22 @@ class Module
);
return false;
}
$this->registerWebIntegration();
$this->registered = true;
return true;
}
/**
* Return whether this module has been registered
*
* @return bool
*/
public function isRegistered()
{
return $this->registered;
}
/**
* Test for an enabled module by name
*
@ -913,7 +936,7 @@ class Module
*/
protected function launchConfigScript()
{
if ($this->triedToLaunchConfigScript) {
if ($this->triedToLaunchConfigScript || !$this->registered) {
return;
}
$this->triedToLaunchConfigScript = true;

View File

@ -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');
}
}

View File

@ -96,10 +96,15 @@ class DbUserBackend extends UserBackend
'SELECT password_hash FROM icingaweb_user WHERE name = :name AND active = 1'
);
}
$stmt->execute(array(':name' => $username));
$stmt->bindColumn(1, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
return is_resource($lob) ? stream_get_contents($lob) : $lob;
if (is_resource($lob)) {
$lob = stream_get_contents($lob);
}
return $this->conn->getDbType() === 'pgsql' ? pg_unescape_bytea($lob) : $lob;
}
/**

View File

@ -9,6 +9,7 @@ use Icinga\Protocol\Ldap\Query;
use Icinga\Protocol\Ldap\Connection;
use Icinga\Exception\AuthenticationException;
use Icinga\Protocol\Ldap\Exception as LdapException;
use Icinga\Protocol\Ldap\Expression;
class LdapUserBackend extends UserBackend
{
@ -25,14 +26,23 @@ class LdapUserBackend extends UserBackend
protected $userNameAttribute;
protected $customFilter;
protected $groupOptions;
public function __construct(Connection $conn, $userClass, $userNameAttribute, $baseDn, $groupOptions = null)
{
public function __construct(
Connection $conn,
$userClass,
$userNameAttribute,
$baseDn,
$cutomFilter,
$groupOptions = null
) {
$this->conn = $conn;
$this->baseDn = trim($baseDn) !== '' ? $baseDn : $conn->getDN();
$this->baseDn = trim($baseDn) ?: $conn->getDN();
$this->userClass = $userClass;
$this->userNameAttribute = $userNameAttribute;
$this->customFilter = trim($cutomFilter);
$this->groupOptions = $groupOptions;
}
@ -43,12 +53,18 @@ class LdapUserBackend extends UserBackend
*/
protected function selectUsers()
{
return $this->conn->select()->setBase($this->baseDn)->from(
$query = $this->conn->select()->setBase($this->baseDn)->from(
$this->userClass,
array(
$this->userNameAttribute
)
);
if ($this->customFilter) {
$query->addFilter(new Expression($this->customFilter));
}
return $query;
}
/**
@ -88,9 +104,10 @@ class LdapUserBackend extends UserBackend
if ($result === null) {
throw new AuthenticationException(
'No objects with objectClass="%s" in DN="%s" found.',
'No objects with objectClass="%s" in DN="%s" found. (Filter: %s)',
$this->userClass,
$this->baseDn
$this->baseDn,
$this->customFilter ?: 'None'
);
}

View File

@ -103,6 +103,7 @@ abstract class UserBackend implements Countable
$backendConfig->get('user_class', 'user'),
$backendConfig->get('user_name_attribute', 'sAMAccountName'),
$backendConfig->get('base_dn', $resource->getDN()),
$backendConfig->get('filter'),
$groupOptions
);
break;
@ -130,6 +131,7 @@ abstract class UserBackend implements Countable
$backendConfig->user_class,
$backendConfig->user_name_attribute,
$backendConfig->get('base_dn', $resource->getDN()),
$backendConfig->get('filter'),
$groupOptions
);
break;

View File

@ -16,7 +16,7 @@ use Icinga\Chart\Unit\LinearUnit;
/**
* Axis class for the GridChart class.
*
* Implements drawing functions for the axis and it's labels but delegates tick and label calculations
* Implements drawing functions for the axis and its labels but delegates tick and label calculations
* to the AxisUnit implementations
*
* @see GridChart

View File

@ -0,0 +1,30 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Protocol\Ldap;
class Expression
{
protected $value;
public function __construct($value)
{
$this->value = $value;
}
public function setValue($value)
{
$this->value = $value;
return $this;
}
public function getValue()
{
return $this->value;
}
public function __toString()
{
return (string) $this->getValue();
}
}

View File

@ -306,6 +306,19 @@ class Query
return $paginator;
}
/**
* Add a filter expression to this query
*
* @param Expression $expression
*
* @return Query
*/
public function addFilter(Expression $expression)
{
$this->filters[] = $expression;
return $this;
}
/**
* Returns the LDAP filter that will be applied
*
@ -318,11 +331,15 @@ class Query
throw new Exception('Object class is mandatory');
}
foreach ($this->filters as $key => $value) {
$parts[] = sprintf(
'%s=%s',
LdapUtils::quoteForSearch($key),
LdapUtils::quoteForSearch($value, true)
);
if ($value instanceof Expression) {
$parts[] = (string) $value;
} else {
$parts[] = sprintf(
'%s=%s',
LdapUtils::quoteForSearch($key),
LdapUtils::quoteForSearch($value, true)
);
}
}
if (count($parts) > 1) {
return '(&(' . implode(')(', $parts) . '))';

View File

@ -203,12 +203,14 @@ class DbStore extends PreferencesStore
foreach ($preferences as $key => $value) {
$db->update(
$this->table,
array(self::COLUMN_VALUE => $value),
array(
self::COLUMN_VALUE => $value,
self::COLUMN_MODIFIED_TIME => new Zend_Db_Expr('NOW()')
),
array(
self::COLUMN_USERNAME . '=?' => $this->getUser()->getUsername(),
$db->quoteIdentifier(self::COLUMN_SECTION) . '=?' => $section,
$db->quoteIdentifier(self::COLUMN_PREFERENCE) . '=?' => $key,
self::COLUMN_MODIFIED_TIME => new Zend_Db_Expr('NOW()')
$db->quoteIdentifier(self::COLUMN_PREFERENCE) . '=?' => $key
)
);
}

View File

@ -27,7 +27,7 @@ class BasePreferenceController extends ActionController
}
/**
* Initialize the controller and collect all tabs for it from the application and it's modules
* Initialize the controller and collect all tabs for it from the application and its modules
*
* @see ActionController::init()
*/

View File

@ -157,7 +157,7 @@ class Form extends Zend_Form
public static $defaultElementDecorators = array(
array('ViewHelper', array('separator' => '')),
array('Errors', array('separator' => '')),
array('Help'),
array('Help', array('placement' => 'PREPEND')),
array('Label', array('separator' => '')),
array('HtmlTag', array('tag' => 'div', 'class' => 'element'))
);
@ -622,7 +622,7 @@ class Form extends Zend_Form
public function addSubForm(Zend_Form $form, $name = null, $order = null)
{
if ($form instanceof self) {
$form->removeDecorator('Form');
$form->setDecorators(array('FormElements')); // TODO: Makes it difficult to customise subform decorators..
$form->setSubmitLabel('');
$form->setTokenDisabled();
$form->setUidDisabled();
@ -743,7 +743,7 @@ class Form extends Zend_Form
if (($cue = $this->getRequiredCue()) !== null && ($label = $element->getDecorator('label')) !== false) {
$element->setLabel($this->getView()->escape($element->getLabel()));
$label->setOption('escape', false);
$label->setOption('requiredSuffix', sprintf(' <span aria-hidden="true">%s</span>', $cue));
$label->setRequiredSuffix(sprintf(' <span aria-hidden="true">%s</span>', $cue));
}
}

View File

@ -13,6 +13,29 @@ use Icinga\Web\Form;
*/
class FormDescriptions extends Zend_Form_Decorator_Abstract
{
/**
* A list of element class names to be ignored when detecting which message to use to describe required elements
*
* @var array
*/
protected $blacklist;
/**
* {@inheritdoc}
*/
public function __construct($options = null)
{
parent::__construct($options);
$this->blacklist = array(
'Zend_Form_Element_Hidden',
'Zend_Form_Element_Submit',
'Zend_Form_Element_Button',
'Icinga\Web\Form\Element\Note',
'Icinga\Web\Form\Element\Button',
'Icinga\Web\Form\Element\CsrfCounterMeasure'
);
}
/**
* Render form descriptions
*
@ -32,9 +55,16 @@ class FormDescriptions extends Zend_Form_Decorator_Abstract
return $content;
}
$descriptions = $form->getDescriptions();
if (($requiredDesc = $this->getRequiredDescription($form)) !== null) {
$descriptions[] = $requiredDesc;
$descriptions = $this->recurseForm($form, $entirelyRequired);
if ($entirelyRequired) {
$descriptions[] = $form->getView()->translate(
'All fields are required and must be filled in to complete the form.'
);
} elseif ($entirelyRequired === false) {
$descriptions[] = $form->getView()->translate(sprintf(
'Required fields are marked with %s and must be filled in to complete the form.',
$form->getRequiredCue()
));
}
if (empty($descriptions)) {
@ -60,53 +90,57 @@ class FormDescriptions extends Zend_Form_Decorator_Abstract
}
/**
* Return the description for the given form's required elements
* Recurse the given form and return the descriptions for it and all of its subforms
*
* @param Form $form
* @param Form $form The form to recurse
* @param mixed $entirelyRequired Set by reference, true means all elements in the hierarchy are
* required, false only a partial subset and null none at all
* @param bool $elementsPassed Whether there were any elements passed during the recursion until now
*
* @return string|null
* @return array
*/
protected function getRequiredDescription(Form $form)
protected function recurseForm(Form $form, & $entirelyRequired = null, $elementsPassed = false)
{
if (($cue = $form->getRequiredCue()) === null) {
return;
}
$requiredLabels = array();
$entirelyRequired = true;
$partiallyRequired = false;
$blacklist = array(
'Zend_Form_Element_Hidden',
'Zend_Form_Element_Submit',
'Zend_Form_Element_Button',
'Icinga\Web\Form\Element\Note',
'Icinga\Web\Form\Element\Button',
'Icinga\Web\Form\Element\CsrfCounterMeasure'
);
foreach ($form->getElements() as $element) {
if (! in_array($element->getType(), $blacklist)) {
if (! $element->isRequired()) {
$entirelyRequired = false;
} else {
$partiallyRequired = true;
if (($label = $element->getDecorator('label')) !== false) {
$requiredLabels[] = $label;
if ($form->getRequiredCue() !== null) {
$partiallyRequired = $partiallyOptional = false;
foreach ($form->getElements() as $element) {
if (! in_array($element->getType(), $this->blacklist)) {
if (! $element->isRequired()) {
$partiallyOptional = true;
if ($entirelyRequired) {
$entirelyRequired = false;
}
} else {
$partiallyRequired = true;
if (($label = $element->getDecorator('label')) !== false) {
$requiredLabels[] = $label;
}
}
}
}
if (! $elementsPassed) {
$elementsPassed = $partiallyRequired || $partiallyOptional;
if ($entirelyRequired === null && $partiallyRequired) {
$entirelyRequired = ! $partiallyOptional;
}
} elseif ($entirelyRequired === null && $partiallyRequired) {
$entirelyRequired = false;
}
}
if ($entirelyRequired && $partiallyRequired) {
$descriptions = array($form->getDescriptions());
foreach ($form->getSubForms() as $subForm) {
$descriptions[] = $this->recurseForm($subForm, $entirelyRequired, $elementsPassed);
}
if ($entirelyRequired) {
foreach ($requiredLabels as $label) {
$label->setRequiredSuffix('');
}
return $form->getView()->translate('All fields are required and must be filled in to complete the form.');
} elseif ($partiallyRequired) {
return $form->getView()->translate(sprintf(
'Required fields are marked with %s and must be filled in to complete the form.',
$cue
));
}
return call_user_func_array('array_merge', $descriptions);
}
}

View File

@ -76,18 +76,35 @@ class Help extends Zend_Form_Decorator_Abstract
*/
public function render($content = '')
{
if ($content && ($description = $this->getElement()->getDescription()) !== null) {
$element = $this->getElement();
$description = $element->getDescription();
$requirement = $element->getAttrib('requirement');
unset($element->requirement);
$helpContent = '';
if ($description || $requirement) {
if ($this->accessible) {
$content = '<span id="'
$helpContent = '<span id="'
. $this->getDescriptionId()
. '" class="sr-only">'
. $description
. '</span>' . $content;
. ($description && $requirement ? ' ' : '')
. $requirement
. '</span>';
}
$content = $this->getView()->icon('help', $description, array('aria-hidden' => 'true')) . $content;
$helpContent = $this->getView()->icon(
'help',
$description . ($description && $requirement ? ' ' : '') . $requirement,
array('aria-hidden' => $this->accessible ? 'true' : 'false')
) . $helpContent;
}
return $content;
switch ($this->getPlacement()) {
case self::APPEND:
return $content . $helpContent;
case self::PREPEND:
return $helpContent . $content;
}
}
}

View File

@ -26,7 +26,7 @@ abstract class AbstractWidget
{
/**
* If you are going to access the current view with the view() function,
* it's instance is stored here for performance reasons.
* its instance is stored here for performance reasons.
*
* @var Zend_View_Abstract
*/

View File

@ -268,7 +268,7 @@ class HistoryColorGrid extends AbstractWidget {
}
$week++;
}
if ($day > cal_days_in_month(CAL_GREGORIAN, $month, $year)) {
if ($day > date('t', mktime(0, 0, 0, $month, 1, $year))) {
$month++;
if ($month > 12) {
$year++;

View File

@ -18,7 +18,7 @@ use Icinga\Web\Url;
*
* The terminology is as follows:
* - Dashlet: A single view showing a specific url
* - Pane: Aggregates one or more dashlets on one page, displays it's title as a tab
* - Pane: Aggregates one or more dashlets on one page, displays its title as a tab
* - Dashboard: Shows all panes
*
*/
@ -347,7 +347,7 @@ class Dashboard extends AbstractWidget
}
/**
* Activates the default pane of this dashboard and returns it's name
* Activates the default pane of this dashboard and returns its name
*
* @return mixed
*/

View File

@ -140,6 +140,10 @@ class Tab extends AbstractWidget
*/
public function getLabel()
{
if (! $this->label) {
return $this->title;
}
return $this->label;
}
@ -238,7 +242,7 @@ class Tab extends AbstractWidget
$classes[] = 'active';
}
$caption = $view->escape($this->label);
$caption = $view->escape($this->getLabel());
$tagParams = $this->tagParams;
if ($this->title) {

View File

@ -207,7 +207,7 @@ EOT;
* with tab properties or an instance of an existing Tab
*
* @param string $name The new tab name
* @param array|Tab $tab The tab itself of it's properties
* @param array|Tab $tab The tab itself of its properties
*
* @return self
*
@ -232,7 +232,7 @@ EOT;
* of an existing Tab
*
* @param string $name The new tab name
* @param array|Tab $tab The tab itself of it's properties
* @param array|Tab $tab The tab itself of its properties
*
* @return self
*/
@ -279,7 +279,7 @@ EOT;
}
/**
* Render the dropdown area with it's tabs and return the resulting HTML
* Render the dropdown area with its tabs and return the resulting HTML
*
* @return mixed|string
*/

View File

@ -1,4 +1,4 @@
Module: doc
Version: 2.0.0
Description: Documentation module
Extracts, shows and exports documentation for Icinga Web 2 and it's modules.
Extracts, shows and exports documentation for Icinga Web 2 and its modules.

View File

@ -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;
}
}

View File

@ -272,7 +272,8 @@ class AdminAccountPage extends Form
ResourceFactory::createResource(new ConfigObject($this->resourceConfig)),
$this->backendConfig['user_class'],
$this->backendConfig['user_name_attribute'],
$this->backendConfig['base_dn']
$this->backendConfig['base_dn'],
$this->backendConfig['filter']
);
} else {
throw new LogicException(

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Setup\Forms;
use Exception;
use Zend_Validate_NotEmpty;
use Icinga\Web\Form;
use Icinga\Web\Form\ErrorLabeller;
@ -68,9 +69,12 @@ class LdapDiscoveryPage extends Form
}
if (isset($data['domain']) && $data['domain']) {
$this->discovery = Discovery::discoverDomain($data['domain']);
if ($this->discovery->isSuccess()) {
return true;
try {
$this->discovery = Discovery::discoverDomain($data['domain']);
if ($this->discovery->isSuccess()) {
return true;
}
} catch (Exception $e) {
}
$this->addError(

View File

@ -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();
}
}

View File

@ -20,12 +20,12 @@ $showRadioBoxes = strpos(strtolower(get_class($radioElem)), 'radio') !== false;
<?php if (($byNameElem = $form->getElement('by_name')) !== null): ?>
<div>
<div class="instructions">
<?= $byNameElem; ?>
<?= $showRadioBoxes ? $byNameElem->setAttrib('data-related-radiobtn', 'by_name') : $byNameElem; ?>
</div>
<?php if ($showRadioBoxes): ?>
<div class="radiobox">
<label>
<input type="radio" name="user_type" value="by_name"<?= $radioElem->getValue() === 'by_name' ? ' checked' : ''; ?> class="autosubmit" aria-required="true" required>
<input type="radio" id="by_name" name="user_type" value="by_name"<?= $radioElem->getValue() === 'by_name' ? ' checked' : ''; ?> class="autosubmit" aria-required="true" required>
<?= $radioElem->getMultiOption('by_name'); ?>
</label>
</div>
@ -35,12 +35,12 @@ $showRadioBoxes = strpos(strtolower(get_class($radioElem)), 'radio') !== false;
<?php if (($existingUserElem = $form->getElement('existing_user')) !== null): ?>
<div>
<div class="instructions">
<?= $existingUserElem; ?>
<?= $showRadioBoxes ? $existingUserElem->setAttrib('data-related-radiobtn', 'existing_user') : $existingUserElem; ?>
</div>
<?php if ($showRadioBoxes): ?>
<div class="radiobox">
<label>
<input type="radio" name="user_type" value="existing_user"<?= $radioElem->getValue() === 'existing_user' ? ' checked' : ''; ?> class="autosubmit" aria-required="true" required>
<input type="radio" id="existing_user" name="user_type" value="existing_user"<?= $radioElem->getValue() === 'existing_user' ? ' checked' : ''; ?> class="autosubmit" aria-required="true" required>
<?= $radioElem->getMultiOption('existing_user'); ?>
</label>
</div>
@ -50,14 +50,14 @@ $showRadioBoxes = strpos(strtolower(get_class($radioElem)), 'radio') !== false;
<?php if (($newUserElem = $form->getElement('new_user')) !== null): ?>
<div>
<div class="instructions">
<?= $newUserElem; ?>
<?= $showRadioBoxes ? $newUserElem->setAttrib('data-related-radiobtn', 'new_user') : $newUserElem; ?>
<?= $form->getElement('new_user_password'); ?>
<?= $form->getElement('new_user_2ndpass'); ?>
</div>
<?php if ($showRadioBoxes): ?>
<div class="radiobox">
<label>
<input type="radio" name="user_type" value="new_user"<?= $radioElem->getValue() === 'new_user' ? ' checked' : ''; ?> class="autosubmit" aria-required="true" required>
<input type="radio" id="new_user" name="user_type" value="new_user"<?= $radioElem->getValue() === 'new_user' ? ' checked' : ''; ?> class="autosubmit" aria-required="true" required>
<?= $radioElem->getMultiOption('new_user'); ?>
</label>
</div>

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -18,7 +18,7 @@ interface SetupWizard
/**
* Return the requirements of this wizard
*
* @return Requirements
* @return RequirementSet
*/
public function getRequirements();
}

View File

@ -126,11 +126,15 @@ class AuthenticationStep extends Step
. '</tr>'
. ($authType === 'ldap' ? (
'<tr>'
. '<td><strong>' . t('User Object Class') . '</strong></td>'
. '<td><strong>' . mt('setup', 'User Object Class') . '</strong></td>'
. '<td>' . $this->data['backendConfig']['user_class'] . '</td>'
. '</tr>'
. '<tr>'
. '<td><strong>' . t('User Name Attribute') . '</strong></td>'
. '<td><strong>' . mt('setup', 'Custom Filter') . '</strong></td>'
. '<td>' . trim($this->data['backendConfig']['filter']) ?: t('None', 'auth.ldap.filter') . '</td>'
. '</tr>'
. '<tr>'
. '<td><strong>' . mt('setup', 'User Name Attribute') . '</strong></td>'
. '<td>' . $this->data['backendConfig']['user_name_attribute'] . '</td>'
. '</tr>'
) : ($authType === 'external' ? (

View File

@ -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;
}
}

View File

@ -25,6 +25,7 @@ location ~ ^{urlPath}/index\.php(.*)$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME {documentRoot}/index.php;
fastcgi_param ICINGAWEB_CONFIGDIR {configDir};
fastcgi_param REMOTE_USER $remote_user;
}
location ~ ^{urlPath}(.+)? {

View File

@ -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();
}
}

View File

@ -2,4 +2,4 @@ Module: test
Version: 2.0.0~alpha4
Description: Translation module
This module allows developers to run (unit) tests against Icinga Web 2 and
any of it's modules. Usually you do not need to enable this.
any of its modules. Usually you do not need to enable this.

View File

@ -15,7 +15,7 @@ use Icinga\Module\Translation\Util\GettextTranslationHelper;
* Domains are the global one 'icinga' and all available and enabled modules
* identified by their name.
*
* Once a PO-file is compiled it's content is used by Icinga Web 2 to display
* Once a PO-file is compiled its content is used by Icinga Web 2 to display
* messages in the configured language.
*/
class CompileCommand extends TranslationCommand

View File

@ -109,7 +109,7 @@ When you are done, just save your new settings.
To work with Icinga Web 2 .po files, you can open for e.g. the german icinga.po file which is located under
`application/locale/de_DE/LC_MESSAGES/icinga.po`, as shown below, you will get then a full list of all available
translation strings for the core application. Each module names it's translation files `%module_name%.po`. For a
translation strings for the core application. Each module names its translation files `%module_name%.po`. For a
module called __yourmodule__ the .po translation file will be named `yourmodule.po`.
@ -196,4 +196,4 @@ The last step is to compile the __yourmodule.po__ to the __yourmodule.mo__:
icingacli translation compile module development ll_CC
At this moment, everywhere in the module where the `Dummy` should be translated, it would returns the translated
string `Attrappe`.
string `Attrappe`.

View File

@ -2,6 +2,6 @@ Module: translation
Version: 2.0.0~alpha4
Description: Translation module
This module allows developers and translators to translate Icinga Web 2 and
it's modules for multiple languages. You do not need this module to run an
its modules for multiple languages. You do not need this module to run an
internationalized web frontend. This is only for people who want to contribute
translations or translate just their own moduls.

View File

@ -1,3 +0,0 @@
PLEASE DO NOT BUILD PACKAGES BASES ON THIS
Packages may still be renamed

View File

@ -1,5 +0,0 @@
icingaweb (2.0.0) stable; urgency=low
* First stable release (Closes: #0001)
-- Thomas Gelf <thomas@gelf.net> Fri, 28 Mar 2014 23:37:31 +0100

View File

@ -1 +0,0 @@
9

View File

@ -1,68 +0,0 @@
Source: icingaweb
Section: admin
Maintainer: Icinga Development Team <info@icinga.org>
Priority: optional
Build-Depends: debhelper (>=9)
Standards-Version: 3.9.4
Homepage: https://www.icinga.org
Package: php-icinga
Architecture: any
Depends: php5 (>= 5.3.2)
Recommends: php5-ldap, php5-mysql, php5-json
Suggests: php5-pgsql
Description: Icinga PHP libraries
PHP libraries
Package: icingaweb-common
Architecture: any
Depends: php-icinga
Description: Icinga PHP common libraries
PHP common libraries, application and modules
Package: icingaweb-module-doc
Architecture: any
Depends: icingaweb-common
Description: Icingaweb documentation module
This module renders documentation for Icingaweb and it's modules
Package: icingaweb-module-monitoring
Architecture: any
Depends: icingaweb-common
Description: Icingaweb monitoring module
Use this module to visualize your monitoring environment in Icingaweb
Package: icingaweb-module-setup
Architecture: any
Depends: icingaweb-common
Description: Icingaweb setup module
This setup wizard does your initial Icingaweb configuration
Package: icingaweb-module-test
Architecture: any
Depends: icingacli
Description: Icingaweb test module
Use this module to run unit tests against Icingaweb or any of it's modules
Package: icingaweb-module-translation
Architecture: any
Depends: icingaweb-common
Description: Icingaweb translation module
This module helps translators to get Icingaweb translations done
Package: icingacli
Architecture: any
Depends: icingaweb-common, php5-cli (>= 5.3.2)
Description: Icinga CLI tool
The Icinga CLI allows one to access it's Icinga monitoring
system from a terminal.
.
The CLI is based on the Icinga PHP libraries
Package: icingaweb
Architecture: any
Depends: icingaweb-common, libapache2-mod-php5, zendframework | icingaweb-vendor-zend, icingaweb-vendor-parsedown, icingaweb-vendor-lessphp, icingaweb-vendor-jshrink, icingaweb-vendor-htmlpurifier, icingaweb-module-setup
Recommends: icingaweb-module-monitoring, icingaweb-module-doc
Suggests: php5-ldap
Description: Icingaweb Frontend
Icingaweb is a modular web frontend

View File

@ -1 +0,0 @@
library/Icinga usr/share/php

View File

@ -1,3 +0,0 @@
packages/files/bin/icingacli usr/bin
etc/bash_completion.d etc/bash_completion.d
application/clicommands usr/share/icingaweb/application

View File

@ -1 +0,0 @@
etc/icingaweb

View File

@ -1,2 +0,0 @@
application/locales usr/share/icingaweb/application
modules usr/share/icingaweb

View File

@ -1 +0,0 @@
modules/doc usr/share/icingaweb/modules

View File

@ -1 +0,0 @@
modules/doc usr/share/icingaweb/modules

View File

@ -1 +0,0 @@
modules/setup usr/share/icingaweb/modules

View File

@ -1 +0,0 @@
modules/test usr/share/icingaweb/modules

View File

@ -1 +0,0 @@
modules/translation usr/share/icingaweb/modules

View File

@ -1 +0,0 @@
library/vendor/HTMLPurifier usr/share/icingaweb/library/vendor

View File

@ -1 +0,0 @@
library/vendor/JShrink usr/share/icingaweb/library/vendor

View File

@ -1 +0,0 @@
library/vendor/Zend usr/share/icingaweb/library/vendor

View File

@ -1 +0,0 @@
library/vendor/Parsedown usr/share/icingaweb/library/vendor

View File

@ -1 +0,0 @@
library/vendor/Zend usr/share/icingaweb/library/vendor

View File

@ -1,10 +0,0 @@
public/css usr/share/icingaweb/public
public/img usr/share/icingaweb/public
public/js usr/share/icingaweb/public
public/error_norewrite.html usr/share/icingaweb/public
application/controllers usr/share/icingaweb/application
application/fonts usr/share/icingaweb/application
application/layouts usr/share/icingaweb/application
application/views usr/share/icingaweb/application
packages/files/public/index.php usr/share/icingaweb/public
packages/files/apache/icingaweb.conf etc/apache2/conf.d

View File

@ -1,35 +0,0 @@
#!/usr/bin/make -f
#export DH_VERBOSE=1
%:
dh $@
clean:
dh_testdir
dh_clean
build:
dh_testdir
binary:
dh_testroot
dh_prep
dh_installdirs
dh_install
dh_installchangelogs
dh_installexamples
dh_installman
dh_installcron
dh_installdebconf
dh_installinfo
dh_installinit
dpkg-statoverride --force --add root www-data 2770 /etc/icingaweb
dh_compress
dh_fixperms
dh_strip
dh_shlibdeps
dh_installdeb
dh_gencontrol
dh_md5sums
dh_builddeb

View File

@ -1 +0,0 @@
3.0 (git)

View File

@ -1 +0,0 @@
misc:Depends=

View File

@ -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;
}
}
}
}
}
}

View File

@ -125,6 +125,10 @@
$(document).on('change', 'form select.autosubmit', { self: this }, this.autoSubmitForm);
$(document).on('change', 'form input.autosubmit', { self: this }, this.autoSubmitForm);
// Automatically check a radio button once a specific input is focused
$(document).on('focus', 'form select[data-related-radiobtn]', { self: this }, this.autoCheckRadioButton);
$(document).on('focus', 'form input[data-related-radiobtn]', { self: this }, this.autoCheckRadioButton);
$(document).on('keyup', '#menu input.search', {self: this}, this.autoSubmitSearch);
$(document).on('click', '.tree .handle', { self: this }, this.treeNodeToggle);
@ -163,6 +167,15 @@
icinga.ui.fixControls();
},
autoCheckRadioButton: function (event) {
var $input = $(event.currentTarget);
var $radio = $('#' + $input.attr('data-related-radiobtn'));
if ($radio.length) {
$radio.prop('checked', true);
}
return true;
},
autoSubmitSearch: function(event) {
var self = event.data.self;
if ($('#menu input.search').val() === self.searchValue) {
@ -560,6 +573,8 @@
$(document).off('submit', 'form', this.submitForm);
$(document).off('change', 'form select.autosubmit', this.submitForm);
$(document).off('change', 'form input.autosubmit', this.submitForm);
$(document).off('focus', 'form select[data-related-radiobtn]', this.autoCheckRadioButton);
$(document).off('focus', 'form input[data-related-radiobtn]', this.autoCheckRadioButton);
},
destroy: function() {

View File

@ -726,7 +726,7 @@ EOD;
}
/**
* Write a INI-configuration string to a temporary file and return it's path
* Write a INI-configuration string to a temporary file and return its path
*
* @param string $config The config string to write
*