commit
ddafae6271
application
controllers
layouts/scripts
views/scripts/layout
doc
library/Icinga
Application/Modules
Web
modules
doc
application
controllers
views/scripts
library/Doc
monitoring
test/php
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
// @codingStandardsIgnoreStart
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
use Icinga\Web\Controller\ActionController;
|
||||
use Icinga\Web\Hook;
|
||||
use Icinga\Web\Menu;
|
||||
use Icinga\Web\Url;
|
||||
|
||||
/**
|
||||
* Create complex layout parts
|
||||
*/
|
||||
class LayoutController extends ActionController
|
||||
{
|
||||
/**
|
||||
* Render the menu
|
||||
*/
|
||||
public function menuAction()
|
||||
{
|
||||
$this->view->url = Url::fromRequest()->getRelativeUrl();
|
||||
$this->view->items = Menu::fromConfig()->getChildren();
|
||||
$this->view->sub = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the top bar
|
||||
*/
|
||||
public function topbarAction()
|
||||
{
|
||||
$topbarHtmlParts = array();
|
||||
|
||||
/** @var Hook\Layout\TopBar $hook */
|
||||
$hook = null;
|
||||
|
||||
foreach (Hook::all(Hook::TARGET_LAYOUT_TOPBAR) as $hook) {
|
||||
$topbarHtmlParts[] = $hook->getHtml($this->getRequest(), $this->view);
|
||||
}
|
||||
|
||||
$this->view->topbarHtmlParts = $topbarHtmlParts;
|
||||
|
||||
|
||||
$this->renderScript('parts/topbar.phtml');
|
||||
}
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
|
@ -1,9 +1,13 @@
|
|||
<?php echo $this->render('parts/topbar.phtml') ?>
|
||||
<div class="row">
|
||||
<?= $this->action('topbar', 'layout'); ?>
|
||||
|
||||
<div class="row">
|
||||
<!-- Only required for left/right tabs -->
|
||||
<div class="col-sm-12 col-xs-12 col-md-2 col-lg-2" id="menu">
|
||||
<?php echo $this->render('parts/navigation.phtml') ?>
|
||||
<div class="col-sm-12 col-xs-12 col-md-2 col-lg-2">
|
||||
<?= $this->partial('layout/menu.phtml', 'default', array(
|
||||
'url' => \Icinga\Web\Url::fromRequest()->getRelativeUrl(),
|
||||
'items' => \Icinga\Web\Menu::fromConfig()->getChildren(),
|
||||
'sub' => false
|
||||
)); ?>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-xs-12 col-md-10 col-lg-10">
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
<ul>
|
||||
<?php
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
|
||||
printf(
|
||||
' <li%s><a href="%s">%s%s</a>',
|
||||
$this->href($this->url) === $this->href($item->getUrl()) ? ' class="active"' : '',
|
||||
$item->getUrl() ? $this->href($item->getUrl()) : '#',
|
||||
$item->getIcon() ? $this->img(
|
||||
$item->getIcon(),
|
||||
array('height' => '16px', 'width' => '16px')
|
||||
) . ' ' : '',
|
||||
$item->getTitle()
|
||||
);
|
||||
|
||||
if ($item->hasChildren()) {
|
||||
echo $this->partial(
|
||||
'parts/menu.phtml',
|
||||
array('items' => $item->getChildren(), 'url' => $this->url)
|
||||
);
|
||||
}
|
||||
|
||||
echo "</li>\n";
|
||||
}
|
||||
|
||||
?>
|
||||
</ul>
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
// determine current key
|
||||
$url = Icinga\Web\Url::fromRequest()->getRelativeUrl();
|
||||
$menu = Icinga\Web\Menu::fromConfig();
|
||||
|
||||
|
||||
if ($this->auth()->isAuthenticated()) {
|
||||
echo $this->partial(
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<?php
|
||||
use Icinga\Web\Topbar;
|
||||
?>
|
||||
<nav class="navbar-fixed-top" id="icingatopbar" role="navigation">
|
||||
<div class="navbar-header">
|
||||
<a href="<?= $this->baseUrl('/') ?>" class="navbar-brand icinga-logo">Icinga</a>
|
||||
</div>
|
||||
|
||||
<?php foreach (Topbar::getPartials() as $partial) {
|
||||
echo $this->partial($partial['viewScriptName'], $partial['moduleName'], $partial['data']);
|
||||
} ?>
|
||||
<?php if (count($this->topbarHtmlParts)): ?>
|
||||
<ul class="nav navbar-nav">
|
||||
<?php foreach ($this->topbarHtmlParts as $part): ?>
|
||||
<li><?= $part; ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($this->auth()->isAuthenticated()): ?>
|
||||
<ul class="nav navbar-nav pull-right" >
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<?= $sub ? '<ul>' : '<ul class="nav nav-stacked">' ?>
|
||||
<?php foreach ($items as $item): ?>
|
||||
<?php
|
||||
$itemClass = '';
|
||||
if ($sub) {
|
||||
$itemClass .= 'submenu ';
|
||||
}
|
||||
if ($this->href($url) === $this->href($item->getUrl())) {
|
||||
$itemClass .= 'active ';
|
||||
}
|
||||
?>
|
||||
<li <?php if (!empty($itemClass)): ?>class="<?= $itemClass ?>"<?php endif ?>>
|
||||
<?php if($item->getUrl()): ?>
|
||||
<a href="<?= $this->href($item->getUrl()); ?>" <?php foreach($item->getAttribs() as $attrib => $value): ?> <?= $attrib ?>="<?= $value ?>"<?php endforeach?>>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
if ($icon = $item->getIcon()) {
|
||||
echo $this->img($icon, array('height' => 16, 'width' => 16));
|
||||
}
|
||||
?>
|
||||
<?php if ($iconClass = $item->getIconClass()): ?>
|
||||
<i class="<?= $iconClass ?>"></i>
|
||||
<?php endif ?>
|
||||
<?= $item->getTitle();?>
|
||||
<?php if($item->getUrl()): ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
if($item->hasChildren()) {
|
||||
echo $this->partial(
|
||||
'layout/menu.phtml',
|
||||
'default',
|
||||
array('items' => $item->getChildren(), 'sub' => true, 'url' => $this->url)
|
||||
);
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
|
@ -8,21 +8,23 @@ INI files as source it enables you to store configuration in a familiar format.
|
|||
defines some configuration files for its own purposes. Please note that both modules and framework
|
||||
keep their main configuration in the INI file called config.ini. Here's some example code:
|
||||
|
||||
<?php
|
||||
use \Icinga\Application\Config as IcingaConfig;
|
||||
```php
|
||||
<?php
|
||||
use \Icinga\Application\Config as IcingaConfig;
|
||||
|
||||
// Retrieve the default timezone using 'Europe/Berlin' in case it is not set
|
||||
IcingaConfig::app()->global->get('defaultTimezone', 'Europe/Berlin');
|
||||
// Retrieve the default timezone using 'Europe/Berlin' in case it is not set
|
||||
IcingaConfig::app()->global->get('defaultTimezone', 'Europe/Berlin');
|
||||
|
||||
// If you don't pass a configuration name to IcingaConfig::app it tries to load values from the
|
||||
// application's config.ini. For using other files you have to pass this parameter though.
|
||||
// The following example loads a section from the application's authentication.ini:
|
||||
IcingaConfig::app('authentication')->get('ldap-authentication');
|
||||
// If you don't pass a configuration name to IcingaConfig::app it tries to load values from the
|
||||
// application's config.ini. For using other files you have to pass this parameter though.
|
||||
// The following example loads a section from the application's authentication.ini:
|
||||
IcingaConfig::app('authentication')->get('ldap-authentication');
|
||||
|
||||
// If you don't pass a configuration name to IcingaConfig::module it tries to load values from
|
||||
// the module's config.ini. For using other files you have to pass this parameter though.
|
||||
// The following example loads values from the example module's extra.ini:
|
||||
IcingaConfig::module('example', 'extra')->logging->get('enabled', true);
|
||||
// If you don't pass a configuration name to IcingaConfig::module it tries to load values from
|
||||
// the module's config.ini. For using other files you have to pass this parameter though.
|
||||
// The following example loads values from the example module's extra.ini:
|
||||
IcingaConfig::module('example', 'extra')->logging->get('enabled', true);
|
||||
```
|
||||
|
||||
## Reload from disk
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ A component name consists of two parts: the namespace and the name of the compon
|
|||
is named exactly like its JavaScript file, while the namespace is the name of the Icinga2-Web module that contains
|
||||
the component. Each Icinga2-Web module can contain its own components in the folder *public/js*.
|
||||
|
||||
<module>/<component>
|
||||
<module>/<component>
|
||||
|
||||
|
||||
NOTE: The namespace used for modules defined in the Icinga2-Web core application is "app". In opposition to
|
||||
|
@ -45,10 +45,10 @@ The full name for the component *modules/monitoring/public/js/someComponent.js*
|
|||
"monitoring/someComponent"
|
||||
|
||||
|
||||
The full component name for the component *public/js/icinga/components/datetime.js* in the Icinga2-Web
|
||||
core application would:
|
||||
The full component name for the component *public/js/icinga/components/datetime.js* in the Icinga2-Web core application
|
||||
would:
|
||||
|
||||
"app/datetime"
|
||||
"app/datetime"
|
||||
|
||||
|
||||
## Creating a component
|
||||
|
@ -95,7 +95,7 @@ with right time-format available.
|
|||
### Component ids
|
||||
|
||||
When an ID is assigned to the HTML element, it will be used by the component loader to reference this
|
||||
component. Otherwise an ID in the form "icinga-component-<ID>" will be created and the ID attribute in the
|
||||
component. Otherwise an ID in the form "icinga-component-<ID>" will be created and the ID attribute in the
|
||||
HTML Element will be updated accordingly.
|
||||
|
||||
|
||||
|
|
|
@ -40,4 +40,4 @@ By default, the config/dashboard/dashboard.ini is used for storing dashboards in
|
|||
url = "/monitoring/show/host/host1" ; ...and define it's url
|
||||
|
||||
|
||||
[dashboards1]: res/Dashboard.png
|
||||
[dashboards1]: res/Dashboard.png
|
||||
|
|
|
@ -73,15 +73,15 @@ code from special directories:
|
|||
<table>
|
||||
<tr>
|
||||
<th>Class name</th>
|
||||
<th>File path</tg>
|
||||
<th>File path</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\Icinga\Form\Test\MyForm</td>
|
||||
</td>application/forms/Test/MyForm.php</td>
|
||||
<td>application/forms/Test/MyForm.php</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\MyModule\Form\Test</td>
|
||||
</td>modules/forms/Test.php</td>
|
||||
<td>modules/forms/Test.php</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
@ -219,4 +219,4 @@ request dummy which can be passed to your form.
|
|||
* [Zend API documentation](http://framework.zend.com/apidoc/1.10/_Form.html#Zend_Form)
|
||||
|
||||
|
||||
[form1]: res/Form.png
|
||||
[form1]: res/Form.png
|
||||
|
|
|
@ -101,7 +101,7 @@ is a timestamp. The above DateTimePicker utilizes this validator and should be u
|
|||
### ConditionalHidden Decorator
|
||||
|
||||
The `Icinga\Web\Form\Decorator\ConditionalHidden` allows you to hide a form element with the 'conditional' attribute for
|
||||
users that don't have JavaScript enabled (the form is rendered in a \<noscript> tag when conditional is 1). Users with
|
||||
users that don't have JavaScript enabled (the form is rendered in a <noscript> tag when conditional is 1). Users with
|
||||
javascript won't see the elements, users with javascript will see it. This is useful in a lot of cases to allow icingaweb
|
||||
to be fully functional without JavaScript: Forms can show only sensible forms for most users (and, for example hide the
|
||||
debug log filepath input when debugging is disabled) and automatically reload the form as soon as the forms should be
|
||||
|
@ -133,6 +133,6 @@ the 'helptext' property in your form elements.
|
|||
### BootstrapForm Decorator
|
||||
|
||||
`Icinga\Web\Form\Decorator\BoostrapForm` is the decorator we use for our forms.
|
||||
It causes the forms to be rendered in a bootstrap friendly manner instead of the \<dd> \<dt> encapsulated way Zend normally
|
||||
It causes the forms to be rendered in a bootstrap friendly manner instead of the <dd> <dt> encapsulated way Zend normally
|
||||
renders the forms. You usually don't have to work with this decorator as our Form implementation automatically uses it,
|
||||
but it's always good to know why forms look how they look.
|
|
@ -72,7 +72,7 @@ create all database tables. You will find the installation guides for the differ
|
|||
|
||||
> **Note**
|
||||
>
|
||||
> RPM packages install the schema into /usr/share/doc/icingaweb-<version>/schema
|
||||
> RPM packages install the schema into /usr/share/doc/icingaweb-<version>/schema
|
||||
|
||||
bash$ mysql -u root -p icingaweb < etc/schema/accounts.mysql.sql
|
||||
|
||||
|
@ -105,7 +105,7 @@ And restart your database ('service postgresql restart' or '/etc/init.d/postgres
|
|||
|
||||
> **Note**
|
||||
>
|
||||
> RPM packages install the schema into /usr/share/doc/icingaweb-<version>/schema
|
||||
> RPM packages install the schema into /usr/share/doc/icingaweb-<version>/schema
|
||||
|
||||
bash$ psql -U icingaweb -a -f etc/schema/accounts.pgsql.sql
|
||||
|
||||
|
|
|
@ -244,18 +244,22 @@ class Manager
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
clearstatcache(true);
|
||||
$target = $this->installedBaseDirs[$name];
|
||||
$link = $this->enableDir . '/' . $name;
|
||||
|
||||
if (!is_writable($this->enableDir)) {
|
||||
throw new SystemPermissionException(
|
||||
'Can not enable module "' . $name . '". '
|
||||
. 'Insufficient system permissions for enabling modules.'
|
||||
);
|
||||
}
|
||||
|
||||
if (file_exists($link) && is_link($link)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (!@symlink($target, $link)) {
|
||||
$error = error_get_last();
|
||||
if (strstr($error["message"], "File exists") === false) {
|
||||
|
@ -266,7 +270,12 @@ class Manager
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->enabledDirs[$name] = $link;
|
||||
|
||||
$this->loadModule($name);
|
||||
$this->getModule($name)->launchRegisterScript();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,13 @@ class Module
|
|||
*/
|
||||
private $runScript;
|
||||
|
||||
/**
|
||||
* Module initialization script
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $registerScript;
|
||||
|
||||
/**
|
||||
* Module configuration script
|
||||
*
|
||||
|
@ -145,17 +152,18 @@ class Module
|
|||
*/
|
||||
public function __construct(ApplicationBootstrap $app, $name, $basedir)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->name = $name;
|
||||
$this->basedir = $basedir;
|
||||
$this->cssdir = $basedir. '/public/css';
|
||||
$this->libdir = $basedir. '/library';
|
||||
$this->configdir = $basedir. '/config';
|
||||
$this->localedir = $basedir. '/application/locale';
|
||||
$this->formdir = $basedir. '/application/forms';
|
||||
$this->controllerdir = $basedir. '/application/controllers';
|
||||
$this->runScript = $basedir. '/register.php';
|
||||
$this->configScript = $basedir. '/configuration.php';
|
||||
$this->app = $app;
|
||||
$this->name = $name;
|
||||
$this->basedir = $basedir;
|
||||
$this->cssdir = $basedir . '/public/css';
|
||||
$this->libdir = $basedir . '/library';
|
||||
$this->configdir = $basedir . '/config';
|
||||
$this->localedir = $basedir . '/application/locale';
|
||||
$this->formdir = $basedir . '/application/forms';
|
||||
$this->controllerdir = $basedir . '/application/controllers';
|
||||
$this->runScript = $basedir . '/run.php';
|
||||
$this->registerScript = $basedir . '/register.php';
|
||||
$this->configScript = $basedir . '/configuration.php';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -503,6 +511,16 @@ class Module
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run module registration script
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function launchRegisterScript()
|
||||
{
|
||||
return $this->includeScript($this->registerScript);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run module bootstrap script
|
||||
*
|
||||
|
@ -510,13 +528,26 @@ class Module
|
|||
*/
|
||||
protected function launchRunScript()
|
||||
{
|
||||
if (file_exists($this->runScript)
|
||||
&& is_readable($this->runScript)) {
|
||||
include($this->runScript);
|
||||
return $this->includeScript($this->runScript);
|
||||
}
|
||||
|
||||
/**
|
||||
* Include a php script if it is readable
|
||||
*
|
||||
* @param string $file File to include
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
protected function includeScript($file)
|
||||
{
|
||||
if (is_readable($file) === true) {
|
||||
include($file);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run module config script
|
||||
*/
|
||||
|
|
|
@ -266,8 +266,6 @@ class ActionController extends Zend_Controller_Action
|
|||
return call_user_func_array(array($this, $deprecatedMethod), $params);
|
||||
}
|
||||
|
||||
parent::__call($name, $params);
|
||||
|
||||
return null;
|
||||
return parent::__call($name, $params);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,11 @@ use \Icinga\Exception\ProgrammingError;
|
|||
*/
|
||||
class Hook
|
||||
{
|
||||
/**
|
||||
* Hook name
|
||||
*/
|
||||
const TARGET_LAYOUT_TOPBAR = 'Layout\\TopBar';
|
||||
|
||||
/**
|
||||
* Our hook name registry
|
||||
*
|
||||
|
|
|
@ -27,23 +27,23 @@
|
|||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Web;
|
||||
namespace Icinga\Web\Hook\Layout;
|
||||
|
||||
class Topbar
|
||||
use \Icinga\Web\Request;
|
||||
use \Zend_View;
|
||||
|
||||
/**
|
||||
* Hook to extend topbar items
|
||||
*/
|
||||
interface TopBar
|
||||
{
|
||||
private static $partials = array();
|
||||
|
||||
public static function addPartial($viewScriptName, $moduleName, $data)
|
||||
{
|
||||
self::$partials[] = array(
|
||||
'viewScriptName' => $viewScriptName,
|
||||
'moduleName' => $moduleName,
|
||||
'data' => $data
|
||||
);
|
||||
}
|
||||
|
||||
public static function getPartials()
|
||||
{
|
||||
return self::$partials;
|
||||
}
|
||||
/**
|
||||
* Function to generate top bar content
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Zend_View $view
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHtml($request, $view);
|
||||
}
|
|
@ -61,6 +61,8 @@ class MenuItem
|
|||
*/
|
||||
private $children = array();
|
||||
|
||||
private $attribs = array();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MenuItem
|
||||
|
@ -308,6 +310,28 @@ class MenuItem
|
|||
throw new ProgrammingError(sprintf('Trying to get invalid Menu child "%s"', $id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set HTML a tag attributes
|
||||
*
|
||||
* @param array $attribs
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setAttribs(array $attribs)
|
||||
{
|
||||
$this->attribs = $attribs;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HTML a tag attributes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttribs()
|
||||
{
|
||||
return $this->attribs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare children based on priority and title
|
||||
|
|
|
@ -358,11 +358,14 @@ class Url
|
|||
/**
|
||||
* Set the url anchor-part
|
||||
*
|
||||
* @param $anchor The site's anchor string without the '#'
|
||||
* @param $anchor The site's anchor string without the '#'
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setAnchor($anchor)
|
||||
{
|
||||
$this->anchor = '#' . $anchor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
// @codingStandardsIgnoreStart
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
use Icinga\Module\Doc\Controller as DocController;
|
||||
|
||||
class Doc_IndexController extends DocController
|
||||
{
|
||||
/**
|
||||
* Display the application's documentation
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
$this->populateView();
|
||||
}
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
// @codingStandardsIgnoreStart
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Module\Doc\Controller as DocController;
|
||||
|
||||
class Doc_ModuleController extends DocController
|
||||
{
|
||||
/**
|
||||
* Display module documentations index
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->enabledModules = Icinga::app()->getModuleManager()->listEnabledModules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a module's documentation
|
||||
*/
|
||||
public function viewAction()
|
||||
{
|
||||
$this->populateView($this->getParam('name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide run-time dispatching of module documentation
|
||||
*
|
||||
* @param string $methodName
|
||||
* @param array $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($methodName, $args)
|
||||
{
|
||||
// TODO(el): Setup routing to retrieve module name as param and point route to moduleAction
|
||||
$moduleManager = Icinga::app()->getModuleManager();
|
||||
$moduleName = substr($methodName, 0, -6); // Strip 'Action' suffix
|
||||
if (!$moduleManager->hasEnabled($moduleName)) {
|
||||
// TODO(el): Throw a not found exception once the code has been moved to the moduleAction (see TODO above)
|
||||
return parent::__call($methodName, $args);
|
||||
}
|
||||
$this->_helper->redirector->gotoSimpleAndExit('view', null, null, array('name' => $moduleName));
|
||||
}
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
|
@ -0,0 +1,5 @@
|
|||
<h1>Icinga 2 Documentation</h1>
|
||||
<?= $this->partial('module/view.phtml', 'doc', array(
|
||||
'toc' => $toc,
|
||||
'html' => $html
|
||||
)); ?>
|
|
@ -0,0 +1,6 @@
|
|||
<h1>Module documentations</h1>
|
||||
<ul>
|
||||
<?php foreach ($enabledModules as $module): ?>
|
||||
<li><a href="<?= $this->href('doc/module/view', array('name' => $module)); ?>"><?= $module ?></a></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
|
@ -0,0 +1,21 @@
|
|||
<?php if ($html === null): ?>
|
||||
<p>No documentation available.</p>
|
||||
<?php else: ?>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-xs-12 col-md-2 col-lg-2">
|
||||
<?= $this->partial(
|
||||
'layout/menu.phtml',
|
||||
'default',
|
||||
array(
|
||||
'items' => $toc->getChildren(),
|
||||
'sub' => false,
|
||||
'url' => ''
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<div class="col-sm-12 col-xs-12 col-md-10 col-lg-10">
|
||||
<?= $html ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Doc;
|
||||
|
||||
use Icinga\Web\Controller\ActionController;
|
||||
|
||||
class Controller extends ActionController
|
||||
{
|
||||
/**
|
||||
* Set HTML and toc
|
||||
*
|
||||
* @param string $module
|
||||
*/
|
||||
protected function populateView($module = null)
|
||||
{
|
||||
$parser = new DocParser($module);
|
||||
list($html, $toc) = $parser->getDocumentation();
|
||||
$this->view->html = $html;
|
||||
$this->view->toc = $toc;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Doc;
|
||||
|
||||
use \Exception;
|
||||
|
||||
class DocException extends Exception
|
||||
{
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}
|
||||
|
||||
namespace Icinga\Module\Doc;
|
||||
|
||||
require_once 'vendor/Parsedown/Parsedown.php';
|
||||
|
||||
use \RecursiveIteratorIterator;
|
||||
use \RecursiveDirectoryIterator;
|
||||
use \Parsedown;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Web\Menu;
|
||||
use Icinga\Web\Url;
|
||||
|
||||
/**
|
||||
* Parser for documentation written in Markdown
|
||||
*/
|
||||
class DocParser
|
||||
{
|
||||
protected $dir;
|
||||
|
||||
protected $module;
|
||||
|
||||
/**
|
||||
* Create a new documentation parser for the given module or the application
|
||||
*
|
||||
* @param string $module
|
||||
*
|
||||
* @throws DocException
|
||||
*/
|
||||
public function __construct($module = null)
|
||||
{
|
||||
if ($module === null) {
|
||||
$dir = Icinga::app()->getApplicationDir('/../doc');
|
||||
} else {
|
||||
$mm = Icinga::app()->getModuleManager();
|
||||
if (!$mm->hasInstalled($module)) {
|
||||
throw new DocException('Module is not installed');
|
||||
}
|
||||
if (!$mm->hasEnabled($module)) {
|
||||
throw new DocException('Module is not enabled');
|
||||
}
|
||||
$dir = $mm->getModuleDir($module, '/doc');
|
||||
}
|
||||
if (!is_dir($dir)) {
|
||||
throw new DocException('Doc directory does not exist');
|
||||
}
|
||||
$this->dir = $dir;
|
||||
$this->module = $module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve table of contents and HTML converted from markdown files sorted by filename
|
||||
*
|
||||
* @return array
|
||||
* @throws DocException
|
||||
*/
|
||||
public function getDocumentation()
|
||||
{
|
||||
$iter = new RecursiveIteratorIterator(
|
||||
new MarkdownFileIterator(
|
||||
new RecursiveDirectoryIterator($this->dir)
|
||||
)
|
||||
);
|
||||
$fileInfos = iterator_to_array($iter);
|
||||
natcasesort($fileInfos);
|
||||
$cat = array();
|
||||
$toc = array((object) array(
|
||||
'level' => 0,
|
||||
'item' => new Menu('doc')
|
||||
));
|
||||
$itemPriority = 1;
|
||||
foreach ($fileInfos as $fileInfo) {
|
||||
try {
|
||||
$fileObject = $fileInfo->openFile();
|
||||
} catch (RuntimeException $e) {
|
||||
throw new DocException($e->getMessage());
|
||||
}
|
||||
if ($fileObject->flock(LOCK_SH) === false) {
|
||||
throw new DocException('Couldn\'t get the lock');
|
||||
}
|
||||
$line = null;
|
||||
while (!$fileObject->eof()) {
|
||||
// Save last line for setext-style headers
|
||||
$lastLine = $line;
|
||||
$line = $fileObject->fgets();
|
||||
$header = $this->extractHeader($line, $lastLine);
|
||||
if ($header !== null) {
|
||||
list($header, $level) = $header;
|
||||
$id = $this->extractHeaderId($header);
|
||||
$attribs = array();
|
||||
$this->reduceToc($toc, $level);
|
||||
if ($id === null) {
|
||||
$path = array();
|
||||
foreach (array_slice($toc, 1) as $entry) {
|
||||
$path[] = $entry->item->getTitle();
|
||||
}
|
||||
$path[] = $header;
|
||||
$id = implode('-', $path);
|
||||
$attribs['rel'] = 'nofollow';
|
||||
}
|
||||
$id = urlencode(str_replace('.', '.', strip_tags($id)));
|
||||
$item = end($toc)->item->addChild(
|
||||
$id,
|
||||
array(
|
||||
'url' => Url::fromPath(
|
||||
'doc/module/view',
|
||||
array(
|
||||
'name' => $this->module
|
||||
)
|
||||
)->setAnchor($id)->getRelativeUrl(),
|
||||
'title' => htmlspecialchars($header),
|
||||
'priority' => $itemPriority++,
|
||||
'attribs' => $attribs
|
||||
)
|
||||
);
|
||||
$toc[] = ((object) array(
|
||||
'level' => $level,
|
||||
'item' => $item
|
||||
));
|
||||
$line = '<span id="' . $id . '"></span>' . PHP_EOL . $line;
|
||||
}
|
||||
$cat[] = $line;
|
||||
}
|
||||
$fileObject->flock(LOCK_UN);
|
||||
}
|
||||
$html = Parsedown::instance()->parse(implode('', $cat));
|
||||
$html = preg_replace_callback(
|
||||
'#<pre><code class="language-php">(.*?)\</code></pre>#s',
|
||||
array($this, 'highlight'),
|
||||
$html
|
||||
);
|
||||
return array($html, $toc[0]->item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax highlighting for PHP code
|
||||
*
|
||||
* @param $match
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function highlight($match)
|
||||
{
|
||||
return highlight_string(htmlspecialchars_decode($match[1]), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract atx- or setext-style headers from the given lines
|
||||
*
|
||||
* @param string $line
|
||||
* @param string $lastLine
|
||||
*
|
||||
* @return array|null An array containing the header and the header level or null if there's nothing to extract
|
||||
*/
|
||||
protected function extractHeader($line, $lastLine)
|
||||
{
|
||||
if (!$line) {
|
||||
return null;
|
||||
}
|
||||
$header = null;
|
||||
if ($line &&
|
||||
$line[0] === '#' &&
|
||||
preg_match('/^#+/', $line, $match) === 1
|
||||
) {
|
||||
// Atx-style
|
||||
$level = strlen($match[0]);
|
||||
$header = trim(substr($line, $level));
|
||||
if (!$header) {
|
||||
return null;
|
||||
}
|
||||
} elseif (
|
||||
$line &&
|
||||
($line[0] === '=' || $line[0] === '-') &&
|
||||
preg_match('/^[=-]+\s*$/', $line, $match) === 1
|
||||
) {
|
||||
// Setext
|
||||
$header = trim($lastLine);
|
||||
if (!$header) {
|
||||
return null;
|
||||
}
|
||||
if ($match[0][0] === '=') {
|
||||
$level = 1;
|
||||
} else {
|
||||
$level = 2;
|
||||
}
|
||||
}
|
||||
if ($header === null) {
|
||||
return null;
|
||||
}
|
||||
return array($header, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract header id in an a or a span tag
|
||||
*
|
||||
* @param string &$header
|
||||
*
|
||||
* @return id|null
|
||||
*/
|
||||
protected function extractHeaderId(&$header)
|
||||
{
|
||||
if ($header[0] === '<' &&
|
||||
preg_match('#(?:<(?P<tag>a|span) id="(?P<id>.+)"></(?P=tag)>)#u', $header, $match)
|
||||
) {
|
||||
$header = str_replace($match[0], '', $header);
|
||||
return $match['id'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the toc to the given level
|
||||
*
|
||||
* @param array &$toc
|
||||
* @param int $level
|
||||
*/
|
||||
protected function reduceToc(array &$toc, $level) {
|
||||
while (end($toc)->level >= $level) {
|
||||
array_pop($toc);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}
|
||||
|
||||
namespace Icinga\Module\Doc;
|
||||
|
||||
use \RecursiveFilterIterator;
|
||||
|
||||
/**
|
||||
* Iterator over Markdown files recursively
|
||||
*/
|
||||
class MarkdownFileIterator extends RecursiveFilterIterator
|
||||
{
|
||||
/**
|
||||
* Accept files with .md suffix
|
||||
*
|
||||
* @return bool Whether the current element of the iterator is acceptable
|
||||
* through this filter
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
$current = $this->getInnerIterator()->current();
|
||||
if (!$current->isFile()) {
|
||||
return false;
|
||||
}
|
||||
$filename = $current->getFilename();
|
||||
$sfx = substr($filename, -3);
|
||||
return $sfx === false ? false : strtolower($sfx) === '.md';
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# The instance.ini configuration file
|
||||
# <a id="instances"></a> The instance.ini configuration file
|
||||
|
||||
## Abstract
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga Web 2.
|
||||
*
|
||||
* Icinga Web 2 - Head for multiple monitoring backends.
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Monitoring\Web\Hook;
|
||||
|
||||
use Icinga\Web\Hook\Layout\TopBar as IcingaTopBar;
|
||||
use Icinga\Module\Monitoring\DataView\StatusSummary as StatusSummaryView;
|
||||
use Icinga\Web\Request;
|
||||
use Zend_View;
|
||||
|
||||
/**
|
||||
* Render status summary into the topbar of icinga
|
||||
*/
|
||||
class TopBar implements IcingaTopBar
|
||||
{
|
||||
/**
|
||||
* Function to generate top bar content
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Zend_View $view
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHtml($request, $view)
|
||||
{
|
||||
$hostSummary = StatusSummaryView::fromRequest(
|
||||
$request,
|
||||
array(
|
||||
'hosts_up',
|
||||
'hosts_unreachable_handled',
|
||||
'hosts_unreachable_unhandled',
|
||||
'hosts_down_handled',
|
||||
'hosts_down_unhandled',
|
||||
'hosts_pending'
|
||||
)
|
||||
)->getQuery()->fetchRow();
|
||||
|
||||
$serviceSummary = StatusSummaryView::fromRequest(
|
||||
$request,
|
||||
array(
|
||||
'services_ok',
|
||||
'services_critical_handled',
|
||||
'services_critical_unhandled',
|
||||
'services_warning_handled',
|
||||
'services_warning_unhandled',
|
||||
'services_unknown_handled',
|
||||
'services_unknown_unhandled',
|
||||
'services_pending'
|
||||
)
|
||||
)->getQuery()->fetchRow();
|
||||
|
||||
return $view->partial(
|
||||
'layout/topbar.phtml',
|
||||
'monitoring',
|
||||
array(
|
||||
'hostSummary' => $hostSummary,
|
||||
'serviceSummary' => $serviceSummary
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,48 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Authentication\Manager as AuthManager;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Module\Monitoring\DataView\StatusSummary as StatusSummaryView;
|
||||
use Icinga\Web\Topbar;
|
||||
|
||||
if (Icinga::app()->isCli()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = Icinga::app()->getFrontController()->getRequest();
|
||||
|
||||
if (AuthManager::getInstance()->isAuthenticated()) {
|
||||
$hostSummary = StatusSummaryView::fromRequest(
|
||||
$request,
|
||||
array(
|
||||
'hosts_up',
|
||||
'hosts_unreachable_handled',
|
||||
'hosts_unreachable_unhandled',
|
||||
'hosts_down_handled',
|
||||
'hosts_down_unhandled',
|
||||
'hosts_pending'
|
||||
)
|
||||
)->getQuery()->fetchRow();
|
||||
|
||||
$serviceSummary = StatusSummaryView::fromRequest(
|
||||
$request,
|
||||
array(
|
||||
'services_ok',
|
||||
'services_critical_handled',
|
||||
'services_critical_unhandled',
|
||||
'services_warning_handled',
|
||||
'services_warning_unhandled',
|
||||
'services_unknown_handled',
|
||||
'services_unknown_unhandled',
|
||||
'services_pending'
|
||||
)
|
||||
)->getQuery()->fetchRow();
|
||||
|
||||
Topbar::addPartial(
|
||||
'topbar.phtml',
|
||||
'monitoring',
|
||||
array('hostSummary' => $hostSummary, 'serviceSummary' => $serviceSummary)
|
||||
);
|
||||
}
|
||||
|
||||
?>
|
||||
/*
|
||||
* register.php
|
||||
*
|
||||
* This file runs only on installation
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
/*
|
||||
* run.php
|
||||
*
|
||||
* This file runs every request to register runtime functionality
|
||||
*
|
||||
*/
|
||||
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Authentication\Manager as AuthManager;
|
||||
use Icinga\Web\Hook;
|
||||
|
||||
if (Icinga::app()->isCli()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (AuthManager::getInstance()->isAuthenticated()) {
|
||||
Hook::register(
|
||||
Hook::TARGET_LAYOUT_TOPBAR,
|
||||
'monitoring-topbar',
|
||||
'Icinga\\Module\\Monitoring\\Web\\Hook\\TopBar'
|
||||
);
|
||||
}
|
|
@ -44,6 +44,7 @@ require_once BaseTestCase::$appDir . '/forms/Config/GeneralForm.php';
|
|||
require_once BaseTestCase::$appDir . '/views/helpers/DateFormat.php';
|
||||
require_once BaseTestCase::$libDir . '/Util/ConfigAwareFactory.php';
|
||||
require_once BaseTestCase::$libDir . '/Util/DateTimeFactory.php';
|
||||
require_once BaseTestCase::$libDir . '/Util/Translator.php';
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
use \DateTimeZone;
|
||||
|
|
|
@ -29,188 +29,168 @@
|
|||
|
||||
namespace Tests\Icinga\Application;
|
||||
|
||||
require_once 'Zend/Log.php';
|
||||
require_once 'Zend/Config.php';
|
||||
require_once 'Zend/Log/Writer/Mock.php';
|
||||
require_once 'Zend/Log/Writer/Null.php';
|
||||
require_once 'Zend/Log/Filter/Priority.php';
|
||||
// @codingStandardsIgnoreStart
|
||||
require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php');
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
require_once realpath(__DIR__ . '/../../../../../library/Icinga/Application/Logger.php');
|
||||
require_once realpath(__DIR__ . '/../../../../../library/Icinga/Exception/ConfigurationError.php');
|
||||
|
||||
use \Icinga\Application\Logger;
|
||||
use \Zend_Config;
|
||||
use Icinga\Application\Logger;
|
||||
use Icinga\Test\BaseTestCase;
|
||||
|
||||
/**
|
||||
* Test class for Logger
|
||||
*
|
||||
* @backupStaticAttributes enabled
|
||||
**/
|
||||
class LoggerTest extends \PHPUnit_Framework_TestCase
|
||||
class LoggerTest extends BaseTestCase
|
||||
{
|
||||
private $timeZone;
|
||||
private $tempDir;
|
||||
|
||||
protected function setUp()
|
||||
private $logTarget;
|
||||
|
||||
private $debugTarget;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
date_default_timezone_set('GMT');
|
||||
$this->tempDir = tempnam(sys_get_temp_dir(), 'icingaweb-log');
|
||||
unlink($this->tempDir); // tempnam create the file automatically
|
||||
|
||||
if (!is_dir($this->tempDir)) {
|
||||
mkdir($this->tempDir, 0755);
|
||||
}
|
||||
|
||||
$this->debugTarget = $this->tempDir . '/debug.log';
|
||||
$this->logTarget = $this->tempDir . '/application.log';
|
||||
|
||||
$loggingConfigurationArray = array(
|
||||
'enable' => 1,
|
||||
'type' => 'stream',
|
||||
'verbose' => 1,
|
||||
'target' => $this->logTarget,
|
||||
|
||||
'debug' => array(
|
||||
'enable' => 1,
|
||||
'type' => 'stream',
|
||||
'target' => $this->debugTarget
|
||||
)
|
||||
);
|
||||
|
||||
$loggingConfiguration = new Zend_Config($loggingConfigurationArray);
|
||||
|
||||
Logger::reset();
|
||||
}
|
||||
|
||||
public function testOverwrite()
|
||||
{
|
||||
$cfg1 = new \Zend_Config(
|
||||
array(
|
||||
'debug' => array('enable' => 0),
|
||||
'type' => 'mock',
|
||||
'target' => 'target2'
|
||||
)
|
||||
);
|
||||
$cfg2 = new \Zend_Config(
|
||||
array(
|
||||
'debug' => array(
|
||||
'enable' => 1,
|
||||
'type'=>'mock',
|
||||
'target'=>'target3'
|
||||
),
|
||||
'type' => 'mock',
|
||||
'target' => 'target4'
|
||||
)
|
||||
);
|
||||
|
||||
$logger = new Logger($cfg1);
|
||||
$writers = $logger->getWriters();
|
||||
$this->assertEquals(1, count($writers));
|
||||
|
||||
$logger = new Logger($cfg1);
|
||||
$writers2 = $logger->getWriters();
|
||||
$this->assertEquals(1, count($writers));
|
||||
$this->assertNotEquals($writers[0], $writers2[0]);
|
||||
|
||||
$logger = new Logger($cfg2);
|
||||
$writers2 = $logger->getWriters();
|
||||
$this->assertEquals(2, count($writers2));
|
||||
}
|
||||
|
||||
public function testFormatMessage()
|
||||
{
|
||||
$message = Logger::formatMessage(array('Testmessage'));
|
||||
$this->assertEquals('Testmessage', $message);
|
||||
|
||||
$message = Logger::formatMessage(array('Testmessage %s %s', 'test1', 'test2'));
|
||||
$this->assertEquals('Testmessage test1 test2', $message);
|
||||
|
||||
$message = Logger::formatMessage(array('Testmessage %s', array('test1', 'test2')));
|
||||
$this->assertEquals('Testmessage '.json_encode(array('test1', 'test2')), $message);
|
||||
}
|
||||
|
||||
public function testLoggingOutput()
|
||||
{
|
||||
$cfg1 = new \Zend_Config(
|
||||
array(
|
||||
'debug' => array('enable' => 0),
|
||||
'type' => 'mock',
|
||||
'target' => 'target2'
|
||||
)
|
||||
);
|
||||
|
||||
$logger = Logger::create($cfg1);
|
||||
$writers = $logger->getWriters();
|
||||
|
||||
$logger->warn('Warning');
|
||||
$logger->error('Error');
|
||||
$logger->info('Info');
|
||||
$logger->debug('Debug');
|
||||
|
||||
$writer = $writers[0];
|
||||
$this->assertEquals(2, count($writer->events));
|
||||
$this->assertEquals($writer->events[0]['message'], 'Warning');
|
||||
$this->assertEquals($writer->events[1]['message'], 'Error');
|
||||
Logger::create($loggingConfiguration);
|
||||
|
||||
}
|
||||
|
||||
public function testLogQueuing()
|
||||
public function tearDown()
|
||||
{
|
||||
$cfg1 = new \Zend_Config(
|
||||
array(
|
||||
'debug' => array('enable' => 0),
|
||||
'type' => 'mock',
|
||||
'target' => 'target2'
|
||||
)
|
||||
);
|
||||
if (file_exists($this->debugTarget)) {
|
||||
unlink($this->debugTarget);
|
||||
}
|
||||
|
||||
Logger::warn('Warning');
|
||||
Logger::error('Error');
|
||||
Logger::info('Info');
|
||||
Logger::debug('Debug');
|
||||
if (file_exists($this->logTarget)) {
|
||||
unlink($this->logTarget);
|
||||
}
|
||||
|
||||
$logger = Logger::create($cfg1);
|
||||
$writers = $logger->getWriters();
|
||||
$writer = $writers[0];
|
||||
|
||||
$this->assertEquals(2, count($writer->events));
|
||||
$this->assertEquals($writer->events[0]['message'], 'Warning');
|
||||
$this->assertEquals($writer->events[1]['message'], 'Error');
|
||||
rmdir($this->tempDir);
|
||||
}
|
||||
|
||||
public function testDebugLogErrorCatching()
|
||||
private function getLogData()
|
||||
{
|
||||
$cfg1 = new \Zend_Config(
|
||||
array(
|
||||
'debug' => array(
|
||||
'enable' => 1,
|
||||
'type' => 'Invalid',
|
||||
'target' => '...'
|
||||
),
|
||||
'type' => 'mock',
|
||||
'target' => 'target2'
|
||||
)
|
||||
);
|
||||
|
||||
$logger = Logger::create($cfg1);
|
||||
$writers = $logger->getWriters();
|
||||
$this->assertEquals(1, count($writers));
|
||||
$this->assertEquals(1, count($writers[0]->events));
|
||||
$this->assertEquals(
|
||||
'Could not add log writer of type "Invalid". Type does not exist.',
|
||||
$writers[0]->events[0]['message']
|
||||
return array(
|
||||
explode(PHP_EOL, file_get_contents($this->logTarget)),
|
||||
explode(PHP_EOL, file_get_contents($this->debugTarget))
|
||||
);
|
||||
}
|
||||
|
||||
public function testNotLoggedMessagesQueue()
|
||||
/**
|
||||
* Test error messages
|
||||
*/
|
||||
public function testLoggingErrorMessages()
|
||||
{
|
||||
$cfg1 = new \Zend_Config(
|
||||
array(
|
||||
'debug' => array(
|
||||
'enable' => 0,
|
||||
'type' => 'Invalid',
|
||||
'target' => '...'
|
||||
),
|
||||
'type' => 'invalid',
|
||||
'target' => 'target2'
|
||||
)
|
||||
);
|
||||
Logger::error('test-error-1');
|
||||
Logger::error('test-error-2');
|
||||
|
||||
$logger = Logger::create($cfg1);
|
||||
$this->assertFileExists($this->logTarget);
|
||||
$this->assertFileExists($this->debugTarget);
|
||||
|
||||
list($main, $debug) = $this->getLogData();
|
||||
|
||||
$this->assertCount(3, $main);
|
||||
$this->assertCount(3, $debug);
|
||||
|
||||
$this->assertContains(' ERR (3): test-error-1', $main[0]);
|
||||
$this->assertContains(' ERR (3): test-error-2', $main[1]);
|
||||
|
||||
$this->assertContains(' ERR (3): test-error-1', $debug[0]);
|
||||
$this->assertContains(' ERR (3): test-error-2', $debug[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test debug log and difference between error and debug messages
|
||||
*/
|
||||
public function testLoggingDebugMessages()
|
||||
{
|
||||
Logger::debug('test-debug-1');
|
||||
Logger::error('test-error-1');
|
||||
Logger::debug('test-debug-2');
|
||||
|
||||
$this->assertFileExists($this->logTarget);
|
||||
$this->assertFileExists($this->debugTarget);
|
||||
|
||||
list($main, $debug) = $this->getLogData();
|
||||
|
||||
$this->assertCount(2, $main);
|
||||
$this->assertCount(4, $debug);
|
||||
|
||||
$this->assertContains(' ERR (3): test-error-1', $main[0]);
|
||||
|
||||
$this->assertContains(' DEBUG (7): test-debug-1', $debug[0]);
|
||||
$this->assertContains(' ERR (3): test-error-1', $debug[1]);
|
||||
$this->assertContains(' DEBUG (7): test-debug-2', $debug[2]);
|
||||
}
|
||||
|
||||
public function testLoggingQueueIfNoWriterAvailable()
|
||||
{
|
||||
Logger::reset();
|
||||
|
||||
Logger::error('test-error-1');
|
||||
Logger::debug('test-debug-1');
|
||||
Logger::error('test-error-2');
|
||||
|
||||
list($main, $debug) = $this->getLogData();
|
||||
|
||||
$this->assertCount(1, $main);
|
||||
$this->assertCount(1, $debug);
|
||||
|
||||
$this->assertTrue(Logger::hasErrorsOccurred());
|
||||
|
||||
$queue = Logger::getQueue();
|
||||
|
||||
$this->assertCount(2, $queue);
|
||||
$this->assertCount(3, $queue);
|
||||
|
||||
$this->assertSame(
|
||||
'Could not add log writer of type "Invalid". Type does not exist.',
|
||||
$queue[0][0],
|
||||
'Log message of an invalid writer'
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'test-error-1',
|
||||
3
|
||||
),
|
||||
$queue[0]
|
||||
);
|
||||
|
||||
$this->assertSame(0, $queue[0][1], 'Log level "fatal"');
|
||||
|
||||
$this->assertSame(
|
||||
'Could not flush logs to output. An exception was thrown: No writers were added',
|
||||
$queue[1][0],
|
||||
'Log message that no writer was added to logger'
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'test-debug-1',
|
||||
7
|
||||
),
|
||||
$queue[1]
|
||||
);
|
||||
|
||||
$this->assertSame(0, $queue[1][1], 'Log level "fatal"');
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'test-error-2',
|
||||
3
|
||||
),
|
||||
$queue[2]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue