Merge branch 'master' into bugfix/slow-unhandled-service-summary-query-in-host-overview-9864

This commit is contained in:
Johannes Meyer 2015-08-11 14:01:27 +02:00
commit 3f0d073f43
23 changed files with 454 additions and 142 deletions

View File

@ -447,6 +447,7 @@ class Module
*/
public function getCssFiles()
{
$this->launchConfigScript();
$files = $this->cssFiles;
$files[] = $this->getCssFilename();
return $files;
@ -497,6 +498,7 @@ class Module
*/
public function getJsFiles()
{
$this->launchConfigScript();
$files = $this->jsFiles;
$files[] = $this->getJsFilename();
return $files;

View File

@ -173,8 +173,10 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
/**
* Add a new property or section
*
* @param string $key The name of the new property or section
* @param mixed $value The value to set for the new property or section
* @param string $key The name of the new property or section
* @param mixed $value The value to set for the new property or section
*
* @throws ProgrammingError If the key is null
*/
public function offsetSet($key, $value)
{
@ -254,7 +256,7 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
/**
* Merge the given data with this config
*
* @param array|Config $data An array or a config
* @param array|ConfigObject $data An array or a config
*
* @return $this
*/

View File

@ -3,14 +3,31 @@
namespace Icinga\File\Ini\Dom;
/**
* A single comment-line in an INI file
*/
class Comment
{
/**
* The comment text
*
* @var string
*/
public $content;
protected $content;
/**
* Set the text content of this comment
*
* @param $content
*/
public function setContent($content)
{
$this->content = $content;
}
/**
* Render this comment into INI markup
*
* @return string
*/
public function render()

View File

@ -3,42 +3,57 @@
namespace Icinga\File\Ini\Dom;
use Icinga\Exception\ConfigurationError;
/**
* A key value pair in a Section
*/
class Directive
{
/**
* The value of this configuration directive
*
* @var string
*/
protected $key;
/**
* The immutable name of this configuration directive
*
* @var string
*/
protected $value;
/**
* @var array
*/
public $commentsPre;
/**
* @var string
*/
public $commentPost;
/**
* @param string $key
* Comments added one line before this directive
*
* @throws Exception
* @var Comment[] The comment lines
*/
protected $commentsPre = null;
/**
* Comment added at the end of the same line
*
* @var Comment
*/
protected $commentPost = null;
/**
* @param string $key The name of this configuration directive
*
* @throws ConfigurationError
*/
public function __construct($key)
{
$this->key = trim($key);
if (strlen($this->key) < 1) {
throw new Exception(sprintf('Ini parser error: empty key.'));
throw new ConfigurationError(sprintf('Ini error: empty directive key.'));
}
}
/**
* Return the name of this directive
*
* @return string
*/
public function getKey()
@ -47,7 +62,9 @@ class Directive
}
/**
* @return string
* Return the value of this configuration directive
*
* @return string
*/
public function getValue()
{
@ -55,7 +72,9 @@ class Directive
}
/**
* @param string $value
* Set the value of this configuration directive
*
* @param string $value
*/
public function setValue($value)
{
@ -63,7 +82,39 @@ class Directive
}
/**
* @return string
* Set the comments to be rendered on the line before this directive
*
* @param Comment[] $comments
*/
public function setCommentsPre(array $comments)
{
$this->commentsPre = $comments;
}
/**
* Return the comments to be rendered on the line before this directive
*
* @return Comment[]
*/
public function getCommentsPre()
{
return $this->commentsPre;
}
/**
* Set the comment rendered on the same line of this directive
*
* @param Comment $comment
*/
public function setCommentPost(Comment $comment)
{
$this->commentPost = $comment;
}
/**
* Render this configuration directive into INI markup
*
* @return string
*/
public function render()
{
@ -82,16 +133,35 @@ class Directive
return $str;
}
/**
* Assure that the given identifier contains no newlines and pending or trailing whitespaces
*
* @param $str The string to sanitize
*
* @return string
*/
protected function sanitizeKey($str)
{
return trim(str_replace(PHP_EOL, ' ', $str));
}
/**
* Escape the significant characters in directive values, normalize line breaks and assure that
* the character contains no linebreaks
*
* @param $str The string to sanitize
*
* @return mixed|string
*/
protected function sanitizeValue($str)
{
$str = trim($str);
$str = str_replace('\\', '\\\\', $str);
$str = str_replace('"', '\\"', $str);
return str_replace(PHP_EOL, ' ', $str);
// line breaks in the value should always match the current system EOL sequence
// to assure editable configuration files
$str = preg_replace("/(\r\n)|(\n)/", PHP_EOL, $str);
return $str;
}
}

View File

@ -6,16 +6,22 @@ namespace Icinga\File\Ini\Dom;
class Document
{
/**
* @var array
* The sections of this INI file
*
* @var Section[]
*/
protected $sections = array();
/**
* @var array
* The comemnts at file end that belong to no particular section
*
* @var Comment[]
*/
public $commentsDangling;
protected $commentsDangling;
/**
* Append a section to the end of this INI file
*
* @param Section $section
*/
public function addSection(Section $section)
@ -24,6 +30,8 @@ class Document
}
/**
* Return whether this INI file has the section with the given key
*
* @param string $name
*
* @return bool
@ -34,6 +42,8 @@ class Document
}
/**
* Return the section with the given name
*
* @param string $name
*
* @return Section
@ -44,6 +54,8 @@ class Document
}
/**
* Set the section with the given name
*
* @param string $name
* @param Section $section
*
@ -55,6 +67,8 @@ class Document
}
/**
* Remove the section with the given name
*
* @param string $name
*/
public function removeSection($name)
@ -63,6 +77,28 @@ class Document
}
/**
* Set the dangling comments at file end that belong to no particular directive
*
* @param Comment[] $comments
*/
public function setCommentsDangling(array $comments)
{
$this->commentsDangling = $comments;
}
/**
* Get the dangling comments at file end that belong to no particular directive
*
* @return array
*/
public function getCommentsDangling()
{
return $this->commentsDangling;
}
/**
* Render this document into the corresponding INI markup
*
* @return string
*/
public function render()

View File

@ -5,30 +5,43 @@ namespace Icinga\File\Ini\Dom;
use Icinga\Exception\ConfigurationError;
/**
* A section in an INI file
*/
class Section
{
/**
* The immutable name of this section
*
* @var string
*/
protected $name;
/**
* @var array
* All configuration directives of this section
*
* @var Directive[]
*/
protected $directives = array();
/**
* @var array
* Comments added one line before this section
*
* @var Comment[]
*/
public $commentsPre;
protected $commentsPre;
/**
* Comment added at the end of the same line
*
* @var string
*/
public $commentPost;
protected $commentPost;
/**
* @param string $name
* @param string $name The immutable name of this section
*
* @throws ConfigurationError When the section name is empty
*/
public function __construct($name)
{
@ -39,7 +52,9 @@ class Section
}
/**
* @param Directive $directive
* Append a directive to the end of this section
*
* @param Directive $directive The directive to append
*/
public function addDirective(Directive $directive)
{
@ -47,7 +62,9 @@ class Section
}
/**
* @param string $key
* Remove the directive with the given name
*
* @param string $key They name of the directive to remove
*/
public function removeDirective($key)
{
@ -55,7 +72,9 @@ class Section
}
/**
* @param string $key
* Return whether this section has a directive with the given key
*
* @param string $key The name of the directive
*
* @return bool
*/
@ -65,6 +84,8 @@ class Section
}
/**
* Get the directive with the given key
*
* @param $key string
*
* @return Directive
@ -75,7 +96,9 @@ class Section
}
/**
* @return string
* Return the name of this section
*
* @return string The name
*/
public function getName()
{
@ -83,6 +106,28 @@ class Section
}
/**
* Set the comments to be rendered on the line before this section
*
* @param Comment[] $comments
*/
public function setCommentsPre(array $comments)
{
$this->commentsPre = $comments;
}
/**
* Set the comment rendered on the same line of this section
*
* @param Comment $comment
*/
public function setCommentPost(Comment $comment)
{
$this->commentPost = $comment;
}
/**
* Render this section into INI markup
*
* @return string
*/
public function render()
@ -90,7 +135,9 @@ class Section
$dirs = '';
$i = 0;
foreach ($this->directives as $directive) {
$dirs .= (($i++ > 0 && ! empty($directive->commentsPre)) ? PHP_EOL : '') . $directive->render() . PHP_EOL;
$comments = $directive->getCommentsPre();
$dirs .= (($i++ > 0 && ! empty($comments)) ? PHP_EOL : '')
. $directive->render() . PHP_EOL;
}
$cms = '';
if (! empty($this->commentsPre)) {
@ -106,6 +153,13 @@ class Section
return $cms . sprintf('[%s]', $this->sanitize($this->name)) . $post . PHP_EOL . $dirs;
}
/**
* Escape the significant characters in sections and normalize line breaks
*
* @param $str The string to sanitize
*
* @return mixed
*/
protected function sanitize($str)
{
$str = trim($str);

View File

@ -23,6 +23,14 @@ class IniParser
const COMMENT_END = 9;
const LINE_END = 10;
/**
* Cancel the parsing with an error
*
* @param $message The error description
* @param $line The line in which the error occured
*
* @throws ConfigurationError
*/
private static function throwParseError($message, $line)
{
throw new ConfigurationError(sprintf('Ini parser error: %s. (l. %d)', $message, $line));
@ -85,7 +93,7 @@ class IniParser
$token .= $s;
} else {
$sec = new Section($token);
$sec->commentsPre = $coms;
$sec->setCommentsPre($coms);
$doc->addSection($sec);
$dir = null;
$coms = array();
@ -100,8 +108,7 @@ class IniParser
$token .= $s;
} else {
$dir = new Directive($token);
$dir->commentsPre = $coms;
$dir->setCommentsPre($coms);
if (isset($sec)) {
$sec->addDirective($dir);
} else {
@ -151,9 +158,7 @@ class IniParser
break;
case self::DIRECTIVE_VALUE_QUOTED:
if ($s === "\n") {
self::throwParseError('Unterminated DIRECTIVE_VALUE_QUOTED', $line);
} elseif ($s === '\\') {
if ($s === '\\') {
$state = self::ESCAPE;
$escaping = self::DIRECTIVE_VALUE_QUOTED;
} elseif ($s !== '"') {
@ -171,16 +176,16 @@ class IniParser
$token .= $s;
} else {
$com = new Comment();
$com->content = $token;
$com->setContent($token);
$token = '';
// Comments at the line end belong to the current line's directive or section. Comments
// on empty lines belong to the next directive that shows up.
if ($state === self::COMMENT_END) {
if (isset($dir)) {
$dir->commentPost = $com;
$dir->setCommentPost($com);
} else {
$sec->commentPost = $com;
$sec->setCommentPost($com);
}
} else {
$coms[] = $com;
@ -206,12 +211,12 @@ class IniParser
case self::COMMENT:
case self::COMMENT_END:
$com = new Comment();
$com->content = $token;
$com->setContent($token);
if ($state === self::COMMENT_END) {
if (isset($dir)) {
$dir->commentPost = $com;
$dir->setCommentPost($com);
} else {
$sec->commentPost = $com;
$sec->setCommentPost($com);
}
} else {
$coms[] = $com;
@ -230,7 +235,7 @@ class IniParser
self::throwParseError('File ended in unterminated state ' . $state, $line);
}
if (! empty($coms)) {
$doc->commentsDangling = $coms;
$doc->setCommentsDangling($coms);
}
return $doc;
}

View File

@ -117,7 +117,10 @@ class IniWriter
protected function updateSectionOrder(Config $newconfig, Document $oldDoc)
{
$doc = new Document();
$doc->commentsDangling = $oldDoc->commentsDangling;
$dangling = $oldDoc->getCommentsDangling();
if (isset($dangling)) {
$doc->setCommentsDangling($dangling);
}
foreach ($newconfig->toArray() as $section => $directives) {
$doc->addSection($oldDoc->getSection($section));
}

View File

@ -43,7 +43,7 @@ class Menu implements RecursiveIterator
/**
* The url of this menu
*
* @var string
* @var string|null
*/
protected $url;
@ -404,21 +404,20 @@ class Menu implements RecursiveIterator
*/
public function setUrl($url)
{
if ($url instanceof Url) {
$this->url = $url;
} else {
$this->url = Url::fromPath($url);
}
$this->url = $url;
return $this;
}
/**
* Return the url of this menu
*
* @return Url
* @return Url|null
*/
public function getUrl()
{
if ($this->url !== null && ! $this->url instanceof Url) {
$this->url = Url::fromPath($this->url);
}
return $this->url;
}

View File

@ -20,7 +20,7 @@ class Dashlet extends UserWidget
/**
* The url of this Dashlet
*
* @var \Icinga\Web\Url
* @var Url|null
*/
private $url;
@ -74,16 +74,13 @@ EOD;
{
$this->title = $title;
$this->pane = $pane;
if ($url instanceof Url) {
$this->url = $url;
} elseif ($url) {
$this->url = Url::fromPath($url);
} else {
if (! $url) {
throw new IcingaException(
'Cannot create dashboard dashlet "%s" without valid URL',
$title
);
}
$this->url = $url;
}
/**
@ -107,10 +104,13 @@ EOD;
/**
* Retrieve the dashlets url
*
* @return Url
* @return Url|null
*/
public function getUrl()
{
if ($this->url !== null && ! $this->url instanceof Url) {
$this->url = Url::fromPath($this->url);
}
return $this->url;
}
@ -123,11 +123,7 @@ EOD;
*/
public function setUrl($url)
{
if ($url instanceof Url) {
$this->url = $url;
} else {
$this->url = Url::fromPath($url);
}
$this->url = $url;
return $this;
}
@ -159,7 +155,7 @@ EOD;
public function toArray()
{
$array = array(
'url' => $this->url->getRelativeUrl(),
'url' => $this->getUrl()->getRelativeUrl(),
'title' => $this->getTitle()
);
if ($this->getDisabled() === true) {
@ -178,9 +174,9 @@ EOD;
}
$view = $this->view();
$url = clone($this->url);
$url = $this->getUrl();
$url->setParam('view', 'compact');
$iframeUrl = clone($url);
$iframeUrl = clone $url;
$iframeUrl->setParam('isIframe');
$searchTokens = array(

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Doc;
use CachingIterator;
use LogicException;
use SplStack;
use Icinga\Data\Tree\SimpleTree;
@ -15,6 +16,20 @@ use Icinga\Module\Doc\Exception\DocException;
*/
class DocParser
{
/**
* Internal identifier for Atx-style headers
*
* @var int
*/
const HEADER_ATX = 1;
/**
* Internal identifier for Setext-style headers
*
* @var int
*/
const HEADER_SETEXT = 2;
/**
* Path to the documentation
*
@ -70,11 +85,11 @@ class DocParser
* Extract atx- or setext-style headers from the given lines
*
* @param string $line
* @param string $lastLine
* @param string $nextLine
*
* @return array|null An array containing the header and the header level or null if there's nothing to extract
*/
protected function extractHeader($line, $lastLine)
protected function extractHeader($line, $nextLine)
{
if (! $line) {
return null;
@ -90,13 +105,14 @@ class DocParser
if (! $header) {
return null;
}
$headerStyle = static::HEADER_ATX;
} elseif (
$line
&& ($line[0] === '=' || $line[0] === '-')
&& preg_match('/^[=-]+\s*$/', $line, $match) === 1
$nextLine
&& ($nextLine[0] === '=' || $nextLine[0] === '-')
&& preg_match('/^[=-]+\s*$/', $nextLine, $match) === 1
) {
// Setext
$header = trim($lastLine);
$header = trim($line);
if (! $header) {
return null;
}
@ -105,6 +121,7 @@ class DocParser
} else {
$level = 2;
}
$headerStyle = static::HEADER_SETEXT;
}
if ($header === null) {
return null;
@ -117,7 +134,7 @@ class DocParser
} else {
$id = null;
}
return array($header, $id, $level);
return array($header, $id, $level, $headerStyle);
}
/**
@ -128,15 +145,18 @@ class DocParser
public function getDocTree()
{
$tree = new SimpleTree();
$stack = new SplStack();
foreach ($this->docIterator as $fileInfo) {
/** @var $fileInfo \SplFileInfo */
$file = $fileInfo->openFile();
$lastLine = null;
foreach ($file as $line) {
$header = $this->extractHeader($line, $lastLine);
$stack = new SplStack();
$cachingIterator = new CachingIterator($file, CachingIterator::TOSTRING_USE_CURRENT);
for ($cachingIterator->rewind(); $line = $cachingIterator->valid(); $cachingIterator->next()) {
$fileIterator = $cachingIterator->getInnerIterator();
$line = $cachingIterator->current();
$header = $this->extractHeader($line, $fileIterator->valid() ? $fileIterator->current() : null);
if ($header !== null) {
list($title, $id, $level) = $header;
list($title, $id, $level, $headerStyle) = $header;
while (! $stack->isEmpty() && $stack->top()->getLevel() >= $level) {
$stack->pop();
}
@ -169,14 +189,29 @@ class DocParser
$tree->addChild($section, $stack->top());
}
$stack->push($section);
if ($headerStyle === static::HEADER_SETEXT) {
$cachingIterator->next();
continue;
}
} else {
if ($stack->isEmpty()) {
throw new LogicException('Heading required');
$title = ucfirst($file->getBasename('.' . pathinfo($file->getFilename(), PATHINFO_EXTENSION)));
$id = $title;
if ($tree->getNode($id) !== null) {
$id = uniqid($id);
}
$section = new DocSection();
$section
->setId($id)
->setTitle($title)
->setLevel(1)
->setNoFollow(true);
$section->setChapter($section);
$tree->addChild($section);
$stack->push($section);
}
$stack->top()->appendContent($line);
}
// Save last line for setext-style headers
$lastLine = $line;
}
}
return $tree;

View File

@ -88,6 +88,14 @@ class DocSection extends TreeNode
return $this->content;
}
/**
* {@inheritdoc}
*/
public function setId($id)
{
return parent::setId(str_replace(' ', '-', (string) $id));
}
/**
* Set the header level
*

View File

@ -35,9 +35,15 @@ if (! $this->compact): ?>
?>
<tr class="state <?= $stateName; ?><?= $downtime->is_in_effect ? ' handled' : ''; ?>">
<td class="state">
<?php if ($downtime->start <= time() && ! $downtime->is_in_effect): ?>
<strong><?= $this->translate('Ends'); ?></strong>
<br>
<?= $this->timeUntil($downtime->is_flexible ? $downtime->scheduled_end : $downtime->end, $this->compact) ?>
<?php else: ?>
<strong><?= $downtime->is_in_effect ? $this->translate('Expires') : $this->translate('Starts'); ?></strong>
<br>
<?= $this->timeUntil($downtime->is_in_effect ? $downtime->end : $downtime->start, $this->compact) ?>
<?php endif; ?>
</td>
<td>
<?php if ($isService): ?>

View File

@ -1,9 +1,15 @@
<table class="action">
<tr class="state <?= $stateName; ?><?= $downtime->is_in_effect ? ' handled' : ''; ?>">
<td class="state">
<strong><?= $downtime->is_in_effect ? $this->translate('Expires') : $this->translate('Starts'); ?></strong>
<br>
<?= $this->timeUntil($downtime->is_in_effect ? $downtime->end : $downtime->start, $this->compact) ?>
<?php if ($downtime->start <= time() && ! $downtime->is_in_effect): ?>
<strong><?= $this->translate('Ends'); ?></strong>
<br>
<?= $this->timeUntil($downtime->is_flexible ? $downtime->scheduled_end : $downtime->end, $this->compact) ?>
<?php else: ?>
<strong><?= $downtime->is_in_effect ? $this->translate('Expires') : $this->translate('Starts'); ?></strong>
<br>
<?= $this->timeUntil($downtime->is_in_effect ? $downtime->end : $downtime->start, $this->compact) ?>
<?php endif; ?>
</td>
<td>
<small>

View File

@ -6,9 +6,15 @@
} ?>
<tr class="state <?= $downtime->stateText ?>">
<td class="state">
<?php if ($downtime->start <= time() && ! $downtime->is_in_effect): ?>
<strong><?= $this->translate('Ends'); ?></strong>
<br>
<?= $this->timeUntil($downtime->is_flexible ? $downtime->scheduled_end : $downtime->end, $this->compact) ?>
<?php else: ?>
<strong><?= $downtime->is_in_effect ? $this->translate('Expires') : $this->translate('Starts'); ?></strong>
<br>
<?= $this->timeUntil($downtime->is_in_effect ? $downtime->end : $downtime->start, $this->compact) ?>
<?php endif; ?>
</td>
<td class="name oneline">
<?php if ($downtime->isService): ?>

View File

@ -53,7 +53,12 @@ if (empty($object->comments) && ! $addLink) {
$this->timeUntil($downtime->end)
);
} else {
if ((bool) $downtime->is_fixed) {
if ($downtime->start <= time()) {
$state = sprintf(
$this->translate('ends %s', 'Last format parameter represents the end time'),
$this->timeUntil($downtime->is_flexible ? $downtime->scheduled_end : $downtime->end)
);
} elseif ((bool) $downtime->is_fixed) {
$state = sprintf(
$this->translate('scheduled %s', 'Last format parameter represents the time scheduled'),
$this->timeUntil($downtime->start)

View File

@ -122,7 +122,6 @@ class LocalCommandFile implements CommandTransportInterface
try {
$file = new File($this->path, $this->openMode);
$file->fwrite($commandString . "\n");
$file->fflush();
} catch (Exception $e) {
$message = $e->getMessage();
if ($e instanceof RuntimeException && ($pos = strrpos($message, ':')) !== false) {

View File

@ -279,6 +279,7 @@ abstract class MonitoredObject implements Filterable
'author_name' => 'downtime_author_name',
'start' => 'downtime_start',
'scheduled_start' => 'downtime_scheduled_start',
'scheduled_end' => 'downtime_scheduled_end',
'end' => 'downtime_end',
'duration' => 'downtime_duration',
'is_flexible' => 'downtime_is_flexible',

View File

@ -335,10 +335,6 @@ table.action td.state, table.objectstate td.state {
text-align: center;
}
table.action td.timesince {
width: 3.5em;
}
/* State row behaviour */
@ -1117,10 +1113,6 @@ table.groupview {
font-size: 0.8em;
}
span.timesince {
font-size: 0.8em;
}
&.ok {
border-color: @colorOk;
}

View File

@ -112,38 +112,69 @@
/**
* Load a given module by name
*
* @param {string} name
*
* @return {boolean}
*/
loadModule: function (name) {
if (this.hasModule(name)) {
if (this.isLoadedModule(name)) {
this.logger.error('Cannot load module ' + name + ' twice');
return;
return false;
}
this.modules[name] = new Icinga.Module(this, name);
if (! this.hasModule(name)) {
this.logger.error('Cannot find module ' + name);
return false;
}
this.modules[name] = new Icinga.Module(
this,
name,
Icinga.availableModules[name]
);
return true;
},
/**
* Whether a module matching the given name exists
* Whether a module matching the given name exists or is loaded
*
* @param {string} name
*
* @return {boolean}
*/
hasModule: function (name) {
return 'undefined' !== typeof this.modules[name] ||
return this.isLoadedModule(name) ||
'undefined' !== typeof Icinga.availableModules[name];
},
/**
* Return whether the given module is loaded
*
* @param {string} name The name of the module
*
* @returns {Boolean}
*/
isLoadedModule: function (name) {
return 'undefined' !== typeof this.modules[name];
},
/**
* Get a module by name
*
* @param {string} name
*
* @return {object}
*/
module: function (name) {
if ('undefined' === typeof this.modules[name]) {
if ('undefined' !== typeof Icinga.availableModules[name]) {
this.modules[name] = new Icinga.Module(
this,
name,
Icinga.availableModules[name]
);
}
if (this.hasModule(name) && !this.isLoadedModule(name)) {
this.modules[name] = new Icinga.Module(
this,
name,
Icinga.availableModules[name]
);
}
return this.modules[name];

View File

@ -13,6 +13,7 @@
this.icinga = icinga;
this.searchValue = '';
this.initializeModules = true;
};
Icinga.Events.prototype = {
@ -30,39 +31,63 @@
},
// TODO: What's this?
applyHandlers: function (evt) {
var el = $(evt.target), self = evt.data.self;
applyHandlers: function (event) {
var $target = $(event.target);
var self = event.data.self;
var icinga = self.icinga;
$('.dashboard > div', el).each(function(idx, el) {
var url = $(el).data('icingaUrl');
if (typeof url === 'undefined') return;
icinga.loader.loadUrl(url, $(el)).autorefresh = true;
});
$('td.state span.timesince').attr('title', null);
var moduleName = el.data('icingaModule');
if (moduleName) {
if (icinga.hasModule(moduleName)) {
var module = icinga.module(moduleName);
// NOT YET, the applyOnloadDings: module.applyEventHandlers(mod);
if (self.initializeModules) {
var loaded = false;
var moduleName = $target.data('icingaModule');
if (moduleName) {
if (icinga.hasModule(moduleName) && !icinga.isLoadedModule(moduleName)) {
loaded |= icinga.loadModule(moduleName);
}
}
$('.icinga-module', $target).each(function(idx, mod) {
moduleName = $(mod).data('icingaModule');
if (icinga.hasModule(moduleName) && !icinga.isLoadedModule(moduleName)) {
loaded |= icinga.loadModule(moduleName);
}
});
if (loaded) {
// Modules may register their own handler for the 'renderend' event
// so we need to ensure that it is called the first time they are
// initialized
event.stopImmediatePropagation();
self.initializeModules = false;
var $container = $target.closest('.container');
if (! $container.length) {
// The page obviously got loaded for the first time,
// so we'll trigger the event for all containers
$container = $('.container');
}
$container.trigger('rendered');
// But since we're listening on this event by ourself, we'll have
// to abort our own processing as we'll process it twice otherwise
return false;
}
} else {
self.initializeModules = true;
}
$('.icinga-module', el).each(function(idx, mod) {
var $mod = $(mod);
moduleName = $mod.data('icingaModule');
if (icinga.hasModule(moduleName)) {
var module = icinga.module(moduleName);
// NOT YET, the applyOnloadDings: module.applyEventHandlers(mod);
$('.dashboard > div', $target).each(function(idx, el) {
var $element = $(el);
var $url = $element.data('icingaUrl');
if (typeof $url !== 'undefined') {
icinga.loader.loadUrl($url, $element).autorefresh = true;
}
});
var searchField = $('#menu input.search', el);
var $searchField = $('#menu input.search', $target);
// Remember initial search field value if any
if (searchField.length && searchField.val().length) {
self.searchValue = searchField.val();
if ($searchField.length && $searchField.val().length) {
self.searchValue = $searchField.val();
}
if (icinga.ui.isOneColLayout()) {
@ -76,13 +101,14 @@
* Global default event handlers
*/
applyGlobalDefaults: function () {
// Apply element-specific behavior whenever the layout is rendered
// Note: It is important that this is the first handler for this event!
$(document).on('rendered', { self: this }, this.applyHandlers);
$.each(self.icinga.behaviors, function (name, behavior) {
behavior.bind($(document));
});
// Apply element-specific behavior whenever the layout is rendered
$(document).on('rendered', { self: this }, this.applyHandlers);
// We catch resize events
$(window).on('resize', { self: this.icinga.ui }, this.icinga.ui.onWindowResize);

View File

@ -60,4 +60,19 @@ EOD;
'IniParser does not recognize escaped bracket in section'
);
}
public function testMultilineValues()
{
$config = <<<'EOD'
[section]
key1 = "with some
newline in the value"
EOD;
$doc = IniParser::parseIni($config);
$this->assertEquals(
2,
count(explode("\n", $doc->getSection('section')->getDirective('key1')->getValue())),
'IniParser does not recognize multi-line values'
);
}
}

View File

@ -257,7 +257,7 @@ EOD;
);
}
public function testWhetherLinebreaksAreRemoved()
public function testWhetherLinebreaksAreProcessed()
{
$target = $this->writeConfigToTemporaryFile('');
$writer = new IniWriter(
@ -277,7 +277,7 @@ inkey' => 'blarg'
$rendered = $writer->render();
$this->assertEquals(
count(explode("\n", $rendered)),
4,
5,
'generated config should not contain more than three line breaks'
);
}
@ -327,7 +327,6 @@ EOD;
[section]
key1 = "value with \"quotes\""
key2 = "value with \\"
key3 = "value with newline"
EOD;
$target = $this->writeConfigToTemporaryFile($config);
@ -336,8 +335,7 @@ EOD;
array(
'section' => array(
'key1' => 'value with "quotes"',
'key2' => 'value with \\',
'key3' => 'value with' . PHP_EOL . 'newline'
'key2' => 'value with \\'
)
)
),