icingaweb2-module-director/library/Director/Web/ObjectPreview.php

183 lines
5.3 KiB
PHP

<?php
namespace Icinga\Module\Director\Web;
use gipfl\Web\Widget\Hint;
use ipl\Html\Text;
use Icinga\Module\Director\Exception\NestingError;
use Icinga\Module\Director\Objects\IcingaObject;
use Icinga\Web\Request;
use ipl\Html\Html;
use gipfl\IcingaWeb2\Link;
use gipfl\Translation\TranslationHelper;
use gipfl\IcingaWeb2\Widget\ControlsAndContent;
class ObjectPreview
{
use TranslationHelper;
/** @var IcingaObject */
protected $object;
/** @var Request */
protected $request;
public function __construct(IcingaObject $object, Request $request)
{
$this->object = $object;
$this->request = $request;
}
/**
* @param ControlsAndContent $cc
* @throws \Icinga\Exception\NotFoundError
*/
public function renderTo(ControlsAndContent $cc)
{
$object = $this->object;
$url = $this->request->getUrl();
$params = $url->getParams();
$cc->addTitle(
$this->translate('Config preview: %s'),
$object->getObjectName()
);
if ($params->shift('resolved')) {
$object = $object::fromPlainObject(
$object->toPlainObject(true),
$object->getConnection()
);
$cc->actions()->add(Link::create(
$this->translate('Show normal'),
$url->without('resolved'),
null,
['class' => 'icon-resize-small state-warning']
));
} else {
try {
if ($object->supportsImports() && $object->imports()->count() > 0) {
$cc->actions()->add(Link::create(
$this->translate('Show resolved'),
$url->with('resolved', true),
null,
['class' => 'icon-resize-full']
));
}
} catch (NestingError $e) {
// No resolve link with nesting errors
}
}
$content = $cc->content();
if ($object->isDisabled()) {
$content->add(Hint::error(
$this->translate('This object will not be deployed as it has been disabled')
));
}
if ($object->isExternal()) {
$content->add(Html::tag('p', null, $this->translate((
'This is an external object. It has been imported from Icinga 2 through the'
. ' Core API and cannot be managed with the Icinga Director. It is however'
. ' perfectly valid to create objects using this or referring to this object.'
. ' You might also want to define related Fields to make work based on this'
. ' object more enjoyable.'
))));
}
$config = $object->toSingleIcingaConfig();
foreach ($config->getFiles() as $filename => $file) {
if (! $object->isExternal()) {
$content->add(Html::tag('h2', null, $filename));
}
$classes = array();
if ($object->isDisabled()) {
$classes[] = 'disabled';
} elseif ($object->isExternal()) {
$classes[] = 'logfile';
}
$type = $object->getShortTableName();
$plain = Html::wantHtml($file->getContent())->render();
$plain = preg_replace_callback(
'/^(\s+import\s+\&quot\;)(.+)(\&quot\;)/m',
[$this, 'linkImport'],
$plain
);
if ($type !== 'command') {
$plain = preg_replace_callback(
'/^(\s+(?:check_|event_)?command\s+=\s+\&quot\;)(.+)(\&quot\;)/m',
[$this, 'linkCommand'],
$plain
);
}
$plain = preg_replace_callback(
'/^(\s+host_name\s+=\s+\&quot\;)(.+)(\&quot\;)/m',
[$this, 'linkHost'],
$plain
);
$text = Text::create($plain)->setEscaped();
$content->add(Html::tag('pre', ['class' => $classes], $text));
}
}
/**
* @api internal
* @param $match
* @return string
*/
public function linkImport($match)
{
$blacklist = [
'plugin-notification-command',
'plugin-check-command',
];
if (in_array($match[2], $blacklist)) {
return $match[1] . $match[2] . $match[3];
}
$urlObjectType = $this->object->getShortTableName();
if ($urlObjectType === 'service_set') {
$urlObjectType = 'service';
}
return $match[1] . Link::create(
$match[2],
sprintf("director/$urlObjectType"),
['name' => $match[2]]
)->render() . $match[3];
}
/**
* @api internal
* @param $match
* @return string
*/
public function linkCommand($match)
{
return $match[1] . Link::create(
$match[2],
sprintf('director/command'),
['name' => $match[2]]
)->render() . $match[3];
}
/**
* @api internal
* @param $match
* @return string
*/
public function linkHost($match)
{
return $match[1] . Link::create(
$match[2],
sprintf('director/host'),
['name' => $match[2]]
)->render() . $match[3];
}
}