Merge branch 'master' into bugfix/do-not-use-count-queries-for-emptiness-checks-9632

Conflicts:
	modules/monitoring/application/views/scripts/service/history.phtml
This commit is contained in:
Johannes Meyer 2015-08-03 16:46:27 +02:00
commit d1917ad2b4
6 changed files with 208 additions and 154 deletions

View File

@ -0,0 +1,23 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
/**
* Helper for creating ticket links from ticket hooks
*/
class Zend_View_Helper_CreateTicketLinks extends Zend_View_Helper_Abstract
{
/**
* Create ticket links form ticket hooks
*
* @param string $text
*
* @return string
* @see \Icinga\Web\Hook\TicketHook::createLinks()
*/
public function createTicketLinks($text)
{
$tickets = $this->view->tickets;
/** @var \Icinga\Web\Hook\TicketHook $tickets */
return isset($tickets) ? $tickets->createLinks($text) : $text;
}
}

View File

@ -3,23 +3,29 @@
namespace Icinga\Web\Hook; namespace Icinga\Web\Hook;
use ErrorException;
use Exception;
use Icinga\Application\Logger;
use Icinga\Exception\IcingaException;
/** /**
* Icinga Web Ticket Hook base class * Base class for ticket hooks
* *
* Extend this class if you want to integrate your ticketing solution nicely into * Extend this class if you want to integrate your ticketing solution Icinga Web 2
* Icinga Web
*
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
* @author Icinga-Web Team <info@icinga.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/ */
abstract class TicketHook abstract class TicketHook
{ {
/** /**
* Constructor must live without arguments right now * Last error, if any
* *
* Therefore the constructor is final, we might change our opinion about * @var string|null
* this one far day */
protected $lastError;
/**
* Create a new ticket hook
*
* @see init() For hook initialization.
*/ */
final public function __construct() final public function __construct()
{ {
@ -27,16 +33,92 @@ abstract class TicketHook
} }
/** /**
* Overwrite this function if you want to do some initialization stuff * Overwrite this function for hook initialization, e.g. loading the hook's config
*
* @return void
*/ */
protected function init() protected function init()
{ {
} }
/**
* Set the hook as failed w/ the given message
*
* @param string $message Error message or error format string
* @param mixed ...$arg Format string argument
*/
private function fail($message)
{
$args = array_slice(func_get_args(), 1);
$lastError = vsprintf($message, $args);
Logger::debug($lastError);
$this->lastError = $lastError;
}
/**
* Get the last error, if any
*
* @return string|null
*/
public function getLastError()
{
return $this->lastError;
}
/**
* Get the pattern
*
* @return string
*/
abstract public function getPattern(); abstract public function getPattern();
/**
* Create a link for each matched element in the subject text
*
* @param array $match Array of matched elements according to {@link getPattern()}
*
* @return string Replacement string
*/
abstract public function createLink($match); abstract public function createLink($match);
/**
* Create links w/ {@link createLink()} in the given text that matches to the subject from {@link getPattern()}
*
* In case of errors a debug message is recorded to the log and any subsequent call to {@link createLinks()} will
* be a no-op.
*
* @param string $text
*
* @return string
*/
final public function createLinks($text)
{
if ($this->lastError !== null) {
return $text;
}
try {
$pattern = $this->getPattern();
} catch (Exception $e) {
$this->fail('Can\'t create ticket links: Retrieving the pattern failed: %s', IcingaException::describe($e));
return $text;
}
if (empty($pattern)) {
$this->fail('Can\'t create ticket links: Pattern is empty');
return $text;
}
try {
$text = preg_replace_callback(
$pattern,
array($this, 'createLink'),
$text
);
} catch (ErrorException $e) {
$this->fail('Can\'t create ticket links: Pattern is invalid: %s', IcingaException::describe($e));
return $text;
} catch (Exception $e) {
$this->fail('Can\'t create ticket links: %s', IcingaException::describe($e));
return $text;
}
return $text;
}
} }

View File

@ -106,15 +106,7 @@ if (! $this->compact): ?>
<br> <br>
<?= date('d.m. H:i', $event->timestamp); ?> <?= date('d.m. H:i', $event->timestamp); ?>
</td> </td>
<td><?php <td>
$output = $this->tickets ? preg_replace_callback(
$this->tickets->getPattern(),
array($this->tickets, 'createLink'),
$msg
) : $msg;
?>
<?php if ($isService): ?> <?php if ($isService): ?>
<?= sprintf( <?= sprintf(
$this->translate('%s on %s', 'Service running on host'), $this->translate('%s on %s', 'Service running on host'),
@ -138,7 +130,7 @@ $output = $this->tickets ? preg_replace_callback(
<?php endif ?> <?php endif ?>
<br> <br>
<div> <div>
<?= $this->icon($icon, $title); ?> <?= empty($msg) ? '' : $msg; ?> <?= $this->icon($icon, $title); ?> <?= $this->createTicketLinks($msg) ?>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -104,15 +104,7 @@ if (! $this->compact): ?>
<br> <br>
<?= date('d.m. H:i', $event->timestamp); ?> <?= date('d.m. H:i', $event->timestamp); ?>
</td> </td>
<td><?php <td>
$output = $this->tickets ? preg_replace_callback(
$this->tickets->getPattern(),
array($this->tickets, 'createLink'),
$msg
) : $msg;
?>
<?= sprintf( <?= sprintf(
$this->translate('%s on %s', 'Service running on host'), $this->translate('%s on %s', 'Service running on host'),
$this->escape($event->service_display_name), $this->escape($event->service_display_name),
@ -120,7 +112,7 @@ $output = $this->tickets ? preg_replace_callback(
) ?> ) ?>
<br> <br>
<div> <div>
<?= $this->icon($icon, $title); ?> <?= empty($msg) ? '' : $msg; ?> <?= $this->icon($icon, $title); ?> <?= $this->createTicketLinks($msg) ?>
</div> </div>
</td> </td>
</tr> </tr>
@ -130,4 +122,4 @@ $output = $this->tickets ? preg_replace_callback(
<?php if (! $history->hasResult()): ?> <?php if (! $history->hasResult()): ?>
<?= $this->translate('No history events found matching the filter'); ?> <?= $this->translate('No history events found matching the filter'); ?>
<?php endif ?> <?php endif ?>
</div> </div>

View File

@ -1,7 +1,5 @@
<?php <?php
$addLink = false;
$addLink = '';
if ($this->hasPermission('monitoring/command/comment/add')) { if ($this->hasPermission('monitoring/command/comment/add')) {
/** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */ /** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
if ($object->getType() === $object::TYPE_HOST) { if ($object->getType() === $object::TYPE_HOST) {
@ -28,63 +26,49 @@ if ($this->hasPermission('monitoring/command/comment/add')) {
); );
} }
} }
if (empty($object->comments) && ! $addLink) { if (empty($object->comments) && ! $addLink) {
return; return;
} }
?> ?>
<tr> <tr>
<th><?php <th><?php
echo $this->translate('Comments'); echo $this->translate('Comments');
if (! empty($object->comments) && $addLink) { if (! empty($object->comments) && $addLink) {
echo '<br />' . $addLink; echo '<br />' . $addLink;
} }
?></th> ?></th>
<td data-base-target="_self"> <td data-base-target="_self">
<?php if (empty($object->comments)): ?> <?php if (empty($object->comments)):
<?= $addLink ?> echo $addLink;
<?php else: ?> else: ?>
<ul class="inline-comments"> <ul class="inline-comments">
<?php foreach ($object->comments as $comment): ?> <?php foreach ($object->comments as $comment):
<?php // Form is unset if the current user lacks the respective permission
if (isset($delCommentForm)) {
// Ticket hook sample $deleteButton = clone($delCommentForm);
$commentText = $this->tickets ? preg_replace_callback( $deleteButton->populate(
$this->tickets->getPattern(), array(
array($this->tickets, 'createLink'), 'comment_id' => $comment->id,
$this->escape($comment->comment) 'comment_is_service' => isset($comment->service_description)
) : $this->escape($comment->comment); )
);
} else {
// Form is unset if the current user lacks the respective permission $deleteButton = '';
if (isset($delCommentForm)) { }
$deleteButton = clone($delCommentForm); ?>
$deleteButton->populate( <li class="comment-item">
array( <h3>
'comment_id' => $comment->id, <span class="author"><?= $this->escape($comment->author) ?></span>
'comment_is_service' => isset($comment->service_description) <?= $this->timeAgo($comment->timestamp) ?>
) <?= $deleteButton ?>
); </h3>
} else { <p>
$deleteButton = ''; <span class="sr-only">(<?= $this->translate('Comment') ?>): </span>
} <?= str_replace(array('\r\n', '\n'), '<br>', $this->createTicketLinks($comment->comment)) ?>
</p>
?> </li>
<li class="comment-item"> <?php endforeach ?>
<h3> </ul>
<span class="author"><?= $this->escape($comment->author) ?></span> <?php endif ?>
<?= $this->timeAgo($comment->timestamp) ?>
<?= $deleteButton ?>
</h3>
<p><span class="sr-only">(<?= $this->translate('Comment'); ?>): </span><?= str_replace(array('\r\n', '\n'), '<br>', $commentText) ?></p>
</li>
<?php endforeach ?>
</ul>
<?php endif ?>
</td> </td>
</tr> </tr>

View File

@ -1,7 +1,5 @@
<?php <?php
$addLink = false;
$addLink = '';
if ($this->hasPermission('monitoring/command/downtime/schedule')) { if ($this->hasPermission('monitoring/command/downtime/schedule')) {
/** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */ /** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
if ($object->getType() === $object::TYPE_HOST) { if ($object->getType() === $object::TYPE_HOST) {
@ -32,85 +30,68 @@ if ($this->hasPermission('monitoring/command/downtime/schedule')) {
); );
} }
} }
if (empty($object->comments) && ! $addLink) { if (empty($object->comments) && ! $addLink) {
return; return;
} }
?> ?>
<tr> <tr>
<th><?php <th><?php
echo $this->translate('Downtimes'); echo $this->translate('Downtimes');
if (! empty($object->downtimes) && $addLink) { if (! empty($object->downtimes) && $addLink) {
echo '<br />' . $addLink; echo '<br />' . $addLink;
} }
?></th> ?></th>
<td data-base-target="_self"> <td data-base-target="_self">
<?php if (empty($object->downtimes)): ?> <?php if (empty($object->downtimes)):
<?= $addLink ?> echo $addLink;
<?php else: ?> else: ?>
<ul class="inline-comments"> <ul class="inline-comments">
<?php foreach ($object->downtimes as $downtime):
<?php foreach ($object->downtimes as $downtime): ?> if ((bool) $downtime->is_in_effect) {
<?php $state = sprintf(
$this->translate('expires %s', 'Last format parameter represents the downtime expire time'),
// Ticket hook sample $this->timeUntil($downtime->end)
$commentText = $this->tickets ? preg_replace_callback( );
$this->tickets->getPattern(), } else {
array($this->tickets, 'createLink'), if ((bool) $downtime->is_fixed) {
$this->escape($downtime->comment) $state = sprintf(
) : $this->escape($downtime->comment); $this->translate('scheduled %s', 'Last format parameter represents the time scheduled'),
$this->timeUntil($downtime->start)
if ((bool) $downtime->is_in_effect) { );
$state = sprintf( } else {
$this->translate('expires %s', 'Last format parameter represents the downtime expire time'), $state = sprintf(
$this->timeUntil($downtime->end) $this->translate('scheduled flexible %s', 'Last format parameter represents the time scheduled'),
); $this->timeUntil($downtime->start)
} else { );
if ((bool) $downtime->is_fixed) { }
$state = sprintf( }
$this->translate('scheduled %s', 'Last format parameter represents the time scheduled'), // Form is unset if the current user lacks the respective permission
$this->timeUntil($downtime->start) if (isset($delDowntimeForm)) {
); $deleteButton = clone($delDowntimeForm);
} else { $deleteButton->populate(
$state = sprintf( array(
$this->translate('scheduled flexible %s', 'Last format parameter represents the time scheduled'), 'downtime_id' => $downtime->id,
$this->timeUntil($downtime->start) 'downtime_is_service' => $object->getType() === $object::TYPE_SERVICE
); )
} );
} } else {
$deleteButton = '';
}
// Form is unset if the current user lacks the respective permission ?>
if (isset($delDowntimeForm)) { <li class="comment-item">
$deleteButton = clone($delDowntimeForm); <h3>
$deleteButton->populate( <span class="author"><?= $this->escape($downtime->author_name) ?></span>
array( <?= $this->timeAgo($downtime->entry_time) ?>
'downtime_id' => $downtime->id, <?= $deleteButton ?>
'downtime_is_service' => $object->getType() === $object::TYPE_SERVICE </h3>
) <p>
); <span class="sr-only"><?= $this->translate('Downtime') ?></span>
} else { <?= $state ?> -
$deleteButton = ''; <?= str_replace(array('\r\n', '\n'), '<br>', $this->createTicketLinks($downtime->comment)) ?>
} </p>
</li>
?> <?php endforeach ?>
</ul>
<li class="comment-item"> <?php endif ?>
<h3>
<span class="author"><?= $this->escape($downtime->author_name) ?></span>
<?= $this->timeAgo($downtime->entry_time) ?>
<?= $deleteButton ?>
</h3>
<p> <span class="sr-only"><?= $this->translate('Downtime'); ?></span><?= $state; ?> - <?= str_replace(array('\r\n', '\n'), '<br>', $commentText); ?></p>
</li>
<?php endforeach ?>
</ul>
<?php endif ?>
</td> </td>
</tr> </tr>