Merge branch 'master' into feature/display-documentation-4820

This commit is contained in:
Eric Lippmann 2014-07-11 16:05:09 +02:00
commit 906c132dc0
90 changed files with 1162 additions and 1943 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
.git* export-ignore

View File

@ -18,6 +18,11 @@ title = "Configuration"
url = "config"
priority = 300
[System.ApplicationLog]
title = "Application log"
url = "list/applicationlog"
priority = 400
[Logout]
url = "authentication/logout"
icon = img/icons/logout.png

View File

@ -71,6 +71,11 @@ title = "Comments"
url = "monitoring/list/comments"
priority = 70
[Overview.Contacts]
title = "Contacts"
url = "monitoring/list/contacts"
priority = 70
[History]
icon = "img/icons/history.png"
@ -87,6 +92,10 @@ url = "monitoring/list/notifications"
title = "All Events"
url = "monitoring/list/eventhistory?timestamp>=-7%20days"
[History.Timeline]
title = "Timeline"
url = "monitoring/timeline"
[System.Process Info]
title = "Process Info"
url = "monitoring/process/info"

View File

@ -202,7 +202,7 @@ exec { 'iptables-allow-http':
exec { 'icinga-htpasswd':
creates => '/usr/share/icinga/htpasswd.users',
command => 'mkdir /usr/share/icinga && htpasswd -b -c /usr/share/icinga/htpasswd.users icingaadmin icinga',
command => 'mkdir -p /usr/share/icinga && htpasswd -b -c /usr/share/icinga/htpasswd.users icingaadmin icinga',
require => Class['apache']
}

View File

@ -32,8 +32,8 @@ install: install-config install-basic ensure-writable-folders install-cli
#
install-cli:
$(INSTALL) -m 755 -d $(INSTALL_OPTS) $(bindir)
$(INSTALL) -m 755 $(INSTALL_OPTS) "./bin/icingacli" $(bindir)/icingacli;
$(INSTALL) -m 755 -d $(INSTALL_OPTS) $(bindir)
$(INSTALL) -m 755 $(INSTALL_OPTS) "./bin/icingacli" $(bindir)/icingacli;
#
# Installs the whole application w\o configuration

View File

@ -77,14 +77,14 @@ class AuthenticationController extends ActionController
new Exception('Cannot load authentication configuration. An exception was thrown:', 0, $e)
);
throw new ConfigurationError(
'No authentication methods available. It seems that none authentication method has been set'
. ' up. Please check the system log or Icinga Web 2 log for more information'
t(
'No authentication methods available. Authentication configuration could not be loaded.'
. ' Please check the system log or Icinga Web 2 log for more information'
)
);
}
$chain = new AuthChain($config);
if ($this->getRequest()->isGet()) {
$user = new User('');
foreach ($chain as $backend) {
@ -119,7 +119,15 @@ class AuthenticationController extends ActionController
$this->rerenderLayout()->redirectNow($redirectUrl);
}
}
if ($backendsWithError === $backendsTried) {
if ($backendsTried === 0) {
throw new ConfigurationError(
t(
'No authentication methods available. It seems that no authentication method has been set'
. ' up. Please check the system log or Icinga Web 2 log for more information'
)
);
}
if ($backendsTried === $backendsWithError) {
throw new ConfigurationError(
$this->translate(
'No authentication methods available. It seems that all set up authentication methods have'

View File

@ -1,108 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Web\Session;
use Icinga\Web\Wizard\Wizard;
use Icinga\Web\Controller\ActionController;
class InstallController extends ActionController
{
/**
* Whether the controller requires the user to be authenticated
*
* The install wizard has its own authentication mechanism.
*
* @var bool
*/
protected $requiresAuthentication = false;
/**
* Whether the controller requires configuration
*
* The install wizard does not require any configuration.
*
* @var bool
*/
protected $requiresConfiguration = false;
/**
* Show the wizard and run the installation once its finished
*/
public function indexAction()
{
$wizard = $this->createWizard();
if ($wizard->isSubmittedAndValid()) {
$wizard->navigate();
if ($wizard->isFinished()) {
// TODO: Run the installer (Who creates an installer? How do we handle module installers?)
$this->dropConfiguration(); // TODO: Should only be done if the installation has been successfully completed
$this->view->installer = '';
} else {
$this->storeConfiguration($wizard->getConfig());
}
}
$this->view->wizard = $wizard;
}
/**
* Create the wizard and register all pages
*
* @return Wizard
*/
protected function createWizard()
{
$wizard = new Wizard();
$wizard->setTitle('Web');
$wizard->setRequest($this->getRequest());
$wizard->setConfiguration($this->loadConfiguration());
$wizard->addPages(
array(
// t('Welcome') => 'Icinga\Form\Install\WelcomePage',
// t('Requirements') => 'Icinga\Form\Install\RequirementsPage',
// t('Authentication') => 'Icinga\Form\Install\AuthenticationPage',
// t('Administration') => 'Icinga\Form\Install\AdministrationPage',
// t('Preferences') => 'Icinga\Form\Install\PreferencesPage',
t('Logging') => 'Icinga\Form\Install\LoggingPage',
// t('Database Setup') => 'Icinga\Form\Install\DatabasePage',
// t('Summary') => 'Icinga\Form\Install\SummaryPage'
)
);
return $wizard;
}
/**
* Store the given configuration values
*
* @param Zend_Config $config The configuration
*/
protected function storeConfiguration(Zend_Config $config)
{
$session = Session::getSession();
$session->getNamespace('WebWizard')->setAll($config->toArray(), true);
$session->write();
}
/**
* Load all configuration values
*
* @return Zend_Config
*/
protected function loadConfiguration()
{
return new Zend_Config(Session::getSession()->getNamespace('WebWizard')->getAll(), true);
}
/**
* Clear all stored configuration values
*/
protected function dropConfiguration()
{
$session = Session::getSession();
$session->removeNamespace('WebWizard');
$session->write();
}
}

View File

@ -2,6 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Web\MenuRenderer;
use Icinga\Web\Controller\ActionController;
use Icinga\Web\Hook;
use Icinga\Web\Menu;
@ -17,9 +18,7 @@ class LayoutController extends ActionController
*/
public function menuAction()
{
$this->view->url = Url::fromRequest()->getRelativeUrl();
$this->view->items = Menu::fromConfig()->getChildren();
$this->view->sub = false;
$this->view->menuRenderer = new MenuRenderer(Menu::fromConfig()->order(), Url::fromRequest()->getRelativeUrl());
}
/**

View File

@ -32,6 +32,7 @@ use Icinga\Web\Widget\Tab;
use Icinga\Application\Config as IcingaConfig;
use Icinga\Web\Url;
use Icinga\Form\Preference\GeneralForm;
use Icinga\Web\Notification;
/**
* Application wide preference controller for user preferences
@ -69,14 +70,14 @@ class PreferenceController extends BasePreferenceController
if ($form->isSubmittedAndValid()) {
try {
$this->savePreferences($form->getPreferences());
$this->view->successMessage = 'Preferences Updated Successfully';
Notification::success(t('Preferences updated successfully'));
// Recreate form to show new values
// TODO(el): It must sufficient to call $form->populate(...)
$form = new GeneralForm();
$form->setConfiguration(IcingaConfig::app());
$form->setRequest($this->getRequest());
} catch (Exception $e) {
$this->view->exceptionMessage = $e->getMessage();
Notification::error(sprintf(t('Failed to persist preferences. (%s)'), $e->getMessage()));
}
}
$this->view->form = $form;

View File

@ -160,7 +160,7 @@ class LdapBackendForm extends BaseBackendForm
*/
public function isValidAuthenticationBackend()
{
if (!ResourceFactory::ldapAvailable()) {
if (! ResourceFactory::ldapAvailable()) {
/*
* It should be possible to run icingaweb without the php ldap extension, when
* no ldap backends are needed. When the user tries to create an ldap backend
@ -187,7 +187,7 @@ class LdapBackendForm extends BaseBackendForm
*/
} catch (Exception $exc) {
$this->addErrorMessage(
t('Connection Validation Failed: ' . $exc->getMessage())
t('Connection Validation Failed: ' . $exc->getMessage())
);
return false;
}

View File

@ -1,33 +0,0 @@
<?php
if (! $this->level) {
$this->level = 0;
}
?>
<ul<?= $this->level === 0 ? ' role="navigation"' : '' ?>>
<?php
foreach ($this->items as $item) {
printf(
' <li%s><a href="%s">%s%s</a>',
$this->href($this->url) === $this->href($item->getUrl()) ? ' class="active"' : '',
$item->getUrl() ? $this->href($item->getUrl()) : '#',
$item->getIcon() ? $this->img(
$item->getIcon(),
array('class' => 'icon')
) . ' ' : '',
$this->escape($item->getTitle())
);
if ($item->hasChildren()) {
echo $this->partial(
'parts/menu.phtml',
array('items' => $item->getChildren(), 'url' => $this->url, 'level' => $this->level + 1)
);
}
echo "</li>\n";
}
?>
</ul>

View File

@ -2,22 +2,17 @@
use Icinga\Web\Url;
use Icinga\Web\Menu;
use Icinga\Web\MenuRenderer;
// Don't render a menu for unauthenticated users unless menu is auth aware
if (! $this->auth()->isAuthenticated()) {
return;
}
// Current url
$url = Url::fromRequest()->getRelativeUrl();
$menu = Menu::fromConfig();
?>
<div id="menu" data-base-target="_main">
<form action="<?= $this->href('search') ?>" method="get" role="search">
<input type="text" name="q" class="search autofocus" placeholder="<?= $this->translate('Search...') ?>" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
</form>
<?= $this->partial('parts/menu.phtml', array(
'items' => $menu->getChildren(),
'url' => $url
)) ?>
<?= new MenuRenderer(Menu::fromConfig()->order(), Url::fromRequest()->getRelativeUrl()); ?>
</div>

View File

@ -1,40 +0,0 @@
<div class="wizard">
<div class="header">
<img src="<?= $this->baseUrl('img/logo_icinga-inv.png'); ?>">
<h1><?= $wizard->getTitle(); ?></h1>
</div>
<div class="sidebar">
<ul>
<?php foreach ($wizard->getPages() as $page): ?>
<li class="<?= $wizard->isCompletedPage($page) ? 'complete' : (
$wizard->isCurrentPage($page) ? 'active' : 'pending'
); ?>">
<?= $page->getTitle(); ?>
<?php if ($wizard->isWizard($page) && $wizard->isCurrentPage($page) && !$wizard->isCompletedPage($page)): ?>
<ul>
<?php foreach ($page->getPages() as $subPage): ?>
<?php if ($page->isCurrentPage($subPage)): ?>
<li class="child active">
<?php else: ?>
<li class="child">
<?php endif ?>
<?= $subPage->getTitle(); ?>
</li>
<?php endforeach ?>
</ul>
<?php endif ?>
</li>
<?php endforeach ?>
<li class="install<?= $wizard->isFinished() ? ' active' : ''; ?>">
<?= $this->translate('Installation'); ?>
</li>
</ul>
</div>
<div class="panel">
<?php if ($wizard->isFinished()): ?>
<?= $this->partial('install/index/installog.phtml', array('installer' => $installer)); ?>
<?php else: ?>
<?= $wizard; ?>
<?php endif ?>
</div>
</div>

View File

@ -1 +0,0 @@
<?= $installer; ?>

View File

@ -1,39 +1 @@
<ul>
<?php foreach ($items as $item): ?>
<?php
$itemClass = '';
if ($sub) {
// $itemClass .= 'submenu ';
}
if ($this->href($url) === $this->href($item->getUrl())) {
$itemClass .= 'active ';
}
?>
<li <?php if (!empty($itemClass)): ?>class="<?= $itemClass ?>"<?php endif ?>>
<?php if($item->getUrl()): ?>
<a href="<?= $this->href($item->getUrl()); ?>" <?php foreach($item->getAttribs() as $attrib => $value): ?> <?= $attrib ?>="<?= $value ?>"<?php endforeach?>>
<?php endif; ?>
<?php
if ($icon = $item->getIcon()) {
echo $this->img($icon, array('height' => 16, 'width' => 16));
}
?>
<?php if ($iconClass = $item->getIconClass()): ?>
<i class="<?= $iconClass ?>"></i>
<?php endif ?>
<?= $item->getTitle();?>
<?php if($item->getUrl()): ?>
</a>
<?php endif; ?>
<?php
if($item->hasChildren()) {
echo $this->partial(
'layout/menu.phtml',
'default',
array('items' => $item->getChildren(), 'sub' => true, 'url' => $this->url)
);
}
?>
</li>
<?php endforeach ?>
</ul>
<?= $menuRenderer; ?>

View File

@ -71,6 +71,11 @@ title = "Comments"
url = "monitoring/list/comments"
priority = 70
[Overview.Contacts]
title = "Contacts"
url = "monitoring/list/contacts"
priority = 70
[History]
icon = "img/icons/history.png"

View File

@ -4,7 +4,7 @@
namespace Icinga\Application;
use Exception;
use Icinga\Exception\ProgrammingError;
class Loader
{
@ -39,7 +39,7 @@ class Loader
public function registerNamespace($namespace, $directory)
{
if (!is_dir($directory)) {
throw new Exception(sprintf(
throw new ProgrammingError(sprintf(
'Namespace directory "%s" for "%s" does not exist',
$namespace,
$directory

View File

@ -91,20 +91,24 @@ class LdapUserBackend extends UserBackend
{
$q = $this->conn->select()->from($this->userClass);
$result = $q->fetchRow();
if (!isset($result)) {
if (! isset($result)) {
throw new AuthenticationException(
sprintf('No objects with objectClass="%s" in DN="%s" found.',
$this->userClass,
$this->conn->getDN()
));
sprintf(
'No objects with objectClass="%s" in DN="%s" found.',
$this->userClass,
$this->conn->getDN()
)
);
}
if (!isset($result->{$this->userNameAttribute})) {
if (! isset($result->{$this->userNameAttribute})) {
throw new AuthenticationException(
sprintf('UserNameAttribute "%s" not existing in objectClass="%s"',
sprintf(
'UserNameAttribute "%s" not existing in objectClass="%s"',
$this->userNameAttribute,
$this->userClass
));
)
);
}
}

View File

@ -29,14 +29,14 @@
namespace Icinga\Chart;
use \DOMElement;
use \Icinga\Chart\Primitive\Drawable;
use \Icinga\Chart\Primitive\Line;
use \Icinga\Chart\Primitive\Text;
use \Icinga\Chart\Render\RenderContext;
use \Icinga\Chart\Unit\AxisUnit;
use \Icinga\Chart\Unit\CalendarUnit;
use \Icinga\Chart\Unit\LinearUnit;
use DOMElement;
use Icinga\Chart\Primitive\Drawable;
use Icinga\Chart\Primitive\Line;
use Icinga\Chart\Primitive\Text;
use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Unit\AxisUnit;
use Icinga\Chart\Unit\CalendarUnit;
use Icinga\Chart\Unit\LinearUnit;
/**
* Axis class for the GridChart class.

View File

@ -29,11 +29,11 @@
namespace Icinga\Chart;
use \Exception;
use \Icinga\Chart\Legend;
use \Icinga\Chart\Palette;
use \Icinga\Chart\Primitive\Drawable;
use \Icinga\Chart\SVGRenderer;
use Exception;
use Icinga\Chart\Legend;
use Icinga\Chart\Palette;
use Icinga\Chart\Primitive\Drawable;
use Icinga\Chart\SVGRenderer;
/**
* Base class for charts, extended by all other Chart classes.

View File

@ -0,0 +1,46 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Chart;
class Format
{
/**
* Format a number into a number-string as defined by the SVG-Standard
*
* @see http://www.w3.org/TR/SVG/types.html#DataTypeNumber
*
* @param $number
*
* @return string
*/
public static function formatSVGNumber($number)
{
return number_format($number, 1, '.', '');
}
}

View File

@ -29,12 +29,12 @@
namespace Icinga\Chart\Graph;
use \DOMElement;
use \Icinga\Chart\Primitive\Animation;
use \Icinga\Chart\Primitive\Drawable;
use \Icinga\Chart\Primitive\Rect;
use \Icinga\Chart\Primitive\Styleable;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Primitive\Animation;
use Icinga\Chart\Primitive\Drawable;
use Icinga\Chart\Primitive\Rect;
use Icinga\Chart\Primitive\Styleable;
use Icinga\Chart\Render\RenderContext;
/**
* Bar graph implementation
@ -94,7 +94,7 @@ class BarGraph extends Styleable implements Drawable
$group = $doc->createElement('g');
$idx = 0;
foreach ($this->dataSet as $point) {
$rect = new Rect($point[0]-1, $point[1], $this->barWidth, 100- $point[1]);
$rect = new Rect($point[0] - 1, $point[1], 2, 100 - $point[1]);
$rect->setFill($this->fill);
$rect->setStrokeWidth($this->strokeWidth);
$rect->setStrokeColor('black');

View File

@ -30,12 +30,12 @@
namespace Icinga\Chart\Graph;
use \DOMElement;
use \Icinga\Chart\Primitive\Drawable;
use \Icinga\Chart\Primitive\Path;
use \Icinga\Chart\Primitive\Circle;
use \Icinga\Chart\Primitive\Styleable;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Primitive\Drawable;
use Icinga\Chart\Primitive\Path;
use Icinga\Chart\Primitive\Circle;
use Icinga\Chart\Primitive\Styleable;
use Icinga\Chart\Render\RenderContext;
/**
* LineGraph implementation for drawing a set of datapoints as

View File

@ -29,9 +29,9 @@
namespace Icinga\Chart\Graph;
use \DOMElement;
use \Icinga\Chart\Primitive\Drawable;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Primitive\Drawable;
use Icinga\Chart\Render\RenderContext;
/**
* Graph implementation that stacks several graphs and displays them in a cumulative way

View File

@ -29,18 +29,18 @@
namespace Icinga\Chart;
use \DOMElement;
use \Icinga\Chart\Chart;
use \Icinga\Chart\Axis;
use \Icinga\Chart\Graph\BarGraph;
use \Icinga\Chart\Graph\LineGraph;
use \Icinga\Chart\Graph\StackedGraph;
use \Icinga\Chart\Primitive\Canvas;
use \Icinga\Chart\Primitive\Rect;
use \Icinga\Chart\Primitive\Path;
use \Icinga\Chart\Render\LayoutBox;
use \Icinga\Chart\Render\RenderContext;
use \Icinga\Chart\Unit\AxisUnit;
use DOMElement;
use Icinga\Chart\Chart;
use Icinga\Chart\Axis;
use Icinga\Chart\Graph\BarGraph;
use Icinga\Chart\Graph\LineGraph;
use Icinga\Chart\Graph\StackedGraph;
use Icinga\Chart\Primitive\Canvas;
use Icinga\Chart\Primitive\Rect;
use Icinga\Chart\Primitive\Path;
use Icinga\Chart\Render\LayoutBox;
use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Unit\AxisUnit;
/**
* Base class for grid based charts.

View File

@ -40,7 +40,8 @@ namespace Icinga\Chart\Inline;
* Class Inline
* @package Icinga\Chart\Inline
*/
class Inline {
class Inline
{
/**
* The data displayed in this chart

View File

@ -29,14 +29,14 @@
namespace Icinga\Chart;
use \DOMElement;
use \Icinga\Chart\Palette;
use \Icinga\Chart\Primitive\Canvas;
use \Icinga\Chart\Primitive\Drawable;
use \Icinga\Chart\Primitive\Rect;
use \Icinga\Chart\Primitive\Text;
use \Icinga\Chart\Render\LayoutBox;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Palette;
use Icinga\Chart\Primitive\Canvas;
use Icinga\Chart\Primitive\Drawable;
use Icinga\Chart\Primitive\Rect;
use Icinga\Chart\Primitive\Text;
use Icinga\Chart\Render\LayoutBox;
use Icinga\Chart\Render\RenderContext;
/**
* Drawable for creating a Graph Legend on the bottom of a graph.

View File

@ -29,14 +29,14 @@
namespace Icinga\Chart;
use \DOMElement;
use \Icinga\Chart\Chart;
use \Icinga\Chart\Primitive\Canvas;
use \Icinga\Chart\Primitive\PieSlice;
use \Icinga\Chart\Primitive\RawElement;
use \Icinga\Chart\Primitive\Rect;
use \Icinga\Chart\Render\RenderContext;
use \Icinga\Chart\Render\LayoutBox;
use DOMElement;
use Icinga\Chart\Chart;
use Icinga\Chart\Primitive\Canvas;
use Icinga\Chart\Primitive\PieSlice;
use Icinga\Chart\Primitive\RawElement;
use Icinga\Chart\Primitive\Rect;
use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Render\LayoutBox;
/**
* Graphing component for rendering Pie Charts.

View File

@ -29,8 +29,8 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Render\RenderContext;
/**
* Base interface for animatable objects

View File

@ -29,8 +29,8 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Render\RenderContext;
/**
* Drawable for the SVG animate tag

View File

@ -30,9 +30,9 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \Icinga\Chart\Render\LayoutBox;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Render\LayoutBox;
use Icinga\Chart\Render\RenderContext;
/**
* Canvas SVG component that encapsulates grouping and padding and allows rendering

View File

@ -30,8 +30,9 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Format;
/**
* Drawable for svg circles
@ -83,8 +84,8 @@ class Circle extends Styleable implements Drawable
{
$coords = $ctx->toAbsolute($this->x, $this->y);
$circle = $ctx->getDocument()->createElement('circle');
$circle->setAttribute('cx', $coords[0]);
$circle->setAttribute('cy', $coords[1]);
$circle->setAttribute('cx', Format::formatSVGNumber($coords[0]));
$circle->setAttribute('cy', Format::formatSVGNumber($coords[1]));
$circle->setAttribute('r', 5);
$circle->setAttribute('style', $this->getStyle());
$this->applyAttributes($circle);

View File

@ -29,8 +29,8 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Render\RenderContext;
/**
* Drawable element for creating svg out of components

View File

@ -29,8 +29,9 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Format;
/**
* Drawable for the svg line element
@ -101,10 +102,10 @@ class Line extends Styleable implements Drawable
list($x1, $y1) = $ctx->toAbsolute($this->xStart, $this->yStart);
list($x2, $y2) = $ctx->toAbsolute($this->xEnd, $this->yEnd);
$line = $doc->createElement('line');
$line->setAttribute('x1', $x1);
$line->setAttribute('x2', $x2);
$line->setAttribute('y1', $y1);
$line->setAttribute('y2', $y2);
$line->setAttribute('x1', Format::formatSVGNumber($x1));
$line->setAttribute('x2', Format::formatSVGNumber($x2));
$line->setAttribute('y1', Format::formatSVGNumber($y1));
$line->setAttribute('y2', Format::formatSVGNumber($y2));
$line->setAttribute('style', $this->getStyle());
$this->applyAttributes($line);
return $line;

View File

@ -30,8 +30,9 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Format;
/**
* Drawable for creating a svg path element
@ -177,6 +178,8 @@ class Path extends Styleable implements Drawable
if (!$this->isAbsolute) {
$point = $ctx->toAbsolute($point[0], $point[1]);
}
$point[0] = Format::formatSVGNumber($point[0]);
$point[1] = Format::formatSVGNumber($point[1]);
if ($lastPoint && $this->discrete) {
$pathDescription .= sprintf($tpl, $point[0], $lastPoint[1]);
}

View File

@ -29,8 +29,9 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Format;
/**
* Component for drawing a pie slice
@ -138,15 +139,15 @@ class PieSlice extends Animatable implements Drawable
$yEnd = $y - ($r * cos($this->endRadian));
// Draw a straight line to the upper part of the arc
$pathString .= 'L ' . $xStart . ' ' . $yStart;
$pathString .= 'L ' . Format::formatSVGNumber($xStart) . ' ' . Format::formatSVGNumber($yStart);
// Instead of directly connecting the upper part of the arc (leaving a triangle), draw a bow with the radius
$pathString .= ' A ' . $r . ' ' . $r ;
$pathString .= ' A ' . Format::formatSVGNumber($r) . ' ' . Format::formatSVGNumber($r);
// These are the flags for the bow, see the SVG path documentation for details
// http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
$pathString .= ' 0 ' . (($this->endRadian - $this->startRadian > M_PI) ? '1' : '0 ') . ' 1';
// xEnd and yEnd are the lower point of the arc
$pathString .= ' '.$xEnd . ' ' . $yEnd;
$pathString .= ' ' . Format::formatSVGNumber($xEnd) . ' ' . Format::formatSVGNumber($yEnd);
return $pathString;
}

View File

@ -29,8 +29,8 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use Icinga\Chart\Render\RenderContext;
/**
* Wrapper for raw elements to be added as Drawable's

View File

@ -31,6 +31,7 @@ namespace Icinga\Chart\Primitive;
use \DomElement;
use \Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Format;
/**
* Drawable representing the SVG rect element
@ -116,10 +117,10 @@ class Rect extends Animatable implements Drawable
if ($this->keepRatio) {
$ctx->ignoreRatio();
}
$rect->setAttribute('x', $x);
$rect->setAttribute('y', $y);
$rect->setAttribute('width', $width);
$rect->setAttribute('height', $height);
$rect->setAttribute('x', Format::formatSVGNumber($x));
$rect->setAttribute('y', Format::formatSVGNumber($y));
$rect->setAttribute('width', Format::formatSVGNumber($width));
$rect->setAttribute('height', Format::formatSVGNumber($height));
$rect->setAttribute('style', $this->getStyle());
$this->applyAttributes($rect);

View File

@ -30,7 +30,7 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use DOMElement;
/**
* Base class for stylable drawables

View File

@ -30,9 +30,10 @@
namespace Icinga\Chart\Primitive;
use \DOMElement;
use \DOMText;
use \Icinga\Chart\Render\RenderContext;
use DOMElement;
use DOMText;
use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Format;
/**
* Wrapper for the SVG text element
@ -184,7 +185,7 @@ class Text extends Styleable implements Drawable
{
list($x, $y) = $ctx->toAbsolute($this->x, $this->y);
$text = $ctx->getDocument()->createElement('text');
$text->setAttribute('x', $x - 15);
$text->setAttribute('x', Format::formatSVGNumber($x - 15));
$text->setAttribute(
'style',
$this->getStyle()
@ -196,7 +197,7 @@ class Text extends Styleable implements Drawable
. 'text-anchor: ' . $this->alignment
);
$text->setAttribute('y', $y);
$text->setAttribute('y', Format::formatSVGNumber($y));
$text->appendChild(new DOMText($this->text));
return $text;
}

View File

@ -29,6 +29,8 @@
namespace Icinga\Chart\Render;
use Icinga\Chart\Format;
/**
* Layout class encapsulating size, padding and margin information
*/
@ -147,7 +149,13 @@ class LayoutBox
$scaleX *= $this->getWidth()/100;
$scaleY *= $this->getHeight()/100;
return sprintf('translate(%s, %s) scale(%s, %s)', $translateX, $translateY, $scaleX, $scaleY);
return sprintf(
'translate(%s, %s) scale(%s, %s)',
Format::formatSVGNumber($translateX),
Format::formatSVGNumber($translateY),
Format::formatSVGNumber($scaleX),
Format::formatSVGNumber($scaleY)
);
}
/**

View File

@ -30,8 +30,7 @@
namespace Icinga\Chart\Render;
use \DOMDocument;
use \Icinga\Util\Dimension;
use DOMDocument;
/**
* Context for rendering, handles ratio based coordinate calculations.
@ -93,9 +92,9 @@ class RenderContext
{
$this->document = $document;
if ($width > $height) {
$this->xratio = $width/$height;
} elseif ($height < $width) {
$this->yratio = $width/$height;
$this->xratio = $width / $height;
} elseif ($height > $width) {
$this->yratio = $height / $width;
}
}

View File

@ -29,14 +29,13 @@
namespace Icinga\Chart;
use \DOMNode;
use \DOMElement;
use \DOMDocument;
use \DOMImplementation;
use \Icinga\Util\Dimension;
use \Icinga\Chart\Render\LayoutBox;
use \Icinga\Chart\Render\RenderContext;
use \Icinga\Chart\Primitive\Canvas;
use DOMNode;
use DOMElement;
use DOMDocument;
use DOMImplementation;
use Icinga\Chart\Render\LayoutBox;
use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Primitive\Canvas;
/**
* SVG Renderer component.
@ -107,9 +106,9 @@ class SVGRenderer
$ctx = $this->createRenderContext();
$svg = $this->document->createElement('svg');
$svg->setAttribute('xmlns', 'http://www.w3.org/2000/svg');
$svg->setATtribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
$svg->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
$svg->setAttribute('width', $this->width . '%');
$svg->setAttribute('height', $this->width . '%');
$svg->setAttribute('height', $this->height . '%');
$svg->setAttribute(
'viewBox',
sprintf(

View File

@ -29,7 +29,7 @@
namespace Icinga\Chart\Unit;
use \Iterator;
use Iterator;
/**
* Base class for Axis Units

View File

@ -30,10 +30,7 @@
namespace Icinga\Chart\Unit;
use \Zend_Config;
use \Icinga\Application\Icinga;
use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Util\DateTimeFactory;
use Icinga\Util\DateTimeFactory;
/**
* Calendar Axis Unit that transforms timestamps into user-readable values

View File

@ -35,10 +35,12 @@ class StaticAxis implements AxisUnit
private $items = array();
/**
* Add a dataset to this AxisUnit, required for dynamic min and max vlaues
* Add a dataset to this AxisUnit, required for dynamic min and max values
*
* @param array $dataset The dataset that will be shown in the Axis
* @param int $id The idx in the dataset (0 for x, 1 for y)
* @param int $idx The idx in the dataset (0 for x, 1 for y)
*
* @return self Fluent interface
*/
public function addValues(array $dataset, $idx = 0)
{

View File

@ -203,7 +203,7 @@ class IniEditor
public function setSection($section, $extend = null)
{
if (isset($extend)) {
$decl = '[' . $section . ' : ' . $extend.']';
$decl = '[' . $section . ' : ' . $extend . ']';
} else {
$decl = '[' . $section . ']';
}
@ -276,7 +276,7 @@ class IniEditor
*/
$j = $i - 1;
$comments = array();
while ($j > 0 && $this->isComment($this->text[$j])) {
while ($j >= 0 && $this->isComment($this->text[$j])) {
array_push($comments, array_pop($sections[$section]));
$j--;
}
@ -296,6 +296,8 @@ class IniEditor
* Extract the section name from a section declaration
*
* @param String $declaration The section declaration
*
* @return string The section name
*/
private function getSectionFromDeclaration($declaration)
{
@ -319,9 +321,9 @@ class IniEditor
/**
* Insert the key at the end of the corresponding section
*
* @param array $key The key to insert
* @param mixed $value The value to insert
* @param array $key The key to insert
* @param array $key The key to insert
* @param mixed $value The value to insert
* @param array $section The key to insert
*/
private function insert(array $key, $value, $section = null)
{
@ -392,7 +394,7 @@ class IniEditor
* Update the line $lineNr
*
* @param int $lineNr The line number of the target line
* @param string $toInsert The new line content
* @param string $content The new line content
*/
private function updateLine($lineNr, $content)
{
@ -612,6 +614,8 @@ class IniEditor
*
* @param $array The array to use
* @param $pos The position to remove
*
* @return array The altered array
*/
private function removeFromArray($array, $pos)
{

View File

@ -177,29 +177,42 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract
// Iterate over all properties in the old configuration file and search for deleted properties
foreach ($oldconfig as $key => $value) {
$nextParents = array_merge($parents, array($key));
$newvalue = $newconfig->get($key);
$keyIdentifier = empty($parents) ? array($key) : array_slice($nextParents, 1, null, true);
if ($newvalue === null) {
if ($value instanceof Zend_Config) {
// The deleted value is a nested Zend_Config, handle it recursively
$this->diffConfigs($value, new Zend_Config(array()), $editor, $nextParents);
if ($section === null) {
$editor->removeSection($key);
}
} else {
// The deleted value is a plain value, use the editor to delete it
if (is_numeric($key)) {
$editor->resetArrayElement($keyIdentifier, $section);
} elseif (!empty($parents)) {
// Drop nested properties, fixes #5958
$editor->resetArrayElement($nextParents, $section);
} else {
$editor->reset($keyIdentifier, $section);
}
if ($newconfig->get($key) === null) {
$nextParents = array_merge($parents, array($key));
$keyIdentifier = empty($parents) ? array($key) : array_slice($nextParents, 1, null, true);
foreach ($this->getPropertyIdentifiers($value, $keyIdentifier) as $propertyIdentifier) {
$editor->reset($propertyIdentifier, $section);
}
}
}
}
/**
* Return all possible combinations of property identifiers for the given value
*
* @param mixed $value The value to return all combinations for
* @param array $key The root property identifier, if any
*
* @return array All property combinations that are possible
*
* @todo Cannot handle array properties yet (e.g. a.b[]='c')
*/
protected function getPropertyIdentifiers($value, array $key = null)
{
$combinations = array();
$rootProperty = $key !== null ? $key : array();
if ($value instanceof Zend_Config) {
foreach ($value as $subProperty => $subValue) {
$combinations = array_merge(
$combinations,
$this->getPropertyIdentifiers($subValue, array_merge($rootProperty, array($subProperty)))
);
}
} elseif (is_string($value)) {
$combinations[] = $rootProperty;
}
return $combinations;
}
}

View File

@ -25,11 +25,22 @@ class FileWriter extends LogWriter
/**
* Create a new log writer initialized with the given configuration
*
* @throws ConfigurationError In case the log path does not exist
*/
public function __construct(Zend_Config $config)
{
$this->path = $config->target;
$this->setup();
if (substr($this->path, 0, 6) !== 'php://' && false === file_exists(dirname($this->path))) {
throw new ConfigurationError('Log path "' . dirname($this->path) . '" does not exist');
}
try {
$this->write(''); // Avoid to handle such errors on every write access
} catch (Exception $e) {
throw new ConfigurationError('Cannot write to log file "' . $this->path . '" (' . $e->getMessage() . ')');
}
}
/**
@ -40,23 +51,7 @@ class FileWriter extends LogWriter
*/
public function log($severity, $message)
{
$this->write(date('c') . ' ' . $this->getSeverityString($severity) . ' ' . $message);
}
/**
* Create the file if it does not already exist
*/
protected function setup()
{
if (substr($this->path, 0, 6) !== 'php://') {
if (!file_exists($this->path) && (!@touch($this->path) || !@chmod($this->path, 0664))) {
throw new ConfigurationError('Cannot create log file "' . $this->path . '"');
}
if (!@is_writable($this->path)) {
throw new ConfigurationError('Cannot write to log file "' . $this->path . '"');
}
}
$this->write(date('c') . ' ' . $this->getSeverityString($severity) . ' ' . $message . PHP_EOL);
}
/**
@ -94,7 +89,7 @@ class FileWriter extends LogWriter
protected function write($text)
{
$file = new File($this->path, 'a');
$file->fwrite($text . PHP_EOL);
$file->fwrite($text);
$file->fflush();
}
}

View File

@ -31,14 +31,14 @@ namespace Icinga\Protocol\Statusdat;
use Icinga\Util\File;
use Icinga\Logger\Logger;
use Icinga\Data\DatasourceInterface;
use Icinga\Data\Selectable;
use Icinga\Exception\ConfigurationError;
/**
* Class Reader
* @package Icinga\Protocol\Statusdat
*/
class Reader implements IReader, DatasourceInterface
class Reader implements IReader, Selectable
{
/**
* The default lifetime of the cache in milliseconds

View File

@ -5,7 +5,6 @@
namespace Icinga\User\Preferences\Store;
use Exception;
use Zend_Db_Select;
use Icinga\Exception\NotReadableError;
use Icinga\Exception\NotWritableError;
use Icinga\User\Preferences;
@ -73,10 +72,10 @@ class DbStore extends PreferencesStore
public function load()
{
try {
$select = new Zend_Db_Select($this->getStoreConfig()->connection->getConnection());
$select = $this->getStoreConfig()->connection->select();
$result = $select->from($this->table, array(self::COLUMN_PREFERENCE, self::COLUMN_VALUE))
->where(self::COLUMN_USERNAME . ' = ?', $this->getUser()->getUsername())
->query()->fetchAll();
->fetchAll();
} catch (Exception $e) {
throw new NotReadableError(
'Cannot fetch preferences for user ' . $this->getUser()->getUsername() . ' from database', 0, $e

View File

@ -141,17 +141,18 @@ class Translator
public static function getAvailableLocaleCodes()
{
$codes = array();
$postfix = '.UTF-8';
foreach (array_values(self::$knownDomains) as $directory) {
$dh = opendir($directory);
while (false !== ($name = readdir($dh))) {
if (substr($name, 0, 1) === '.') continue;
if (substr($name, -6) !== $postfix) continue;
if (is_dir($directory . DIRECTORY_SEPARATOR . $name)) {
$codes[] = substr($name, 0, -6);
if (substr($name, 0, 1) !== '.'
&& false === in_array($name, $codes)
&& is_dir($directory . DIRECTORY_SEPARATOR . $name)
) {
$codes[] = $name;
}
}
}
return $codes;
}

View File

@ -63,13 +63,6 @@ class ActionController extends Zend_Controller_Action
*/
protected $requiresAuthentication = true;
/**
* Whether the controller requires configuration
*
* @var bool
*/
protected $requiresConfiguration = true;
private $config;
private $configs = array();
@ -111,12 +104,11 @@ class ActionController extends Zend_Controller_Action
$this->handlerBrowserWindows();
$this->view->translationDomain = 'icinga';
$this->_helper->layout()->isIframe = $this->params->shift('isIframe');
$this->_helper->layout()->moduleName = false;
if ($this->rerenderLayout = $this->params->shift('renderLayout')) {
$this->xhrLayout = 'body';
}
if ($this->requiresConfig()) {
$this->redirectNow(Url::fromPath('install'));
}
if ($this->requiresLogin()) {
$this->redirectToLogin(Url::fromRequest());
@ -214,39 +206,11 @@ class ActionController extends Zend_Controller_Action
}
}
/**
* Check whether the controller requires configuration. That is when no configuration
* is available and when it is possible to setup the configuration
*
* @return bool
*
* @see requiresConfiguration
*/
protected function requiresConfig()
{
if (!$this->requiresConfiguration) {
return false;
}
if (file_exists(Config::$configDir . '/setup.token')) {
try {
$config = Config::app()->toArray();
} catch (NotReadableError $e) {
return true;
}
return empty($config);
} else {
return false;
}
}
/**
* Check whether the controller requires a login. That is when the controller requires authentication and the
* user is currently not authenticated
*
* @return bool
*
* @see requiresAuthentication
*/
protected function requiresLogin()
@ -375,7 +339,6 @@ class ActionController extends Zend_Controller_Action
$req = $this->getRequest();
$layout = $this->_helper->layout();
$layout->moduleName = false;
if ($user = $req->getUser()) {
// Cast preference app.show_benchmark to bool because preferences loaded from a preferences storage are

View File

@ -24,6 +24,7 @@ class ModuleActionController extends ActionController
) {
parent::__construct($request, $response, $invokeArgs);
$this->moduleName = $request->getModuleName();
$this->_helper->layout()->moduleName = $this->moduleName;
$this->view->translationDomain = $this->moduleName;
$this->moduleInit();
}
@ -59,11 +60,9 @@ class ModuleActionController extends ActionController
{
$req = $this->getRequest();
$resp = $this->getResponse();
$layout = $this->_helper->layout();
$layout->moduleName = $this->moduleName;
if ($this->isXhr()) {
$resp->setHeader('X-Icinga-Module', $layout->moduleName);
$resp->setHeader('X-Icinga-Module', $this->moduleName);
}
parent::postDispatch();

View File

@ -127,15 +127,6 @@ class Form extends Zend_Form
*/
protected $last_note_id = 0;
/**
* Whether buttons are shown or not
*
* This is just a q&d solution and MUST NOT survive any refactoring!
*
* @var bool
*/
protected $buttonsHidden = false;
/**
* Getter for the session ID
*
@ -288,11 +279,11 @@ class Form extends Zend_Form
$this->initCsrfToken();
$this->create();
if (!$this->buttonsHidden && $this->submitLabel) {
if ($this->submitLabel) {
$this->addSubmitButton();
}
if (!$this->buttonsHidden && $this->cancelLabel) {
if ($this->cancelLabel) {
$this->addCancelButton();
}
@ -614,18 +605,4 @@ class Form extends Zend_Form
return $this;
}
public function hideButtons()
{
$this->buttonsHidden = true;
}
/**
* q&d solution to be able to recreate a form
*/
public function reset()
{
$this->created = false;
$this->clearElements();
}
}

View File

@ -1,41 +1,83 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
*
* Icinga Web 2 - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web;
use Icinga\Logger\Logger;
use Zend_Config;
use RecursiveIterator;
use Icinga\Application\Config;
use Icinga\Application\Icinga;
use Icinga\Exception\NotReadableError;
use Icinga\Exception\ProgrammingError;
class Menu extends MenuItem
class Menu implements RecursiveIterator
{
/**
* The id of this menu
*
* @type string
*/
protected $id;
/**
* The title of this menu
*
* Used for sorting when priority is unset or equal to other items
*
* @type string
*/
protected $title;
/**
* The priority of this menu
*
* Used for sorting
*
* @type int
*/
protected $priority = 100;
/**
* The url of this menu
*
* @type string
*/
protected $url;
/**
* The path to the icon of this menu
*
* @type string
*/
protected $icon;
/**
* The sub menus of this menu
*
* @type array
*/
protected $subMenus = array();
/**
* Create a new menu
*
* @param int $id The id of this menu
* @param Zend_Config $config The configuration for this menu
*/
public function __construct($id, Zend_Config $config = null)
{
$this->id = $id;
if ($config !== null) {
foreach ($config as $key => $value) {
$method = 'set' . implode('', array_map('ucfirst', explode('_', strtolower($key))));
if (method_exists($this, $method)) {
$this->{$method}($value);
}
}
}
}
/**
* Create menu from the application's menu config file plus the config files from all enabled modules
*
@ -45,35 +87,236 @@ class Menu extends MenuItem
{
$menu = new static('menu');
$manager = Icinga::app()->getModuleManager();
try {
$menuConfigs = array(Config::app('menu'));
} catch (NotReadableError $e) {
Logger::error($e);
$menuConfigs = array();
}
try {
$modules = $manager->listEnabledModules();
} catch (NotReadableError $e) {
Logger::error($e);
$modules = array();
}
$modules = $manager->listEnabledModules();
$menuConfigs = array(Config::app('menu'));
foreach ($modules as $moduleName) {
try {
$moduleMenuConfig = Config::module($moduleName, 'menu');
} catch (NotReadableError $e) {
Logger::error($e);
$moduleMenuConfig = array();
}
if (!empty($moduleMenuConfig)) {
$moduleMenuConfig = Config::module($moduleName, 'menu');
if (false === empty($moduleMenuConfig)) {
$menuConfigs[] = $moduleMenuConfig;
}
}
return $menu->loadMenuItems($menu->flattenConfigs($menuConfigs));
return $menu->loadSubMenus($menu->flattenConfigs($menuConfigs));
}
/**
* Set the id of this menu
*
* @param string $id The id to set for this menu
*
* @return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Return the id of this menu
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Set the title of this menu
*
* @param string $title The title to set for this menu
*
* @return self
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Return the title of this menu if set, otherwise its id
*
* @return string
*/
public function getTitle()
{
return $this->title ? $this->title : $this->id;
}
/**
* Set the priority of this menu
*
* @param int $priority The priority to set for this menu
*
* @return self
*/
public function setPriority($priority)
{
$this->priority = (int) $priority;
return $this;
}
/**
* Return the priority of this menu
*
* @return int
*/
public function getPriority()
{
return $this->priority;
}
/**
* Set the url of this menu
*
* @param string $url The url to set for this menu
*
* @return self
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* Return the url of this menu
*
* @return string
*/
public function getUrl()
{
return $this->url;
}
/**
* Set the path to the icon of this menu
*
* @param string $path The path to the icon for this menu
*
* @return self
*/
public function setIcon($path)
{
$this->icon = $path;
return $this;
}
/**
* Return the path to the icon of this menu
*
* @return string
*/
public function getIcon()
{
return $this->icon;
}
/**
* Return whether this menu has any sub menus
*
* @return bool
*/
public function hasSubMenus()
{
return false === empty($this->subMenus);
}
/**
* Add a sub menu to this menu
*
* @param string $id The id of the menu to add
* @param Zend_Config $itemConfig The config with which to initialize the menu
*
* @return self
*/
public function addSubMenu($id, Zend_Config $menuConfig = null)
{
if (false === ($pos = strpos($id, '.'))) {
$subMenu = new self($id, $menuConfig);
$this->subMenus[$id] = $subMenu;
} else {
list($parentId, $id) = explode('.', $id, 2);
if ($this->hasSubMenu($parentId)) {
$parent = $this->getSubMenu($parentId);
} else {
$parent = $this->addSubMenu($parentId);
}
$subMenu = $parent->addSubMenu($id, $menuConfig);
}
return $subMenu;
}
/**
* Return whether a sub menu with the given id exists
*
* @param string $id The id of the sub menu
*
* @return bool
*/
public function hasSubMenu($id)
{
return array_key_exists($id, $this->subMenus);
}
/**
* Get sub menu by its id
*
* @param string $id The id of the sub menu
*
* @return Menu The found sub menu
*
* @throws ProgrammingError In case there is no sub menu with the given id to be found
*/
public function getSubMenu($id)
{
if (false === $this->hasSubMenu($id)) {
throw new ProgrammingError('Tried to get invalid sub menu "' . $id . '"');
}
return $this->subMenus[$id];
}
/**
* Order this menu's sub menus based on their priority
*
* @return self
*/
public function order()
{
uasort($this->subMenus, array($this, 'cmpSubMenus'));
foreach ($this->subMenus as $subMenu) {
if ($subMenu->hasSubMenus()) {
$subMenu->order();
}
}
return $this;
}
/**
* Compare sub menus based on priority and title
*
* @param Menu $a
* @param Menu $b
*
* @return int
*/
protected function cmpSubMenus($a, $b)
{
if ($a->priority == $b->priority) {
return $a->getTitle() > $b->getTitle() ? 1 : (
$a->getTitle() < $b->getTitle() ? -1 : 0
);
}
return $a->priority > $b->priority ? 1 : -1;
}
/**
@ -83,7 +326,7 @@ class Menu extends MenuItem
*
* @return array The flattened config, as key-value array
*/
public function flattenConfigs(array $configs)
protected function flattenConfigs(array $configs)
{
$flattened = array();
foreach ($configs as $menuConfig) {
@ -99,18 +342,89 @@ class Menu extends MenuItem
}
/**
* Load menu items
* Load the sub menus
*
* @param array $items The items to load, as key-value array
* @param array $menus The menus to load, as key-value array
*
* @return self
*/
public function loadMenuItems(array $items)
protected function loadSubMenus(array $menus)
{
foreach ($items as $id => $itemConfig) {
$this->addChild($id, $itemConfig);
foreach ($menus as $menuId => $menuConfig) {
$this->addSubMenu($menuId, $menuConfig);
}
return $this;
}
/**
* Check whether the current menu node has any sub menus
*
* @return bool
*/
public function hasChildren()
{
$current = $this->current();
if (false !== $current) {
return $current->hasSubMenus();
}
return false;
}
/**
* Return a iterator for the current menu node
*
* @return RecursiveIterator
*/
public function getChildren()
{
return $this->current();
}
/**
* Rewind the iterator to its first menu node
*/
public function rewind()
{
reset($this->subMenus);
}
/**
* Return whether the iterator position is valid
*
* @return bool
*/
public function valid()
{
return $this->key() !== null;
}
/**
* Return the current menu node
*
* @return Menu
*/
public function current()
{
return current($this->subMenus);
}
/**
* Return the id of the current menu node
*
* @return string
*/
public function key()
{
return key($this->subMenus);
}
/**
* Move the iterator to the next menu node
*/
public function next()
{
next($this->subMenus);
}
}

View File

@ -1,361 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web;
use Icinga\Exception\ProgrammingError;
class MenuItem
{
/**
* Item id
*
* @type string
*/
protected $id;
/**
* Item title
*
* Used for sorting when priority is unset or equal to other items
*
* @type string
*/
protected $title;
/**
* Item priority
*
* Used for sorting
*
* @type int
*/
protected $priority = 100;
/**
* Item url
*
* @type string
*/
protected $url;
/**
* Item icon path
*
* @type string
*/
protected $icon;
/**
* Item icon class
*
* @type string
*/
protected $iconClass;
/**
* Item's children
*
* @type array
*/
protected $children = array();
/**
* HTML anchor tag attributes
*
* @var array
*/
protected $attribs = array();
/**
* Create a new MenuItem
*
* @param int $id
* @param object $config
*/
public function __construct($id, $config = null)
{
$this->id = $id;
if ($config !== null) {
$this->setConfig($config);
}
}
/**
* Setter for id
*
* @param string $id
*
* @return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Getter for id
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Setter for title
*
* @param string $title
*
* @return self
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Getter for title
*
* @return string
*/
public function getTitle()
{
return $this->title ? $this->title : $this->id;
}
/**
* Setter for priority
*
* @param int $priority
*
* @return self
*/
public function setPriority($priority)
{
$this->priority = (int) $priority;
return $this;
}
/**
* Getter for priority
*
* @return int
*/
public function getPriority()
{
return $this->priority;
}
/**
* Setter for URL
*
* @param string $url
*
* @return self
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* Getter for URL
*
* @return string
*/
public function getUrl()
{
return $this->url;
}
/**
* Setter for icon path
*
* @param string $path
*
* @return self
*/
public function setIcon($path)
{
$this->icon = $path;
return $this;
}
/**
* Getter for icon path
*
* @return string
*/
public function getIcon()
{
return $this->icon;
}
/**
* Setter for icon class
*
* @param string $iconClass
*
* @return self
*/
public function setIconClass($iconClass)
{
$this->iconClass = $iconClass;
return $this;
}
/**
* Getter for icon class
*
* @return string
*/
public function getIconClass()
{
return $this->iconClass;
}
/**
* Set the configuration for the item
*
* @param Zend_Config $config
*/
public function setConfig($config)
{
foreach ($config as $key => $value) {
$method = 'set' . implode('', array_map('ucfirst', explode('_', strtolower($key))));
if (method_exists($this, $method)) {
$this->{$method}($value);
}
}
}
/**
* Add a child to MenuItem
*
* @param string $id
* @param object $itemConfig
*
* @return self
*/
public function addChild($id, $itemConfig = null)
{
if (false === ($pos = strpos($id, '.'))) {
// Root item
$menuItem = new self($id, $itemConfig);
$this->children[$id] = $menuItem;
} else {
// Submenu item
list($parentId, $id) = explode('.', $id, 2);
if ($this->hasChild($parentId)) {
$parent = $this->getChild($parentId);
} else {
$parent = $this->addChild($parentId);
}
$menuItem = $parent->addChild($id, $itemConfig);
}
return $menuItem;
}
/**
* Check whether the item has any children
*
* @return bool
*/
public function hasChildren()
{
return !empty($this->children);
}
/**
* Get sorted children
*
* @return array
*
* @see MenuItem::cmpChildren()
*/
public function getChildren()
{
usort($this->children, array($this, 'cmpChildren'));
return $this->children;
}
/**
* Return whether a given child id exists
*
* @param string $id
*
* @return bool
*/
public function hasChild($id)
{
return array_key_exists($id, $this->children);
}
/**
* Get child by its id
*
* @param string $id
* @param mixed $default
*
* @return MenuItem
*
* @throws ProgrammingError
*/
public function getChild($id)
{
if (!$this->hasChild($id)) {
throw new ProgrammingError(sprintf('Trying to get invalid Menu child "%s"', $id));
}
return $this->children[$id];
}
/**
* Set HTML anchor tag attributes
*
* @param array $attribs
*
* @return self
*/
public function setAttribs(array $attribs)
{
$this->attribs = $attribs;
return $this;
}
/**
* Get HTML anchor tag attributes
*
* @return array
*/
public function getAttribs()
{
return $this->attribs;
}
/**
* Compare children based on priority and title
*
* @param MenuItem $a
* @param MenuItem $b
*
* @return int
*/
protected function cmpChildren($a, $b)
{
if ($a->priority === $b->priority) {
return ($a->getTitle() > $b->getTitle()) ? 1 : -1;
}
return ($a->priority > $b->priority) ? 1 : -1;
}
}

View File

@ -0,0 +1,151 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web;
use RecursiveIteratorIterator;
/**
* A renderer to draw a menu with its sub-menus using an unordered html list
*/
class MenuRenderer extends RecursiveIteratorIterator
{
/**
* The relative url of the current request
*
* @var string
*/
protected $url;
/**
* The html tags to assemble the menu with
*
* @var array
*/
protected $tags = array();
/**
* Create a new MenuRenderer
*
* @param Menu $menu The menu to render
* @param string $url A relative url to identify "active" children with
*/
public function __construct(Menu $menu, $url = null)
{
$this->url = $url;
parent::__construct($menu, RecursiveIteratorIterator::CHILD_FIRST);
}
/**
* Register the outer ul opening html-tag
*/
public function beginIteration()
{
$this->tags[] = '<ul role="navigation">';
}
/**
* Register the outer ul closing html-tag
*/
public function endIteration()
{
$this->tags[] = '</ul>';
}
/**
* Register a inner ul opening html-tag
*/
public function beginChildren()
{
// The iterator runs in mode CHILD_FIRST so we need to remember
// where to insert the parent's opening html tag once its rendered
$parent = $this->getSubIterator(0)->current();
$this->tags[$parent->getId() . '_begin'] = null;
$this->tags[] = '<ul>';
}
/**
* Register a inner ul closing html-tag
*/
public function endChildren()
{
$this->tags[] = '</ul>';
// Remember the position of the parent's closing html-tag
$parent = $this->getSubIterator(0)->current();
$this->tags[$parent->getId() . '_end'] = null;
}
/**
* Render the given child
*
* @param Menu $child The menu's child to render
*
* @return string The child rendered as html
*/
public function renderChild(Menu $child)
{
return sprintf(
'<a href="%s">%s%s</a>',
$child->getUrl() ? Url::fromPath($child->getUrl()) : '#',
$child->getIcon() ? '<img src="' . Url::fromPath($child->getIcon()) . '" class="icon" /> ' : '',
htmlspecialchars($child->getTitle())
);
}
/**
* Return the menu rendered as html
*
* @return string
*/
public function render()
{
$passedActiveChild = false;
foreach ($this as $child) {
$childIsActive = $this->isActive($child);
if ($childIsActive && $this->getDepth() > 0) {
$passedActiveChild = true;
}
if ($childIsActive || ($passedActiveChild && $this->getDepth() === 0)) {
$passedActiveChild &= $this->getDepth() !== 0;
$openTag = '<li class="active">';
} else {
$openTag = '<li>';
}
$content = $this->renderChild($child);
$closingTag = '</li>';
if (array_key_exists($child->getId() . '_begin', $this->tags)) {
$this->tags[$child->getId() . '_begin'] = $openTag . $content;
$this->tags[$child->getId() . '_end'] = $closingTag;
} else {
$this->tags[] = $openTag . $content . $closingTag;
}
}
return implode("\n", $this->tags);
}
/**
* @see MenuRenderer::render()
*/
public function __toString()
{
return $this->render();
}
/**
* Return whether the current request url references the child's url
*
* @param Menu $child The menu's child to check
*
* @return bool
*/
protected function isActive(Menu $child)
{
return html_entity_decode(rawurldecode($this->url)) === html_entity_decode(rawurldecode($child->getUrl()));
}
}

View File

@ -3,7 +3,23 @@
namespace Icinga\Web;
use Zend_Controller_Response_Http;
use Icinga\Application\Icinga;
class Response extends Zend_Controller_Response_Http
{
public function redirectAndExit($url)
{
if (! $url instanceof Url) {
$url = Url::fromPath($url);
}
$url->getParams()->setSeparator('&');
if (Icinga::app()->getFrontController()->getRequest()->isXmlHttpRequest()) {
$this->setHeader('X-Icinga-Redirect', rawurlencode($url));
} else {
$this->setRedirect($url->getAbsoluteUrl());
}
$this->sendHeaders();
exit;
}
}

View File

@ -21,7 +21,6 @@ class StyleSheet
'css/icinga/monitoring-colors.less',
'css/icinga/selection-toolbar.less',
'css/icinga/login.less',
'css/icinga/install.less',
);
public static function compileForPdf()

View File

@ -95,6 +95,8 @@ class FilterEditor extends AbstractWidget
. $view->escape(t('Click to remove this part of your filter'))
. '">' . $view->icon('remove.png') . '</a>';
/*
// Temporarilly removed, not implemented yet
$addUrl = clone($url);
$addUrl->setParam('addToId', $idx);
$addLink = ' <a href="' . $addUrl . '" title="'
@ -103,7 +105,7 @@ class FilterEditor extends AbstractWidget
$addLink .= ' <a href="' . $addUrl . '" title="'
. $view->escape(t('Click to add a filter expression to this operator'))
. '">' . t('Expression') . ' (=, &lt;, &gt;, &lt;=, &gt;=)</a>';
*/
$selectedIndex = ($idx === $this->selectedIdx ? ' -&lt;--' : '');
$selectIndex = ' <a href="' . $markUrl . '">o</a>';
@ -125,7 +127,7 @@ class FilterEditor extends AbstractWidget
),
$filter->getOperatorName(),
array('style' => 'width: 5em')
) . $removeLink . ' ' . t('Add') . ': ' . $addLink;
) . $removeLink; // Disabled: . ' ' . t('Add') . ': ' . $addLink;
$html .= '<span class="handle"> </span>';
if ($level === 0) {

View File

@ -1,93 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Wizard;
use Icinga\Web\Form;
class Page extends Form
{
/**
* Whether a CSRF token should not be added to this wizard page
*
* @var bool
*/
protected $tokenDisabled = true;
/**
* The wizard this page is part of
*
* @var Wizard
*/
protected $wizard;
/**
* The title of this wizard page
*
* @var string
*/
protected $title = '';
/**
* Create a new wizard page
*
* @param Wizard $wizard The wizard this page is part of
* @param mixed $options Zend_Form options
*/
public function __construct(Wizard $wizard = null, $options = null)
{
parent::__construct($options);
$this->wizard = $wizard;
}
/**
* Overwrite this to initialize this wizard page
*/
public function init()
{
}
/**
* Return whether this page needs to be shown to the user
*
* Overwrite this to add page specific handling
*
* @return bool
*/
public function isRequired()
{
return true;
}
/**
* Set the title for this wizard page
*
* @param string $title The title to set
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Return the title of this wizard page
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Return a config containing all values provided by the user
*
* @return Zend_Config
*/
public function getConfig()
{
return $this->getConfiguration();
}
}

View File

@ -1,385 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Wizard;
use Zend_Config;
use Icinga\Web\Form;
use Icinga\Exception\ProgrammingError;
/**
* Multistep form with support for nesting and dynamic behaviour
*
* @todo Pages that were displayed initially and filled out by the user remain
* currently in the configuration returned by Wizard::getConfig()
*/
class Wizard extends Page
{
/**
* Whether this wizard has been completed
*
* @var bool
*/
protected $finished = false;
/**
* The wizard pages
*
* @var array
*/
protected $pages = array();
/**
* Return the wizard pages
*
* @return array
*/
public function getPages()
{
return array_filter($this->pages, function ($page) { return $page->isRequired(); });
}
/**
* Return a page by its name or null if it's not found
*
* @param string $pageName The name of the page
*
* @return Page|null
*/
public function getPage($pageName)
{
$candidates = array_filter(
$this->pages, // Cannot use getPages() here because I might get called as part of Page::isRequired()
function ($page) use ($pageName) { return $page->getName() === $pageName; }
);
if (!empty($candidates)) {
return array_shift($candidates);
} elseif ($this->wizard !== null) {
return $this->wizard->getPage($pageName);
}
}
/**
* Add a new page to this wizard
*
* @param Page $page The page to add
*/
public function addPage(Page $page)
{
if (!($pageName = $page->getName())) {
throw new ProgrammingError('Wizard page "' . get_class($page) . '" has no unique name');
}
$wizardConfig = $this->getConfig();
if ($wizardConfig->get($pageName) === null) {
$wizardConfig->{$pageName} = new Zend_Config(array(), true);
}
$page->setConfiguration($wizardConfig->{$pageName});
$page->setRequest($this->getRequest());
$page->setTokenDisabled(); // Usually default for pages, but not for wizards
$this->pages[] = $page;
}
/**
* Add multiple pages to this wizard
*
* The given array's keys are titles and its values are class names to add
* as wizard pages. An array as value causes a sub-wizard being added.
*
* @param array $pages The pages to add to the wizard
*/
public function addPages(array $pages)
{
foreach ($pages as $title => $pageClassOrArray) {
if (is_array($pageClassOrArray)) {
$wizard = new static($this);
$wizard->setTitle($title);
$this->addPage($wizard);
$wizard->addPages($pageClassOrArray);
} else {
$page = new $pageClassOrArray($this);
$page->setTitle($title);
$this->addPage($page);
}
}
}
/**
* Return this wizard's progress
*
* @param int $default The step to return in case this wizard has no progress information yet
*
* @return int The current step
*/
public function getProgress($default = 0)
{
return $this->getConfig()->get('progress', $default);
}
/**
* Set this wizard's progress
*
* @param int $step The current step
*/
public function setProgress($step)
{
$config = $this->getConfig();
$config->progress = $step;
}
/**
* Return the current page
*
* @return Page
*
* @throws ProgrammingError In case there are not any pages registered
*/
public function getCurrentPage()
{
$pages = $this->getPages();
if (empty($pages)) {
throw new ProgrammingError('This wizard has no pages');
}
return $pages[$this->getProgress()];
}
/**
* Return whether the given page is the current page
*
* @param Page $page The page to check
*
* @return bool
*/
public function isCurrentPage(Page $page)
{
return $this->getCurrentPage() === $page;
}
/**
* Return whether the given page is the first page in the wizard
*
* @param Page $page The page to check
*
* @return bool
*
* @throws ProgrammingError In case there are not any pages registered
*/
public function isFirstPage(Page $page)
{
$pages = $this->getPages();
if (empty($pages)) {
throw new ProgrammingError('This wizard has no pages');
}
return $pages[0] === $page;
}
/**
* Return whether the given page has been completed
*
* @param Page $page The page to check
*
* @return bool
*
* @throws ProgrammingError In case there are not any pages registered
*/
public function isCompletedPage(Page $page)
{
$pages = $this->getPages();
if (empty($pages)) {
throw new ProgrammingError('This wizard has no pages');
}
return $this->isFinished() || array_search($page, $pages, true) < $this->getProgress();
}
/**
* Return whether the given page is the last page in the wizard
*
* @param Page $page The page to check
*
* @return bool
*
* @throws ProgrammingError In case there are not any pages registered
*/
public function isLastPage(Page $page)
{
$pages = $this->getPages();
if (empty($pages)) {
throw new ProgrammingError('This wizard has no pages');
}
return $pages[count($pages) - 1] === $page;
}
/**
* Return whether this wizard has been completed
*
* @return bool
*/
public function isFinished()
{
return $this->finished && $this->isLastPage($this->getCurrentPage());
}
/**
* Return whether the given page is a wizard
*
* @param Page $page The page to check
*
* @return bool
*/
public function isWizard(Page $page)
{
return $page instanceof self;
}
/**
* Return whether either the back- or next-button was clicked
*
* @see Form::isSubmitted()
*/
public function isSubmitted()
{
$checkData = $this->getRequest()->getParams();
return isset($checkData['btn_return']) || isset($checkData['btn_advance']);
}
/**
* Update the wizard's progress
*
* @param bool $lastStepIsLast Whether the last step of this wizard is actually the very last one
*/
public function navigate($lastStepIsLast = true)
{
$currentPage = $this->getCurrentPage();
if (($pageName = $this->getRequest()->getParam('btn_advance'))) {
if (!$this->isWizard($currentPage) || $currentPage->navigate(false) || $currentPage->isFinished()) {
if ($this->isLastPage($currentPage) && (!$lastStepIsLast || $pageName === 'install')) {
$this->finished = true;
} else {
$pages = $this->getPages();
$newStep = $this->getProgress() + 1;
if (isset($pages[$newStep]) && $pages[$newStep]->getName() === $pageName) {
$this->setProgress($newStep);
$this->reset();
}
}
}
} elseif (($pageName = $this->getRequest()->getParam('btn_return'))) {
if ($this->isWizard($currentPage) && $currentPage->getProgress() > 0) {
$currentPage->navigate(false);
} elseif (!$this->isFirstPage($currentPage)) {
$pages = $this->getPages();
$newStep = $this->getProgress() - 1;
if ($pages[$newStep]->getName() === $pageName) {
$this->setProgress($newStep);
$this->reset();
}
}
}
$config = $this->getConfig();
$config->{$currentPage->getName()} = $currentPage->getConfig();
}
/**
* Setup the current wizard page
*/
protected function create()
{
$currentPage = $this->getCurrentPage();
if ($this->isWizard($currentPage)) {
$this->createWizard($currentPage);
} else {
$this->createPage($currentPage);
}
}
/**
* Display the given page as this wizard's current page
*
* @param Page $page The page
*/
protected function createPage(Page $page)
{
$pages = $this->getPages();
$currentStep = $this->getProgress();
$page->buildForm(); // Needs to get called manually as it's nothing that Zend knows about
$this->addSubForm($page, $page->getName());
if (!$this->isFirstPage($page)) {
$this->addElement(
'button',
'btn_return',
array(
'type' => 'submit',
'label' => t('Previous'),
'value' => $pages[$currentStep - 1]->getName()
)
);
}
$this->addElement(
'button',
'btn_advance',
array(
'type' => 'submit',
'label' => $this->isLastPage($page) ? t('Install') : t('Next'),
'value' => $this->isLastPage($page) ? 'install' : $pages[$currentStep + 1]->getName()
)
);
}
/**
* Display the current page of the given wizard as this wizard's current page
*
* @param Wizard $wizard The wizard
*/
protected function createWizard(Wizard $wizard)
{
$isFirstPage = $this->isFirstPage($wizard);
$isLastPage = $this->isLastPage($wizard);
$currentSubPage = $wizard->getCurrentPage();
$isFirstSubPage = $wizard->isFirstPage($currentSubPage);
$isLastSubPage = $wizard->isLastPage($currentSubPage);
$currentSubPage->buildForm(); // Needs to get called manually as it's nothing that Zend knows about
$this->addSubForm($currentSubPage, $currentSubPage->getName());
if (!$isFirstPage || !$isFirstSubPage) {
$pages = $isFirstSubPage ? $this->getPages() : $wizard->getPages();
$currentStep = $isFirstSubPage ? $this->getProgress() : $wizard->getProgress();
$this->addElement(
'button',
'btn_return',
array(
'type' => 'submit',
'label' => t('Previous'),
'value' => $pages[$currentStep - 1]->getName()
)
);
}
$pages = $isLastSubPage ? $this->getPages() : $wizard->getPages();
$currentStep = $isLastSubPage ? $this->getProgress() : $wizard->getProgress();
$this->addElement(
'button',
'btn_advance',
array(
'type' => 'submit',
'label' => $isLastPage && $isLastSubPage ? t('Install') : t('Next'),
'value' => $isLastPage && $isLastSubPage ? 'install' : $pages[$currentStep + 1]->getName()
)
);
}
}

View File

@ -47,15 +47,15 @@ use Icinga\Chart\Unit\StaticAxis;
class Monitoring_ChartController extends Controller
{
public function testAction() {
public function testAction()
{
$this->chart = new GridChart();
$this->chart->setAxisLabel('X axis label', 'Y axis label')->setXAxis(new StaticAxis());
$data1 = array();
$data2 = array();
$data3 = array();
for ($i=0; $i<25; $i++) {
$data3[] = array('Label ' . $i, rand(0,30));
for ($i = 0; $i < 25; $i++) {
$data3[] = array('Label ' . $i, rand(0, 30));
}
/*
@ -164,29 +164,30 @@ class Monitoring_ChartController extends Controller
$unknownBars[] = array($servicegroup->servicegroup, $servicegroup->services_unknown_unhandled);
}
$this->view->chart = new GridChart();
$this->view->chart->setAxisLabel('', 'Services')
$this->view->chart->setAxisLabel('', t('Services'))
->setXAxis(new \Icinga\Chart\Unit\StaticAxis());
$this->view->chart->drawBars(
array(
'label' => 'Ok',
'label' => t('Ok'),
'color' => '#44bb77',
'stack' => 'stack1',
'data' => $okBars
),
array(
'label' => 'Warning',
'label' => t('Warning'),
'color' => '#ffaa44',
'stack' => 'stack1',
'data' => $warningBars
),
array(
'label' => 'Critical',
'label' => t('Critical'),
'color' => '#ff5566',
'stack' => 'stack1',
'data' => $critBars
),
array(
'label' => 'Unknown',
'label' => t('Unknown'),
'color' => '#dd66ff',
'stack' => 'stack1',
'data' => $unknownBars
@ -200,27 +201,36 @@ class Monitoring_ChartController extends Controller
$downBars = array();
$unreachableBars = array();
foreach ($query as $hostgroup) {
$upBars[] = array($hostgroup->hostgroup, $hostgroup->hosts_up);
$downBars[] = array($hostgroup->hostgroup, $hostgroup->hosts_down_unhandled);
$unreachableBars[] = array($hostgroup->hostgroup, $hostgroup->hosts_unreachable_unhandled);
$upBars[] = array(
$hostgroup->hostgroup,
$hostgroup->hosts_up
);
$downBars[] = array(
$hostgroup->hostgroup,
$hostgroup->hosts_down_unhandled
);
$unreachableBars[] = array(
$hostgroup->hostgroup,
$hostgroup->hosts_unreachable_unhandled
);
}
$this->view->chart = new GridChart();
$this->view->chart->setAxisLabel('', 'Hosts')->setXAxis(new StaticAxis());
$this->view->chart->setAxisLabel('', t('Hosts'))->setXAxis(new StaticAxis());
$this->view->chart->drawBars(
array(
'label' => 'Up',
'label' => t('Up'),
'color' => '#44bb77',
'stack' => 'stack1',
'data' => $upBars
),
array(
'label' => 'Down',
'label' => t('Down'),
'color' => '#ff5566',
'stack' => 'stack1',
'data' => $downBars
),
array(
'label' => 'Unreachable',
'label' => t('Unreachable'),
'color' => '#dd66ff',
'stack' => 'stack1',
'data' => $unreachableBars
@ -244,11 +254,11 @@ class Monitoring_ChartController extends Controller
'colors' => array( '#ff4444', '#ff0000', '#E066FF', '#f099FF', '#fefefe'),
'labels'=> array(
// (int) $query->hosts_up . ' Up Hosts',
(int) $query->hosts_down_handled . ' Down Hosts (Handled)',
(int) $query->hosts_down_unhandled . ' Down Hosts (Unhandled)',
(int) $query->hosts_unreachable_handled . ' Unreachable Hosts (Handled)',
(int) $query->hosts_unreachable_unhandled . ' Unreachable Hosts (Unhandled)',
(int) $query->hosts_pending . ' Pending Hosts'
(int) $query->hosts_down_handled . t(' Down Hosts (Handled)'),
(int) $query->hosts_down_unhandled . t(' Down Hosts (Unhandled)'),
(int) $query->hosts_unreachable_handled . t(' Unreachable Hosts (Handled)'),
(int) $query->hosts_unreachable_unhandled . t(' Unreachable Hosts (Unhandled)'),
(int) $query->hosts_pending . t(' Pending Hosts')
)
), array(
'data' => array(
@ -264,14 +274,13 @@ class Monitoring_ChartController extends Controller
'colors' => array('#ff4444', '#ff0000', '#ffff00', '#ffff33', '#E066FF', '#f099FF', '#fefefe'),
'labels'=> array(
// $query->services_ok . ' Up Services',
$query->services_warning_handled . ' Warning Services (Handled)',
$query->services_warning_unhandled . ' Warning Services (Unhandled)',
$query->services_critical_handled . ' Down Services (Handled)',
$query->services_critical_unhandled . ' Down Services (Unhandled)',
$query->services_unknown_handled . ' Unreachable Services (Handled)',
$query->services_unknown_unhandled . ' Unreachable Services (Unhandled)',
$query->services_pending . ' Pending Services',
$query->services_warning_handled . t(' Warning Services (Handled)'),
$query->services_warning_unhandled . t(' Warning Services (Unhandled)'),
$query->services_critical_handled . t(' Down Services (Handled)'),
$query->services_critical_unhandled . t(' Down Services (Unhandled)'),
$query->services_unknown_handled . t(' Unreachable Services (Handled)'),
$query->services_unknown_unhandled . t(' Unreachable Services (Unhandled)'),
$query->services_pending . t(' Pending Services')
)
));
}

View File

@ -524,7 +524,9 @@ class Monitoring_ListController extends Controller
'query' => $query
));
}
$query->applyFilter($filter);
if (! $filter->isEmpty()) {
$query->applyFilter($filter);
}
$this->view->filter = $filter;
if ($sort) {
$query->order($sort, $dir);

View File

@ -1,37 +1,12 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
*
* Icinga Web 2 - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Form\Config\Backend;
use \Zend_Config;
use \Icinga\Web\Form;
use \Icinga\Application\Icinga;
use Zend_Config;
use Icinga\Web\Form;
use Icinga\Application\Icinga;
use Icinga\Data\ResourceFactory;
/**
@ -44,32 +19,14 @@ class EditBackendForm extends Form
*
* @var array
*/
private $resources;
protected $resources;
/**
* The Backend configuration to use for populating the form
*
* @var Zend_Config
*/
private $backend;
/**
* Mapping from form fields to configuration fields
*
* @var array
*/
private $propertyMapping = array(
'livestatus' => array(
'backend_livestatus_socket' => 'socket'
),
'ido' => array(
'backend_ido_resource' => 'resource'
),
'statusdat' => array(
'backend_statusdat_statusfile' => 'status_file',
'backend_statusdat_objectfile' => 'object_file'
)
);
protected $backend;
/**
* Set the configuration to be used for initial population of the form
@ -105,124 +62,24 @@ class EditBackendForm extends Form
}
/**
* Return a list of all database resource ready to be used as the multiOptions
* attribute in a Zend_Form_Element_Select object
* Return a list of all resources of the given type ready to be used as content for a select input
*
* @return array
* @param string $type The type of resources to return
*
* @return array
*/
private function getDatabaseResources()
protected function getResourcesByType($type)
{
$backends = array();
foreach ($this->getResources() as $resname => $resource) {
if ($resource['type'] !== 'db') {
continue;
foreach ($this->getResources() as $name => $resource) {
if ($resource['type'] === $type) {
$backends[$name] = $name;
}
$backends[$resname] = $resname;
}
return $backends;
}
/**
* Add form elements used for setting IDO backend parameters
*/
private function addIdoBackendForm()
{
$this->addElement(
'select',
'backend_ido_resource',
array(
'label' => 'IDO Connection',
'value' => $this->backend->resource,
'required' => true,
'multiOptions' => $this->getDatabaseResources(),
'helptext' => 'The database to use for querying monitoring data',
)
);
}
/**
* Add form elements used for setting status.dat backend parameters
*/
private function addStatusDatForm()
{
$this->addElement(
'text',
'backend_statusdat_statusfile',
array (
'label' => 'Status.dat File',
'value' => $this->backend->status_file,
'required' => true,
'helptext' => 'Location of your icinga status.dat file'
)
);
$this->addElement(
'text',
'backend_statusdat_objectfile',
array (
'label' => 'Objects.cache File',
'value' => $this->backend->status_file,
'required' => true,
'helptext' => 'Location of your icinga objects.cache file'
)
);
}
/**
* Add form elements used for setting Livestatus parameters
*/
private function addLivestatusForm()
{
$this->addElement(
'text',
'backend_livestatus_socket',
array(
'label' => 'Livestatus Socket Location',
'required' => true,
'helptext' => 'The path to your livestatus socket used for querying monitoring data',
'value' => $this->backend->socket,
)
);
}
/**
* Add a checkbox to disable this backends
*/
private function addDisableButton()
{
$this->addElement(
'checkbox',
'backend_disable',
array(
'label' => 'Disable This Backend',
'required' => true,
'value' => $this->backend->disabled
)
);
}
/**
* Add a select box for choosing the type to use for this backend
*/
private function addTypeSelectionBox()
{
$this->addElement(
'select',
'backend_type',
array(
'label' => 'Backend Type',
'value' => $this->backend->type,
'required' => true,
'helptext' => 'The data source used for retrieving monitoring information',
'multiOptions' => array(
'ido' => 'IDO Backend',
'statusdat' => 'Status.dat',
'livestatus' => 'Livestatus'
)
)
);
$this->enableAutoSubmit(array('backend_type'));
}
/**
* Create this form
*
@ -230,23 +87,45 @@ class EditBackendForm extends Form
*/
public function create()
{
$this->addTypeSelectionBox();
switch ($this->getRequest()->getParam('backend_type', $this->backend->type)) {
case 'ido':
$this->addIdoBackendForm();
break;
case 'statusdat':
$this->addStatusDatForm();
break;
case 'livestatus':
$this->addLivestatusForm();
break;
default:
$this->removeElement('backend_type');
$this->addNote('Unknown Backend Type "' . $this->backend->type. '"');
return;
}
$this->addDisableButton();
$backendType = $this->getRequest()->getParam('backend_type', $this->backend->type);
$this->addElement(
'select',
'backend_type',
array(
'label' => 'Backend Type',
'value' => $this->backend->type,
'required' => true,
'helptext' => 'The data source used for retrieving monitoring information',
'multiOptions' => array(
'ido' => 'IDO Backend',
'statusdat' => 'Status.dat',
'livestatus' => 'Livestatus'
)
)
);
$this->addElement(
'select',
'backend_resource',
array(
'label' => 'Resource',
'value' => $this->backend->resource,
'required' => true,
'multiOptions' => $this->getResourcesByType($backendType === 'ido' ? 'db' : $backendType),
'helptext' => 'The resource to use'
)
);
$this->addElement(
'checkbox',
'backend_disable',
array(
'label' => 'Disable This Backend',
'required' => true,
'value' => $this->backend->disabled
)
);
$this->enableAutoSubmit(array('backend_type'));
$this->setSubmitLabel('{{SAVE_ICON}} Save Changes');
}
@ -258,16 +137,12 @@ class EditBackendForm extends Form
public function getConfig()
{
$values = $this->getValues();
$type = $values['backend_type'];
$map = $this->propertyMapping[$type];
$result = array(
'type' => $type,
'disabled' => $values['backend_disable']
return new Zend_Config(
array(
'type' => $values['backend_type'],
'disabled' => $values['backend_disable'],
'resource' => $values['backend_resource']
)
);
foreach ($map as $formKey => $mappedKey) {
$result[$mappedKey] = $values[$formKey];
}
return new Zend_Config($result);
}
}

View File

@ -29,7 +29,7 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract
if (! $perfdata->isPercentage()) {
$pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)');
}
$pieChart->setStyle('float: left; margin: 0.2em 0.5em 0.2em 0.5em;');
$pieChart->setStyle('margin: 0.2em 0.5em 0.2em 0.5em;');
$table[] = '<tr><th>' . $pieChart->render()
. htmlspecialchars($label)
. '</th><td> '

View File

@ -1,10 +1,13 @@
<div class="controls">
<?= $this->tabs->render($this); ?>
<div style="margin: 1em" class="dontprint">
<?= $this->translate('Sort by') ?> <?= $this->sortControl->render($this); ?>
</div>
<?= $this->paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
</div>
<?php if (!$this->compact): ?>
<div class="controls">
<?= $this->tabs->render($this); ?>
<div style="margin: 1em" class="dontprint">
<?= $this->translate('Sort by') ?> <?= $this->sortControl->render($this); ?>
</div>
<?= $this->paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
</div>
<?php endif; ?>
<div class="content">
<?php if (empty($history)): ?>

View File

@ -81,20 +81,6 @@ if ($hosts->count() === 0) {
<td class="state" title="<?= $helper->getStateTitle($host, 'host') ?>">
<?php if (! $this->compact): ?>
<div>
<?php if (isset($host->host_unhandled_services) && $host->host_unhandled_services > 0): ?>
<span
class="badge pull-right"
title="<?= $host->host_unhandled_services ?> Service Problems on Host"
>
<a
href="<?= $this->href(
'monitoring/show/services',
array('host' => $host->host_name, 'service_problem' => 1)
) ?>"
><?= $host->host_unhandled_services ?></a>
</span>
<?php endif; ?>
<strong><?= ucfirst($helper->monitoringState($host, 'host')) ?></strong><br />
<div class="small-row">
<?php endif; ?>
@ -122,14 +108,31 @@ if ($hosts->count() === 0) {
) ?>
<?php endif; ?>
<?= implode(' ', $icons) ?>
<?php endif; ?>
<?php endif ?>
<a href="<?= $this->compact ? $hostLink : $this->href(
'monitoring/show/host',
array('host' => $host->host_name)
) ?>"><?= $host->host_name ?></a><br />
) ?>"><?= $host->host_name ?></a>
<?php if (isset($host->host_unhandled_services) && $host->host_unhandled_services > 0): ?>
<span style="font-weight: normal" title="<?=
$host->host_unhandled_services
?> Service Problems on Host"> (<?= $this->qlink(
sprintf($this->translate('%d unhandled services'), $host->host_unhandled_services),
'monitoring/show/services',
array(
'host' => $host->host_name,
'service_problem' => 1,
'service_acknowledged' => 0,
'service_in_downtime' => 0
),
array('style' => 'font-weight: normal')
) ?>)</span>
<?php endif ?>
<br />
<?= $this->escape(substr(strip_tags($host->host_output), 0, 10000)) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

View File

@ -1,13 +1,16 @@
<div class="controls">
<?= $this->tabs ?>
<div class="dontprint">
<?= $this->translate('Sort by') ?> <?= $this->sortControl->render($this) ?>
<?= $this->selectionToolbar('single') ?>
</div>
<?= $this->widget('limiter') ?>
<?php if ($notifications->count() >= 100): ?><br /><?php endif ?>
<?= $this->paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?>
</div>
<?php if (!$this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<div class="dontprint">
<?= $this->translate('Sort by') ?> <?= $this->sortControl->render($this) ?>
<?= $this->selectionToolbar('single') ?>
</div>
<?= $this->widget('limiter') ?>
<?php if ($notifications->count() >= 100): ?><br /><?php endif ?>
<?= $this->paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?>
</div>
<?php endif ?>
<div class="content">
<?php

View File

@ -29,7 +29,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use \Zend_Db_Select;
use Zend_Db_Select;
/**
* Query check summaries out of database
@ -50,43 +50,49 @@ class RuntimesummaryQuery extends IdoQuery
protected function joinBaseTables()
{
$p = $this->prefix;
$hosts = $this->db->select()->from(
array('ho' => $this->prefix . 'objects'),
array()
)->join(
array('hs' => $this->prefix . 'hoststatus'),
'ho.object_id = hs.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
array()
)->columns(
array(
'check_type' => 'CASE '
. 'WHEN hs.active_checks_enabled = 0 AND hs.passive_checks_enabled = 1 THEN \'passive\' '
. 'WHEN hs.active_checks_enabled = 1 THEN \'active\' '
. 'END',
'active_checks_enabled' => 'hs.active_checks_enabled',
'passive_checks_enabled' => 'hs.passive_checks_enabled',
'execution_time' => 'SUM(hs.execution_time)',
'latency' => 'SUM(hs.latency)',
'object_count' => 'COUNT(*)',
'object_type' => "('host')"
)
)->group('check_type')->group('active_checks_enabled')->group('passive_checks_enabled');
$hostColumns = array(
'check_type' => 'CASE '
. 'WHEN ' . $p
. 'hoststatus.active_checks_enabled = 0 AND '
. $p . 'hoststatus.passive_checks_enabled = 1 '
. 'THEN \'passive\' '
. 'WHEN ' . $p . 'hoststatus.active_checks_enabled = 1 THEN \'active\' END',
'active_checks_enabled' => 'active_checks_enabled',
'passive_checks_enabled' => 'passive_checks_enabled',
'execution_time' => 'SUM(execution_time)',
'latency' => 'SUM(latency)',
'object_count' => 'COUNT(*)',
'object_type' => "('host')"
);
$serviceColumns = array(
'check_type' => 'CASE '
. 'WHEN ' . $p
. 'servicestatus.active_checks_enabled = 0 AND ' . $p
. 'servicestatus.passive_checks_enabled = 1 '
. 'THEN \'passive\' '
. 'WHEN ' . $p . 'servicestatus.active_checks_enabled = 1 THEN \'active\' END',
'active_checks_enabled' => 'active_checks_enabled',
'passive_checks_enabled' => 'passive_checks_enabled',
'execution_time' => 'SUM(execution_time)',
'latency' => 'SUM(latency)',
'object_count' => 'COUNT(*)',
'object_type' => "('service')"
);
$hosts = $this->db->select()->from($this->prefix . 'hoststatus', $hostColumns)
->group('check_type')->group('active_checks_enabled')->group('passive_checks_enabled');
$services = $this->db->select()->from($this->prefix . 'servicestatus', $serviceColumns)
->group('check_type')->group('active_checks_enabled')->group('passive_checks_enabled');
$services = $this->db->select()->from(
array('so' => $this->prefix . 'objects'),
array()
)->join(
array('ss' => $this->prefix . 'servicestatus'),
'so.object_id = ss.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
array()
)->columns(
array(
'check_type' => 'CASE '
. 'WHEN ss.active_checks_enabled = 0 AND ss.passive_checks_enabled = 1 THEN \'passive\' '
. 'WHEN ss.active_checks_enabled = 1 THEN \'active\' '
. 'END',
'active_checks_enabled' => 'ss.active_checks_enabled',
'passive_checks_enabled' => 'ss.passive_checks_enabled',
'execution_time' => 'SUM(ss.execution_time)',
'latency' => 'SUM(ss.latency)',
'object_count' => 'COUNT(*)',
'object_type' => "('service')"
)
)->group('check_type')->group('active_checks_enabled')->group('passive_checks_enabled');
$union = $this->db->select()->union(
array('s' => $services, 'h' => $hosts),

View File

@ -1,96 +0,0 @@
div.wizard {
div.header {
padding: 0.6em 0 0 1em;
height: 3em;
position: fixed;
top: 0;
left: 0;
right: 0;
color: #eee;
background-color: #555;
background-image: linear-gradient(top, #777, #555);
background-image: -o-linear-gradient(top, #777, #555);
background-image: -ms-linear-gradient(top, #777, #555);
background-image: -webkit-linear-gradient(top, #777, #555);
h1 {
margin: 0 3.5em;
display: inline-block;
font-size: 2em;
}
}
div.sidebar {
width: 13em;
position: fixed;
top: 3.6em;
left: 0;
bottom: 0;
background-color: #999;
box-shadow: inset -0.5em 0 0.5em -0.5em #555;
-moz-box-shadow: inset -0.5em 0 0.5em -0.5em #555;
-webkit-box-shadow: inset -0.5em 0 0.5em -0.5em #555;
& > ul {
margin: 0;
padding: 0;
list-style: none;
& > li {
color: #f5f5f5;
font-size: 1.1em;
padding: 0.5em;
margin-left: 0.5em;
text-shadow: #555 -1px 1px 0px;
border-bottom: 1px solid #888;
&.active {
color: black;
margin-left: 0;
padding-left: 1em;
text-shadow: none;
background-color: white;
}
&.complete {
color: green;
}
&.pending {
color: red;
}
&.install {
border-bottom: 0;
}
ul {
margin: 0;
padding: 0;
list-style: none;
li.child {
font-size: 0.9em;
padding: 0.4em 0.8em 0;
&.active {
font-weight: bold;
}
}
}
}
}
}
div.panel {
padding: 1em;
position: fixed;
top: 3.6em;
left: 13em;
right: 0;
bottom: 0;
}
}

View File

@ -144,12 +144,15 @@ table.perfdata {
}
table.perfdata th {
white-space: nowrap;
padding: 0;
text-align: left;
padding-right: 0.5em;
}
table.perfdata td {
white-space: nowrap;
}
table.objectlist {
min-width: 28em;
th {

View File

@ -260,6 +260,7 @@
if ($('#col1').data('icingaUrl') === redirect) {
icinga.ui.layout1col();
req.$target = $('#col1');
delete(this.requests['col2']);
}
}
@ -393,6 +394,9 @@
classes.push('module-' + moduleName);
} else {
req.$target.removeData('icingaModule');
if (req.$target.attr('data-icinga-module')) {
req.$target.removeAttr('data-icinga-module');
}
}
req.$target.attr('class', classes.join(' '));
@ -406,6 +410,9 @@
req.$target.data('icingaRefresh', refresh);
} else {
req.$target.removeData('icingaRefresh');
if (req.$target.attr('data-icinga-refresh')) {
req.$target.removeAttr('data-icinga-refresh');
}
}
// Set a window identifier if the server asks us to do so

View File

@ -11,6 +11,7 @@ require_once realpath(dirname(__FILE__) . '/../../../../bootstrap.php');
use Mockery;
use Icinga\Test\BaseTestCase;
use Icinga\Form\Config\Authentication\LdapBackendForm;
use Icinga\Exception\AuthenticationException;
class LdapBackendFormTest extends BaseTestCase
{
@ -26,10 +27,9 @@ class LdapBackendFormTest extends BaseTestCase
*/
public function testValidBackendIsValid()
{
Mockery::mock('alias:Icinga\Authentication\UserBackend')
->shouldReceive('create')->with('test', Mockery::type('\Zend_Config'))->andReturnUsing(
function () { return Mockery::mock(array('count' => 1)); }
);
$this->setUpResourceFactoryMock();
Mockery::mock('overload:Icinga\Authentication\Backend\LdapUserBackend')
->shouldReceive('assertAuthenticationPossible')->andReturn(null);
$form = new LdapBackendForm();
$form->setBackendName('test');
@ -49,10 +49,9 @@ class LdapBackendFormTest extends BaseTestCase
*/
public function testInvalidBackendIsNotValid()
{
Mockery::mock('alias:Icinga\Authentication\UserBackend')
->shouldReceive('create')->with('test', Mockery::type('\Zend_Config'))->andReturnUsing(
function () { return Mockery::mock(array('count' => 0)); }
);
$this->setUpResourceFactoryMock();
Mockery::mock('overload:Icinga\Authentication\Backend\LdapUserBackend')
->shouldReceive('assertAuthenticationPossible')->andThrow(new AuthenticationException);
$form = new LdapBackendForm();
$form->setBackendName('test');
@ -65,4 +64,16 @@ class LdapBackendFormTest extends BaseTestCase
'LdapBackendForm claims that an invalid authentication backend without users is valid'
);
}
protected function setUpResourceFactoryMock()
{
Mockery::mock('alias:Icinga\Data\ResourceFactory')
->shouldReceive('ldapAvailable')
->andReturn(true)
->shouldReceive('getResourceConfig')
->andReturn(new \Zend_Config(array()))
->shouldReceive('createResource')
->with(Mockery::type('\Zend_Config'))
->andReturn(Mockery::mock('Icinga\Protocol\Ldap\Connection'));
}
}

View File

@ -111,7 +111,6 @@ EOD;
/**
* @expectedException Icinga\Exception\ProgrammingError
* @expectedExceptionMessage Directory does not exist: /trullalla/123
*/
public function testNonexistingDirectory()
{

View File

@ -467,7 +467,7 @@ EOD
);
}
public function testWhetherSectionAndPropertyOrderIsPreserved()
public function testWhetherSectionOrderIsUpdated()
{
$config = <<<'EOD'
[one]
@ -483,6 +483,22 @@ d.e = "f"
[three]
key = "value"
foo.bar = "raboof"
EOD;
$reverted = <<<'EOD'
[three]
key = "value"
foo.bar = "raboof"
[two]
a.b = "c"
d.e = "f"
[one]
key1 = "1"
key2 = "2"
EOD;
$target = $this->writeConfigToTemporaryFile($config);
$writer = new PreservingIniWriter(
@ -514,12 +530,52 @@ EOD;
);
$this->assertEquals(
$config,
$writer->render(),
trim($reverted),
trim($writer->render()),
'PreservingIniWriter does not preserve section and/or property order'
);
}
public function testWhetherCommentOrderIsUpdated()
{
$config = <<<'EOD'
; comment 1
[one]
; comment 2
[two]
EOD;
$reverted = <<<'EOD'
; comment 2
[two]
; comment 1
[one]
EOD;
$target = $this->writeConfigToTemporaryFile($config);
$writer = new PreservingIniWriter(
array(
'config' => new Zend_Config(
array(
'two' => array(),
'one' => array()
)
),
'filename' => $target
)
);
$this->assertEquals(
trim($reverted),
trim($writer->render()),
'PreservingIniWriter does not preserve section and/or property order'
);
}
public function testWhetherCommentsOnEmptyLinesArePreserved()
{
$config = <<<'EOD'

View File

@ -15,7 +15,7 @@ class CsvTest extends BaseTestCase
$queryMock = Mockery::mock(
'Icinga\Data\SimpleQuery',
array(
'fetchAll' => array(
'getQuery->fetchAll' => array(
array('col1' => 'val1', 'col2' => 'val2', 'col3' => 'val3', 'col4' => 'val4'),
array('col1' => 'val5', 'col2' => 'val6', 'col3' => 'val7', 'col4' => 'val8')
)

View File

@ -1,29 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Tests\Icinga\Web;
use Zend_Config;
use Icinga\Web\MenuItem;
use Icinga\Test\BaseTestCase;
class MenuItemTest extends BaseTestCase
{
public function testWhetherMenuItemsAreNaturallySorted()
{
$item = new MenuItem('test');
$item->addChild(5, new Zend_Config(array('title' => 'ccc5')));
$item->addChild(0, new Zend_Config(array('title' => 'aaa')));
$item->addChild(3, new Zend_Config(array('title' => 'ccc')));
$item->addChild(2, new Zend_Config(array('title' => 'bbb')));
$item->addChild(4, new Zend_Config(array('title' => 'ccc2')));
$item->addChild(1, new Zend_Config(array('title' => 'bb')));
$this->assertEquals(
array('aaa', 'bb', 'bbb', 'ccc', 'ccc2', 'ccc5'),
array_map(function ($it) { return $it->getTitle(); }, $item->getChildren()),
'MenuItem::getChildren does not return its elements in natural order'
);
}
}

View File

@ -0,0 +1,29 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Tests\Icinga\Web;
use Zend_Config;
use Icinga\Web\Menu;
use Icinga\Test\BaseTestCase;
class MenuTest extends BaseTestCase
{
public function testWhetherMenusAreNaturallySorted()
{
$menu = new Menu('test');
$menu->addSubMenu(5, new Zend_Config(array('title' => 'ccc5')));
$menu->addSubMenu(0, new Zend_Config(array('title' => 'aaa')));
$menu->addSubMenu(3, new Zend_Config(array('title' => 'ccc')));
$menu->addSubMenu(2, new Zend_Config(array('title' => 'bbb')));
$menu->addSubMenu(4, new Zend_Config(array('title' => 'ccc2')));
$menu->addSubMenu(1, new Zend_Config(array('title' => 'bb')));
$this->assertEquals(
array('aaa', 'bb', 'bbb', 'ccc', 'ccc2', 'ccc5'),
array_map(function ($m) { return $m->getTitle(); }, iterator_to_array($menu->order())),
'Menu::order() does not return its elements in natural order'
);
}
}

View File

@ -1,72 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Tests\Icinga\Web\Paginator\Adapter;
use \Zend_Config;
use Icinga\Test\BaseTestCase;
use Icinga\Protocol\Statusdat\Reader;
use Icinga\Module\Monitoring\Backend;
use Icinga\Web\Paginator\Adapter\QueryAdapter;
class QueryAdapterTest extends BaseTestCase
{
private $cacheDir;
private $backendConfig;
private $resourceConfig;
public function setUp()
{
parent::setUp();
$this->cacheDir = '/tmp'. Reader::STATUSDAT_DEFAULT_CACHE_PATH;
if (!file_exists($this->cacheDir)) {
mkdir($this->cacheDir);
}
$statusdatFile = BaseTestCase::$testDir . '/res/status/icinga.status.dat';
$cacheFile = BaseTestCase::$testDir . '/res/status/icinga.objects.cache';
$this->backendConfig = new Zend_Config(
array(
'type' => 'statusdat'
)
);
$this->resourceConfig = new Zend_Config(
array(
'status_file' => $statusdatFile,
'object_file' => $cacheFile,
'type' => 'statusdat'
)
);
}
public function testLimit1()
{
$backend = new Backend($this->backendConfig, $this->resourceConfig);
$query = $backend->select()->from('status');
$adapter = new QueryAdapter($query);
$this->assertEquals(30, $adapter->count());
$data = $adapter->getItems(0, 10);
$this->assertCount(10, $data);
$data = $adapter->getItems(10, 20);
$this->assertCount(10, $data);
}
public function testLimit2()
{
$backend = new Backend($this->backendConfig, $this->resourceConfig);
$query = $backend->select()->from('status');
$adapter = new QueryAdapter($query);
$this->assertEquals(30, $adapter->count());
}
}

View File

@ -6,63 +6,12 @@ namespace Tests\Icinga\Web\Paginator\ScrollingStyle;
require_once realpath(ICINGA_LIBDIR . '/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorder.php');
use \Mockery;
use \Zend_Config;
use \Zend_Paginator;
use Mockery;
use Zend_Paginator;
use Icinga\Test\BaseTestCase;
use Icinga\Protocol\Statusdat\Reader;
use Icinga\Web\Paginator\Adapter\QueryAdapter;
use Icinga\Module\Monitoring\Backend;
class SlidingwithborderTest extends BaseTestCase
{
private $cacheDir;
private $backendConfig;
private $resourceConfig;
public function setUp()
{
parent::setUp();
$this->cacheDir = '/tmp'. Reader::STATUSDAT_DEFAULT_CACHE_PATH;
if (!file_exists($this->cacheDir)) {
mkdir($this->cacheDir);
}
$statusdatFile = BaseTestCase::$testDir . '/res/status/icinga.status.dat';
$cacheFile = BaseTestCase::$testDir . '/res/status/icinga.objects.cache';
$this->backendConfig = new Zend_Config(
array(
'type' => 'statusdat'
)
);
$this->resourceConfig = new Zend_Config(
array(
'status_file' => $statusdatFile,
'object_file' => $cacheFile,
'type' => 'statusdat'
)
);
}
public function testGetPages1()
{
$backend = new Backend($this->backendConfig, $this->resourceConfig);
$adapter = new QueryAdapter($backend->select()->from('status'));
$this->assertEquals(30, $adapter->count());
$scrollingStyle = new \Icinga_Web_Paginator_ScrollingStyle_SlidingWithBorder();
$paginator = new Zend_Paginator($adapter);
$pages = $scrollingStyle->getPages($paginator);
$this->assertInternalType('array', $pages);
$this->assertCount(3, $pages);
}
public function testGetPages2()
{
$scrollingStyle = new \Icinga_Web_Paginator_ScrollingStyle_SlidingWithBorder();