Merge branch 'master' into feature/dashboard-component-disabled-property-6986
This commit is contained in:
commit
acbd2bd7c0
|
@ -2,10 +2,11 @@
|
|||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
use Zend_Controller_Action_Exception as ActionException;
|
||||
use Icinga\Web\Controller\ActionController;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Logger\Logger;
|
||||
use Icinga\Web\FileCache;
|
||||
use Zend_Controller_Action_Exception as ActionException;
|
||||
|
||||
/**
|
||||
* Delivery static content to clients
|
||||
|
@ -30,8 +31,25 @@ class StaticController extends ActionController
|
|||
|
||||
public function gravatarAction()
|
||||
{
|
||||
$cache = FileCache::instance();
|
||||
$filename = md5(strtolower(trim($this->_request->getParam('email'))));
|
||||
$cacheFile = 'gravatar-' . $filename;
|
||||
header('Cache-Control: public');
|
||||
header('Pragma: cache');
|
||||
if ($etag = $cache->etagMatchesCachedFile($cacheFile)) {
|
||||
header("HTTP/1.1 304 Not Modified");
|
||||
return;
|
||||
}
|
||||
|
||||
header('Content-Type: image/jpg');
|
||||
$img = file_get_contents('http://www.gravatar.com/avatar/' . md5(strtolower(trim($this->_request->getParam('email')))) . '?s=200&d=mm');
|
||||
if ($cache->has($cacheFile)) {
|
||||
header('ETag: "' . $cache->etagForCachedFile($cacheFile) . '"');
|
||||
$cache->send($cacheFile);
|
||||
return;
|
||||
}
|
||||
$img = file_get_contents('http://www.gravatar.com/avatar/' . $filename . '?s=200&d=mm');
|
||||
$cache->store($cacheFile, $img);
|
||||
header('ETag: "' . $cache->etagForCachedFile($cacheFile) . '"');
|
||||
echo $img;
|
||||
}
|
||||
|
||||
|
|
|
@ -452,9 +452,8 @@ abstract class ApplicationBootstrap
|
|||
*/
|
||||
protected function setupInternationalization()
|
||||
{
|
||||
$localeDir = $this->getApplicationDir('locale');
|
||||
if (file_exists($localeDir) && is_dir($localeDir)) {
|
||||
Translator::registerDomain(Translator::DEFAULT_DOMAIN, $localeDir);
|
||||
if ($this->hasLocales()) {
|
||||
Translator::registerDomain(Translator::DEFAULT_DOMAIN, $this->getLocaleDir());
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -469,4 +468,48 @@ abstract class ApplicationBootstrap
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Our locale directory
|
||||
*/
|
||||
public function getLocaleDir()
|
||||
{
|
||||
return $this->getApplicationDir('locale');
|
||||
}
|
||||
|
||||
/**
|
||||
* return bool Whether Icinga Web has translations
|
||||
*/
|
||||
public function hasLocales()
|
||||
{
|
||||
$localedir = $this->getLocaleDir();
|
||||
return file_exists($localedir) && is_dir($localedir);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available locales
|
||||
*
|
||||
* NOTE: Might be a candidate for a static function in Translator
|
||||
*
|
||||
* return array Locale list
|
||||
*/
|
||||
public function listLocales()
|
||||
{
|
||||
$locales = array();
|
||||
if (! $this->hasLocales()) {
|
||||
return $locales;
|
||||
}
|
||||
$localedir = $this->getLocaleDir();
|
||||
|
||||
$dh = opendir($localedir);
|
||||
while (false !== ($file = readdir($dh))) {
|
||||
$filename = $localedir . DIRECTORY_SEPARATOR . $file;
|
||||
if (preg_match('/^[a-z]{2}_[A-Z]{2}$/', $file) && is_dir($filename)) {
|
||||
$locales[] = $file;
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
sort($locales);
|
||||
return $locales;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -708,12 +708,44 @@ class Module
|
|||
*/
|
||||
protected function registerLocales()
|
||||
{
|
||||
if (file_exists($this->localedir) && is_dir($this->localedir)) {
|
||||
if ($this->hasLocales()) {
|
||||
Translator::registerDomain($this->name, $this->localedir);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* return bool Whether this module has translations
|
||||
*/
|
||||
public function hasLocales()
|
||||
{
|
||||
return file_exists($this->localedir) && is_dir($this->localedir);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available locales
|
||||
*
|
||||
* return array Locale list
|
||||
*/
|
||||
public function listLocales()
|
||||
{
|
||||
$locales = array();
|
||||
if (! $this->hasLocales()) {
|
||||
return $locales;
|
||||
}
|
||||
|
||||
$dh = opendir($this->localedir);
|
||||
while (false !== ($file = readdir($dh))) {
|
||||
$filename = $this->localedir . DIRECTORY_SEPARATOR . $file;
|
||||
if (preg_match('/^[a-z]{2}_[A-Z]{2}$/', $file) && is_dir($filename)) {
|
||||
$locales[] = $file;
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
sort($locales);
|
||||
return $locales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register web integration
|
||||
*
|
||||
|
|
|
@ -13,8 +13,6 @@ use Icinga\Logger\Logger;
|
|||
use Icinga\Web\Request;
|
||||
use Icinga\Web\Response;
|
||||
use Icinga\Web\View;
|
||||
use Icinga\Web\Session\Session as BaseSession;
|
||||
use Icinga\Web\Session;
|
||||
use Icinga\User;
|
||||
use Icinga\Util\Translator;
|
||||
use Icinga\Util\DateTimeFactory;
|
||||
|
@ -59,13 +57,6 @@ class Web extends ApplicationBootstrap
|
|||
*/
|
||||
private $request;
|
||||
|
||||
/**
|
||||
* Session object
|
||||
*
|
||||
* @var BaseSession
|
||||
*/
|
||||
private $session;
|
||||
|
||||
/**
|
||||
* User object
|
||||
*
|
||||
|
@ -92,7 +83,6 @@ class Web extends ApplicationBootstrap
|
|||
->setupErrorHandling()
|
||||
->loadConfig()
|
||||
->setupResourceFactory()
|
||||
->setupSession()
|
||||
->setupUser()
|
||||
->setupTimezone()
|
||||
->setupLogger()
|
||||
|
@ -172,7 +162,6 @@ class Web extends ApplicationBootstrap
|
|||
|
||||
$this->setupFrontController();
|
||||
$this->setupViewRenderer();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -192,17 +181,6 @@ class Web extends ApplicationBootstrap
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a session provider
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function setupSession()
|
||||
{
|
||||
$this->session = Session::create();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject dependencies into request
|
||||
*
|
||||
|
|
|
@ -132,12 +132,12 @@ abstract class Filter
|
|||
public static function expression($col, $op, $expression)
|
||||
{
|
||||
switch ($op) {
|
||||
case '=': return new FilterEqual($col, $op, $expression);
|
||||
case '=': return new FilterMatch($col, $op, $expression);
|
||||
case '<': return new FilterLessThan($col, $op, $expression);
|
||||
case '>': return new FilterGreaterThan($col, $op, $expression);
|
||||
case '>=': return new FilterEqualOrGreaterThan($col, $op, $expression);
|
||||
case '<=': return new FilterEqualOrLessThan($col, $op, $expression);
|
||||
case '!=': return new FilterNotEqual($col, $op, $expression);
|
||||
case '!=': return new FilterMatchNot($col, $op, $expression);
|
||||
default: throw new ProgrammingError(
|
||||
'There is no such filter sign: %s',
|
||||
$op
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Data\Filter;
|
||||
|
||||
class FilterMatch extends FilterExpression
|
||||
{
|
||||
public function matches($row)
|
||||
{
|
||||
$expression = (string) $this->expression;
|
||||
if (strpos($expression, '*') === false) {
|
||||
return (string) $row->{$this->column} === $expression;
|
||||
} else {
|
||||
$parts = array();
|
||||
foreach (preg_split('/\*/', $expression) as $part) {
|
||||
$parts[] = preg_quote($part);
|
||||
}
|
||||
return preg_match('/^' . implode('.*', $parts) . '$/', $row->{$this->column});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Data\Filter;
|
||||
|
||||
class FilterMatchNot extends FilterExpression
|
||||
{
|
||||
public function matches($row)
|
||||
{
|
||||
$expression = (string) $this->expression;
|
||||
if (strpos($expression, '*') === false) {
|
||||
return (string) $row->{$this->column} !== $expression;
|
||||
} else {
|
||||
$parts = array();
|
||||
foreach (preg_split('/\*/', $expression) as $part) {
|
||||
$parts[] = preg_quote($part);
|
||||
}
|
||||
return ! preg_match('/^' . implode('.*', $parts) . '$/', $row->{$this->column});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Data\Filter;
|
||||
|
||||
class FilterNotEqual extends FilterExpression
|
||||
{
|
||||
public function matches($row)
|
||||
{
|
||||
return (string) $row->{$this->column} !== (string) $this->expression;
|
||||
}
|
||||
}
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace Icinga\Protocol\File;
|
||||
|
||||
use RuntimeException;
|
||||
use Icinga\Exception\IcingaException;
|
||||
|
||||
/**
|
||||
* Exception thrown if a file reader specific error occurs
|
||||
*/
|
||||
class FileReaderException extends RuntimeException {}
|
||||
class FileReaderException extends IcingaException {}
|
||||
|
|
|
@ -40,7 +40,7 @@ class Reader extends FilterIterator
|
|||
{
|
||||
foreach (array('filename', 'fields') as $key) {
|
||||
if (! isset($config->{$key})) {
|
||||
throw new FileReaderException('The directive `' . $key . '\' is required');
|
||||
throw new FileReaderException('The directive `%s\' is required', $key);
|
||||
}
|
||||
}
|
||||
$this->fields = $config->fields;
|
||||
|
|
|
@ -348,7 +348,9 @@ class ActionController extends Zend_Controller_Action
|
|||
// Cast preference app.show_benchmark to bool because preferences loaded from a preferences storage are
|
||||
// always strings
|
||||
if ((bool) $user->getPreferences()->get('app.show_benchmark', false) === true) {
|
||||
$layout->benchmark = $this->renderBenchmark();
|
||||
if (!$this->_helper->viewRenderer->getNoRender()) {
|
||||
$layout->benchmark = $this->renderBenchmark();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Web;
|
||||
|
||||
class FileCache
|
||||
{
|
||||
/**
|
||||
* FileCache singleton instances
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $instances = array();
|
||||
|
||||
/**
|
||||
* Cache instance base directory
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $basedir;
|
||||
|
||||
/**
|
||||
* Instance name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Whether the cache is enabled
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $enabled = false;
|
||||
|
||||
/**
|
||||
* The protected constructor creates a new instance with the given name
|
||||
*
|
||||
* @param string $name Cache instance name
|
||||
*/
|
||||
protected function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
$tmpdir = sys_get_temp_dir();
|
||||
$basedir = $tmpdir . '/FileCache_' . $name;
|
||||
|
||||
if (file_exists($basedir) && is_writeable($basedir)) {
|
||||
|
||||
$this->basedir = $basedir;
|
||||
$this->enabled = true;
|
||||
|
||||
} elseif (file_exists($tmpdir) && is_writeable($tmpdir)) {
|
||||
|
||||
if (mkdir($basedir, '0750', true)) {
|
||||
$this->enabled = true;
|
||||
$this->basedir = $basedir;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the given content to the desired file name
|
||||
*
|
||||
* @param string $file new (relative) filename
|
||||
* @param string $content the content to be stored
|
||||
*
|
||||
* @return bool whether the file has been stored
|
||||
*/
|
||||
public function store($file, $content)
|
||||
{
|
||||
if (! $this->enabled) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return file_put_contents($this->filename($file), $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out whether a given file exists
|
||||
*
|
||||
* @param string $file the (relative) filename
|
||||
* @param int $newerThan optional timestamp to compare against
|
||||
*
|
||||
* @return bool whether such file exists
|
||||
*/
|
||||
public function has($file, $newerThan = null)
|
||||
{
|
||||
if (! $this->enabled) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$filename = $this->filename($file);
|
||||
|
||||
if (! file_exists($filename) || ! is_readable($filename)) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($newerThan === null) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$info = stat($file);
|
||||
|
||||
if ($info === false) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return (int) $newerThan < $info['mtime'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific file or false if no such file available
|
||||
*
|
||||
* @param string $file the disired file name
|
||||
*
|
||||
* @return string|bool Filename content or false
|
||||
*/
|
||||
public function get($file)
|
||||
{
|
||||
if ($this->has($file)) {
|
||||
return file_get_contents($this->filename($file));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a specific file to the browser (output)
|
||||
*
|
||||
* @param string $file the disired file name
|
||||
*
|
||||
* @return bool Whether the file has been sent
|
||||
*/
|
||||
public function send($file)
|
||||
{
|
||||
if ($this->has($file)) {
|
||||
readfile($this->filename($file));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get absolute filename for a given file
|
||||
*
|
||||
* @param string $file the disired file name
|
||||
*
|
||||
* @return string absolute filename
|
||||
*/
|
||||
protected function filename($file)
|
||||
{
|
||||
return $this->basedir . '/' . $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given ETag matches a cached file
|
||||
*
|
||||
* If no ETag is given we'll try to fetch the one from the current
|
||||
* HTTP request.
|
||||
*
|
||||
* @param string $file The cached file you want to check
|
||||
* @param string $match The ETag to match against
|
||||
*
|
||||
* @return string|bool ETag on match, otherwise false
|
||||
*/
|
||||
public function etagMatchesCachedFile($file, $match = null)
|
||||
{
|
||||
return self::etagMatchesFiles($this->filename($file), $match);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ETag for the given file
|
||||
*
|
||||
* @param string $file The desired cache file
|
||||
*
|
||||
* @return string your ETag
|
||||
*/
|
||||
public function etagForCachedFile($file)
|
||||
{
|
||||
return self::etagForFiles($this->filename($file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given ETag matchesspecific file(s) on disk
|
||||
*
|
||||
* If no ETag is given we'll try to fetch the one from the current
|
||||
* HTTP request.
|
||||
*
|
||||
* @param string|array $files file(s) to check
|
||||
* @param string $match ETag to match against
|
||||
*
|
||||
* @return string|bool ETag on match, otherwise false
|
||||
*/
|
||||
public static function etagMatchesFiles($files, $match = null)
|
||||
{
|
||||
if ($match === null) {
|
||||
$match = isset($_SERVER['HTTP_IF_NONE_MATCH'])
|
||||
? trim($_SERVER['HTTP_IF_NONE_MATCH'], '"')
|
||||
: false;
|
||||
}
|
||||
if (! $match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$etag = self::etagForFiles($files);
|
||||
return $match === $etag ? $etag : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ETag for the given files
|
||||
*
|
||||
* Custom algorithm creating an ETag based on filenames, mtimes
|
||||
* and file sizes. Supports single files or a list of files. This
|
||||
* way we are able to create ETags for virtual files depending on
|
||||
* multiple source files (e.g. compressed JS, CSS).
|
||||
*
|
||||
* @param string|array $files Single file or a list of such
|
||||
*
|
||||
* @return string The generated ETag
|
||||
*/
|
||||
public static function etagForFiles($files)
|
||||
{
|
||||
if (is_string($files)) {
|
||||
$files = array($files);
|
||||
}
|
||||
|
||||
$sizes = array();
|
||||
$mtimes = array();
|
||||
|
||||
foreach ($files as $file) {
|
||||
$file = realpath($file);
|
||||
if ($file !== false && $info = stat($file)) {
|
||||
$mtimes[] = $info['mtime'];
|
||||
$sizes[] = $info['size'];
|
||||
} else {
|
||||
$mtimes[] = time();
|
||||
$sizes[] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'%s-%s-%s',
|
||||
hash('crc32', implode('|', $files)),
|
||||
hash('crc32', implode('|', $sizes)),
|
||||
hash('crc32', implode('|', $mtimes))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory creating your cache instance
|
||||
*
|
||||
* @param string $name Instance name
|
||||
*
|
||||
* @return FileCache
|
||||
*/
|
||||
public static function instance($name = 'icingaweb')
|
||||
{
|
||||
if ($name !== 'icingaweb') {
|
||||
$name = 'icingaweb/modules/' . $name;
|
||||
}
|
||||
|
||||
if (!array_key_exists($name, self::$instances)) {
|
||||
self::$instances[$name] = new static($name);
|
||||
}
|
||||
|
||||
return self::$instances[$name];
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
namespace Icinga\Web;
|
||||
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Web\FileCache;
|
||||
use JShrink\Minifier;
|
||||
|
||||
class JavaScript
|
||||
|
@ -62,36 +63,58 @@ class JavaScript
|
|||
$js = $out = '';
|
||||
$min = $minified ? '.min' : '';
|
||||
|
||||
// TODO: Cache header
|
||||
header('Content-Type: application/javascript');
|
||||
$cacheFile = '/tmp/cache_icinga' . $min . '.js';
|
||||
if (file_exists($cacheFile)) {
|
||||
readfile($cacheFile);
|
||||
exit;
|
||||
}
|
||||
|
||||
// We do not minify vendor files
|
||||
// Prepare vendor file list
|
||||
$vendorFiles = array();
|
||||
foreach (self::$vendorFiles as $file) {
|
||||
$out .= file_get_contents($basedir . '/' . $file . $min . '.js');
|
||||
$vendorFiles[] = $basedir . '/' . $file . $min . '.js';
|
||||
}
|
||||
|
||||
// Prepare Icinga JS file list
|
||||
$jsFiles = array();
|
||||
foreach (self::$jsFiles as $file) {
|
||||
$js .= file_get_contents($basedir . '/' . $file);
|
||||
$jsFiles[] = $basedir . '/' . $file;
|
||||
}
|
||||
|
||||
foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $name => $module) {
|
||||
if ($module->hasJs()) {
|
||||
$js .= file_get_contents($module->getJsFilename());
|
||||
$jsFiles[] = $module->getJsFilename();
|
||||
}
|
||||
}
|
||||
$files = array_merge($vendorFiles, $jsFiles);
|
||||
|
||||
if ($etag = FileCache::etagMatchesFiles($files)) {
|
||||
header("HTTP/1.1 304 Not Modified");
|
||||
return;
|
||||
} else {
|
||||
$etag = FileCache::etagForFiles($files);
|
||||
}
|
||||
header('Cache-Control: public');
|
||||
header('ETag: "' . $etag . '"');
|
||||
header('Content-Type: application/javascript');
|
||||
|
||||
$cacheFile = 'icinga-' . $etag . $min . '.js';
|
||||
$cache = FileCache::instance();
|
||||
if ($cache->has($cacheFile)) {
|
||||
$cache->send($cacheFile);
|
||||
return;
|
||||
}
|
||||
|
||||
// We do not minify vendor files
|
||||
foreach ($vendorFiles as $file) {
|
||||
$out .= file_get_contents($file);
|
||||
}
|
||||
|
||||
foreach ($jsFiles as $file) {
|
||||
$js .= file_get_contents($file);
|
||||
}
|
||||
|
||||
if ($minified) {
|
||||
require_once 'IcingaVendor/JShrink/Minifier.php';
|
||||
$out .= Minifier::minify($js, array('flaggedComments' => false));
|
||||
} else {
|
||||
$out .= $js;
|
||||
}
|
||||
// Not yet, this is for tests only. Waiting for Icinga\Web\Cache
|
||||
// file_put_contents($cacheFile, $out);
|
||||
$cache->store($cacheFile, $out);
|
||||
echo $out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class Session
|
|||
public static function getSession()
|
||||
{
|
||||
if (self::$session === null) {
|
||||
throw new ProgrammingError('No session created yet');
|
||||
self::create();
|
||||
}
|
||||
|
||||
return self::$session;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
namespace Icinga\Web;
|
||||
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Web\FileCache;
|
||||
use Icinga\Web\LessCompiler;
|
||||
|
||||
class StyleSheet
|
||||
|
@ -44,28 +45,45 @@ class StyleSheet
|
|||
|
||||
public static function send($minified = false)
|
||||
{
|
||||
$app = Icinga::app();
|
||||
$basedir = $app->getBootstrapDirecory();
|
||||
foreach (self::$lessFiles as $file) {
|
||||
$lessFiles[] = $basedir . '/' . $file;
|
||||
}
|
||||
$files = $lessFiles;
|
||||
foreach ($app->getModuleManager()->getLoadedModules() as $name => $module) {
|
||||
if ($module->hasCss()) {
|
||||
$files[] = $module->getCssFilename();
|
||||
}
|
||||
}
|
||||
|
||||
if ($etag = FileCache::etagMatchesFiles($files)) {
|
||||
header("HTTP/1.1 304 Not Modified");
|
||||
return;
|
||||
} else {
|
||||
$etag = FileCache::etagForFiles($files);
|
||||
}
|
||||
header('Cache-Control: public');
|
||||
header('ETag: "' . $etag . '"');
|
||||
header('Content-Type: text/css');
|
||||
|
||||
$min = $minified ? '.min' : '';
|
||||
$cacheFile = '/tmp/cache_icinga' . $min . '.css';
|
||||
if (file_exists($cacheFile)) {
|
||||
readfile($cacheFile);
|
||||
exit;
|
||||
$cacheFile = 'icinga-' . $etag . $min . '.css';
|
||||
$cache = FileCache::instance();
|
||||
if ($cache->has($cacheFile)) {
|
||||
$cache->send($cacheFile);
|
||||
return;
|
||||
}
|
||||
|
||||
$less = new LessCompiler();
|
||||
$basedir = Icinga::app()->getBootstrapDirecory();
|
||||
foreach (self::$lessFiles as $file) {
|
||||
$less->addFile($basedir . '/' . $file);
|
||||
foreach ($lessFiles as $file) {
|
||||
$less->addFile($file);
|
||||
}
|
||||
$less->addLoadedModules();
|
||||
if ($minified) {
|
||||
$less->compress();
|
||||
}
|
||||
$out = $less->compile();
|
||||
// Not yet, this is for tests only. Waiting for Icinga\Web\Cache
|
||||
// file_put_contents($cacheFile, $out);
|
||||
$cache->store($cacheFile, $out);
|
||||
echo $out;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,9 +183,10 @@ class FilterEditor extends AbstractWidget
|
|||
{
|
||||
$name = 'sign_' . $filter->getId();
|
||||
$signs = array(
|
||||
'=' => '=',
|
||||
'>' => '>',
|
||||
'<' => '<',
|
||||
'=' => '=',
|
||||
'!=' => '!=',
|
||||
'>' => '>',
|
||||
'<' => '<',
|
||||
'>=' => '>=',
|
||||
'<=' => '<=',
|
||||
);
|
||||
|
|
|
@ -34,8 +34,21 @@ class Monitoring_ListController extends Controller
|
|||
|
||||
protected function hasBetterUrl()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$url = clone($this->url);
|
||||
|
||||
if ($this->getRequest()->isPost()) {
|
||||
|
||||
if ($request->getPost('sort')) {
|
||||
$url->setParam('sort', $request->getPost('sort'));
|
||||
if ($request->getPost('dir')) {
|
||||
$url->setParam('dir', $request->getPost('dir'));
|
||||
} else {
|
||||
$url->removeParam('dir');
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
$q = $this->getRequest()->getPost('q');
|
||||
} else {
|
||||
$q = $url->shift('q');
|
||||
|
@ -488,15 +501,8 @@ class Monitoring_ListController extends Controller
|
|||
$request = $this->getRequest();
|
||||
|
||||
$limit = $params->shift('limit');
|
||||
|
||||
$sort = null;
|
||||
$dir = null;
|
||||
if ($request->isPost()) {
|
||||
$sort = $request->getPost('sort', null);
|
||||
$dir = $request->getPost('dir', null);
|
||||
}
|
||||
$sort = $params->shift('sort', $sort);
|
||||
$dir = $params->shift('dir', $dir);
|
||||
$sort = $params->shift('sort');
|
||||
$dir = $params->shift('dir');
|
||||
$page = $params->shift('page');
|
||||
$format = $params->shift('format');
|
||||
$view = $params->shift('view');
|
||||
|
@ -533,7 +539,9 @@ class Monitoring_ListController extends Controller
|
|||
$query->applyFilter($filter);
|
||||
}
|
||||
$this->view->filter = $filter;
|
||||
$query->order($sort, $dir);
|
||||
if ($sort) {
|
||||
$query->order($sort, $dir);
|
||||
}
|
||||
$this->applyRestrictions($query);
|
||||
$this->handleFormatRequest($query);
|
||||
return $query;
|
||||
|
|
|
@ -89,9 +89,8 @@ class Monitoring_ShowController extends Controller
|
|||
$this->getTabs()->activate('history');
|
||||
//$this->view->object->populate();
|
||||
$this->view->object->fetchEventHistory();
|
||||
$this->view->history = $this->view->object->eventhistory->paginate($this->params->get('limit', 50));
|
||||
$this->handleFormatRequest($this->view->object->eventhistory);
|
||||
$this->view->history = $this->view->object->eventhistory
|
||||
->paginate($this->params->get('limit', 50));
|
||||
}
|
||||
|
||||
public function servicesAction()
|
||||
|
|
|
@ -1,284 +0,0 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
use Icinga\Module\Monitoring\Object\AbstractObject;
|
||||
|
||||
/**
|
||||
* Class Zend_View_Helper_MonitoringProperties
|
||||
*/
|
||||
class Zend_View_Helper_MonitoringProperties extends Zend_View_Helper_Abstract
|
||||
{
|
||||
/**
|
||||
* Value for check type active
|
||||
*/
|
||||
const CHECK_ACTIVE = 'ACTIVE';
|
||||
|
||||
/**
|
||||
* Value for check type passive
|
||||
*/
|
||||
const CHECK_PASSIVE = 'PASSIVE';
|
||||
|
||||
/**
|
||||
* Value for check type disabled
|
||||
*/
|
||||
const CHECK_DISABLED = 'DISABLED';
|
||||
|
||||
/**
|
||||
* Return value for not available
|
||||
*/
|
||||
const VALUE_NA = 'N/A';
|
||||
|
||||
/**
|
||||
* Return value for "YES"
|
||||
*/
|
||||
const VALUE_YES = 'YES';
|
||||
|
||||
/**
|
||||
* Return value for "NO"
|
||||
*/
|
||||
const VALUE_NO = 'NO';
|
||||
|
||||
/**
|
||||
* Label / value mapping for object keys
|
||||
*
|
||||
* Keys can be callables in this object
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $keys = array(
|
||||
'buildAttempt' => 'Current Attempt',
|
||||
'buildCheckType' => 'Check Type',
|
||||
'buildLatency' => 'Check Latency / Duration',
|
||||
'buildLastStateChange' => 'Last State Change',
|
||||
'buildLastNotification' => 'Last Notification',
|
||||
'buildFlapping' => 'Is This %s Flapping?',
|
||||
'buildScheduledDowntime' => 'In Scheduled Downtime?',
|
||||
'status_update_time' => 'Last Update'
|
||||
);
|
||||
|
||||
private static $notificationReasons = array(
|
||||
0 => 'NORMAL',
|
||||
1 => 'ACKNOWLEDGEMENT',
|
||||
2 => 'FLAPPING START',
|
||||
3 => 'FLAPPING STOP',
|
||||
4 => 'FLAPPING DISABLED',
|
||||
5 => 'DOWNTIME START',
|
||||
6 => 'DOWNTIME END',
|
||||
7 => 'DOWNTIME CANCELLED',
|
||||
8 => 'CUSTOM',
|
||||
9 => 'STALKING'
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the object type
|
||||
* @param stdClass $object
|
||||
* @return mixed
|
||||
*/
|
||||
private function getObjectType($object)
|
||||
{
|
||||
$keys = array_keys(get_object_vars($object));
|
||||
$keyParts = explode('_', array_shift($keys), 2);
|
||||
return array_shift($keyParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all object specific attribute prefixes
|
||||
* @param stdClass $object
|
||||
* @param $type
|
||||
* @return object
|
||||
*/
|
||||
private function dropObjectType($object, $type)
|
||||
{
|
||||
$vars = get_object_vars($object);
|
||||
$out = array();
|
||||
foreach ($vars as $name => $value) {
|
||||
$name = str_replace($type. '_', '', $name);
|
||||
$out[$name] = $value;
|
||||
}
|
||||
return (object)$out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string for attempt
|
||||
* @param stdClass $object
|
||||
* @return string
|
||||
*/
|
||||
private function buildAttempt($object)
|
||||
{
|
||||
return sprintf(
|
||||
'%s/%s (%s state)',
|
||||
$object->current_check_attempt,
|
||||
$object->max_check_attempts,
|
||||
($object->state_type === '1') ? 'HARD' : 'SOFT'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic fomatter for float values
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
private function floatFormatter($value)
|
||||
{
|
||||
return sprintf('%.4f', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string for check type
|
||||
* @param stdClass $object
|
||||
* @return string
|
||||
*/
|
||||
private function buildCheckType($object)
|
||||
{
|
||||
if ($object->passive_checks_enabled === '1' && $object->active_checks_enabled === '0') {
|
||||
return self::CHECK_PASSIVE;
|
||||
} elseif ($object->passive_checks_enabled === '0' && $object->active_checks_enabled === '0') {
|
||||
return self::CHECK_DISABLED;
|
||||
}
|
||||
|
||||
return self::CHECK_ACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string for latency
|
||||
* @param stdClass $object
|
||||
* @return string
|
||||
*/
|
||||
private function buildLatency($object)
|
||||
{
|
||||
$val = '';
|
||||
if ($this->buildCheckType($object) === self::CHECK_PASSIVE) {
|
||||
$val .= self::VALUE_NA;
|
||||
} else {
|
||||
$val .= $this->floatFormatter(
|
||||
(isset($object->check_latency)) ? $object->check_latency : 0
|
||||
);
|
||||
}
|
||||
|
||||
$val .= ' / '. $this->floatFormatter(
|
||||
isset($object->check_execution_time) ? $object->check_execution_time : 0
|
||||
). ' seconds';
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string for next check
|
||||
* @param stdClass $object
|
||||
* @return string
|
||||
*/
|
||||
private function buildNextCheck($object)
|
||||
{
|
||||
if ($this->buildCheckType($object) === self::CHECK_PASSIVE) {
|
||||
return self::VALUE_NA;
|
||||
} else {
|
||||
return $object->next_check;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date for last state change
|
||||
* @param stdClass $object
|
||||
* @return string
|
||||
*/
|
||||
private function buildLastStateChange($object)
|
||||
{
|
||||
return strftime('%Y-%m-%d %H:%M:%S', $object->last_state_change);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string for "last notification"
|
||||
* @param stdClass $object
|
||||
* @return string
|
||||
*/
|
||||
private function buildLastNotification($object)
|
||||
{
|
||||
$val = '';
|
||||
|
||||
if ($object->last_notification === '0000-00-00 00:00:00') {
|
||||
$val .= self::VALUE_NA;
|
||||
} else {
|
||||
$val .= $object->last_notification;
|
||||
}
|
||||
|
||||
$val .= sprintf(' (notification %d)', $object->current_notification_number);
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string for "is flapping"
|
||||
* @param stdClass $object
|
||||
* @return string
|
||||
*/
|
||||
private function buildFlapping($object)
|
||||
{
|
||||
$val = '';
|
||||
|
||||
if ($object->is_flapping === '0') {
|
||||
$val .= self::VALUE_NO;
|
||||
} else {
|
||||
$val .= self::VALUE_YES;
|
||||
}
|
||||
|
||||
$val .= sprintf(' (%.2f%% state change)', $object->percent_state_change);
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string for scheduled downtime
|
||||
* @param stdClass $object
|
||||
* @return string
|
||||
*/
|
||||
private function buildScheduledDowntime($object)
|
||||
{
|
||||
if ($object->in_downtime === '1') {
|
||||
return self::VALUE_YES;
|
||||
}
|
||||
|
||||
return self::VALUE_NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array which represent monitoring properties
|
||||
*
|
||||
* @param stdClass $object
|
||||
* @return array
|
||||
*/
|
||||
public function monitoringProperties($object)
|
||||
{
|
||||
$type = $this->getObjectType($object);
|
||||
//$object = $this->dropObjectType($object, $type);
|
||||
|
||||
$out = array();
|
||||
foreach (self::$keys as $property => $label) {
|
||||
$label = sprintf($label, ucfirst($type));
|
||||
if (is_callable(array(&$this, $property))) {
|
||||
$out[$label] = $this->$property($object);
|
||||
} elseif (isset($object->{$property})) {
|
||||
$out[$label] = $object->{$property};
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function getNotificationType($notification)
|
||||
{
|
||||
$reason = intval($notification->notification_reason);
|
||||
if (!isset(self::$notificationReasons[$reason])) {
|
||||
return 'N/A';
|
||||
}
|
||||
$type = self::$notificationReasons[$reason];
|
||||
if ($reason === 8) {
|
||||
if (intval($notification->notification_type) === 0) {
|
||||
$type .= '(UP)';
|
||||
} else {
|
||||
$type .= '(OK)';
|
||||
}
|
||||
}
|
||||
return $type;
|
||||
}
|
||||
}
|
|
@ -86,7 +86,7 @@ class Backend implements Selectable, Queryable, ConnectionInterface
|
|||
}
|
||||
} else {
|
||||
foreach ($config as $name => $backendConfig) {
|
||||
if ((bool) $config->get('disabled', false) === false) {
|
||||
if ((bool) $backendConfig->get('disabled', false) === false) {
|
||||
$backendName = $name;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class CommentdeletionhistoryQuery extends IdoQuery
|
|||
array()
|
||||
)->join(
|
||||
array('h' => $this->prefix . 'commenthistory'),
|
||||
'o.' . $this->object_id . ' = h.' . $this->object_id . " AND o.is_active = 1 AND h.deletion_time > '1970-01-01 00:00:00' AND h.entry_type <> 2",
|
||||
'o.' . $this->object_id . ' = h.' . $this->object_id . " AND o.is_active = 1 AND h.deletion_time > '1970-01-02 00:00:00' AND h.entry_type <> 2",
|
||||
array()
|
||||
);
|
||||
$this->joinedVirtualTables = array('commenthistory' => true);
|
||||
|
|
|
@ -47,7 +47,7 @@ class DowntimeendhistoryQuery extends IdoQuery
|
|||
array('h' => $this->prefix . 'downtimehistory'),
|
||||
'o.' . $this->object_id . ' = h.' . $this->object_id . ' AND o.is_active = 1',
|
||||
array()
|
||||
)->where('h.actual_end_time > ?', '1970-01-01 00:00:00');
|
||||
)->where('h.actual_end_time > ?', '1970-01-02 00:00:00');
|
||||
$this->joinedVirtualTables = array('downtimehistory' => true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class DowntimestarthistoryQuery extends IdoQuery
|
|||
array('h' => $this->prefix . 'downtimehistory'),
|
||||
'o.' . $this->object_id . ' = h.' . $this->object_id . ' AND o.is_active = 1',
|
||||
array()
|
||||
)->where('h.actual_start_time > ?', '1970-01-01 00:00:00');
|
||||
)->where('h.actual_start_time > ?', '1970-01-02 00:00:00');
|
||||
$this->joinedVirtualTables = array('downtimehistory' => true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class StatusQuery extends IdoQuery
|
|||
'host_next_check' => 'CASE hs.should_be_scheduled WHEN 1 THEN UNIX_TIMESTAMP(hs.next_check) ELSE NULL END',
|
||||
'host_check_execution_time' => 'hs.execution_time',
|
||||
'host_check_latency' => 'hs.latency',
|
||||
'host_problem' => 'CASE WHEN hs.current_state = 0 THEN 0 ELSE 1 END',
|
||||
'host_problem' => 'CASE WHEN COALESCE(hs.current_state, 0) = 0 THEN 0 ELSE 1 END',
|
||||
|
||||
'host_notifications_enabled' => 'hs.notifications_enabled',
|
||||
|
||||
|
@ -278,20 +278,41 @@ class StatusQuery extends IdoQuery
|
|||
ELSE 0
|
||||
END'
|
||||
),
|
||||
|
||||
'serviceproblemsummary' => array(
|
||||
'host_unhandled_services' => 'sps.unhandled_services_count'
|
||||
),
|
||||
'lasthostcomment' => array(
|
||||
'host_last_comment' => 'hlc.last_comment_data',
|
||||
'host_last_downtime' => 'hlc.last_downtime_data',
|
||||
'host_last_flapping' => 'hlc.last_flapping_data',
|
||||
'host_last_ack' => 'hlc.last_ack_data',
|
||||
|
||||
'lasthostcommentgeneric' => array(
|
||||
'host_last_comment' => 'hlcg.last_comment_data'
|
||||
),
|
||||
'lastservicecomment' => array(
|
||||
'service_last_comment' => 'slc.last_comment_data',
|
||||
'service_last_downtime' => 'slc.last_downtime_data',
|
||||
'service_last_flapping' => 'slc.last_flapping_data',
|
||||
'service_last_ack' => 'slc.last_ack_data',
|
||||
|
||||
'lasthostcommentdowntime' => array(
|
||||
'host_last_downtime' => 'hlcd.last_downtime_data'
|
||||
),
|
||||
|
||||
'lasthostcommentflapping' => array(
|
||||
'host_last_flapping' => 'hlcf.last_flapping_data'
|
||||
),
|
||||
|
||||
'lasthostcommentack' => array(
|
||||
'host_last_ack' => 'hlca.last_ack_data'
|
||||
),
|
||||
|
||||
'lastservicecommentgeneric' => array(
|
||||
'service_last_comment' => 'slcg.last_comment_data'
|
||||
),
|
||||
|
||||
'lastservicecommentdowntime' => array(
|
||||
'service_last_downtime' => 'slcd.last_downtime_data'
|
||||
),
|
||||
|
||||
'lastservicecommentflapping' => array(
|
||||
'service_last_flapping' => 'slcf.last_flapping_data'
|
||||
),
|
||||
|
||||
'lastservicecommentack' => array(
|
||||
'service_last_ack' => 'slca.last_ack_data'
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -483,42 +504,117 @@ class StatusQuery extends IdoQuery
|
|||
);
|
||||
}
|
||||
|
||||
protected function getLastCommentSubQuery()
|
||||
/**
|
||||
* Create a subquery to join comments into status query
|
||||
* @param int $entryType
|
||||
* @param string $fieldName
|
||||
* @return Zend_Db_Expr
|
||||
*/
|
||||
protected function getLastCommentSubQuery($entryType, $fieldName)
|
||||
{
|
||||
$sub = '(SELECT'
|
||||
. ' lc.object_id,'
|
||||
. " CASE WHEN lc.entry_type = 1 THEN '[' || c.author_name || '] ' || c.comment_data ELSE NULL END AS last_comment_data,"
|
||||
. " CASE WHEN lc.entry_type = 2 THEN '[' || c.author_name || '] ' || c.comment_data ELSE NULL END AS last_downtime_data,"
|
||||
. " CASE WHEN lc.entry_type = 3 THEN '[' || c.author_name || '] ' || c.comment_data ELSE NULL END AS last_flapping_data,"
|
||||
. " CASE WHEN lc.entry_type = 4 THEN '[' || c.author_name || '] ' || c.comment_data ELSE NULL END AS last_ack_data"
|
||||
. ' FROM icinga_comments c'
|
||||
. ' JOIN (SELECT'
|
||||
. ' MAX(comment_id) as comment_id,'
|
||||
. ' object_id,'
|
||||
. ' entry_type'
|
||||
. ' FROM icinga_comments'
|
||||
. ' WHERE entry_type = 1 OR entry_type = 4'
|
||||
. ' GROUP BY object_id, entry_type'
|
||||
. ') lc ON lc.comment_id = c.comment_id'
|
||||
. ' GROUP BY lc.object_id, lc.entry_type, c.author_name, c.comment_data)';
|
||||
. ' c.object_id,'
|
||||
. " '[' || c.author_name || '] ' || c.comment_data AS $fieldName"
|
||||
. ' FROM icinga_comments c JOIN ('
|
||||
. ' SELECT MAX(comment_id) AS comment_id, object_id FROM icinga_comments'
|
||||
. ' WHERE entry_type = ' . $entryType . ' GROUP BY object_id'
|
||||
. ' ) lc ON c.comment_id = lc.comment_id)';
|
||||
|
||||
return new Zend_Db_Expr($sub);
|
||||
}
|
||||
|
||||
protected function joinLasthostcomment()
|
||||
/**
|
||||
* Join last host comment
|
||||
*/
|
||||
protected function joinLasthostcommentgeneric()
|
||||
{
|
||||
$this->select->joinLeft(
|
||||
array('hlc' => $this->getLastCommentSubQuery()),
|
||||
'hlc.object_id = hs.host_object_id',
|
||||
array('hlcg' => $this->getLastCommentSubQuery(1, 'last_comment_data')),
|
||||
'hlcg.object_id = hs.host_object_id',
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Terribly slow. As I have no idea of how to fix this we should remove it.
|
||||
protected function joinLastservicecomment()
|
||||
/**
|
||||
* Join last host downtime comment
|
||||
*/
|
||||
protected function joinLasthostcommentdowntime()
|
||||
{
|
||||
$this->select->joinLeft(
|
||||
array('slc' => $this->getLastCommentSubQuery()),
|
||||
'slc.object_id = ss.service_object_id',
|
||||
array('hlcd' => $this->getLastCommentSubQuery(2, 'last_downtime_data')),
|
||||
'hlcg.object_id = hs.host_object_id',
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join last host flapping comment
|
||||
*/
|
||||
protected function joinLastHostcommentflapping()
|
||||
{
|
||||
$this->select->joinLeft(
|
||||
array('hlcf' => $this->getLastCommentSubQuery(3, 'last_flapping_data')),
|
||||
'hlcg.object_id = hs.host_object_id',
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join last host acknowledgement comment
|
||||
*/
|
||||
protected function joinLasthostcommentack()
|
||||
{
|
||||
$this->select->joinLeft(
|
||||
array('hlca' => $this->getLastCommentSubQuery(4, 'last_ack_data')),
|
||||
'hlca.object_id = hs.host_object_id',
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join last service comment
|
||||
*/
|
||||
protected function joinLastservicecommentgeneric()
|
||||
{
|
||||
$this->select->joinLeft(
|
||||
array('slcg' => $this->getLastCommentSubQuery(1, 'last_comment_data')),
|
||||
'slcg.object_id = ss.service_object_id',
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join last service downtime comment
|
||||
*/
|
||||
protected function joinLastservicecommentdowntime()
|
||||
{
|
||||
$this->select->joinLeft(
|
||||
array('slcd' => $this->getLastCommentSubQuery(2, 'last_downtime_data')),
|
||||
'slcd.object_id = ss.service_object_id',
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join last service flapping comment
|
||||
*/
|
||||
protected function joinLastservicecommentflapping()
|
||||
{
|
||||
$this->select->joinLeft(
|
||||
array('slcf' => $this->getLastCommentSubQuery(3, 'last_flapping_data')),
|
||||
'slcf.object_id = ss.service_object_id',
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join last service acknowledgement comment
|
||||
*/
|
||||
protected function joinLastservicecommentack()
|
||||
{
|
||||
$this->select->joinLeft(
|
||||
array('slca' => $this->getLastCommentSubQuery(4, 'last_ack_data')),
|
||||
'slca.object_id = ss.service_object_id',
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -33,23 +33,27 @@ class StatusSummaryQuery extends IdoQuery
|
|||
'hosts_flapping' => 'SUM(CASE WHEN object_type = \'host\' AND is_flapping = 1 THEN 1 ELSE 0 END)'
|
||||
),
|
||||
'servicestatussummary' => array(
|
||||
'services_total' => 'SUM(CASE WHEN object_type = \'service\' THEN 1 ELSE 0 END)',
|
||||
'services_problem' => 'SUM(CASE WHEN object_type = \'service\' AND state > 0 THEN 1 ELSE 0 END)',
|
||||
'services_problem_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state > 0 AND (acknowledged + in_downtime + host_problem) > 0 THEN 1 ELSE 0 END)',
|
||||
'services_problem_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state > 0 AND (acknowledged + in_downtime + host_problem) = 0 THEN 1 ELSE 0 END)',
|
||||
'services_ok' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)',
|
||||
'services_ok_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
|
||||
'services_pending' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)',
|
||||
'services_pending_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
|
||||
'services_warning' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)',
|
||||
'services_warning_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) > 0 THEN 1 ELSE 0 END)',
|
||||
'services_warning_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) = 0 THEN 1 ELSE 0 END)',
|
||||
'services_warning_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND (acknowledged + in_downtime + host_problem) > 0 THEN 1 ELSE 0 END)',
|
||||
'services_warning_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND (acknowledged + in_downtime + host_problem) = 0 THEN 1 ELSE 0 END)',
|
||||
'services_warning_passive' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
|
||||
'services_warning_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
|
||||
'services_critical' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)',
|
||||
'services_critical_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) > 0 THEN 1 ELSE 0 END)',
|
||||
'services_critical_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) = 0 THEN 1 ELSE 0 END)',
|
||||
'services_critical_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND (acknowledged + in_downtime + host_problem) > 0 THEN 1 ELSE 0 END)',
|
||||
'services_critical_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND (acknowledged + in_downtime + host_problem) = 0 THEN 1 ELSE 0 END)',
|
||||
'services_critical_passive' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
|
||||
'services_critical_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
|
||||
'services_unknown' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)',
|
||||
'services_unknown_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) > 0 THEN 1 ELSE 0 END)',
|
||||
'services_unknown_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) = 0 THEN 1 ELSE 0 END)',
|
||||
'services_unknown_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND (acknowledged + in_downtime + host_problem) > 0 THEN 1 ELSE 0 END)',
|
||||
'services_unknown_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND (acknowledged + in_downtime + host_problem) = 0 THEN 1 ELSE 0 END)',
|
||||
'services_unknown_passive' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
|
||||
'services_unknown_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
|
||||
'services_active' => 'SUM(CASE WHEN object_type = \'service\' AND is_active_checked = 1 THEN 1 ELSE 0 END)',
|
||||
|
@ -131,6 +135,7 @@ class StatusSummaryQuery extends IdoQuery
|
|||
'acknowledged' => 'hs.problem_has_been_acknowledged',
|
||||
'in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
|
||||
'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END',
|
||||
'host_problem' => 'CASE WHEN COALESCE(hs.current_state, 0) = 0 THEN 0 ELSE 1 END',
|
||||
'is_passive_checked' => 'CASE WHEN hs.active_checks_enabled = 0 AND hs.passive_checks_enabled = 1 THEN 1 ELSE 0 END',
|
||||
'is_active_checked' => 'hs.active_checks_enabled',
|
||||
'is_processing_events' => 'hs.event_handler_enabled',
|
||||
|
@ -144,6 +149,7 @@ class StatusSummaryQuery extends IdoQuery
|
|||
'acknowledged' => 'ss.problem_has_been_acknowledged',
|
||||
'in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
|
||||
'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END',
|
||||
'host_problem' => 'CASE WHEN COALESCE(hs.current_state, 0) = 0 THEN 0 ELSE 1 END',
|
||||
'is_passive_checked' => 'CASE WHEN ss.active_checks_enabled = 0 AND ss.passive_checks_enabled = 1 THEN 1 ELSE 0 END',
|
||||
'is_active_checked' => 'ss.active_checks_enabled',
|
||||
'is_processing_events' => 'ss.event_handler_enabled',
|
||||
|
|
|
@ -31,6 +31,8 @@ abstract class DataView implements Browsable, Filterable, Sortable
|
|||
|
||||
protected $connection;
|
||||
|
||||
protected $isSorted = false;
|
||||
|
||||
/**
|
||||
* Create a new view
|
||||
*
|
||||
|
@ -99,6 +101,7 @@ public function dump()
|
|||
protected function applyUrlFilter($request = null)
|
||||
{
|
||||
$url = Url::fromRequest();
|
||||
|
||||
$limit = $url->shift('limit');
|
||||
$sort = $url->shift('sort');
|
||||
$dir = $url->shift('dir');
|
||||
|
@ -132,20 +135,19 @@ public function dump()
|
|||
}
|
||||
}
|
||||
|
||||
$order = isset($params['order']) ? $params['order'] : null;
|
||||
if ($order !== null) {
|
||||
if (strtolower($order) === 'desc') {
|
||||
$order = self::SORT_DESC;
|
||||
} else {
|
||||
$order = self::SORT_ASC;
|
||||
if (isset($params['sort'])) {
|
||||
|
||||
$order = isset($params['order']) ? $params['order'] : null;
|
||||
if ($order !== null) {
|
||||
if (strtolower($order) === 'desc') {
|
||||
$order = self::SORT_DESC;
|
||||
} else {
|
||||
$order = self::SORT_ASC;
|
||||
}
|
||||
}
|
||||
|
||||
$view->sort($params['sort'], $order);
|
||||
}
|
||||
|
||||
$view->sort(
|
||||
isset($params['sort']) ? $params['sort'] : null,
|
||||
$order
|
||||
);
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
|
@ -226,6 +228,7 @@ public function dump()
|
|||
foreach ($sortColumns['columns'] as $column) {
|
||||
$this->query->order($column, $order);
|
||||
}
|
||||
$this->isSorted = true;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
@ -285,6 +288,7 @@ public function dump()
|
|||
*/
|
||||
public function getQuery()
|
||||
{
|
||||
if (! $this->isSorted) { $this->sort(); }
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Test\Modules\Monitoring\Application\Views\Helpers;
|
||||
|
||||
use Zend_View_Helper_MonitoringProperties;
|
||||
use Icinga\Test\BaseTestCase;
|
||||
|
||||
require_once realpath(BaseTestCase::$moduleDir . '/monitoring/application/views/helpers/MonitoringProperties.php');
|
||||
|
||||
class HostStruct4Properties
|
||||
{
|
||||
public $host_name = 'localhost';
|
||||
public $host_address = '127.0.0.1';
|
||||
public $host_state = '1';
|
||||
public $host_handled = '1';
|
||||
public $in_downtime = '1';
|
||||
public $acknowledged = '1';
|
||||
public $check_command = 'check-host-alive';
|
||||
public $last_state_change = '1372937083';
|
||||
public $host_alias = 'localhost';
|
||||
public $output = 'DDD';
|
||||
public $long_output = '';
|
||||
public $perfdata = '';
|
||||
public $current_check_attempt = '1';
|
||||
public $max_check_attempts = '10';
|
||||
public $attempt = '1/10';
|
||||
public $last_check = '2013-07-04 11:24:42';
|
||||
public $next_check = '2013-07-04 11:29:43';
|
||||
public $heck_type = '1';
|
||||
public $last_hard_state_change = '2013-07-04 11:24:43';
|
||||
public $last_hard_state = '0';
|
||||
public $last_time_up = '2013-07-04 11:20:23';
|
||||
public $last_time_down = '2013-07-04 11:24:43';
|
||||
public $last_time_unreachable = '0000-00-00 00:00:00';
|
||||
public $state_type = '1';
|
||||
public $last_notification = '0000-00-00 00:00:00';
|
||||
public $next_notification = '0000-00-00 00:00:00';
|
||||
public $no_more_notifications = '0';
|
||||
public $host_notifications_enabled = '1';
|
||||
public $host_problem_has_been_acknowledged = '1';
|
||||
public $host_acknowledgement_type = '2';
|
||||
public $current_notification_number = '0';
|
||||
public $passive_checks_enabled = '1';
|
||||
public $active_checks_enabled = '0';
|
||||
public $event_handler_enabled = '0';
|
||||
public $flap_detection_enabled = '1';
|
||||
public $is_flapping = '0';
|
||||
public $percent_state_change = '12.36842';
|
||||
public $check_latency = '0.12041';
|
||||
public $check_execution_time = '0';
|
||||
public $scheduled_downtime_depth = '1';
|
||||
public $host_failure_prediction_enabled = '1';
|
||||
public $host_process_performance_data = '1';
|
||||
public $host_obsessing = '1';
|
||||
public $host_modified_host_attributes = '14';
|
||||
public $host_event_handler = '';
|
||||
public $host_normal_check_interval = '5';
|
||||
public $host_retry_check_interval = '1';
|
||||
public $host_check_timeperiod_object_id = '27';
|
||||
public $host_status_update_time = '2013-07-08 10:10:10';
|
||||
}
|
||||
|
||||
/**
|
||||
* @TODO(el): This test is subject to bug #4679
|
||||
*/
|
||||
class MonitoringPropertiesTest extends BaseTestCase
|
||||
{
|
||||
public function testOutput1()
|
||||
{
|
||||
$host = new HostStruct4Properties();
|
||||
$host->current_check_attempt = '5';
|
||||
|
||||
$propertyHelper = new Zend_View_Helper_MonitoringProperties();
|
||||
$items = $propertyHelper->monitoringProperties($host);
|
||||
|
||||
$this->assertEquals('5/10 (HARD state)', $items['Current Attempt']);
|
||||
}
|
||||
|
||||
public function testOutput2()
|
||||
{
|
||||
$host = new HostStruct4Properties();
|
||||
$host->current_check_attempt = '5';
|
||||
$host->active_checks_enabled = '1';
|
||||
$host->passive_checks_enabled = '0';
|
||||
$host->is_flapping = '1';
|
||||
|
||||
$propertyHelper = new Zend_View_Helper_MonitoringProperties();
|
||||
$items = $propertyHelper->monitoringProperties($host);
|
||||
|
||||
$test = array(
|
||||
'Current Attempt' => "5/10 (HARD state)",
|
||||
'Check Type' => "ACTIVE",
|
||||
'Check Latency / Duration' => "0.1204 / 0.0000 seconds",
|
||||
'Last State Change' => "2013-07-04 11:24:43",
|
||||
'Last Notification' => "N/A (notification 0)",
|
||||
'Is This Host Flapping?' => "YES (12.37% state change)",
|
||||
'In Scheduled Downtime?' => "YES"
|
||||
);
|
||||
|
||||
$this->assertEquals($test, $items);
|
||||
}
|
||||
}
|
|
@ -329,8 +329,7 @@
|
|||
this.icinga.ui.reloadCss();
|
||||
}
|
||||
|
||||
var redirect = req.getResponseHeader('X-Icinga-Redirect');
|
||||
if (this.processRedirectHeader(req)) return;
|
||||
if (req.getResponseHeader('X-Icinga-Redirect')) return;
|
||||
|
||||
// div helps getting an XML tree
|
||||
var $resp = $('<div>' + req.responseText + '</div>');
|
||||
|
@ -567,6 +566,7 @@
|
|||
delete this.requests[req.$target.attr('id')];
|
||||
this.icinga.ui.fadeNotificationsAway();
|
||||
|
||||
this.processRedirectHeader(req);
|
||||
|
||||
if (typeof req.loadNext !== 'undefined') {
|
||||
if ($('#col2').length) {
|
||||
|
@ -665,7 +665,11 @@
|
|||
var self = this;
|
||||
var containerId = $container.attr('id');
|
||||
if (typeof containerId !== 'undefined') {
|
||||
scrollPos = $container.scrollTop();
|
||||
if (autorefresh) {
|
||||
scrollPos = $container.scrollTop();
|
||||
} else {
|
||||
scrollPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var origFocus = document.activeElement;
|
||||
|
|
|
@ -26,10 +26,10 @@ class DbBackendFormTest extends BaseTestCase
|
|||
*/
|
||||
public function testValidBackendIsValid()
|
||||
{
|
||||
$this->setUpUserBackendMock()
|
||||
$this->setUpResourceFactoryMock();
|
||||
Mockery::mock('overload:Icinga\Authentication\Backend\DbUserBackend')
|
||||
->shouldReceive('count')
|
||||
->andReturn(2);
|
||||
$this->setUpResourceFactoryMock();
|
||||
|
||||
$form = new DbBackendForm();
|
||||
$form->setBackendName('test');
|
||||
|
@ -49,10 +49,10 @@ class DbBackendFormTest extends BaseTestCase
|
|||
*/
|
||||
public function testInvalidBackendIsNotValid()
|
||||
{
|
||||
$this->setUpUserBackendMock()
|
||||
$this->setUpResourceFactoryMock();
|
||||
Mockery::mock('overload:Icinga\Authentication\Backend\DbUserBackend')
|
||||
->shouldReceive('count')
|
||||
->andReturn(0);
|
||||
$this->setUpResourceFactoryMock();
|
||||
|
||||
$form = new DbBackendForm();
|
||||
$form->setBackendName('test');
|
||||
|
@ -66,18 +66,10 @@ class DbBackendFormTest extends BaseTestCase
|
|||
);
|
||||
}
|
||||
|
||||
protected function setUpUserBackendMock()
|
||||
{
|
||||
return Mockery::mock('overload:Icinga\Authentication\Backend\DbUserBackend');
|
||||
}
|
||||
|
||||
protected function setUpResourceFactoryMock()
|
||||
{
|
||||
Mockery::mock('alias:Icinga\Data\ResourceFactory')
|
||||
->shouldReceive('getResourceConfig')
|
||||
->andReturn(new \Zend_Config(array()))
|
||||
->shouldReceive('createResource')
|
||||
->with(Mockery::type('\Zend_Config'))
|
||||
->shouldReceive('create')
|
||||
->andReturn(Mockery::mock('Icinga\Data\Db\DbConnection'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ class TranslatorTest extends BaseTestCase
|
|||
public function testWhetherGetAvailableLocaleCodesReturnsAllAvailableLocaleCodes()
|
||||
{
|
||||
$this->assertEquals(
|
||||
array('de_DE', 'fr_FR'),
|
||||
array(Translator::DEFAULT_LOCALE, 'de_DE', 'fr_FR'),
|
||||
Translator::getAvailableLocaleCodes(),
|
||||
'Translator::getAvailableLocaleCodes does not return all available locale codes'
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue