Merge branch 'master' into feature/rename-monitoring-instances-to-command-transports-and-allow-to-link-them-with-a-monitoring-instance-9651

Conflicts:
	modules/monitoring/application/controllers/ConfigController.php
This commit is contained in:
Johannes Meyer 2015-08-31 13:05:10 +02:00
commit 1c51735629
99 changed files with 1791 additions and 1544 deletions

View File

@ -1,10 +1,10 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
# namespace Icinga\Application\Controllers;
namespace Icinga\Controllers;
use Icinga\Web\Controller\ActionController;
use Icinga\Application\Version;
use Icinga\Web\Controller\ActionController;
class AboutController extends ActionController
{

View File

@ -1,12 +1,11 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
# namespace Icinga\Application\Controllers;
namespace Icinga\Controllers;
use Icinga\Application\Icinga;
use Icinga\Forms\Authentication\LoginForm;
use Icinga\Web\Controller;
use Icinga\Web\Cookie;
use Icinga\Web\Url;
/**
@ -39,8 +38,11 @@ class AuthenticationController extends Controller
}
if (! $requiresSetup) {
if (! $this->getRequest()->hasCookieSupport()) {
echo $this->translate("Cookies must be enabled to run this application.\n");
$this->getResponse()->setHttpResponseCode(403)->sendHeaders();
$this
->getResponse()
->setBody("Cookies must be enabled to run this application.\n")
->setHttpResponseCode(403)
->sendResponse();
exit();
}
$form->handleRequest();

View File

@ -1,21 +1,24 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Exception;
use InvalidArgumentException;
use Icinga\Application\Config;
use Icinga\Application\Icinga;
use Icinga\Application\Modules\Module;
use Icinga\Data\ResourceFactory;
use Icinga\Exception\ConfigurationError;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\Config\UserBackendConfigForm;
use Icinga\Forms\Config\UserBackendReorderForm;
use Icinga\Forms\Config\GeneralConfigForm;
use Icinga\Forms\Config\ResourceConfigForm;
use Icinga\Forms\Config\UserBackendConfigForm;
use Icinga\Forms\Config\UserBackendReorderForm;
use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Security\SecurityException;
use Icinga\Web\Controller;
use Icinga\Web\Notification;
use Icinga\Web\Url;
use Icinga\Web\Widget;
/**

View File

@ -1,12 +1,16 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Exception;
use Zend_Controller_Action_Exception;
use Icinga\Exception\ProgrammingError;
use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Forms\Dashboard\DashletForm;
use Icinga\Web\Controller\ActionController;
use Icinga\Web\Form;
use Icinga\Web\Notification;
use Icinga\Web\Controller\ActionController;
use Icinga\Web\Url;
use Icinga\Web\Widget\Dashboard;
use Icinga\Web\Widget\Tabextension\DashboardSettings;

View File

@ -1,6 +1,9 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Zend_Controller_Plugin_ErrorHandler;
use Icinga\Application\Icinga;
use Icinga\Application\Logger;
use Icinga\Exception\Http\HttpMethodNotAllowedException;

View File

@ -1,92 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Web\Controller\ActionController;
use Icinga\Filter\Filter;
use Icinga\Application\Logger;
/**
* Application wide interface for filtering
*/
class FilterController extends ActionController
{
/**
* The current filter registry
*
* @var Filter
*/
private $registry;
private $moduleRegistry;
/**
* Entry point for filtering, uses the filter_domain and filter_module request parameter
* to determine which filter registry should be used
*/
public function indexAction()
{
$this->registry = new Filter();
$query = $this->getRequest()->getParam('query', '');
$target = $this->getRequest()->getParam('filter_domain', '');
if ($this->getRequest()->getHeader('accept') == 'application/json') {
$this->getResponse()->setHeader('Content-Type', 'application/json');
$this->setupQueries(
$target,
$this->getParam('filter_module', '')
);
$this->_helper->json($this->parse($query, $target));
} else {
$this->setupQueries(
$target,
$this->getParam('filter_module')
);
$urlTarget = $this->parse($query, $target);
$this->redirect($urlTarget['urlParam']);
}
}
/**
* Set up the query handler for the given domain and module
*
* @param string $domain The domain to use
* @param string $module The module to use
*/
private function setupQueries($domain, $module = 'default')
{
$class = '\\Icinga\\Module\\' . ucfirst($module) . '\\Filter\\Registry';
$factory = strtolower($domain) . 'Filter';
$this->moduleRegistry = $class;
$this->registry->addDomain($class::$factory());
}
/**
* Parse the given query text and returns the json as expected by the semantic search box
*
* @param String $text The query to parse
* @return array The result structure to be returned in json format
*/
private function parse($text, $target)
{
try {
$queryTree = $this->registry->createQueryTreeForFilter($text);
$registry = $this->moduleRegistry;
return array(
'state' => 'success',
'proposals' => $this->registry->getProposalsForQuery($text),
'urlParam' => $registry::getUrlForTarget($target, $queryTree),
'valid' => count($this->registry->getIgnoredQueryParts()) === 0
);
} catch (\Exception $exc) {
Logger::error($exc);
$this->getResponse()->setHttpResponseCode(500);
return array(
'state' => 'error',
'message' => 'Search service is currently not available'
);
}
}
}

View File

@ -1,10 +1,13 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Exception;
use Icinga\Application\Logger;
use Icinga\Data\DataArray\ArrayDatasource;
use Icinga\Data\Reducible;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Reducible;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\Config\UserGroup\AddMemberForm;
use Icinga\Forms\Config\UserGroup\UserGroupForm;

View File

@ -1,10 +1,9 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
# namespace Icinga\Application\Controllers;
namespace Icinga\Controllers;
use Icinga\Web\Controller\ActionController;
use Icinga\Application\Benchmark;
use Icinga\Web\Url;
/**
@ -18,6 +17,7 @@ class IndexController extends ActionController
public function preDispatch()
{
if ($this->getRequest()->getActionName() !== 'welcome') {
// @TODO(el): Avoid landing page redirects: https://dev.icinga.org/issues/9656
$this->redirectNow(Url::fromRequest()->setPath('dashboard'));
}
}

View File

@ -1,10 +1,12 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Web\MenuRenderer;
namespace Icinga\Controllers;
use Icinga\Web\Controller\ActionController;
use Icinga\Web\Hook;
use Icinga\Web\Menu;
use Icinga\Web\MenuRenderer;
use Icinga\Web\Url;
/**

View File

@ -1,6 +1,8 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Icinga\Application\Config;
use Icinga\Application\Logger;
use Icinga\Data\ConfigObject;
@ -11,8 +13,6 @@ use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Widget\Tabextension\OutputFormat;
/**
* Class ListController
*
* Application wide controller for various listing actions
*/
class ListController extends Controller

View File

@ -1,16 +1,20 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Icinga\Application\Config;
use Icinga\Data\ConfigObject;
use Icinga\Forms\PreferenceForm;
use Icinga\User\Preferences\PreferencesStore;
use Icinga\Web\Controller\BasePreferenceController;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tab;
use Icinga\Application\Config;
use Icinga\Forms\PreferenceForm;
use Icinga\Data\ConfigObject;
use Icinga\User\Preferences\PreferencesStore;
/**
* Application wide preference controller for user preferences
*
* @TODO(el): Rename to PreferencesController: https://dev.icinga.org/issues/10014
*/
class PreferenceController extends BasePreferenceController
{

View File

@ -1,12 +1,21 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Icinga\Application\Config;
use Icinga\Exception\AlreadyExistsException;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Forms\Security\RoleForm;
use Icinga\Web\Controller\AuthBackendController;
use Icinga\Web\Notification;
/**
* Manage user permissions and restrictions based on roles
*
* @TODO(el): Rename to RolesController: https://dev.icinga.org/issues/10015
*/
class RoleController extends AuthBackendController
{
/**
@ -31,7 +40,7 @@ class RoleController extends AuthBackendController
$values = $role->getValues();
try {
$role->add($name, $values);
} catch (InvalidArgumentException $e) {
} catch (AlreadyExistsException $e) {
$role->addError($e->getMessage());
return false;
}
@ -54,19 +63,11 @@ class RoleController extends AuthBackendController
/**
* Update a role
*
* @throws Zend_Controller_Action_Exception If the required parameter 'role' is missing or the role does not exist
*/
public function editAction()
{
$this->assertPermission('config/authentication/roles/edit');
$name = $this->_request->getParam('role');
if (empty($name)) {
throw new Zend_Controller_Action_Exception(
sprintf($this->translate('Required parameter \'%s\' missing'), 'role'),
400
);
}
$name = $this->params->getRequired('role');
$role = new RoleForm();
$role->setTitle(sprintf($this->translate('Update Role %s'), $name));
$role->setSubmitLabel($this->translate('Update Role'));
@ -74,11 +75,8 @@ class RoleController extends AuthBackendController
$role
->setIniConfig(Config::app('roles', true))
->load($name);
} catch (InvalidArgumentException $e) {
throw new Zend_Controller_Action_Exception(
$e->getMessage(),
400
);
} catch (NotFoundError $e) {
$this->httpNotFound($e->getMessage());
}
$role
->setOnSuccess(function (RoleForm $role) use ($name) {
@ -87,7 +85,7 @@ class RoleController extends AuthBackendController
$values = $role->getValues();
try {
$role->update($name, $values, $oldName);
} catch (InvalidArgumentException $e) {
} catch (NotFoundError $e) {
$role->addError($e->getMessage());
return false;
}
@ -105,35 +103,24 @@ class RoleController extends AuthBackendController
/**
* Remove a role
*
* @throws Zend_Controller_Action_Exception If the required parameter 'role' is missing or the role does not exist
*/
public function removeAction()
{
$this->assertPermission('config/authentication/roles/remove');
$name = $this->_request->getParam('role');
if (empty($name)) {
throw new Zend_Controller_Action_Exception(
sprintf($this->translate('Required parameter \'%s\' missing'), 'role'),
400
);
}
$name = $this->params->getRequired('role');
$role = new RoleForm();
try {
$role
->setIniConfig(Config::app('roles', true))
->load($name);
} catch (InvalidArgumentException $e) {
throw new Zend_Controller_Action_Exception(
$e->getMessage(),
400
);
} catch (NotFoundError $e) {
$this->httpNotFound($e->getMessage());
}
$confirmation = new ConfirmRemovalForm(array(
'onSuccess' => function (ConfirmRemovalForm $confirmation) use ($name, $role) {
try {
$role->remove($name);
} catch (InvalidArgumentException $e) {
} catch (NotFoundError $e) {
Notification::error($e->getMessage());
return false;
}
@ -162,15 +149,15 @@ class RoleController extends AuthBackendController
$tabs->add(
'role/list',
array(
'title' => $this->translate(
'baseTarget' => '_main',
'label' => $this->translate('Roles'),
'title' => $this->translate(
'Configure roles to permit or restrict users and groups accessing Icinga Web 2'
),
'label' => $this->translate('Roles'),
'url' => 'role/list',
'baseTarget' => '_main'
'url' => 'role/list'
)
);
return $tabs;
}
}

View File

@ -1,6 +1,8 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Icinga\Web\Controller\ActionController;
use Icinga\Web\Widget;
use Icinga\Web\Widget\SearchDashboard;

View File

@ -1,16 +1,18 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Web\Controller\ActionController;
namespace Icinga\Controllers;
use Icinga\Web\Controller;
use Icinga\Application\Icinga;
use Icinga\Application\Logger;
use Icinga\Web\FileCache;
use Zend_Controller_Action_Exception as ActionException;
use Icinga\Web\LessCompiler;
/**
* Delivery static content to clients
*/
class StaticController extends ActionController
class StaticController extends Controller
{
/**
* Static routes don't require authentication
@ -57,17 +59,15 @@ class StaticController extends ActionController
*/
public function imgAction()
{
// TODO(el): I think this action only retrieves images from modules
$module = $this->_getParam('module_name');
$file = $this->_getParam('file');
$basedir = Icinga::app()->getModuleManager()->getModule($module)->getBaseDir();
$filePath = realpath($basedir . '/public/img/' . $file);
if (! $filePath || strpos($filePath, $basedir) !== 0) {
throw new ActionException(sprintf(
'%s does not exist',
$filePath
), 404);
if ($filePath === false) {
$this->httpNotFound('%s does not exist', $filePath);
}
if (preg_match('/\.([a-z]+)$/i', $file, $m)) {
$extension = $m[1];
@ -80,10 +80,7 @@ class StaticController extends ActionController
header(sprintf('ETag: "%x-%x-%x"', $s['ino'], $s['size'], (float) str_pad($s['mtime'], 16, '0')));
header('Cache-Control: public, max-age=3600');
header('Pragma: cache');
header('Last-Modified: ' . gmdate(
'D, d M Y H:i:s',
$s['mtime']
) . ' GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $s['mtime']) . ' GMT');
readfile($filePath);
}
@ -100,7 +97,7 @@ class StaticController extends ActionController
$basedir = Icinga::app()->getApplicationDir('../public/js/icinga/components/');
$filePath = $basedir . $file;
} else {
if (!Icinga::app()->getModuleManager()->hasEnabled($module)) {
if (! Icinga::app()->getModuleManager()->hasEnabled($module)) {
Logger::error(
'Non-existing frontend component "' . $module . '/' . $file
. '" was requested. The module "' . $module . '" does not exist or is not active.'
@ -112,7 +109,7 @@ class StaticController extends ActionController
$filePath = $basedir . '/public/js/' . $file;
}
if (!file_exists($filePath)) {
if (! file_exists($filePath)) {
Logger::error(
'Non-existing frontend component "' . $module . '/' . $file
. '" was requested, which would resolve to the the path: ' . $filePath
@ -122,41 +119,41 @@ class StaticController extends ActionController
}
$response = $this->getResponse();
$response->setHeader('Content-Type', 'text/javascript');
$this->setCacheHeader(3600);
$this->setCacheHeader();
$response->setHeader(
'Last-Modified',
gmdate(
'D, d M Y H:i:s',
filemtime($filePath)
) . ' GMT'
gmdate('D, d M Y H:i:s', filemtime($filePath)) . ' GMT'
);
readfile($filePath);
}
/**
* Set cache header for this response
* Set cache header for the response
*
* @param integer $maxAge The maximum age to set
* @param int $maxAge The maximum age to set
*/
private function setCacheHeader($maxAge)
private function setCacheHeader($maxAge = 3600)
{
$this->_response->setHeader('Cache-Control', 'max-age=3600', true);
$this->_response->setHeader('Pragma', 'cache', true);
$this->_response->setHeader(
'Expires',
gmdate(
'D, d M Y H:i:s',
time()+3600
) . ' GMT',
true
);
$maxAge = (int) $maxAge;
$this
->getResponse()
->setHeader('Cache-Control', sprintf('max-age=%d', $maxAge), true)
->setHeader('Pragma', 'cache', true)
->setHeader(
'Expires',
gmdate('D, d M Y H:i:s', time() + $maxAge) . ' GMT',
true
);
}
/**
* Send application's and modules' CSS
*/
public function stylesheetAction()
{
$lessCompiler = new \Icinga\Web\LessCompiler();
$lessCompiler = new LessCompiler();
$moduleManager = Icinga::app()->getModuleManager();
$publicDir = realpath(dirname($_SERVER['SCRIPT_FILENAME']));
@ -172,7 +169,7 @@ class StaticController extends ActionController
}
}
$this->_response->setHeader('Content-Type', 'text/css');
$this->getResponse()->setHeader('Content-Type', 'text/css');
$this->setCacheHeader(3600);
$lessCompiler->printStack();

View File

@ -1,12 +1,15 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Exception;
use Icinga\Application\Logger;
use Icinga\Data\DataArray\ArrayDatasource;
use Icinga\Exception\ConfigurationError;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\Config\User\CreateMembershipForm;
use Icinga\Forms\Config\User\UserForm;
use Icinga\Data\DataArray\ArrayDatasource;
use Icinga\User;
use Icinga\Web\Controller\AuthBackendController;
use Icinga\Web\Form;

View File

@ -1,13 +1,15 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Controllers;
use Exception;
use Icinga\Application\Config;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Forms\Config\UserGroup\UserGroupBackendForm;
use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Web\Controller;
use Icinga\Web\Notification;
use Icinga\Web\Url;
/**
* Controller to configure user group backends

View File

@ -350,8 +350,21 @@ class ResourceConfigForm extends ConfigForm
'decorators' => array('ViewHelper')
)
);
$this->setAttrib('data-progress-element', 'resource-progress');
$this->addElement(
'note',
'resource-progress',
array(
'decorators' => array(
'ViewHelper',
array('Spinner', array('id' => 'resource-progress'))
)
)
);
$this->addDisplayGroup(
array('btn_submit', 'resource_validation'),
array('btn_submit', 'resource_validation', 'resource-progress'),
'submit_validation',
array(
'decorators' => array(

View File

@ -3,10 +3,11 @@
namespace Icinga\Forms\Security;
use InvalidArgumentException;
use LogicException;
use Zend_Form_Element;
use Icinga\Application\Icinga;
use Icinga\Exception\AlreadyExistsException;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\ConfigForm;
use Icinga\Util\String;
@ -168,6 +169,7 @@ class RoleForm extends ConfigForm
* @return $this
*
* @throws LogicException If the config is not set
* @throws NotFoundError If the given role does not exist
* @see ConfigForm::setConfig() For setting the config.
*/
public function load($name)
@ -176,10 +178,10 @@ class RoleForm extends ConfigForm
throw new LogicException(sprintf('Can\'t load role \'%s\'. Config is not set', $name));
}
if (! $this->config->hasSection($name)) {
throw new InvalidArgumentException(sprintf(
throw new NotFoundError(
$this->translate('Can\'t load role \'%s\'. Role does not exist'),
$name
));
);
}
$role = $this->config->getSection($name)->toArray();
$role['permissions'] = ! empty($role['permissions'])
@ -202,14 +204,14 @@ class RoleForm extends ConfigForm
/**
* Add a role
*
* @param string $name The name of the role
* @param string $name The name of the role
* @param array $values
*
* @return $this
*
* @throws LogicException If the config is not set
* @throws InvalidArgumentException If the role to add already exists
* @see ConfigForm::setConfig() For setting the config.
* @throws LogicException If the config is not set
* @throws AlreadyExistsException If the role to add already exists
* @see ConfigForm::setConfig() For setting the config.
*/
public function add($name, array $values)
{
@ -217,10 +219,10 @@ class RoleForm extends ConfigForm
throw new LogicException(sprintf('Can\'t add role \'%s\'. Config is not set', $name));
}
if ($this->config->hasSection($name)) {
throw new InvalidArgumentException(sprintf(
throw new AlreadyExistsException(
$this->translate('Can\'t add role \'%s\'. Role already exists'),
$name
));
);
}
$this->config->setSection($name, $values);
return $this;
@ -229,13 +231,13 @@ class RoleForm extends ConfigForm
/**
* Remove a role
*
* @param string $name The name of the role
* @param string $name The name of the role
*
* @return $this
*
* @throws LogicException If the config is not set
* @throws InvalidArgumentException If the role does not exist
* @see ConfigForm::setConfig() For setting the config.
* @throws LogicException If the config is not set
* @throws NotFoundError If the role does not exist
* @see ConfigForm::setConfig() For setting the config.
*/
public function remove($name)
{
@ -243,10 +245,10 @@ class RoleForm extends ConfigForm
throw new LogicException(sprintf('Can\'t remove role \'%s\'. Config is not set', $name));
}
if (! $this->config->hasSection($name)) {
throw new InvalidArgumentException(sprintf(
throw new NotFoundError(
$this->translate('Can\'t remove role \'%s\'. Role does not exist'),
$name
));
);
}
$this->config->removeSection($name);
return $this;
@ -255,15 +257,15 @@ class RoleForm extends ConfigForm
/**
* Update a role
*
* @param string $name The possibly new name of the role
* @param string $name The possibly new name of the role
* @param array $values
* @param string $oldName The name of the role to update
* @param string $oldName The name of the role to update
*
* @return $this
*
* @throws LogicException If the config is not set
* @throws InvalidArgumentException If the role to update does not exist
* @see ConfigForm::setConfig() For setting the config.
* @throws LogicException If the config is not set
* @throws NotFoundError If the role to update does not exist
* @see ConfigForm::setConfig() For setting the config.
*/
public function update($name, array $values, $oldName)
{
@ -276,10 +278,10 @@ class RoleForm extends ConfigForm
$this->add($name, $values);
} else {
if (! $this->config->hasSection($name)) {
throw new InvalidArgumentException(sprintf(
throw new NotFoundError(
$this->translate('Can\'t update role \'%s\'. Role does not exist'),
$name
));
);
}
$this->config->setSection($name, $values);
}

View File

@ -78,9 +78,9 @@ abstract class ApplicationBootstrap
protected $configDir;
/**
* Icinga auto loader
* Icinga class loader
*
* @var Loader
* @var ClassLoader
*/
private $loader;
@ -183,7 +183,7 @@ abstract class ApplicationBootstrap
/**
* Getter for class loader
*
* @return Loader
* @return ClassLoader
*/
public function getLoader()
{
@ -339,15 +339,15 @@ abstract class ApplicationBootstrap
}
/**
* Setup Icinga auto loader
* Setup Icinga class loader
*
* @return $this
*/
public function setupAutoloader()
{
require $this->libDir . '/Icinga/Application/Loader.php';
require $this->libDir . '/Icinga/Application/ClassLoader.php';
$this->loader = new Loader();
$this->loader = new ClassLoader();
$this->loader->registerNamespace('Icinga', $this->libDir. '/Icinga');
$this->loader->register();

View File

@ -0,0 +1,113 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Application;
/**
* PSR-4 class loader
*/
class ClassLoader
{
/**
* Namespace separator
*/
const NAMESPACE_SEPARATOR = '\\';
/**
* Namespaces
*
* @var array
*/
private $namespaces = array();
/**
* Register a base directory for a namespace prefix
*
* @param string $namespace
* @param string $directory
*
* @return $this
*/
public function registerNamespace($namespace, $directory)
{
$this->namespaces[$namespace] = $directory;
return $this;
}
/**
* Test whether a namespace exists
*
* @param string $namespace
*
* @return bool
*/
public function hasNamespace($namespace)
{
return array_key_exists($namespace, $this->namespaces);
}
/**
* Get the source file of the given class or interface
*
* @param string $class Name of the class or interface
*
* @return string|null
*/
public function getSourceFile($class)
{
foreach ($this->namespaces as $namespace => $dir) {
if ($class === strstr($class, $namespace)) {
$classPath = str_replace(
self::NAMESPACE_SEPARATOR,
DIRECTORY_SEPARATOR,
substr($class, strlen($namespace))
) . '.php';
if (file_exists($file = $dir . $classPath)) {
return $file;
}
}
}
return null;
}
/**
* Load the given class or interface
*
* @param string $class Name of the class or interface
*
* @return bool Whether the class or interface has been loaded
*/
public function loadClass($class)
{
if ($file = $this->getSourceFile($class)) {
require $file;
return true;
}
return false;
}
/**
* Register {@link loadClass()} as an autoloader
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
}
/**
* Unregister {@link loadClass()} as an autoloader
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Unregister this as an autoloader
*/
public function __destruct()
{
$this->unregister();
}
}

View File

@ -1,138 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Application;
use Icinga\Exception\ProgrammingError;
class Loader
{
/**
* Namespace separator
*/
const NAMESPACE_SEPARATOR = '\\';
/**
* List of namespaces
*
* @var array
*/
private $namespaces = array();
/**
* Detach spl autoload method from stack
*/
public function __destruct()
{
$this->unRegister();
}
/**
* Register new namespace for directory
*
* @param string $namespace
* @param string $directory
*
* @throws ProgrammingError
*/
public function registerNamespace($namespace, $directory)
{
if (!is_dir($directory)) {
throw new ProgrammingError(
'Directory "%s" for namespace "%s" does not exist',
$directory,
$namespace
);
}
$this->namespaces[$namespace] = $directory;
}
/**
* Test if a namespace exists
*
* @param string $namespace
*
* @return bool
*/
public function hasNamespace($namespace)
{
return array_key_exists($namespace, $this->namespaces);
}
/**
* Class loader
*
* Ignores all but classes in registered namespaces.
*
* @param string $class
*
* @return boolean
*/
public function loadClass($class)
{
$namespace = $this->getNamespaceForClass($class);
if ($namespace) {
$file = $this->namespaces[$namespace] . preg_replace('/^' . preg_quote($namespace) . '/', '', $class);
$file = str_replace(self::NAMESPACE_SEPARATOR, '/', $file) . '.php';
if (@file_exists($file)) {
require_once $file;
return true;
}
}
return false;
}
/**
* Test if we have a registered namespaces for this class
*
* Return is the longest match in the array found
*
* @param string $className
*
* @return bool|string
*/
private function getNamespaceForClass($className)
{
$testNamespace = '';
$testLength = 0;
foreach (array_keys($this->namespaces) as $namespace) {
$stub = preg_replace(
'/^' . preg_quote($namespace) . '(' . preg_quote(self::NAMESPACE_SEPARATOR) . '|$)/', '', $className
);
$length = strlen($className) - strlen($stub);
if ($length > $testLength) {
$testLength = $length;
$testNamespace = $namespace;
}
}
if ($testLength > 0) {
return $testNamespace;
}
return false;
}
/**
* Effectively registers the autoloader the PHP/SPL way
*/
public function register()
{
// Think about to add class pathes to php include path
// this could be faster (tg)
spl_autoload_register(array(&$this, 'loadClass'));
}
/**
* Detach autoloader from spl registration
*/
public function unRegister()
{
spl_autoload_unregister(array(&$this, 'loadClass'));
}
}

View File

@ -4,23 +4,24 @@
namespace Icinga\Application\Modules;
use Exception;
use Zend_Controller_Router_Route;
use Zend_Controller_Router_Route_Abstract;
use Zend_Controller_Router_Route as Route;
use Zend_Controller_Router_Route_Regex as RegexRoute;
use Zend_Controller_Router_Route_Regex;
use Icinga\Application\ApplicationBootstrap;
use Icinga\Application\Config;
use Icinga\Application\Icinga;
use Icinga\Application\Logger;
use Icinga\Data\ConfigObject;
use Icinga\Exception\IcingaException;
use Icinga\Exception\ProgrammingError;
use Icinga\Module\Setup\SetupWizard;
use Icinga\Util\File;
use Icinga\Util\Translator;
use Icinga\Web\Controller\Dispatcher;
use Icinga\Web\Hook;
use Icinga\Web\Menu;
use Icinga\Web\Widget;
use Icinga\Web\Widget\Dashboard\Pane;
use Icinga\Module\Setup\SetupWizard;
use Icinga\Util\File;
use Icinga\Exception\ProgrammingError;
use Icinga\Exception\IcingaException;
/**
* Module handling
@ -188,7 +189,7 @@ class Module
/**
* A set of menu elements
*
* @var array
* @var Menu[]
*/
protected $menuItems = array();
@ -770,6 +771,7 @@ class Module
{
$this->launchConfigScript();
$tabs = Widget::create('tabs');
/** @var \Icinga\Web\Widget\Tabs $tabs */
$tabs->add('info', array(
'url' => 'config/module',
'urlParams' => array('name' => $this->getName()),
@ -934,7 +936,7 @@ class Module
}
/**
* Register module namespaces on the autoloader
* Register module namespaces on our class loader
*
* @return $this
*/
@ -944,16 +946,17 @@ class Module
return $this;
}
$loader = $this->app->getLoader();
$moduleName = ucfirst($this->getName());
$moduleLibraryDir = $this->getLibDir(). '/'. $moduleName;
if (is_dir($moduleLibraryDir)) {
$this->app->getLoader()->registerNamespace('Icinga\\Module\\' . $moduleName, $moduleLibraryDir);
$loader->registerNamespace('Icinga\\Module\\' . $moduleName, $moduleLibraryDir);
}
$moduleFormDir = $this->getFormDir();
if (is_dir($moduleFormDir)) {
$this->app->getLoader()->registerNamespace('Icinga\\Module\\' . $moduleName. '\\Forms', $moduleFormDir);
$loader->registerNamespace('Icinga\\Module\\' . $moduleName. '\\Forms', $moduleFormDir);
}
$this->registeredAutoloader = true;
@ -1015,19 +1018,23 @@ class Module
*/
protected function registerWebIntegration()
{
if (!$this->app->isWeb()) {
if (! $this->app->isWeb()) {
return $this;
}
if (file_exists($this->controllerdir) && is_dir($this->controllerdir)) {
$moduleControllerDir = $this->getControllerDir();
if (is_dir($moduleControllerDir)) {
$this->app->getfrontController()->addControllerDirectory(
$this->controllerdir,
$this->name
$moduleControllerDir,
$this->getName()
);
$this->app->getLoader()->registerNamespace(
'Icinga\\Module\\' . ucfirst($this->getName()) . '\\' . Dispatcher::CONTROLLER_NAMESPACE,
$moduleControllerDir
);
}
$this->registerLocales()
->registerRoutes();
$this
->registerLocales()
->registerRoutes();
return $this;
}
@ -1039,27 +1046,30 @@ class Module
protected function registerRoutes()
{
$router = $this->app->getFrontController()->getRouter();
/** @var \Zend_Controller_Router_Rewrite $router */
foreach ($this->routes as $name => $route) {
$router->addRoute($name, $route);
}
$router->addRoute(
$this->name . '_jsprovider',
new Route(
new Zend_Controller_Router_Route(
'js/' . $this->name . '/:file',
array(
'action' => 'javascript',
'controller' => 'static',
'action' =>'javascript',
'module' => 'default',
'module_name' => $this->name
)
)
);
$router->addRoute(
$this->name . '_img',
new RegexRoute(
new Zend_Controller_Router_Route_Regex(
'img/' . $this->name . '/(.+)',
array(
'controller' => 'static',
'action' => 'img',
'controller' => 'static',
'module' => 'default',
'module_name' => $this->name
),
array(

View File

@ -3,12 +3,15 @@
namespace Icinga\Application;
/**
* Retrieve the version of Icinga Web 2
*/
class Version
{
/**
* Get the version of this instance of Icinga Web 2
*
* @return array|bool array on success, false otherwise
* @return array|false array on success, false otherwise
*/
public static function get()
{

View File

@ -15,6 +15,7 @@ use Icinga\Authentication\Auth;
use Icinga\User;
use Icinga\Util\TimezoneDetect;
use Icinga\Util\Translator;
use Icinga\Web\Controller\Dispatcher;
use Icinga\Web\Notification;
use Icinga\Web\Session;
use Icinga\Web\Session\Session as BaseSession;
@ -88,7 +89,7 @@ class Web extends EmbeddedWeb
->setupLogger()
->setupInternationalization()
->setupZendMvc()
->setupFormNamespace()
->setupNamespaces()
->setupModuleManager()
->setupUserBackendFactory()
->loadSetupModuleIfNecessary()
@ -210,6 +211,7 @@ class Web extends EmbeddedWeb
private function setupFrontController()
{
$this->frontController = Zend_Controller_Front::getInstance();
$this->frontController->setDispatcher(new Dispatcher());
$this->frontController->setRequest($this->getRequest());
$this->frontController->setControllerDirectory($this->getApplicationDir('/controllers'));
@ -306,16 +308,22 @@ class Web extends EmbeddedWeb
}
/**
* Setup an autoloader namespace for Icinga\Forms
* Setup class loader namespaces for Icinga\Controllers and Icinga\Forms
*
* @return $this
*/
private function setupFormNamespace()
private function setupNamespaces()
{
$this->getLoader()->registerNamespace(
'Icinga\\Forms',
$this->getApplicationDir('forms')
);
$this
->getLoader()
->registerNamespace(
'Icinga\\' . Dispatcher::CONTROLLER_NAMESPACE,
$this->getApplicationDir('controllers')
)
->registerNamespace(
'Icinga\\Forms',
$this->getApplicationDir('forms')
);
return $this;
}
}

View File

@ -3,11 +3,9 @@
namespace Icinga\Application;
use Icinga\Application\EmbeddedWeb;
use Icinga\Application\Web;
use Icinga\Web\StyleSheet;
use Icinga\Web\JavaScript;
use Icinga\Chart\Inline\PieChart;
use Icinga\Web\JavaScript;
use Icinga\Web\StyleSheet;
error_reporting(E_ALL | E_STRICT);

View File

@ -4,12 +4,11 @@
namespace Icinga\Data;
use Icinga\Data\Filter\Filter;
use Icinga\Data\SimpleQuery;
use Icinga\Application\Icinga;
use Icinga\Web\Paginator\Adapter\QueryAdapter;
use Zend_Paginator;
class PivotTable
class PivotTable implements Sortable
{
/**
* The query to fetch as pivot table
@ -19,53 +18,74 @@ class PivotTable
protected $baseQuery;
/**
* The query to fetch the x axis labels
*
* @var SimpleQuery
*/
protected $xAxisQuery;
/**
* The query to fetch the y axis labels
*
* @var SimpleQuery
*/
protected $yAxisQuery;
/**
* The column that contains the labels for the x axis
* X-axis pivot column
*
* @var string
*/
protected $xAxisColumn;
/**
* The column that contains the labels for the y axis
* Y-axis pivot column
*
* @var string
*/
protected $yAxisColumn;
/**
* The filter being applied on the query for the x axis
* Column for sorting the result set
*
* @var array
*/
protected $order = array();
/**
* The filter being applied on the query for the x-axis
*
* @var Filter
*/
protected $xAxisFilter;
/**
* The filter being applied on the query for the y axis
* The filter being applied on the query for the y-axis
*
* @var Filter
*/
protected $yAxisFilter;
/**
* The query to fetch the leading x-axis rows and their headers
*
* @var SimpleQuery
*/
protected $xAxisQuery;
/**
* The query to fetch the leading y-axis rows and their headers
*
* @var SimpleQuery
*/
protected $yAxisQuery;
/**
* X-axis header column
*
* @var string|null
*/
protected $xAxisHeader;
/**
* Y-axis header column
*
* @var string|null
*/
protected $yAxisHeader;
/**
* Create a new pivot table
*
* @param SimpleQuery $query The query to fetch as pivot table
* @param string $xAxisColumn The column that contains the labels for the x axis
* @param string $yAxisColumn The column that contains the labels for the y axis
* @param SimpleQuery $query The query to fetch as pivot table
* @param string $xAxisColumn X-axis pivot column
* @param string $yAxisColumn Y-axis pivot column
*/
public function __construct(SimpleQuery $query, $xAxisColumn, $yAxisColumn)
{
@ -75,7 +95,32 @@ class PivotTable
}
/**
* Set the filter to apply on the query for the x axis
* {@inheritdoc}
*/
public function getOrder()
{
return $this->order;
}
/**
* {@inheritdoc}
*/
public function hasOrder()
{
return ! empty($this->order);
}
/**
* {@inheritdoc}
*/
public function order($field, $direction = null)
{
$this->order[$field] = $direction;
return $this;
}
/**
* Set the filter to apply on the query for the x-axis
*
* @param Filter $filter
*
@ -88,7 +133,7 @@ class PivotTable
}
/**
* Set the filter to apply on the query for the y axis
* Set the filter to apply on the query for the y-axis
*
* @param Filter $filter
*
@ -100,6 +145,56 @@ class PivotTable
return $this;
}
/**
* Get the x-axis header
*
* Defaults to {@link $xAxisColumn} in case no x-axis header has been set using {@link setXAxisHeader()}
*
* @return string
*/
public function getXAxisHeader()
{
return $this->xAxisHeader !== null ? $this->xAxisHeader : $this->xAxisColumn;
}
/**
* Set the x-axis header
*
* @param string $xAxisHeader
*
* @return $this
*/
public function setXAxisHeader($xAxisHeader)
{
$this->xAxisHeader = (string) $xAxisHeader;
return $this;
}
/**
* Get the y-axis header
*
* Defaults to {@link $yAxisColumn} in case no x-axis header has been set using {@link setYAxisHeader()}
*
* @return string
*/
public function getYAxisHeader()
{
return $this->yAxisHeader !== null ? $this->yAxisHeader : $this->yAxisColumn;
}
/**
* Set the y-axis header
*
* @param string $yAxisHeader
*
* @return $this
*/
public function setYAxisHeader($yAxisHeader)
{
$this->yAxisHeader = (string) $yAxisHeader;
return $this;
}
/**
* Return the value for the given request parameter
*
@ -107,7 +202,7 @@ class PivotTable
* @param string $param The parameter name to return
* @param int $default The default value to return
*
* @return int
* @return int
*/
protected function getPaginationParameter($axis, $param, $default = null)
{
@ -125,23 +220,25 @@ class PivotTable
/**
* Query horizontal (x) axis
*
* @return SimpleQuery
* @return SimpleQuery
*/
protected function queryXAxis()
{
if ($this->xAxisQuery === null) {
$this->xAxisQuery = clone $this->baseQuery;
$this->xAxisQuery->group($this->xAxisColumn);
$this->xAxisQuery->columns(array($this->xAxisColumn));
$this->xAxisQuery->setUseSubqueryCount();
$xAxisHeader = $this->getXAxisHeader();
$columns = array($this->xAxisColumn, $xAxisHeader);
$this->xAxisQuery->group(array_unique($columns)); // xAxisColumn and header may be the same column
$this->xAxisQuery->columns($columns);
if ($this->xAxisFilter !== null) {
$this->xAxisQuery->addFilter($this->xAxisFilter);
}
if (! $this->xAxisQuery->hasOrder($this->xAxisColumn)) {
$this->xAxisQuery->order($this->xAxisColumn, 'asc');
}
$this->xAxisQuery->order(
$xAxisHeader,
isset($this->order[$xAxisHeader]) ? $this->order[$xAxisHeader] : self::SORT_ASC
);
}
return $this->xAxisQuery;
@ -150,30 +247,31 @@ class PivotTable
/**
* Query vertical (y) axis
*
* @return SimpleQuery
* @return SimpleQuery
*/
protected function queryYAxis()
{
if ($this->yAxisQuery === null) {
$this->yAxisQuery = clone $this->baseQuery;
$this->yAxisQuery->group($this->yAxisColumn);
$this->yAxisQuery->columns(array($this->yAxisColumn));
$this->yAxisQuery->setUseSubqueryCount();
$yAxisHeader = $this->getYAxisHeader();
$columns = array($this->yAxisColumn, $yAxisHeader);
$this->yAxisQuery->group(array_unique($columns)); // yAxisColumn and header may be the same column
$this->yAxisQuery->columns($columns);
if ($this->yAxisFilter !== null) {
$this->yAxisQuery->addFilter($this->yAxisFilter);
}
if (! $this->yAxisQuery->hasOrder($this->yAxisColumn)) {
$this->yAxisQuery->order($this->yAxisColumn, 'asc');
}
$this->yAxisQuery->order(
$yAxisHeader,
isset($this->order[$yAxisHeader]) ? $this->order[$yAxisHeader] : self::SORT_ASC
);
}
return $this->yAxisQuery;
}
/**
* Return a pagination adapter for the x axis query
* Return a pagination adapter for the x-axis query
*
* $limit and $page are taken from the current request if not given.
*
@ -204,7 +302,7 @@ class PivotTable
}
/**
* Return a pagination adapter for the y axis query
* Return a pagination adapter for the y-axis query
*
* $limit and $page are taken from the current request if not given.
*
@ -235,9 +333,9 @@ class PivotTable
}
/**
* Return the pivot table as array
* Return the pivot table as an array of pivot data and pivot header
*
* @return array
* @return array
*/
public function toArray()
{
@ -245,33 +343,39 @@ class PivotTable
($this->xAxisFilter === null && $this->yAxisFilter === null)
|| ($this->xAxisFilter !== null && $this->yAxisFilter !== null)
) {
$xAxis = $this->queryXAxis()->fetchColumn();
$yAxis = $this->queryYAxis()->fetchColumn();
$xAxis = $this->queryXAxis()->fetchPairs();
$yAxis = $this->queryYAxis()->fetchPairs();
} else {
if ($this->xAxisFilter !== null) {
$xAxis = $this->queryXAxis()->fetchColumn();
$yAxis = $this->queryYAxis()->where($this->xAxisColumn, $xAxis)->fetchColumn();
$xAxis = $this->queryXAxis()->fetchPairs();
$yAxis = $this->queryYAxis()->where($this->xAxisColumn, $xAxis)->fetchPairs();
} else { // $this->yAxisFilter !== null
$yAxis = $this->queryYAxis()->fetchColumn();
$xAxis = $this->queryXAxis()->where($this->yAxisColumn, $yAxis)->fetchColumn();
$yAxis = $this->queryYAxis()->fetchPairs();
$xAxis = $this->queryXAxis()->where($this->yAxisColumn, $yAxis)->fetchPairs();
}
}
$pivotData = array();
$pivotHeader = array(
'cols' => $xAxis,
'rows' => $yAxis
);
if (! empty($xAxis) && ! empty($yAxis)) {
$xAxisKeys = array_keys($xAxis);
$yAxisKeys = array_keys($yAxis);
$this->baseQuery
->where($this->xAxisColumn, $xAxisKeys)
->where($this->yAxisColumn, $yAxisKeys);
$pivot = array();
if (!empty($xAxis) && !empty($yAxis)) {
$this->baseQuery->where($this->xAxisColumn, $xAxis)->where($this->yAxisColumn, $yAxis);
foreach ($yAxis as $yLabel) {
foreach ($xAxis as $xLabel) {
$pivot[$yLabel][$xLabel] = null;
foreach ($yAxisKeys as $yAxisKey) {
foreach ($xAxisKeys as $xAxisKey) {
$pivotData[$yAxisKey][$xAxisKey] = null;
}
}
foreach ($this->baseQuery as $row) {
$pivot[$row->{$this->yAxisColumn}][$row->{$this->xAxisColumn}] = $row;
$pivotData[$row->{$this->yAxisColumn}][$row->{$this->xAxisColumn}] = $row;
}
}
return $pivot;
return array($pivotData, $pivotHeader);
}
}

View File

@ -0,0 +1,11 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Exception;
/**
* Exception thrown if something to add already exists
*/
class AlreadyExistsException extends IcingaException
{
}

View File

@ -452,16 +452,19 @@ class User
if (isset($this->permissions['*']) || isset($this->permissions[$requiredPermission])) {
return true;
}
// If the permission to check contains a wildcard, grant the permission if any permit related to the permission
// matches
$any = strpos($requiredPermission, '*');
$requiredWildcard = strpos($requiredPermission, '*');
foreach ($this->permissions as $grantedPermission) {
if ($any !== false) {
$wildcard = $any;
if ($requiredWildcard !== false) {
if (($grantedWildcard = strpos($grantedPermission, '*')) !== false) {
$wildcard = min($requiredWildcard, $grantedWildcard);
} else {
$wildcard = $requiredWildcard;
}
} else {
// If the permit contains a wildcard, grant the permission if it's related to the permit
$wildcard = strpos($grantedPermission, '*');
}
if ($wildcard !== false) {
if (substr($requiredPermission, 0, $wildcard) === substr($grantedPermission, 0, $wildcard)) {
return true;
@ -470,6 +473,7 @@ class User
return true;
}
}
return false;
}
}

View File

@ -8,26 +8,24 @@ use Icinga\Application\Icinga;
use Icinga\Web\Widget\Tabs;
/**
* Static helper class that collects tabs provided by the 'createProvidedTabs' method
* of controllers.
* Static helper class that collects tabs provided by the 'createProvidedTabs' method of controllers
*/
class ControllerTabCollector
{
/**
* Scan all controllers with the provided name
* in the application and (loaded) module folders and collects their provided tabs
* Scan all controllers with given name in the application and (loaded) module folders and collects their provided
* tabs
*
* @param string $controller The name of the controllers to use for tab collection
* @param string $controllerName The name of the controllers to use for tab collection
*
* @return Tabs A @see Tabs instance containing the application tabs first
* followed by the tabs provided from the modules
* @return Tabs A {@link Tabs} instance containing the application tabs first followed by the
* tabs provided from the modules
*/
public static function collectControllerTabs($controller)
public static function collectControllerTabs($controllerName)
{
require_once(Icinga::app()->getApplicationDir('/controllers/'.$controller.'.php'));
$controller = '\Icinga\\' . Dispatcher::CONTROLLER_NAMESPACE . '\\' . $controllerName;
$applicationTabs = $controller::createProvidedTabs();
$moduleTabs = self::collectModuleTabs($controller);
$moduleTabs = self::collectModuleTabs($controllerName);
$tabs = new Tabs();
foreach ($applicationTabs as $name => $tab) {
@ -35,7 +33,7 @@ class ControllerTabCollector
}
foreach ($moduleTabs as $name => $tab) {
// don't overwrite application tabs if the module wants to
// Don't overwrite application tabs if the module wants to
if ($tabs->has($name)) {
continue;
}
@ -66,29 +64,30 @@ class ControllerTabCollector
/**
* Collects the tabs from the createProvidedTabs() method in the configuration controller
*
* If the module doesn't have the given controller or createProvidedTabs method in the controller
* an empty array will be returned
* If the module doesn't have the given controller or createProvidedTabs method in the controller an empty array
* will be returned
*
* @param string $controller The name of the controller that provides tabs via createProvidedTabs
* @param Module $module The module instance that provides the controller
* @param string $controllerName The name of the controller that provides tabs via createProvidedTabs
* @param Module $module The module instance that provides the controller
*
* @return array
* @return array
*/
private static function createModuleConfigurationTabs($controller, Module $module)
private static function createModuleConfigurationTabs($controllerName, Module $module)
{
// TODO(el): Only works for controllers w/o namepsace: https://dev.icinga.org/issues/4149
$controllerDir = $module->getControllerDir();
$name = $module->getName();
$controllerDir = $controllerDir . '/' . $controller . '.php';
$controllerName = ucfirst($name) . '_' . $controller;
$controllerDir = $controllerDir . '/' . $controllerName . '.php';
$controllerName = ucfirst($name) . '_' . $controllerName;
if (is_readable($controllerDir)) {
require_once(realpath($controllerDir));
if (!method_exists($controllerName, "createProvidedTabs")) {
if (! method_exists($controllerName, 'createProvidedTabs')) {
return array();
}
$tab = $controllerName::createProvidedTabs();
if (!is_array($tab)) {
if (! is_array($tab)) {
$tab = array($name => $tab);
}
return $tab;

View File

@ -0,0 +1,92 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Web\Controller;
use Exception;
use Zend_Controller_Action;
use Zend_Controller_Action_Interface;
use Zend_Controller_Dispatcher_Exception;
use Zend_Controller_Dispatcher_Standard;
use Zend_Controller_Request_Abstract;
use Zend_Controller_Response_Abstract;
/**
* Dispatcher supporting Zend-style and namespaced controllers
*
* Does not support a namespaced default controller in combination w/ the Zend parameter useDefaultControllerAlways.
*/
class Dispatcher extends Zend_Controller_Dispatcher_Standard
{
/**
* Controller namespace
*
* @var string
*/
const CONTROLLER_NAMESPACE = 'Controllers';
/**
* Dispatch request to a controller and action
*
* @param Zend_Controller_Request_Abstract $request
* @param Zend_Controller_Response_Abstract $response
*
* @throws Zend_Controller_Dispatcher_Exception If the controller is not an instance of
* Zend_Controller_Action_Interface
* @throws Exception If dispatching the request fails
*/
public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response)
{
$this->setResponse($response);
$controllerName = $request->getControllerName();
if (! $controllerName) {
parent::dispatch($request, $response);
return;
}
$controllerName = ucfirst($controllerName) . 'Controller';
$moduleName = $request->getModuleName();
if ($moduleName === null || $moduleName === $this->_defaultModule) {
$controllerClass = 'Icinga\\' . self::CONTROLLER_NAMESPACE . '\\' . $controllerName;
} else {
$controllerClass = 'Icinga\\Module\\' . ucfirst($moduleName) . '\\' . self::CONTROLLER_NAMESPACE . '\\'
. $controllerName;
}
if (! class_exists($controllerClass)) {
parent::dispatch($request, $response);
return;
}
$controller = new $controllerClass($request, $response, $this->getParams());
if (! $controller instanceof Zend_Controller_Action
&& ! $controller instanceof Zend_Controller_Action_Interface
) {
throw new Zend_Controller_Dispatcher_Exception(
'Controller "' . $controllerClass . '" is not an instance of Zend_Controller_Action_Interface'
);
}
$action = $this->getActionMethod($request);
$request->setDispatched(true);
// Buffer output by default
$disableOb = $this->getParam('disableOutputBuffering');
$obLevel = ob_get_level();
if (empty($disableOb)) {
ob_start();
}
try {
$controller->dispatch($action);
} catch (Exception $e) {
// Clean output buffer on error
$curObLevel = ob_get_level();
if ($curObLevel > $obLevel) {
do {
ob_get_clean();
$curObLevel = ob_get_level();
} while ($curObLevel > $obLevel);
}
throw $e;
}
if (empty($disableOb)) {
$content = ob_get_clean();
$response->appendBody($content);
}
}
}

View File

@ -1012,6 +1012,8 @@ class Form extends Zend_Form
* Populate the elements with the given values
*
* @param array $defaults The values to populate the elements with
*
* @return $this
*/
public function populate(array $defaults)
{

View File

@ -12,6 +12,7 @@ class StyleSheet
protected static $lessFiles = array(
'../application/fonts/fontello-ifont/css/ifont-embedded.css',
'css/vendor/tipsy.css',
'css/icinga/mixins.less',
'css/icinga/defaults.less',
'css/icinga/animation.less',
'css/icinga/layout-colors.less',

View File

@ -118,12 +118,12 @@ class SortBox extends AbstractWidget
if ($request === null) {
$request = Icinga::app()->getRequest();
}
if (($sort = $request->getParam('sort'))) {
$this->query->order($sort, $request->getParam('dir'));
} elseif (($dir = $request->getParam('dir'))) {
$this->query->order(null, $dir);
if (null === $sort = $request->getParam('sort')) {
list($sort, $dir) = $this->getSortDefaults();
} else {
list($_, $dir) = $this->getSortDefaults($sort);
}
$this->query->order($sort, $request->getParam('dir', $dir));
}
return $this;
@ -148,8 +148,10 @@ class SortBox extends AbstractWidget
if ($column !== null && isset($sortRules[$column]['order'])) {
$direction = strtoupper($sortRules[$column]['order']) === Sortable::SORT_DESC ? 'desc' : 'asc';
}
} elseif ($column === null) {
reset($this->sortFields);
$column = key($this->sortFields);
}
return array($column, $direction);
}

View File

@ -1,17 +1,19 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Doc\Controllers;
use Icinga\Application\Icinga;
use Icinga\Module\Doc\DocController;
class Doc_IcingawebController extends DocController
class IcingawebController extends DocController
{
/**
* Get the path to Icinga Web 2's documentation
*
* @return string
*
* @throws Zend_Controller_Action_Exception If Icinga Web 2's documentation is not available
* @throws \Icinga\Exception\Http\HttpNotFoundException If Icinga Web 2's documentation is not available
*/
protected function getPath()
{

View File

@ -1,10 +1,20 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Doc\Controllers;
use Icinga\Module\Doc\DocController;
class Doc_IndexController extends DocController
/**
* Documentation module index
*/
class IndexController extends DocController
{
/**
* Documentation module landing page
*
* Lists documentation links
*/
public function indexAction()
{
}

View File

@ -1,12 +1,13 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Doc\Controllers;
use Icinga\Application\Icinga;
use Icinga\Module\Doc\DocController;
use Icinga\Module\Doc\Exception\DocException;
use Icinga\File\Ini\Parser;
class Doc_ModuleController extends DocController
class ModuleController extends DocController
{
/**
* Get the path to a module documentation

View File

@ -1,15 +1,17 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Doc\Controllers;
use Icinga\Application\Icinga;
use Icinga\Module\Doc\DocController;
use Icinga\Module\Doc\DocParser;
use Icinga\Module\Doc\Exception\DocException;
use Icinga\Module\Doc\Renderer\DocSearchRenderer;
use Icinga\Module\Doc\Search\DocSearch;
use Icinga\Module\Doc\Search\DocSearchIterator;
use Icinga\Module\Doc\Renderer\DocSearchRenderer;
class Doc_SearchController extends DocController
class SearchController extends DocController
{
/**
* Render search
@ -77,9 +79,7 @@ class Doc_SearchController extends DocController
/**
* Get the path to Icinga Web 2's documentation
*
* @return string
*
* @throws Zend_Controller_Action_Exception If Icinga Web 2's documentation is not available
* @return string
*/
protected function getWebPath()
{

View File

@ -1,11 +1,13 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Doc\Controllers;
use Icinga\Application\Icinga;
use Icinga\Web\Controller;
use Icinga\Web\Widget;
class Doc_StyleController extends Controller
class StyleController extends Controller
{
public function guideAction()
{

View File

@ -1,15 +1,23 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use stdClass;
use DateInterval;
use DatePeriod;
use DateTime;
use Zend_Controller_Action_Exception;
use Icinga\Chart\GridChart;
use Icinga\Chart\Unit\LinearUnit;
use Icinga\Chart\Unit\StaticAxis;
use Icinga\Data\Filter\FilterExpression;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Web\Widget\SelectBox;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
class Monitoring_AlertsummaryController extends Controller
class AlertsummaryController extends Controller
{
/**
* @var array
@ -95,7 +103,7 @@ class Monitoring_AlertsummaryController extends Controller
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new Icinga\Data\Filter\FilterExpression(
new FilterExpression(
'notification_start_time',
'>=',
$this->getBeginDate($interval)->format('Y-m-d H:i:s')
@ -144,7 +152,7 @@ class Monitoring_AlertsummaryController extends Controller
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new Icinga\Data\Filter\FilterExpression(
new FilterExpression(
'notification_start_time',
'>=',
$beginDate->format('Y-m-d H:i:s')
@ -212,7 +220,7 @@ class Monitoring_AlertsummaryController extends Controller
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new Icinga\Data\Filter\FilterExpression(
new FilterExpression(
'notification_start_time',
'>=',
$this->getBeginDate($interval)->format('Y-m-d H:i:s')
@ -263,7 +271,7 @@ class Monitoring_AlertsummaryController extends Controller
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new Icinga\Data\Filter\FilterExpression(
new FilterExpression(
'timestamp',
'>=',
$this->getBeginDate($interval)->getTimestamp()
@ -271,7 +279,7 @@ class Monitoring_AlertsummaryController extends Controller
);
$query->addFilter(
new Icinga\Data\Filter\FilterExpression(
new FilterExpression(
'state',
'>',
0
@ -329,7 +337,7 @@ class Monitoring_AlertsummaryController extends Controller
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new Icinga\Data\Filter\FilterExpression(
new FilterExpression(
'notification_start_time',
'>=',
$this->getBeginDate($interval)->format('Y-m-d H:i:s')

View File

@ -1,20 +1,18 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Module\Monitoring\Controller;
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Chart\GridChart;
use Icinga\Chart\PieChart;
use Icinga\Chart\Unit\StaticAxis;
use Icinga\Chart\Unit\LogarithmicUnit;
use Icinga\Chart\Unit\LinearUnit;
use Icinga\Chart\Unit\StaticAxis;
use Icinga\Module\Monitoring\Controller;
/**
* Class Monitoring_CommandController
*
* Interface to send commands and display forms
* @TODO(el): Fix and reuse the controller or remove it: https://dev.icinga.org/issues/10019
*/
class Monitoring_ChartController extends Controller
class ChartController extends Controller
{
private function drawLogChart1()
{

View File

@ -1,6 +1,8 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteCommentCommandForm;
use Icinga\Web\Url;
@ -9,12 +11,12 @@ use Icinga\Web\Widget\Tabextension\DashboardAction;
/**
* Display detailed information about a comment
*/
class Monitoring_CommentController extends Controller
class CommentController extends Controller
{
/**
* The fetched comment
*
* @var stdClass
* @var object
*/
protected $comment;
@ -41,19 +43,16 @@ class Monitoring_CommentController extends Controller
))->where('comment_internal_id', $commentId);
$this->applyRestriction('monitoring/filter/objects', $query);
$this->comment = $query->getQuery()->fetchRow();
if ($this->comment === false) {
if (false === $this->comment = $query->fetchRow()) {
$this->httpNotFound($this->translate('Comment not found'));
}
$this->getTabs()->add(
'comment',
array(
'title' => $this->translate(
'Display detailed information about a comment.'
),
'icon' => 'comment',
'icon' => 'comment',
'label' => $this->translate('Comment'),
'title' => $this->translate('Display detailed information about a comment.'),
'url' =>'monitoring/comments/show'
)
)->activate('comment')->extend(new DashboardAction());
@ -64,37 +63,19 @@ class Monitoring_CommentController extends Controller
*/
public function showAction()
{
$listCommentsLink = Url::fromPath('monitoring/list/comments')
->setQueryString('comment_type=(comment|ack)');
$this->view->comment = $this->comment;
if ($this->hasPermission('monitoring/command/comment/delete')) {
$this->view->delCommentForm = $this->createDelCommentForm();
$this->view->delCommentForm->populate(
array(
'redirect' => $listCommentsLink,
'comment_id' => $this->comment->id,
'comment_is_service' => isset($this->comment->service_description)
)
);
$listUrl = Url::fromPath('monitoring/list/comments')->setQueryString('comment_type=(comment|ack)');
$form = new DeleteCommentCommandForm();
$form
->populate(array(
'comment_id' => $this->comment->id,
'comment_is_service' => isset($this->comment->service_description),
'redirect' => $listUrl
))
->handleRequest();
$this->view->delCommentForm = $form;
}
}
/**
* Create a command form to delete a single comment
*
* @return DeleteCommentsCommandForm
*/
private function createDelCommentForm()
{
$this->assertPermission('monitoring/command/comment/delete');
$delCommentForm = new DeleteCommentCommandForm();
$delCommentForm->setAction(
Url::fromPath('monitoring/comment/show')
->setParam('comment_id', $this->comment->id)
);
$delCommentForm->handleRequest();
return $delCommentForm;
}
}

View File

@ -1,34 +1,41 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteCommentsCommandForm;
use Icinga\Web\Url;
use Icinga\Data\Filter\Filter;
/**
* Display detailed information about a comment
* Display detailed information about comments
*/
class Monitoring_CommentsController extends Controller
class CommentsController extends Controller
{
/**
* The fetched comments
* The comments view
*
* @var array
* @var \Icinga\Module\Monitoring\DataView\Comment
*/
protected $comments;
/**
* Fetch all comments matching the current filter and add tabs
* Filter from request
*
* @throws Zend_Controller_Action_Exception
* @var Filter
*/
protected $filter;
/**
* Fetch all comments matching the current filter and add tabs
*/
public function init()
{
$this->filter = Filter::fromQueryString(str_replace(
'comment_id',
'comment_internal_id',
(string)$this->params
(string) $this->params
));
$query = $this->backend->select()->from('comment', array(
'id' => 'comment_internal_id',
@ -46,19 +53,16 @@ class Monitoring_CommentsController extends Controller
))->addFilter($this->filter);
$this->applyRestriction('monitoring/filter/objects', $query);
$this->comments = $query->getQuery()->fetchAll();
if (false === $this->comments) {
throw new Zend_Controller_Action_Exception($this->translate('Comment not found'));
}
$this->comments = $query;
$this->getTabs()->add(
'comments',
array(
'icon' => 'comment',
'label' => $this->translate('Comments') . sprintf(' (%d)', $query->count()),
'title' => $this->translate(
'Display detailed information about multiple comments.'
),
'icon' => 'comment',
'label' => $this->translate('Comments') . sprintf(' (%d)', count($this->comments)),
'url' =>'monitoring/comments/show'
)
)->activate('comments');
@ -71,9 +75,9 @@ class Monitoring_CommentsController extends Controller
{
$this->view->comments = $this->comments;
$this->view->listAllLink = Url::fromPath('monitoring/list/comments')
->setQueryString($this->filter->toQueryString());
->setQueryString($this->filter->toQueryString());
$this->view->removeAllLink = Url::fromPath('monitoring/comments/delete-all')
->setParams($this->params);
->setParams($this->params);
}
/**
@ -89,14 +93,14 @@ class Monitoring_CommentsController extends Controller
$delCommentForm->setTitle($this->view->translate('Remove all Comments'));
$delCommentForm->addDescription(sprintf(
$this->translate('Confirm removal of %d comments.'),
count($this->comments)
$this->comments->count()
));
$delCommentForm->setComments($this->comments)
$delCommentForm->setComments($this->comments->fetchAll())
->setRedirectUrl($listCommentsLink)
->handleRequest();
$this->view->delCommentForm = $delCommentForm;
$this->view->comments = $this->comments;
$this->view->listAllLink = Url::fromPath('monitoring/list/comments')
->setQueryString($this->filter->toQueryString());
->setQueryString($this->filter->toQueryString());
}
}

View File

@ -1,8 +1,12 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use Exception;
use Icinga\Data\ResourceFactory;
use Icinga\Exception\ConfigurationError;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Web\Notification;
use Icinga\Module\Monitoring\Controller;
@ -13,7 +17,7 @@ use Icinga\Module\Monitoring\Forms\Config\TransportConfigForm;
/**
* Configuration controller for editing monitoring resources
*/
class Monitoring_ConfigController extends Controller
class ConfigController extends Controller
{
/**
* Display a list of available backends and command transports

View File

@ -1,33 +1,27 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Object\Service;
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteDowntimeCommandForm;
use Icinga\Module\Monitoring\Command\Object\DeleteDowntimeCommand;
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
/**
* Display detailed information about a downtime
*/
class Monitoring_DowntimeController extends Controller
class DowntimeController extends Controller
{
/**
* The fetched downtime
*
* @var stdClass
* @var object
*/
protected $downtime;
/**
* If the downtime is a service or not
*
* @var boolean
*/
protected $isService;
/**
* Fetch the downtime matching the given id and add tabs
*/
@ -58,29 +52,20 @@ class Monitoring_DowntimeController extends Controller
))->where('downtime_internal_id', $downtimeId);
$this->applyRestriction('monitoring/filter/objects', $query);
$this->downtime = $query->getQuery()->fetchRow();
if ($this->downtime === false) {
if (false === $this->downtime = $query->fetchRow()) {
$this->httpNotFound($this->translate('Downtime not found'));
}
if (isset($this->downtime->service_description)) {
$this->isService = true;
} else {
$this->isService = false;
}
$this->getTabs()->add(
'downtime',
array(
$this->getTabs()
->add(
'downtime',
array(
'title' => $this->translate(
'Display detailed information about a downtime.'
),
'icon' => 'plug',
'label' => $this->translate('Downtime'),
'url' =>'monitoring/downtimes/show'
)
)->activate('downtime')->extend(new DashboardAction());
'icon' => 'plug',
'label' => $this->translate('Downtime'),
'title' => $this->translate('Display detailed information about a downtime.'),
'url' =>'monitoring/downtimes/show'
)
)->activate('downtime')->extend(new DashboardAction());
}
/**
@ -88,52 +73,27 @@ class Monitoring_DowntimeController extends Controller
*/
public function showAction()
{
$isService = isset($this->downtime->service_description);
$this->view->downtime = $this->downtime;
$this->view->isService = $this->isService;
$this->view->stateName = isset($this->downtime->service_description) ?
Service::getStateText($this->downtime->service_state) :
Host::getStateText($this->downtime->host_state);
$this->view->isService = $isService;
$this->view->listAllLink = Url::fromPath('monitoring/list/downtimes');
$this->view->showHostLink = Url::fromPath('monitoring/host/show')
->setParam('host', $this->downtime->host_name);
$this->view->showHostLink = Url::fromPath('monitoring/host/show')->setParam('host', $this->downtime->host_name);
$this->view->showServiceLink = Url::fromPath('monitoring/service/show')
->setParam('host', $this->downtime->host_name)
->setParam('service', $this->downtime->service_description);
$this->view->stateName = $isService ? Service::getStateText($this->downtime->service_state)
: Host::getStateText($this->downtime->host_state);
if ($this->hasPermission('monitoring/command/downtime/delete')) {
$this->view->delDowntimeForm = $this->createDelDowntimeForm();
$this->view->delDowntimeForm->populate(
array(
'redirect' => Url::fromPath('monitoring/list/downtimes'),
'downtime_id' => $this->downtime->id,
'downtime_is_service' => $this->isService
)
);
$form = new DeleteDowntimeCommandForm();
$form
->populate(array(
'downtime_id' => $this->downtime->id,
'downtime_is_service' => $isService,
'redirect' => Url::fromPath('monitoring/list/downtimes'),
))
->handleRequest();
$this->view->delDowntimeForm = $form;
}
}
/**
* Receive DeleteDowntimeCommandForm post from other controller
*/
public function removeAction()
{
$this->assertHttpMethod('POST');
$this->createDelDowntimeForm();
}
/**
* Create a command form to delete a single comment
*
* @return DeleteDowntimeCommandForm
*/
private function createDelDowntimeForm()
{
$this->assertPermission('monitoring/command/downtime/delete');
$delDowntimeForm = new DeleteDowntimeCommandForm();
$delDowntimeForm->setAction(
Url::fromPath('monitoring/downtime/show')
->setParam('downtime_id', $this->downtime->id)
);
$delDowntimeForm->handleRequest();
return $delDowntimeForm;
}
}

View File

@ -1,27 +1,27 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Object\Service;
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteDowntimesCommandForm;
use Icinga\Web\Url;
/**
* Display detailed information about a downtime
* Display detailed information about downtimes
*/
class Monitoring_DowntimesController extends Controller
class DowntimesController extends Controller
{
/**
* The fetched downtimes
* The downtimes view
*
* @var array
* @var \Icinga\Module\Monitoring\DataView\Downtime
*/
protected $downtimes;
/**
* A filter matching all current downtimes
* Filter from request
*
* @var Filter
*/
@ -29,15 +29,13 @@ class Monitoring_DowntimesController extends Controller
/**
* Fetch all downtimes matching the current filter and add tabs
*
* @throws Zend_Controller_Action_Exception
*/
public function init()
{
$this->filter = Filter::fromQueryString(str_replace(
'downtime_id',
'downtime_internal_id',
(string)$this->params
(string) $this->params
));
$query = $this->backend->select()->from('downtime', array(
'id' => 'downtime_internal_id',
@ -62,38 +60,17 @@ class Monitoring_DowntimesController extends Controller
))->addFilter($this->filter);
$this->applyRestriction('monitoring/filter/objects', $query);
$this->downtimes = $query->getQuery()->fetchAll();
if (false === $this->downtimes) {
throw new Zend_Controller_Action_Exception(
$this->translate('Downtime not found')
);
}
$this->downtimes = $query;
$this->getTabs()->add(
'downtimes',
array(
'title' => $this->translate(
'Display detailed information about multiple downtimes.'
),
'icon' => 'plug',
'label' => $this->translate('Downtimes') . sprintf(' (%d)', count($this->downtimes)),
'label' => $this->translate('Downtimes') . sprintf(' (%d)', $query->count()),
'title' => $this->translate('Display detailed information about multiple downtimes.'),
'url' =>'monitoring/downtimes/show'
)
)->activate('downtimes');
foreach ($this->downtimes as $downtime) {
if (isset($downtime->service_description)) {
$downtime->isService = true;
} else {
$downtime->isService = false;
}
if ($downtime->isService) {
$downtime->stateText = Service::getStateText($downtime->service_state);
} else {
$downtime->stateText = Host::getStateText($downtime->host_state);
}
}
}
/**
@ -103,9 +80,8 @@ class Monitoring_DowntimesController extends Controller
{
$this->view->downtimes = $this->downtimes;
$this->view->listAllLink = Url::fromPath('monitoring/list/downtimes')
->setQueryString($this->filter->toQueryString());
$this->view->removeAllLink = Url::fromPath('monitoring/downtimes/delete-all')
->setParams($this->params);
->setQueryString($this->filter->toQueryString());
$this->view->removeAllLink = Url::fromPath('monitoring/downtimes/delete-all')->setParams($this->params);
}
/**
@ -121,10 +97,10 @@ class Monitoring_DowntimesController extends Controller
$delDowntimeForm->setTitle($this->view->translate('Remove all Downtimes'));
$delDowntimeForm->addDescription(sprintf(
$this->translate('Confirm removal of %d downtimes.'),
count($this->downtimes)
$this->downtimes->count()
));
$delDowntimeForm->setRedirectUrl(Url::fromPath('monitoring/list/downtimes'));
$delDowntimeForm->setDowntimes($this->downtimes)->handleRequest();
$delDowntimeForm->setDowntimes($this->downtimes->fetchAll())->handleRequest();
$this->view->delDowntimeForm = $delDowntimeForm;
}
}

View File

@ -1,6 +1,8 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Module\Monitoring\Forms\Command\Object\AcknowledgeProblemCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\AddCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ProcessCheckResultCommandForm;
@ -11,11 +13,11 @@ use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Web\Controller\MonitoredObjectController;
use Icinga\Web\Hook;
class Monitoring_HostController extends MonitoredObjectController
class HostController extends MonitoredObjectController
{
/**
* (non-PHPDoc)
* @see MonitoredObjectController::$commandRedirectUrl For the property documentation.
* {@inheritdoc}
*/
protected $commandRedirectUrl = 'monitoring/host/show';
@ -25,9 +27,7 @@ class Monitoring_HostController extends MonitoredObjectController
public function init()
{
$host = new Host($this->backend, $this->params->getRequired('host'));
$this->applyRestriction('monitoring/filter/objects', $host);
if ($host->fetch() === false) {
$this->httpNotFound($this->translate('Host not found'));
}

View File

@ -1,23 +1,25 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filter\FilterEqual;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Forms\Command\Object\AcknowledgeProblemCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\AddCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\CheckNowCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ObjectsCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ProcessCheckResultCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\RemoveAcknowledgementCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ScheduleHostCheckCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ScheduleHostDowntimeCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\AddCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\SendCustomNotificationCommandForm;
use Icinga\Module\Monitoring\Object\HostList;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
class Monitoring_HostsController extends Controller
class HostsController extends Controller
{
/**
* @var HostList
@ -166,18 +168,6 @@ class Monitoring_HostsController extends Controller
$this->handleCommandForm($form);
}
/**
* Delete a comment
*/
public function deleteCommentAction()
{
$this->assertPermission('monitoring/command/comment/delete');
$form = new DeleteCommentCommandForm();
$form->setTitle($this->translate('Delete Host Comments'));
$this->handleCommandForm($form);
}
/**
* Acknowledge host problems
*/

View File

@ -1,19 +1,22 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Module\Monitoring\Controller;
namespace Icinga\Module\Monitoring\Controllers;
use Zend_Form;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Monitoring\Backend;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\DataView\DataView;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteDowntimeCommandForm;
use Icinga\Module\Monitoring\Forms\StatehistoryForm;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Widget\Tabextension\OutputFormat;
use Icinga\Web\Widget\Tabs;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Monitoring\Forms\StatehistoryForm;
use Icinga\Module\Monitoring\DataView\DataView;
class Monitoring_ListController extends Controller
class ListController extends Controller
{
/**
* @see ActionController::init
@ -556,29 +559,36 @@ class Monitoring_ListController extends Controller
{
$this->addTitleTab('servicegrid', $this->translate('Service Grid'), $this->translate('Show the Service Grid'));
$this->setAutorefreshInterval(15);
$problems = (bool) $this->params->shift('problems', 0);
$query = $this->backend->select()->from('servicestatus', array(
'host_display_name',
'host_name',
'service_description',
'service_state',
'service_display_name',
'service_handled',
'service_output',
'service_handled'
'service_state'
));
$this->applyRestriction('monitoring/filter/objects', $query);
$this->filterQuery($query);
$filter = (bool) $this->params->shift('problems', false) ? Filter::where('service_problem', 1) : null;
$pivot = $query
->pivot(
'service_description',
'host_name',
$filter,
$filter ? clone $filter : null
)
->setXAxisHeader('service_display_name')
->setYAxisHeader('host_display_name');
$this->setupSortControl(array(
'host_name' => $this->translate('Hostname'),
'service_description' => $this->translate('Service description')
), $query);
$pivot = $query->pivot(
'service_description',
'host_name',
$problems ? Filter::where('service_problem', 1) : null,
$problems ? Filter::where('service_problem', 1) : null
);
$this->view->pivot = $pivot;
'host_display_name' => $this->translate('Hostname'),
'service_display_name' => $this->translate('Service Name')
), $pivot);
$this->view->horizontalPaginator = $pivot->paginateXAxis();
$this->view->verticalPaginator = $pivot->paginateYAxis();
$this->view->verticalPaginator = $pivot->paginateYAxis();
list($pivotData, $pivotHeader) = $pivot->toArray();
$this->view->pivotData = $pivotData;
$this->view->pivotHeader = $pivotHeader;
}
/**

View File

@ -1,15 +1,17 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Web\Widget\Tabextension\DashboardAction;
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Forms\Command\Instance\DisableNotificationsExpireCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Instance\ToggleInstanceFeaturesCommandForm;
use Icinga\Web\Widget\Tabextension\DashboardAction;
/**
* Display process and performance information of the monitoring host and program-wide commands
*/
class Monitoring_ProcessController extends Controller
class ProcessController extends Controller
{
/**
* Add tabs
@ -122,20 +124,4 @@ class Monitoring_ProcessController extends Controller
$this->view->form = $form;
}
}
/**
* @todo should be dropped later
*/
public function performanceAction()
{
$this->getTabs()->activate('performance');
$this->setAutorefreshInterval(10);
$this->view->runtimevariables = (object) $this->backend->select()
->from('runtimevariables', array('varname', 'varvalue'))
->getQuery()->fetchPairs();
$this->view->checkperformance = $this->backend->select()
->from('runtimesummary')
->getQuery()->fetchAll();
}
}

View File

@ -1,6 +1,8 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Module\Monitoring\Forms\Command\Object\AcknowledgeProblemCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\AddCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ProcessCheckResultCommandForm;
@ -11,11 +13,10 @@ use Icinga\Module\Monitoring\Object\Service;
use Icinga\Module\Monitoring\Web\Controller\MonitoredObjectController;
use Icinga\Web\Hook;
class Monitoring_ServiceController extends MonitoredObjectController
class ServiceController extends MonitoredObjectController
{
/**
* (non-PHPDoc)
* @see MonitoredObjectController::$commandRedirectUrl For the property documentation.
* {@inheritdoc}
*/
protected $commandRedirectUrl = 'monitoring/service/show';

View File

@ -1,23 +1,24 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Forms\Command\Object\AcknowledgeProblemCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\AddCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\CheckNowCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ObjectsCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ProcessCheckResultCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\RemoveAcknowledgementCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ScheduleServiceCheckCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ScheduleServiceDowntimeCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\AddCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\SendCustomNotificationCommandForm;
use Icinga\Module\Monitoring\Object\ServiceList;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
class Monitoring_ServicesController extends Controller
class ServicesController extends Controller
{
/**
* @var ServiceList
@ -180,20 +181,6 @@ class Monitoring_ServicesController extends Controller
$this->handleCommandForm($form);
}
/**
* Delete a comment
*/
public function deleteCommentAction()
{
$this->assertPermission('monitoring/command/comment/delete');
$form = new DeleteCommentCommandForm();
$form->setTitle($this->translate('Delete Service Comments'));
$this->handleCommandForm($form);
}
/**
* Acknowledge service problems
*/

View File

@ -1,60 +1,27 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Web\Url;
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Module\Monitoring\Backend;
use Icinga\Module\Monitoring\Controller;
use Icinga\Web\Url;
/**
* Class Monitoring_ShowController
*
* Actions for show context
*/
class Monitoring_ShowController extends Controller
class ShowController extends Controller
{
/**
* @var Backend
*/
protected $backend;
/**
* @deprecated
*/
public function serviceAction()
{
$this->redirectNow(Url::fromRequest()->setPath('monitoring/service/show'));
}
/**
* @deprecated
*/
public function hostAction()
{
$this->redirectNow(Url::fromRequest()->setPath('monitoring/host/show'));
}
/**
* @deprecated
*/
public function historyAction()
{
if ($this->params->has('service')) {
$this->redirectNow(Url::fromRequest()->setPath('monitoring/service/history'));
}
$this->redirectNow(Url::fromRequest()->setPath('monitoring/host/history'));
}
public function contactAction()
{
$contactName = $this->getParam('contact_name');
if (! $contactName) {
throw new Zend_Controller_Action_Exception(
$this->translate('The parameter `contact_name\' is required'),
404
);
}
$contactName = $this->params->getRequired('contact_name');
$query = $this->backend->select()->from('contact', array(
'contact_name',

View File

@ -1,11 +1,13 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Module\Monitoring\Controller as MonitoringController;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Url;
namespace Icinga\Module\Monitoring\Controllers;
class Monitoring_TacticalController extends MonitoringController
use Icinga\Module\Monitoring\Controller;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
class TacticalController extends Controller
{
public function indexAction()
{

View File

@ -1,15 +1,19 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Web\Url;
use Icinga\Util\Format;
namespace Icinga\Module\Monitoring\Controllers;
use DateInterval;
use DateTime;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Timeline\TimeLine;
use Icinga\Module\Monitoring\Timeline\TimeRange;
use Icinga\Module\Monitoring\Web\Widget\SelectBox;
use Icinga\Util\Format;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
class Monitoring_TimelineController extends Controller
class TimelineController extends Controller
{
public function indexAction()
{

View File

@ -1,25 +1,19 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<div data-base-target='_next'>
<?= $this->render('partials/comment/comments-header.phtml'); ?>
</div>
<?php if (! $this->compact): ?>
<?= $this->tabs ?>
<?php endif ?>
<?= $this->render('partials/comment/comments-header.phtml') ?>
</div>
<div class="content multi-commands">
<h3><?= $this->icon('reschedule') ?> <?= $this->translate('Commands') ?> </h3>
<h3><?= $this->icon('reschedule') ?><?= $this->translate('Commands') ?></h3>
<?= $this->qlink(
sprintf(
$this->translate('Remove %d comments'),
count($comments)
),
sprintf($this->translate('Remove %d comments'), $comments->count()),
$removeAllLink,
null,
array(
'icon' => 'trash',
'title' => $this->translate('Remove all selected comments.')
'icon' => 'trash',
'title' => $this->translate('Remove all selected comments')
)
) ?>
</div>

View File

@ -1,23 +1,19 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<?= $this->render('partials/downtime/downtimes-header.phtml'); ?>
</p>
<?php if (! $this->compact): ?>
<?= $this->tabs ?>
<?php endif ?>
<?= $this->render('partials/downtime/downtimes-header.phtml') ?>
</div>
<div class="content multi-commands">
<h3><?= $this->translate('Commands') ?> </h3>
<h3><?= $this->icon('reschedule') ?><?= $this->translate('Commands') ?></h3>
<?= $this->qlink(
sprintf(
$this->translate('Remove all %d scheduled downtimes'),
count($downtimes)
),
sprintf($this->translate('Remove all %d scheduled downtimes'), $downtimes->count()),
$removeAllLink,
null,
array(
'icon' => 'trash'
'icon' => 'trash',
'title' => $this->translate('Remove all selected downtimes')
)
) ?>
</div>

View File

@ -12,97 +12,84 @@ if (! $this->compact): ?>
<?php endif ?>
<div class="content" data-base-target="_next">
<?php
$hasHeader = false;
$pivotData = $this->pivot->toArray();
if (count($pivotData) === 0) {
if (empty($pivotData)) {
echo $this->translate('No services found matching the filter') . '</div>';
return;
}
$hostFilter = '(host_name=' . implode('|host_name=', array_keys($pivotData)) . ')';
?>
<table class="pivot servicestates">
<?php foreach ($pivotData as $host_name => $serviceStates): ?>
<?php if (!$hasHeader): ?>
<thead>
<tr>
<th><?= $this->partial(
'joystickPagination.phtml',
'default',
array(
'xAxisPaginator' => $horizontalPaginator,
'yAxisPaginator' => $verticalPaginator
)
); ?></th>
<th colspan="<?= count($serviceStates); ?>">
<div>
<?php
$serviceDescriptions = array_keys($serviceStates);
$serviceFilter = '(service_description=' . implode('|service_description=', $serviceDescriptions) . ')';
foreach ($serviceDescriptions as $service_description): ?>
<span>
<?= $this->qlink(
'<abbr>' . (strlen($service_description) > 18 ? substr($service_description, 0, 18) . '...' : $service_description) . '</abbr>',
<table class="service-grid-table">
<thead>
<tr>
<th><?= $this->partial(
'joystickPagination.phtml',
'default',
array(
'xAxisPaginator' => $horizontalPaginator,
'yAxisPaginator' => $verticalPaginator
)
); ?></th>
<?php foreach ($pivotHeader['cols'] as $serviceDescription => $serviceDisplayName): ?>
<th class="rotate-45"><div><span><?= $this->qlink(
$this->ellipsis($serviceDisplayName, 18),
'monitoring/list/services?' . $hostFilter,
array(
'service_description' => $service_description
),
array(
'title' => sprintf($this->translate('List all services with the name "%s" on all reported hosts'), $service_description)
),
array('service_description' => $serviceDescription),
array('title' => sprintf(
$this->translate('List all services with the name "%s" on all reported hosts'),
$serviceDisplayName
)),
false
); ?>
</span>
<?php endforeach ?>
</div>
</th>
</tr>
) ?></span></div></th>
<?php endforeach ?>
</tr>
</thead>
<tbody>
<?php $hasHeader = true; ?>
<?php endif ?>
<tr>
<th>
<?= $this->qlink(
$host_name,
'monitoring/list/services?' . $serviceFilter,
array('host' => $host_name),
array('title' => sprintf($this->translate('List all reported services on host %s'), $host_name))
); ?>
</th>
<?php foreach (array_values($serviceStates) as $service): ?>
<?php if ($service !== null): ?>
<td>
<span class="sr-only" id="<?= $service->host_name . '_' . $service->service_description . '_desc'; ?>">
<?= $this->escape($service->service_output); ?>
</span>
<?= $this->qlink(
'',
'monitoring/show/service',
array(
'host' => $service->host_name,
'service' => $service->service_description
),
array(
'aria-describedby' => $service->host_name . '_' . $service->service_description . '_desc',
'class' => 'state_' . Service::getStateText($service->service_state). ($service->service_handled ? ' handled' : ''),
'title' => $this->escape($service->service_output),
'aria-label' => sprintf(
$this->translate('Show detailed information for service %s on host %s'),
$service->service_description,
$service->host_name
)
)
); ?>
</td>
<?php else: ?>
<td><span aria-hidden="true">&middot;</span></td>
<?php endif ?>
<?php endforeach ?>
</tr>
<?php endforeach ?>
<?php foreach ($pivotHeader['rows'] as $hostName => $hostDisplayName): ?>
<tr>
<th><?php
$services = $pivotData[$hostName];
$serviceFilter = '(service_description=' . implode('|service_description=', array_keys($services)) . ')';
echo $this->qlink(
$hostDisplayName,
'monitoring/list/services?' . $serviceFilter,
array('host_name' => $hostName),
array('title' => sprintf($this->translate('List all reported services on host %s'), $hostDisplayName))
);
?></th>
<?php foreach (array_keys($pivotHeader['cols']) as $serviceDescription): ?>
<td>
<?php
$service = $pivotData[$hostName][$serviceDescription];
if ($service === null): ?>
<span aria-hidden="true">&middot;</span>
<?php continue; endif ?>
<?php $ariaDescribedById = $this->protectId($service->host_name . '_' . $service->service_description . '_desc') ?>
<span class="sr-only" id="<?= $ariaDescribedById ?>">
<?= $this->escape($service->service_output) ?>
</span>
<?= $this->qlink(
'',
'monitoring/show/service',
array(
'host' => $hostName,
'service' => $serviceDescription
),
array(
'aria-describedby' => $ariaDescribedById,
'class' => 'bg-state-' . Service::getStateText($service->service_state) . ($service->service_handled ? ' handled' : ''),
'title' => $this->escape($service->service_output),
'aria-label' => sprintf(
$this->translate('Show detailed information for service %s on host %s'),
$service->service_display_name,
$service->host_display_name
)
)
); ?>
</td>
<?php endforeach ?>
</tr>
<?php endforeach ?>
</tbody>
</table>
</table>
</div>

View File

@ -1,27 +1,28 @@
<?php
switch ($comment->type) {
switch ($comment->type) {
case 'flapping':
$icon = 'flapping';
$title = $this->translate('Flapping');
$tooltip = $this->translate('Comment was caused by a flapping host or service.');
$tooltip = $this->translate('Comment was caused by a flapping host or service');
break;
case 'comment':
$icon = 'user';
$title = $this->translate('User Comment');
$tooltip = $this->translate('Comment was created by an user.');
$tooltip = $this->translate('Comment was created by an user');
break;
case 'downtime':
$icon = 'plug';
$title = $this->translate('Downtime');
$tooltip = $this->translate('Comment was caused by a downtime.');
$tooltip = $this->translate('Comment was caused by a downtime');
break;
case 'ack':
$icon = 'ok';
$title = $this->translate('Acknowledgement');
$tooltip = $this->translate('Comment was caused by an acknowledgement.');
$tooltip = $this->translate('Comment was caused by an acknowledgement');
break;
}
?>
<strong><?= $this->escape($title); ?></strong><br>
<strong><?= $this->escape($title) ?></strong>
<br>
<?= $this->icon($icon, $tooltip) ?>
<?= $this->timeAgo($comment->timestamp, $this->compact); ?>
<?= $this->timeAgo($comment->timestamp, $this->compact) ?>

View File

@ -1,17 +1,17 @@
<?php if ($comment->objecttype === 'service'): ?>
<?= $this->icon('service', $this->translate('Service')); ?>
<?= $this->icon('service', $this->translate('Service')) ?>
<?= sprintf(
'%s: %s',
$comment->host_display_name,
$comment->service_display_name
) ?>
<?php else: ?>
<?= $this->icon('host', $this->translate('Host')); ?>
<?= $this->link()->host($comment->host_name, $comment->host_display_name); ?>
<?= $this->icon('host', $this->translate('Host')) ?>
<?= $this->link()->host($comment->host_name, $comment->host_display_name) ?>
<?php endif ?>
<br>
<?= $this->icon('comment', $this->translate('Comment')); ?> <?= isset($comment->author)
? '[' . $this->escape($comment->author) . '] '
: '';
?><?= $this->escape($comment->comment); ?>
<?= $this->icon('comment', $this->translate('Comment')) ?>
<?php if (isset($comment->author)): ?>
[<?= $this->escape($comment->author) ?>]
<?php endif ?>
<?= $this->escape($comment->comment) ?>

View File

@ -1,32 +1,32 @@
<table class="action">
<?php $i = 0; foreach ($comments as $comment):
if (++ $i > 5) {
continue;
<table class="action" data-base-target="_next">
<tbody>
<?php
foreach ($comments as $i => $comment):
if ($i > 5) {
break;
}
$this->comment = $comment;
?>
<tr class="state invalid">
<td class="state" style="width: 12em;">
<?= $this->render('partials/comment/comment-description.phtml'); ?>
</td>
<td>
<?= $this->render('partials/comment/comment-detail.phtml'); ?>
</td>
<td class="state" style="width: 12em;">
<?= $this->partial('partials/comment/comment-description.phtml', array('comment' => $comment)) ?>
</td>
<td>
<?= $this->partial('partials/comment/comment-detail.phtml', array('comment' => $comment)) ?>
</td>
</tr>
<?php endforeach; ?>
<?php endforeach ?>
</tbody>
</table>
<?php if ($comments->count() > 5): ?>
<p>
<?php if ($i > 5): ?>
<?= $this->qlink(
sprintf($this->translate('show all %d comments'), $i),
sprintf($this->translate('List all %d comments'), $comments->count()),
$listAllLink,
null,
array(
'icon' => $i > 5 ? 'down-open' : '',
'data-base-target' => "_next"
'data-base-target' => '_next',
'icon' => 'down-open'
)
) ?>
<?php endif ?>
</p>
<?php endif ?>

View File

@ -1,95 +1,111 @@
<table class="action" data-base-target="_next">
<?php
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
?>
<table class="action" data-base-target="_next">
<tbody>
<?php $i = 0; foreach ($downtimes as $downtime):
if (++ $i > 5) {
<?php
foreach ($this->downtimes as $i => $downtime):
if ($i > 5) {
break;
} ?>
<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): ?>
<?= $this->icon('service', $this->translate('Service')) ?>
<?= $this->link()->service(
$downtime->service_description,
$downtime->service_display_name,
$downtime->host_name,
$downtime->host_display_name
); ?>
<?php else: ?>
<?= $this->icon('host', $this->translate('Host')) ?>
<?= $this->link()->host($downtime->host_name, $downtime->host_display_name); ?>
<?php endif; ?>
}
if ($downtime->objecttype === 'service') {
$isService = true;
$stateText = Service::getStateText($downtime->service_state);
} else {
$isService = false;
$stateText = Host::getStateText($downtime->host_state);
}
?>
<tr class="state <?= $stateText . ($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 class="name oneline">
<?php if ($isService): ?>
<?= $this->icon('service', $this->translate('Service')) ?>
<?= $this->link()->service(
$downtime->service_description,
$downtime->service_display_name,
$downtime->host_name,
$downtime->host_display_name
) ?>
<?php else: ?>
<?= $this->icon('host', $this->translate('Host')) ?>
<?= $this->link()->host($downtime->host_name, $downtime->host_display_name) ?>
<?php endif ?>
<br>
<?php if ($downtime->is_flexible): ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
$downtime->isService
? $this->translate('This flexible service downtime was started on %s at %s and lasts for %s until %s at %s.')
: $this->translate('This flexible host downtime was started on %s at %s and lasts for %s until %s at %s.'),
$this->formatDate($downtime->start),
$this->formatTime($downtime->start),
$this->formatDuration($downtime->duration),
$this->formatDate($downtime->end),
$this->formatTime($downtime->end)
); ?>
<?php else: ?>
<?= sprintf(
$downtime->isService
? $this->translate('This flexible service downtime has been scheduled to start between %s - %s and to last for %s.')
: $this->translate('This flexible host downtime has been scheduled to start between %s - %s and to last for %s.'),
$this->formatDateTime($downtime->scheduled_start),
$this->formatDateTime($downtime->scheduled_end),
$this->formatDuration($downtime->duration)
); ?>
<?php endif ?>
<?php else: ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
$downtime->isService
? $this->translate('This fixed service downtime was started on %s at %s and expires on %s at %s.')
: $this->translate('This fixed host downtime was started on %s at %s and expires on %s at %s.'),
$this->formatDate($downtime->start),
$this->formatTime($downtime->start),
$this->formatDate($downtime->end),
$this->formatTime($downtime->end)
); ?>
<?php else: ?>
<?= sprintf(
$downtime->isService
? $this->translate('This fixed service downtime has been scheduled to start on %s at %s and to end on %s at %s.')
: $this->translate('This fixed host downtime has been scheduled to start on %s at %s and to end on %s at %s.'),
$this->formatDate($downtime->scheduled_start),
$this->formatTime($downtime->scheduled_start),
$this->formatDate($downtime->scheduled_end),
$this->formatTime($downtime->scheduled_end)
); ?>
<?php endif ?>
<?php endif ?>
<?php if ($downtime->is_flexible): ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
$isService
? $this->translate('This flexible service downtime was started on %s at %s and lasts for %s until %s at %s.')
: $this->translate('This flexible host downtime was started on %s at %s and lasts for %s until %s at %s.'),
$this->formatDate($downtime->start),
$this->formatTime($downtime->start),
$this->formatDuration($downtime->duration),
$this->formatDate($downtime->end),
$this->formatTime($downtime->end)
) ?>
<?php else: ?>
<?= sprintf(
$isService
? $this->translate('This flexible service downtime has been scheduled to start between %s - %s and to last for %s.')
: $this->translate('This flexible host downtime has been scheduled to start between %s - %s and to last for %s.'),
$this->formatDateTime($downtime->scheduled_start),
$this->formatDateTime($downtime->scheduled_end),
$this->formatDuration($downtime->duration)
) ?>
<?php endif ?>
<?php else: ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
$isService
? $this->translate('This fixed service downtime was started on %s at %s and expires on %s at %s.')
: $this->translate('This fixed host downtime was started on %s at %s and expires on %s at %s.'),
$this->formatDate($downtime->start),
$this->formatTime($downtime->start),
$this->formatDate($downtime->end),
$this->formatTime($downtime->end)
) ?>
<?php else: ?>
<?= sprintf(
$isService
? $this->translate('This fixed service downtime has been scheduled to start on %s at %s and to end on %s at %s.')
: $this->translate('This fixed host downtime has been scheduled to start on %s at %s and to end on %s at %s.'),
$this->formatDate($downtime->scheduled_start),
$this->formatTime($downtime->scheduled_start),
$this->formatDate($downtime->scheduled_end),
$this->formatTime($downtime->scheduled_end)
) ?>
<?php endif ?>
<?php endif ?>
</td>
</tr>
<?php endforeach; ?>
<?php endforeach ?>
</tbody>
</table>
<?php if (count($downtimes) > 5): ?>
<?php if ($downtimes->count() > 5): ?>
<p>
<?= $this->qlink(
sprintf($this->translate('List all %d downtimes'), $i),
sprintf($this->translate('List all %d downtimes'), $downtimes->count()),
$listAllLink,
null,
array(
'icon' => 'down-open',
'data-base-target' => "_next"
'data-base-target' => '_next',
'icon' => 'down-open'
)
) ?>
</p>

View File

@ -1,110 +0,0 @@
<?php if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs; ?>
</div>
<?php endif;
$rv = $this->runtimeVariables()->create($this->runtimevariables);
$cp = $this->checkPerformance()->create($this->checkperformance);
?>
<div class="content processinfo">
<h4>Object summaries</h4>
<table class="table-bordered table">
<thead>
<tr>
<td style="width: 300px;">&nbsp;</td>
<td># overall / scheduled</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<strong>Hosts</strong>
</td>
<td>
<?= $rv->total_hosts; ?>
/ <?= $rv->total_scheduled_hosts; ?>
</td>
</tr>
<tr>
<td>
<strong>Services</strong>
</td>
<td>
<?= $rv->total_services; ?>
/ <?= $rv->total_scheduled_services; ?>
</td>
</tr>
<tr>
<td>
<strong>Average services per host</strong>
</td>
<td>
<?= sprintf('%.2f', $rv->average_services_per_host); ?>
/ <?= sprintf('%.2f', $rv->average_scheduled_services_per_host); ?>
</td>
</tr>
</tbody>
</table>
<h4>Active checks</h4>
<table class="table-bordered table">
<thead>
<tr>
<td style="width: 300px;">&nbsp;</td>
<td>#</td>
<td>Latency</td>
<td>Execution time</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<strong>Host Checks</strong>
</td>
<td><?= $cp->host_active_count; ?></td>
<td><?= sprintf('%.3f', $cp->host_active_latency_avg); ?>s</td>
<td><?= sprintf('%.3f', $cp->host_active_execution_avg); ?>s</td>
</tr>
<tr>
<td>
<strong>Service Checks</strong>
</td>
<td><?= $cp->service_active_count; ?></td>
<td><?= sprintf('%.3f', $cp->service_active_latency_avg); ?>s</td>
<td><?= sprintf('%.3f', $cp->service_active_execution_avg); ?>s</td>
</tr>
</tbody>
</table>
<h4>Passive checks</h4>
<table class="table-bordered table">
<thead>
<tr>
<td style="width: 300px;">&nbsp;</td>
<td>#</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<strong>Host Checks</strong>
</td>
<td><?= $cp->host_passive_count; ?></td>
</tr>
<tr>
<td>
<strong>Service Checks</strong>
</td>
<td><?= $cp->service_passive_count; ?></td>
</tr>
</tbody>
</table>
</div>

View File

@ -240,3 +240,9 @@ $dashboard->add(
$this->translate('Host Problems'),
'monitoring/list/hosts?host_problem=1&sort=host_severity'
);
/*
* CSS
*/
$this->provideCssFile('colors.less');
$this->provideCssFile('service-grid.less');

View File

@ -55,6 +55,20 @@ class CommentQuery extends IdoQuery
*/
protected $subQueries = array();
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -58,6 +58,20 @@ class CommentdeletionhistoryQuery extends IdoQuery
*/
protected $fetchHistoryColumns = false;
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -58,6 +58,20 @@ class CommenthistoryQuery extends IdoQuery
*/
protected $fetchHistoryColumns = false;
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -60,6 +60,20 @@ class DowntimeQuery extends IdoQuery
*/
protected $subQueries = array();
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -58,6 +58,20 @@ class DowntimeendhistoryQuery extends IdoQuery
*/
protected $fetchHistoryColumns = false;
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -58,6 +58,20 @@ class DowntimestarthistoryQuery extends IdoQuery
*/
protected $fetchHistoryColumns = false;
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -75,6 +75,20 @@ class EventhistoryQuery extends IdoQuery
$this->joinedVirtualTables['eventhistory'] = true;
}
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -66,6 +66,20 @@ class HostgroupsummaryQuery extends IdoQuery
*/
protected $subQueries = array();
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -257,62 +257,65 @@ class HoststatusQuery extends IdoQuery
*/
public function getGroup()
{
$group = array();
if ($this->hasJoinedVirtualTable('hostgroups') || $this->hasJoinedVirtualTable('services')) {
$group = array('h.host_id', 'ho.object_id');
if ($this->hasJoinedVirtualTable('hoststatus')) {
$group[] = 'hs.hoststatus_id';
}
if ($this->hasJoinedVirtualTable('serviceproblemsummary')) {
$group[] = 'sps.unhandled_services_count';
}
if ($this->hasJoinedVirtualTable('hostgroups')) {
$selected = false;
foreach ($this->columns as $alias => $column) {
if ($column instanceof Zend_Db_Expr) {
continue;
}
$table = $this->aliasToTableName(
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
);
if ($table === 'hostgroups') {
$selected = true;
break;
}
}
if ($selected) {
$group[] = 'hg.hostgroup_id';
$group[] = 'hgo.object_id';
}
}
if ($this->hasJoinedVirtualTable('servicegroups')) {
$selected = false;
foreach ($this->columns as $alias => $column) {
if ($column instanceof Zend_Db_Expr) {
continue;
}
$table = $this->aliasToTableName(
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
);
if ($table === 'servicegroups') {
$selected = true;
break;
}
}
if ($selected) {
$group[] = 'sg.servicegroup_id';
$group[] = 'sgo.object_id';
}
$group = parent::getGroup() ?: array();
if (! is_array($group)) {
$group = array($group);
}
$groupedTables = array();
if ($this->hasJoinedVirtualTable('servicegroups')) {
$serviceGroupColumns = array_keys($this->columnMap['servicegroups']);
$selectedServiceGroupColumns = array_intersect($serviceGroupColumns, array_keys($this->columns));
if (! empty($selectedServiceGroupColumns)) {
$group[] = 'ho.object_id';
$group[] = 'h.host_id';
$group[] = 'sgo.object_id';
$group[] = 'sg.servicegroup_id';
$groupedTables['hosts'] = true;
$groupedTables['servicegroups'] = true;
}
}
if ($this->hasJoinedVirtualTable('hostgroups')) {
$hostGroupColumns = array_keys($this->columnMap['hostgroups']);
$selectedHostGroupColumns = array_intersect($hostGroupColumns, array_keys($this->columns));
if (! empty($selectedHostGroupColumns)) {
if (! isset($groupedTables['hosts'])) {
$group[] = 'ho.object_id';
$group[] = 'h.host_id';
$groupedTables['hosts'] = true;
}
$group[] = 'hgo.object_id';
$group[] = 'hg.hostgroup_id';
$groupedTables['hostgroups'] = true;
}
}
if (! empty($groupedTables)) {
foreach ($this->columns as $alias => $column) {
if ($column instanceof Zend_Db_Expr || $column === '(NULL)') {
continue;
}
$tableName = $this->aliasToTableName(
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
);
if (isset($groupedTables[$tableName])) {
continue;
}
switch ($tableName) {
case 'hoststatus':
$group[] = 'hs.hoststatus_id';
break;
case 'serviceproblemsummary':
$group[] = 'sps.unhandled_services_count';
break;
case 'services':
$group[] = 'so.object_id';
$group[] = 's.service_id';
break;
default:
continue 2;
}
$groupedTables[$tableName] = true;
}
}
return $group;
}

View File

@ -34,6 +34,14 @@ class HoststatussummaryQuery extends IdoQuery
*/
protected $subSelect;
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
return $this->subSelect->allowsCustomVars();
}
/**
* {@inheritdoc}
*/

View File

@ -461,17 +461,23 @@ abstract class IdoQuery extends DbQuery
if ($filter->getExpression() === '*') {
return; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing
}
$col = $filter->getColumn();
$this->requireColumn($col);
if ($this->isCustomvar($col)) {
$col = $this->getCustomvarColumnName($col);
$alias = $filter->getColumn();
$this->requireColumn($alias);
if ($this->isCustomvar($alias)) {
$column = $this->getCustomvarColumnName($alias);
} else {
$col = $this->aliasToColumnName($col);
$column = $this->aliasToColumnName($alias);
}
if (isset($this->columnsWithoutCollation[$alias])) {
$expression = $filter->getExpression();
if (is_array($expression)) {
$filter->setExpression(array_map('strtolower', $expression));
} else {
$filter->setExpression(strtolower($expression));
$filter->setColumn($col);
}
}
$filter->setColumn($column);
} else {
foreach ($filter->filters() as $filter) {
$this->requireFilterColumns($filter);
@ -489,48 +495,11 @@ abstract class IdoQuery extends DbQuery
return parent::addFilter($filter);
}
/**
* Recurse the given filter and ensure that any string conversion is case-insensitive
*
* @param Filter $filter
*/
protected function lowerColumnsWithoutCollation(Filter $filter)
{
if ($filter instanceof FilterExpression) {
if (
in_array($filter->getColumn(), $this->columnsWithoutCollation)
&& strpos($filter->getColumn(), 'LOWER') !== 0
) {
$filter->setColumn('LOWER(' . $filter->getColumn() . ')');
$expression = $filter->getExpression();
if (is_array($expression)) {
$filter->setExpression(array_map('strtolower', $expression));
} else {
$filter->setExpression(strtolower($expression));
}
}
} else {
foreach ($filter->filters() as $chainedFilter) {
$this->lowerColumnsWithoutCollation($chainedFilter);
}
}
}
protected function applyFilterSql($select)
{
if (! empty($this->columnsWithoutCollation)) {
$this->lowerColumnsWithoutCollation($this->filter);
}
parent::applyFilterSql($select);
}
public function where($condition, $value = null)
{
if ($value === '*') {
return $this; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing
}
$this->requireColumn($condition);
$col = $this->getMappedField($condition);
if ($col === null) {
@ -578,7 +547,6 @@ abstract class IdoQuery extends DbQuery
if (! empty($this->columnsWithoutCollation)) {
return in_array($column, $this->columnsWithoutCollation) || strpos($column, 'LOWER') !== 0;
}
return preg_match('/ COLLATE .+$/', $column) === 1;
}
@ -603,27 +571,27 @@ abstract class IdoQuery extends DbQuery
}
/**
* Apply postgresql specific query initialization
* Apply PostgreSQL specific query initialization
*/
private function initializeForPostgres()
{
$this->customVarsJoinTemplate =
'%1$s = %2$s.object_id AND LOWER(%2$s.varname) = %3$s';
foreach ($this->columnMap as $table => & $columns) {
foreach ($columns as $key => & $value) {
$value = preg_replace('/ COLLATE .+$/', '', $value, -1, $count);
if ($count > 0) {
$this->columnsWithoutCollation[] = $this->getMappedField($key);
foreach ($this->columnMap as $table => &$columns) {
foreach ($columns as $alias => &$column) {
if (false !== $pos = strpos($column, ' COLLATE')) {
$column = 'LOWER(' . substr($column, 0, $pos) . ')';
$this->columnsWithoutCollation[$alias] = true;
}
$value = preg_replace(
$column = preg_replace(
'/inet_aton\(([[:word:].]+)\)/i',
'(CASE WHEN $1 ~ \'(?:[0-9]{1,3}\\\\.){3}[0-9]{1,3}\' THEN $1::inet - \'0.0.0.0\' ELSE NULL END)',
$value
$column
);
$value = preg_replace(
$column = preg_replace(
'/UNIX_TIMESTAMP(\((?>[^()]|(?-1))*\))/i',
'CASE WHEN ($1 < \'1970-01-03 00:00:00+00\'::timestamp with time zone) THEN 0 ELSE UNIX_TIMESTAMP($1) END',
$value
$column
);
}
}

View File

@ -20,7 +20,7 @@ class InstanceQuery extends IdoQuery
*/
protected function joinBaseTables()
{
$this->select()->from(array('i' => $this->prefix . 'instances'));
$this->select()->from(array('i' => $this->prefix . 'instances'), array());
$this->joinedVirtualTables['instances'] = true;
}
}

View File

@ -129,6 +129,20 @@ class NotificationQuery extends IdoQuery
$this->notificationQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
}
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -58,6 +58,20 @@ class ServicegroupsummaryQuery extends IdoQuery
*/
protected $subQueries = array();
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -381,68 +381,60 @@ class ServicestatusQuery extends IdoQuery
if (! is_array($group)) {
$group = array($group);
}
if ($this->hasJoinedVirtualTable('hostgroups') || $this->hasJoinedVirtualTable('servicegroups')) {
$group[] = 's.service_id';
$group[] = 'so.object_id';
if ($this->hasJoinedVirtualTable('hosts')) {
$group[] = 'h.host_id';
}
if ($this->hasJoinedVirtualTable('hoststatus')) {
$group[] = 'hs.hoststatus_id';
}
if ($this->hasJoinedVirtualTable('servicestatus')) {
$group[] = 'ss.servicestatus_id';
}
if ($this->hasJoinedVirtualTable('hostgroups')) {
$selected = false;
foreach ($this->columns as $alias => $column) {
if ($column instanceof Zend_Db_Expr) {
continue;
}
$table = $this->aliasToTableName(
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
);
if ($table === 'hostgroups') {
$selected = true;
break;
}
}
if ($selected) {
$group[] = 'hg.hostgroup_id';
$group[] = 'hgo.object_id';
}
}
if ($this->hasJoinedVirtualTable('servicegroups')) {
$selected = false;
foreach ($this->columns as $alias => $column) {
if ($column instanceof Zend_Db_Expr) {
continue;
}
$table = $this->aliasToTableName(
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
);
if ($table === 'servicegroups') {
$selected = true;
break;
}
}
if ($selected) {
$group[] = 'sg.servicegroup_id';
$group[] = 'sgo.object_id';
}
$groupedTables = array();
if ($this->hasJoinedVirtualTable('servicegroups')) {
$serviceGroupColumns = array_keys($this->columnMap['servicegroups']);
$selectedServiceGroupColumns = array_intersect($serviceGroupColumns, array_keys($this->columns));
if (! empty($selectedServiceGroupColumns)) {
$group[] = 'so.object_id';
$group[] = 's.service_id';
$group[] = 'sgo.object_id';
$group[] = 'sg.servicegroup_id';
$groupedTables['services'] = true;
$groupedTables['servicegroups'] = true;
}
}
if ($this->hasJoinedVirtualTable('hostgroups')) {
$hostGroupColumns = array_keys($this->columnMap['hostgroups']);
$selectedHostGroupColumns = array_intersect($hostGroupColumns, array_keys($this->columns));
if (! empty($selectedHostGroupColumns)) {
if (! isset($groupedTables['services'])) {
$group[] = 'so.object_id';
$group[] = 's.service_id';
$groupedTables['services'] = true;
}
$group[] = 'hgo.object_id';
$group[] = 'hg.hostgroup_id';
$groupedTables['hostgroups'] = true;
}
}
if (! empty($groupedTables)) {
foreach ($this->columns as $alias => $column) {
if ($column instanceof Zend_Db_Expr || $column === '(NULL)') {
continue;
}
$tableName = $this->aliasToTableName(
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
);
if (isset($groupedTables[$tableName])) {
continue;
}
switch ($tableName) {
case 'hosts':
$group[] = 'h.host_id';
break;
case 'hoststatus':
$group[] = 'hs.hoststatus_id';
break;
case 'servicestatus':
$group[] = 'ss.servicestatus_id';
break;
default:
continue 2;
}
$groupedTables[$tableName] = true;
}
}
return $group;
}
}

View File

@ -46,6 +46,14 @@ class ServicestatussummaryQuery extends IdoQuery
*/
protected $subSelect;
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
return $this->subSelect->allowsCustomVars();
}
/**
* {@inheritdoc}
*/

View File

@ -58,6 +58,20 @@ class StatehistoryQuery extends IdoQuery
*/
protected $fetchHistoryColumns = false;
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -130,6 +130,20 @@ We have to find a better solution here.
*/
protected $subQueries = array();
/**
* {@inheritdoc}
*/
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
/**
* {@inheritdoc}
*/

View File

@ -0,0 +1,43 @@
/*! Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
.bg-state-ok,
.bg-state-up {
background-color: @colorOk;
}
.bg-state-warning {
background-color: @colorWarning;
&.handled {
background-color: @colorWarningHandled;
}
}
.bg-state-critical,
.bg-state-down {
background-color: @colorCritical;
&.handled {
background-color: @colorCriticalHandled;
}
}
.bg-state-unreachable {
background-color: @colorUnreachable;
&.handled {
background-color: @colorUnreachableHandled;
}
}
.bg-state-unknown {
background-color: @colorUnknown;
&.handled {
background-color: @colorUnknownHandled;
}
}
.bg-state-pending {
background-color: @colorPending;
}

View File

@ -842,112 +842,6 @@ table.joystick-pagination {
}
}
table.pivot {
a {
text-decoration: none;
color: black;
&:hover {
color: @colorTextDefault;
}
}
& > thead {
th {
height: 6em;
div {
margin-right: -1.5em;
padding-left: 1.3em;
span {
width: 1.5em;
margin-right: 0.25em;
margin-top: 4em;
line-height: 2em;
white-space: nowrap;
display: block;
float: left;
transform: rotate(-45deg);
transform-origin: bottom left;
-o-transform: rotate(-45deg);
-o-transform-origin: bottom left;
-ms-transform: rotate(-45deg);
-ms-transform-origin: bottom left;
-moz-transform: rotate(-45deg);
-moz-transform-origin: bottom left;
-webkit-transform: rotate(-45deg);
-webkit-transform-origin: bottom left;
//filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
abbr {
border: 0; // Remove highlighting in firefox
font-size: 0.8em;
}
}
}
}
}
& > tbody {
th {
padding: 0 14px 0 0;
white-space: nowrap;
a {
font-size: 0.8em;
}
}
td {
padding: 2px;
min-width: 1.5em;
line-height: 1.5em;
text-align: center;
a {
width: 1.5em;
height: 1.5em;
display: block;
border-radius: 0.5em;
&.state_ok {
background-color: @colorOk;
}
&.state_pending {
background-color: @colorPending;
}
&.state_warning {
background-color: @colorWarning;
&.handled {
background-color: @colorWarningHandled;
}
}
&.state_critical {
background-color: @colorCritical;
&.handled {
background-color: @colorCriticalHandled;
}
}
&.state_unknown {
background-color: @colorUnknown;
&.handled {
background-color: @colorUnknownHandled;
}
}
}
}
}
}
/* End of monitoring pivot table styles */
/* Monitoring timeline styles */

View File

@ -0,0 +1,38 @@
/*! Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
table.service-grid-table {
white-space: nowrap;
th {
a {
color: @colorMainLink;
font-weight: normal;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
td {
text-align: center;
width: 1.5em;
a {
.rounded-corners(0.4em);
display: block;
height: 1.5em;
width: 1.5em;
}
}
th.rotate-45 {
height: 6em;
div {
.transform(translate(0.4em, 2.1em) rotate(315deg));
width: 1.5em;
}
}
}

View File

@ -1,10 +1,12 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Web\Controller;
use Icinga\Module\Setup\WebWizard;
namespace Icinga\Module\Setup\Controllers;
class Setup_IndexController extends Controller
use Icinga\Module\Setup\WebWizard;
use Icinga\Web\Controller;
class IndexController extends Controller
{
/**
* Whether the controller requires the user to be authenticated

View File

@ -3,7 +3,7 @@
namespace Icinga\Module\Setup\Forms;
use PDOException;
use Exception;
use Icinga\Web\Form;
use Icinga\Forms\Config\Resource\DbResourceForm;
use Icinga\Module\Setup\Utils\DbTool;
@ -112,7 +112,7 @@ class DbResourcePage extends Form
try {
$db = new DbTool($this->getValues());
$db->checkConnectivity();
} catch (PDOException $e) {
} catch (Exception $e) {
$this->error(sprintf(
$this->translate('Failed to successfully validate the configuration: %s'),
$e->getMessage()
@ -120,34 +120,49 @@ class DbResourcePage extends Form
return false;
}
if ($this->getValue('db') === 'pgsql') {
if (! $db->isConnected()) {
try {
$db->connectToDb();
} catch (PDOException $e) {
$this->warning($this->translate(sprintf(
'Unable to check the server\'s version. This is usually not a critical error as there is'
. ' probably only access to the database permitted which does not exist yet. If you are'
. ' absolutely sure you are running PostgreSQL in a version equal to or newer than 9.1,'
. ' you can skip the validation and safely proceed to the next step. The error was: %s',
$e->getMessage()
)));
return false;
}
}
$state = true;
$connectionError = null;
$version = $db->getServerVersion();
if (version_compare($version, '9.1', '<')) {
$this->error($this->translate(sprintf(
'The server\'s version %s is too old. The minimum required version is %s.',
$version,
'9.1'
try {
$db->connectToDb();
} catch (Exception $e) {
$connectionError = $e;
}
if ($connectionError === null && array_search('icinga_instances', $db->listTables(), true) !== false) {
$this->warning($this->translate(
'The database you\'ve configured to use for Icinga Web 2 seems to be the one of Icinga. Please be aware'
. ' that this database configuration is supposed to be used for Icinga Web 2\'s configuration and that'
. ' it is highly recommended to not mix different schemas in the same database. If this is intentional,'
. ' you can skip the validation and ignore this warning. If not, please provide a different database.'
));
$state = false;
}
if ($this->getValue('db') === 'pgsql') {
if ($connectionError !== null) {
$this->warning($this->translate(sprintf(
'Unable to check the server\'s version. This is usually not a critical error as there is'
. ' probably only access to the database permitted which does not exist yet. If you are'
. ' absolutely sure you are running PostgreSQL in a version equal to or newer than 9.1,'
. ' you can skip the validation and safely proceed to the next step. The error was: %s',
$connectionError->getMessage()
)));
return false;
$state = false;
} else {
$version = $db->getServerVersion();
if (version_compare($version, '9.1', '<')) {
$this->error($this->translate(sprintf(
'The server\'s version %s is too old. The minimum required version is %s.',
$version,
'9.1'
)));
$state = false;
}
}
}
return true;
return $state;
}
/**

View File

@ -24,9 +24,5 @@ use Icinga\Web\Wizard;
<?php endforeach ?>
<?= $form->getElement($form->getTokenElementName()); ?>
<?= $form->getElement($form->getUidElementName()); ?>
<div class="buttons">
<?= $form->getElement(Wizard::BTN_PREV); ?>
<?= $form->getElement(Wizard::BTN_NEXT); ?>
<?= $form->getElement(Wizard::PROGRESS_ELEMENT); ?>
</div>
<?= $form->getDisplayGroup('buttons'); ?>
</form>

View File

@ -2,6 +2,10 @@
use Icinga\Web\Wizard;
if (! $form->getWizard()->getRequirements()->fulfilled()) {
$form->getElement(Wizard::BTN_NEXT)->setAttrib('disabled', 1);
}
?>
<h1>Icinga Web 2</h1>
<?= $form->getWizard()->getRequirements(true); ?>
@ -20,14 +24,12 @@ use Icinga\Web\Wizard;
<?= $form->getElement($form->getTokenElementName()); ?>
<?= $form->getElement($form->getUidElementName()); ?>
<div class="buttons">
<?= $form->getElement(Wizard::BTN_PREV); ?>
<?php
$btn = $form->getElement(Wizard::BTN_NEXT);
if (! $form->getWizard()->getRequirements()->fulfilled()) {
$btn->setAttrib('disabled', 1);
}
echo $btn;
$double = clone $form->getElement(Wizard::BTN_NEXT);
echo $double->setAttrib('class', 'double');
?>
<?= $form->getElement(Wizard::BTN_PREV); ?>
<?= $form->getElement(Wizard::BTN_NEXT); ?>
<?= $form->getElement(Wizard::PROGRESS_ELEMENT); ?>
<div class="requirements-refresh">
<?php $title = $this->translate('You may also need to restart the web-server for the changes to take effect!'); ?>

View File

@ -2,6 +2,8 @@
use Icinga\Web\Wizard;
$form->getElement(Wizard::BTN_NEXT)->setAttrib('class', 'finish');
?>
<p><?= sprintf(
$this->translate(
@ -31,9 +33,5 @@ use Icinga\Web\Wizard;
>
<?= $form->getElement($form->getTokenElementName()); ?>
<?= $form->getElement($form->getUidElementName()); ?>
<div class="buttons">
<?= $form->getElement(Wizard::BTN_PREV); ?>
<?= $form->getElement(Wizard::BTN_NEXT)->setAttrib('class', 'finish'); ?>
<?= $form->getElement(Wizard::PROGRESS_ELEMENT); ?>
</div>
<?= $form->getDisplayGroup('buttons'); ?>
</form>

View File

@ -271,6 +271,8 @@ class DbTool
$this->config['db']
);
}
$this->zendConn->getConnection(); // Force connection attempt
}
/**

View File

@ -0,0 +1,19 @@
/*! Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
.transform(@transform) {
-webkit-transform: @transform;
-moz-transform: @transform;
-ms-transform: @transform;
-o-transform: @transform;
transform: @transform;
}
.rounded-corners(@border-radius: 0.4em) {
-webkit-border-radius: @border-radius;
-moz-border-radius: @border-radius;
border-radius: @border-radius;
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
}

View File

@ -4,8 +4,6 @@
"use strict";
var activeMenuId;
Icinga.Behaviors = Icinga.Behaviors || {};
var Navigation = function (icinga) {
@ -17,49 +15,93 @@
this.on('mouseenter', '#menu > nav > ul > li', this.menuTitleHovered, this);
this.on('mouseleave', '#sidebar', this.leaveSidebar, this);
this.on('rendered', this.onRendered, this);
/**
* The DOM-Path of the active item
*
* @see getDomPath
*
* @type {null|Array}
*/
this.active = null;
/**
* The DOM-Path of the hovered item
*
* @see getDomPath
*
* @type {null|Array}
*/
this.hovered = null;
/**
* @type {HTMLElement}
*/
this.element = null;
};
Navigation.prototype = new Icinga.EventListener();
/**
* Apply the menu selection and hovering according to the current state
*
* @param evt {Object} The event context
*/
Navigation.prototype.onRendered = function(evt) {
var self = evt.data.self;
// get original source element of the rendered-event
var el = evt.target;
if (activeMenuId) {
// restore old menu state
$('#menu li.active', el).removeClass('active');
var $selectedMenu = $('#' + activeMenuId).addClass('active');
var $outerMenu = $selectedMenu.parent().closest('li');
if ($outerMenu.size()) {
$outerMenu.addClass('active');
}
this.element = evt.target;
/*
Recreate the html content of the menu item to force the browser to update the layout, or else
the link would only be visible as active after another click or page reload in Gecko and WebKit.
if (! self.active) {
// There is no stored menu item, therefore it is assumed that this is the first rendering
// of the navigation after the page has been opened.
fixes #7897
*/
$selectedMenu.html($selectedMenu.html());
} else {
// store menu state
var $menus = $('#menu li.active', el);
// initialise the menu selected by the backend as active.
var $menus = $('#menu li.active', evt.target);
if ($menus.size()) {
activeMenuId = $menus[0].id;
$menus.find('li.active').first().each(function () {
activeMenuId = this.id;
$menus.each(function () {
self.setActive($(this));
});
} else {
// if no item is marked as active, try to select the menu from the current URL
self.setActiveByUrl($('#col1').data('icingaUrl'));
}
}
// restore hovered menu after auto-reload
if (self.hovered) {
var hovered = self.icinga.utils.getElementByDomPath(self.hovered);
self.refresh();
};
/**
* Re-render the menu selection and menu hovering according to the current state
*/
Navigation.prototype.refresh = function() {
// restore selection to current active element
if (this.active) {
var $el = $(this.icinga.utils.getElementByDomPath(this.active));
this.setActive($el);
/*
* Recreate the html content of the menu item to force the browser to update the layout, or else
* the link would only be visible as active after another click or page reload in Gecko and WebKit.
*
* fixes #7897
*/
if ($el.is('li')) {
$el.html($el.html());
}
}
// restore hovered menu to current hovered element
if (this.hovered) {
var hovered = this.icinga.utils.getElementByDomPath(this.hovered);
if (hovered) {
self.hoverElement($(hovered));
this.hoverElement($(hovered));
}
}
};
/**
* Handle a link click in the menu
*
* @param event
*/
Navigation.prototype.linkClicked = function(event) {
var $a = $(this);
var href = $a.attr('href');
@ -71,10 +113,8 @@
if (href.match(/#/)) {
// ...it may be a menu section without a dedicated link.
// Switch the active menu item:
self.setActive($a);
$li = $a.closest('li');
$('#menu .active').removeClass('active');
$li.addClass('active');
activeMenuId = $($li).attr('id');
if ($li.hasClass('hover')) {
$li.removeClass('hover');
}
@ -86,7 +126,7 @@
return;
}
} else {
activeMenuId = $(event.target).closest('li').attr('id');
self.setActive($(event.target));
}
// update target url of the menu container to the clicked link
var $menu = $('#menu');
@ -95,9 +135,82 @@
$menu.data('icinga-url', menuDataUrl);
};
/**
* Activate a menu item based on the current URL
*
* Activate a menu item that is an exact match or fall back to items that match the base URL
*
* @param url {String} The url to match
*/
Navigation.prototype.setActiveByUrl = function(url) {
this.resetActive();
// try to active the first item that has an exact URL match
this.setActive($('#menu [href="' + url + '"]'));
// the url may point to the search field, which must be activated too
if (! this.active) {
this.setActive($('#menu form[action="' + this.icinga.utils.parseUrl(url).path + '"]'));
}
// some urls may have custom filters which won't match any menu item, in that case search
// for a menu item that points to the base action without any filters
if (! this.active) {
this.setActive($('#menu [href="' + this.icinga.utils.parseUrl(url).path + '"]').first());
}
// if no item with the base action exists, activate the first URL that beings with the base path
// but may have different filters
if (! this.active) {
this.setActive($('#menu [href^="' + this.icinga.utils.parseUrl(url).path + '"]').first());
}
};
/**
* Try to select a new URL by
*
* @param url
*/
Navigation.prototype.trySetActiveByUrl = function(url) {
var active = this.active;
this.setActiveByUrl(url);
if (! this.active && active) {
this.setActive($(this.icinga.utils.getElementByDomPath(active)));
}
};
/**
* Remove all active elements
*/
Navigation.prototype.clear = function() {
// menu items
$('#menu li.active', this.element).removeClass('active');
// search fields
$('#menu input.active', this.element).removeClass('active');
};
/**
* Select all menu items in the selector as active and unfold surrounding menus when necessary
*
* @param $item {jQuery} The jQuery selector
*/
Navigation.prototype.select = function($item) {
// support selecting the url of the menu entry
var $input = $item.find('input');
$item = $item.closest('li');
if ($item.length) {
// select the current item
var $selectedMenu = $item.addClass('active');
// unfold the containing menu
var $outerMenu = $selectedMenu.parent().closest('li');
if ($outerMenu.size()) {
$outerMenu.addClass('active');
}
} else if ($input.length) {
$input.addClass('active');
}
};
/**
@ -106,14 +219,59 @@
* @param $el {jQuery} A selector pointing to the active element
*/
Navigation.prototype.setActive = function($el) {
$el.closest('li').addClass('active');
$el.parents('li').addClass('active');
activeMenuId = $el.closest('li').attr('id');
this.clear();
this.select($el);
if ($el.closest('li')[0]) {
this.active = this.icinga.utils.getDomPath($el.closest('li')[0]);
} else if ($el.find('input')[0]) {
this.active = this.icinga.utils.getDomPath($el[0]);
} else {
this.active = null;
}
// TODO: push to history
};
/**
* Reset the active element to nothing
*/
Navigation.prototype.resetActive = function() {
$('#menu .active').removeClass('active');
activeMenuId = null;
this.clear();
this.active = null;
};
/**
* Called when the history changes
*
* @param url The url of the new state
* @param data The active menu item of the new state
*/
Navigation.prototype.onPopState = function (url, data) {
// 1. get selection data and set active menu
console.log('popstate:', data);
if (data) {
var active = this.icinga.utils.getElementByDomPath(data);
if (!active) {
this.logger.fail(
'Could not restore active menu from history, path in DOM not found.',
data,
url
);
return;
}
this.setActive($(active));
} else {
this.resetActive();
}
};
/**
* Called when the current state gets pushed onto the history, can return a value
* to be preserved as the current state
*
* @returns {null|Array} The currently active menu item
*/
Navigation.prototype.onPushState = function () {
return this.active;
};
Navigation.prototype.menuTitleHovered = function(event) {

View File

@ -228,11 +228,11 @@
icinga.logger.debug('events/submitForm: Button is event.currentTarget');
}
if ($el && ($el.is('input[type=submit]') || $el.is('button[type=submit]')) && $el.is(':focus')) {
if ($el && ($el.is('input[type=submit]') || $el.is('button[type=submit]'))) {
$button = $el;
} else {
icinga.logger.debug(
'events/submitForm: Can not determine submit button, using the last one in form'
'events/submitForm: Can not determine submit button, using the first one in form'
);
}
}
@ -252,7 +252,7 @@
}
if ($button.length === 0) {
$button = $('button[type=submit]', $form).add('input[type=submit]', $form).last();
$button = $('input[type=submit]', $form).add('button[type=submit]', $form).first();
}
if ($button.length) {

View File

@ -4,7 +4,6 @@
* Icinga.History
*
* This is where we care about the browser History API
*
*/
(function (Icinga, $) {
@ -89,7 +88,6 @@
}
});
// TODO: update navigation
// Did we find any URL? Then push it!
if (url !== '') {
this.push(url);
@ -110,7 +108,26 @@
return;
}
this.lastPushUrl = url;
window.history.pushState({icinga: true}, null, url);
window.history.pushState(
this.getBehaviorState(),
null,
url
);
},
/**
* Fetch the current state of all JS behaviors that need history support
*
* @return {Object} A key-value map, mapping behavior names to state
*/
getBehaviorState: function () {
var data = {};
$.each(this.icinga.behaviors, function (i, behavior) {
if (behavior.onPushState instanceof Function) {
data[i] = behavior.onPushState();
}
});
return data;
},
/**
@ -143,6 +160,13 @@
self.lastPushUrl = location.href;
self.applyLocationBar();
// notify behaviors of the state change
$.each(this.icinga.behaviors, function (i, behavior) {
if (behavior.onPopState instanceof Function && history.state) {
behavior.onPopState(location.href, history.state[i]);
}
});
},
applyLocationBar: function (onload) {

View File

@ -570,34 +570,26 @@
if (! req.autorefresh) {
// TODO: Hook for response/url?
var url = req.url;
if (req.$target[0].id === 'col1') {
self.icinga.behaviors.navigation.trySetActiveByUrl(url);
}
var $forms = $('[action="' + this.icinga.utils.parseUrl(url).path + '"]');
var $matches = $.merge($('[href="' + url + '"]'), $forms);
$matches.each(function (idx, el) {
if ($(el).closest('#menu').length) {
if (req.$target[0].id === 'col1') {
self.icinga.behaviors.navigation.resetActive();
}
}
});
$matches.each(function (idx, el) {
var $el = $(el);
if ($el.closest('#menu').length) {
if ($el.is('form')) {
$('input', $el).addClass('active');
} else {
if (req.$target[0].id === 'col1') {
self.icinga.behaviors.navigation.setActive($el);
}
}
// Interrupt .each, only on menu item shall be active
// Interrupt .each, only one menu item shall be active
return false;
}
});
}
// Update history when necessary. Don't do so for requests triggered
// by history or autorefresh events
// Update history when necessary
if (! req.autorefresh && req.addToHistory) {
if (req.$target.hasClass('container')) {
// We only want to care about top-level containers
@ -640,9 +632,10 @@
/*
* Test if a manual actions comes in and autorefresh is active: Stop refreshing
*/
if (req.addToHistory && ! req.autorefresh && req.$target.data('icingaRefresh') > 0) {
if (req.addToHistory && ! req.autorefresh) {
req.$target.data('icingaRefresh', 0);
req.$target.data('icingaUrl', url);
icinga.history.pushCurrentState();
}
if (typeof req.progressTimer !== 'undefined') {

View File

@ -154,7 +154,7 @@
var kill = this.cutContainer($('#col1'));
this.pasteContainer($('#col1'), col2);
this.fixControls();
this.icinga.behaviors.navigation.setActiveByUrl($('#col1').data('icingaUrl'));
this.icinga.behaviors.navigation.trySetActiveByUrl($('#col1').data('icingaUrl'));
},
cutContainer: function ($col) {
@ -480,8 +480,7 @@
* @param value {String} The value to set, can be '1', '0' and 'unchanged'
* @param $checkbox {jQuery} The checkbox
*/
setTriState: function(value, $checkbox)
{
setTriState: function(value, $checkbox) {
switch (value) {
case ('1'):
$checkbox.prop('checked', true).prop('indeterminate', false);

View File

@ -76,20 +76,19 @@
* @param {selector} element The element to check
* @returns {Boolean}
*/
isVisible: function(element)
{
var $element = $(element);
if (!$element.length) {
return false;
}
isVisible: function(element) {
var $element = $(element);
if (!$element.length) {
return false;
}
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $element.offset().top;
var elemBottom = elemTop + $element.height();
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $element.offset().top;
var elemBottom = elemTop + $element.height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom) &&
(elemBottom <= docViewBottom) && (elemTop >= docViewTop));
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom) &&
(elemBottom <= docViewBottom) && (elemTop >= docViewTop));
},
getUrlHelper: function () {

View File

@ -22,9 +22,9 @@ require_once 'Mockery/Loader.php';
$mockeryLoader = new \Mockery\Loader;
$mockeryLoader->register();
require_once($libraryPath . '/Icinga/Application/Loader.php');
require_once($libraryPath . '/Icinga/Application/ClassLoader.php');
$loader = new Icinga\Application\Loader();
$loader = new Icinga\Application\ClassLoader();
$loader->registerNamespace('Tests', $testLibraryPath);
$loader->registerNamespace('Icinga', $libraryPath . '/Icinga');
$loader->registerNamespace('Icinga\\Forms', $applicationPath . '/forms');

View File

@ -4,9 +4,9 @@
namespace Tests\Icinga\Application;
use Icinga\Test\BaseTestCase;
use Icinga\Application\Loader;
use Icinga\Application\ClassLoader;
class LoaderTest extends BaseTestCase
class ClassLoaderTest extends BaseTestCase
{
private static $classFile = 'test/My/Library/TestStruct.php';
@ -43,7 +43,7 @@ EOD;
public function testObjectCreation1()
{
$loader = new Loader();
$loader = new ClassLoader();
$loader->register();
$check = false;
@ -56,7 +56,7 @@ EOD;
}
$this->assertTrue($check);
$loader->unRegister();
$loader->unregister();
$check = true;
foreach (spl_autoload_functions() as $functions) {
@ -71,7 +71,7 @@ EOD;
public function testNamespaces()
{
$loader = new Loader();
$loader = new ClassLoader();
$loader->registerNamespace('Test\\Laola', '/tmp');
$loader->registerNamespace('Dings\\Var', '/var/tmp');
@ -89,7 +89,7 @@ EOD;
$classFile = $this->baseDir. self::$classFile;
$this->assertFileExists($classFile);
$loader = new Loader();
$loader = new ClassLoader();
$loader->registerNamespace('My\\Library', dirname($classFile));
$this->assertFalse($loader->loadClass('DOES\\NOT\\EXISTS'));
$this->assertTrue($loader->loadClass('My\\Library\\TestStruct'));
@ -100,20 +100,11 @@ EOD;
$classFile = $this->baseDir. self::$classFile;
$this->assertFileExists($classFile);
$loader = new Loader();
$loader = new ClassLoader();
$loader->registerNamespace('My\\Library', dirname($classFile));
$loader->register();
$o = new \My\Library\TestStruct();
$this->assertTrue($o->testFlag());
}
/**
* @expectedException Icinga\Exception\ProgrammingError
*/
public function testNonexistingDirectory()
{
$loader = new Loader();
$loader->registerNamespace('My\\Library', '/trullalla/123');
}
}