TreeRenderer: new renderer, LOTS of cleanup

This commit is contained in:
Thomas Gelf 2016-11-29 00:34:28 +01:00
parent 0810738235
commit 60b66e89b0
10 changed files with 364 additions and 360 deletions

View file

@ -430,23 +430,6 @@ class BpNode extends Node
}
}
protected function getActionIcons($view)
{
$icons = array();
if (! $this->bp->isLocked() && $this->name !== '__unbound__') {
$icons[] = $this->actionIcon(
$view,
'wrench',
$view->url('businessprocess/node/edit', array(
'config' => $this->bp->getName(),
'node' => $this->name
)),
mt('businessprocess', 'Modify this node')
);
}
return $icons;
}
public function toLegacyConfigString(& $rendered = array())
{
$cfg = '';

View file

@ -99,13 +99,6 @@ class BusinessProcess
*/
protected $simulation;
/**
* Whether we are in edit mode
*
* @var boolean
*/
protected $editMode = false;
protected $locked = true;
protected $changeCount = 0;
@ -261,17 +254,6 @@ class BusinessProcess
return $this->simulationCount;
}
public function setEditMode($mode = true)
{
$this->editMode = (bool) $mode;
return $this;
}
public function isEditMode()
{
return $this->editMode;
}
public function clearAppliedChanges()
{
if ($this->appliedChanges !== null) {
@ -735,37 +717,4 @@ class BusinessProcess
{
return $this->countChildren() === 0;
}
public function renderHtml($view)
{
$html = '';
foreach ($this->getRootNodes() as $name => $node) {
$html .= $node->renderHtml($view);
}
return $html;
}
public function renderUnbound($view)
{
$html = '';
$unbound = $this->getUnboundNodes();
if (empty($unbound)) {
return $html;
}
$parent = new BpNode($this, (object) array(
'name' => '__unbound__',
'operator' => '|',
'child_names' => array_keys($unbound)
));
$parent->getState();
$parent->setMissing()
->setDowntime(false)
->setAck(false)
->setAlias('Unbound nodes');
$html .= $parent->renderHtml($view);
return $html;
}
}

View file

@ -49,28 +49,6 @@ class HostNode extends MonitoredNode
return $this->getHostname();
}
protected function getActionIcons($view)
{
$icons = array();
if (! $this->bp->isLocked()) {
$url = Url::fromPath( 'businessprocess/node/simulate', array(
'config' => $this->bp->getName(),
'node' => $this->name
));
$icons[] = $this->actionIcon(
$view,
'magic',
$url,
'Simulation'
);
}
return $icons;
}
public function getHostname()
{
return $this->hostname;
@ -93,13 +71,4 @@ class HostNode extends MonitoredNode
{
return Link::create($this->hostname, $this->getUrl());
}
public function renderLink($view)
{
if ($this->isMissing()) {
return '<span class="missing">' . $view->escape($this->hostname) . '</span>';
}
return $this->getLink()->render();
}
}

View file

@ -3,20 +3,23 @@
namespace Icinga\Module\Businessprocess;
use Icinga\Application\Config;
use Icinga\Web\Url;
use Icinga\Module\Businessprocess\Html\Link;
use Icinga\Module\Businessprocess\Storage\LegacyStorage;
use Exception;
class ImportedNode extends Node
{
/** @var string */
protected $configName;
protected $importedBp;
protected $importedNode;
/** @var BpNode */
private $node;
protected $className = 'subtree';
/**
* @inheritdoc
*/
public function __construct(BusinessProcess $bp, $object)
{
$this->name = $object->name;
@ -29,11 +32,17 @@ class ImportedNode extends Node
}
}
/**
* @return string
*/
public function getConfigName()
{
return $this->configName;
}
/**
* @inheritdoc
*/
public function getState()
{
if ($this->state === null) {
@ -42,17 +51,26 @@ class ImportedNode extends Node
return $this->state;
}
/**
* @inheritdoc
*/
public function getAlias()
{
return $this->importedNode()->getAlias();
}
/**
* @inheritdoc
*/
public function isMissing()
{
return $this->importedNode()->isMissing();
// TODO: WHY? return $this->getState() === null;
return $this->importedNode()->isMissing();
}
/**
* @inheritdoc
*/
public function isInDowntime()
{
if ($this->downtime === null) {
@ -61,6 +79,9 @@ class ImportedNode extends Node
return $this->downtime;
}
/**
* @inheritdoc
*/
public function isAcknowledged()
{
if ($this->ack === null) {
@ -69,68 +90,83 @@ class ImportedNode extends Node
return $this->ack;
}
/**
* @return BpNode
*/
protected function importedNode()
{
if ($this->importedNode === null) {
$storage = new LegacyStorage(
Config::module('businessprocess')->getSection('global')
);
try {
$this->importedBp = $storage->loadProcess($this->configName);
if ($this->bp->usesSoftStates()) {
$this->importedBp->useSoftStates();
} else {
$this->importedBp->useHardStates();
}
$this->importedBp->retrieveStatesFromBackend();
$this->importedNode = $this->importedBp->getNode($this->name);
} catch (Exception $e) {
if ($this->node === null) {
$this->node = $this->loadImportedNode();
}
return $this->node;
}
$node = new BpNode($this->bp, (object) array(
'name' => $this->name,
'operator' => '&',
'child_names' => array()
));
$node->setState(2);
$node->setMissing(false)
->setDowntime(false)
->setAck(false)
->setAlias($e->getMessage());
$this->importedNode = $node;
/**
* @return BpNode
*/
protected function loadImportedNode()
{
try {
$import = $this->storage()->loadProcess($this->configName);
if ($this->bp->usesSoftStates()) {
$import->useSoftStates();
} else {
$import->useHardStates();
}
$import->retrieveStatesFromBackend();
return $import->getNode($this->name);
} catch (Exception $e) {
return $this->createFailedNode($e);
}
return $this->importedNode;
}
protected function getActionIcons($view)
{
$icons = array();
if (! $this->bp->isLocked()) {
$url = Url::fromPath( 'businessprocess/node/simulate', array(
'config' => $this->bp->getName(),
'node' => $this->name
));
$icons[] = $this->actionIcon(
$view,
'magic',
$url,
'Simulation'
);
}
return $icons;
}
public function renderLink($view)
/**
* @return LegacyStorage
*/
protected function storage()
{
return $view->qlink($this->getAlias(), 'businessprocess/process/show', array(
'config' => $this->configName,
'process' => $this->name
return new LegacyStorage(
Config::module('businessprocess')->getSection('global')
);
}
/**
* @param Exception $e
*
* @return BpNode
*/
protected function createFailedNode(Exception $e)
{
$node = new BpNode($this->bp, (object) array(
'name' => $this->name,
'operator' => '&',
'child_names' => array()
));
$node->setState(2);
$node->setMissing(false)
->setDowntime(false)
->setAck(false)
->setAlias($e->getMessage());
return $node;
}
/**
* @inheritdoc
*/
public function getLink()
{
return Link::create(
$this->getAlias(),
'businessprocess/process/show',
array(
'config' => $this->configName,
'process' => $this->name
)
);
}
}

View file

@ -2,7 +2,6 @@
namespace Icinga\Module\Businessprocess;
use Icinga\Module\Businessprocess\Html\Container;
use Icinga\Module\Businessprocess\Html\Link;
abstract class MonitoredNode extends Node
@ -17,19 +16,4 @@ abstract class MonitoredNode extends Node
return Link::create($this->getAlias(), $this->getUrl());
}
}
protected function prepareActions(Container $actions)
{
$actions->add(
$url = Link::create(
$actions->view()->translate('Simulate a specific state'),
'businessprocess/process/show?addSimulation&unlocked',
array(
'config' => $this->bp->getName(),
'simulationNode' => $this->name
),
array('class' => 'icon-magic')
)
);
}
}

View file

@ -2,10 +2,8 @@
namespace Icinga\Module\Businessprocess;
use Icinga\Web\Url;
use Icinga\Exception\ProgrammingError;
use Icinga\Data\Filter\Filter;
use Exception;
use Icinga\Module\Businessprocess\Html\Link;
abstract class Node
{
@ -253,16 +251,6 @@ abstract class Node
return $this->ack;
}
public function isSimulationMode()
{
return $this->bp->isSimulationMode();
}
public function isEditMode()
{
return $this->bp->isEditMode();
}
public function getChildren($filter = null)
{
return array();
@ -323,142 +311,17 @@ abstract class Node
throw new ProgrammingError('Got invalid sorting state %s', $sortState);
}
protected function renderHtmlForChildren($view)
{
$html = '';
if ($this->hasChildren()) {
foreach ($this->getChildren() as $name => $child) {
$html .= '<tr><td>'
. $child->renderHtml($view)
. '</td></tr>';
}
}
return $html;
}
protected function getId($prefix = '')
{
return md5($prefix . (string) $this);
}
protected function getObjectClassName()
public function getObjectClassName()
{
return $this->className;
}
protected function getStateClassNames()
/**
* @return Link
*/
public function getLink()
{
$state = strtolower($this->getStateName());
if ($this->isMissing()) {
return array('missing');
} elseif ($state === 'ok') {
if ($this->hasMissingChildren()) {
return array('ok', 'missing-children');
} else {
return array('ok');
}
} else {
return array('problem', $state);
}
}
public function renderHtml($view, $prefix = '')
{
$id = $this->getId($prefix);
$handled = $this->isAcknowledged() || $this->isInDowntime();
$html = sprintf(
'<table class="bp %s%s%s%s" id="%s"><tbody><tr>',
implode(' ', $this->getStateClassNames()),
$handled ? ' handled' : '',
($this->hasChildren() ? ' operator ' : ' node '),
$this->getObjectClassName(),
$id
);
if ($this->hasChildren()) {
$html .= sprintf(
'<th%s><span class="op">%s</span></th>',
sprintf(' rowspan="%d"', $this->countChildren() + 1),
$this->operatorHtml()
);
}
$title = preg_replace(
'~(</a>)~',
implode('', $this->getIcons($view)) . '$1',
$this->renderLink($view)
);
$title = preg_replace('#</a>#', ' ' . $view->timeSince($this->getLastStateChange()) . '</a>', $title);
$icons = array();
foreach ($this->getActionIcons($view) as $icon) {
$icons[] = $icon;
}
if ($this->hasInfoUrl()) {
$url = $this->getInfoUrl();
$icons[] = $this->actionIcon(
$view,
'help',
$url,
sprintf('%s: %s', mt('businessprocess', 'More information'), $url)
);
}
$title = implode("\n", $icons) . $title;
$html .= sprintf(
'<td>%s</td></tr>',
$title
);
foreach ($this->getChildren() as $name => $child) {
$html .= '<tr><td>' . $child->renderHtml($view, $id . '-') . '</td></tr>';
}
$html .= "</tbody></table>\n";
return $html;
}
protected function getActionIcons($view)
{
return array();
}
protected function actionIcon($view, $icon, $url, $title)
{
if ($url instanceof Url || ! preg_match('~^https?://~', $url)) {
$target = '';
} else {
$target = ' target="_blank"';
}
return sprintf(
' <a href="%s" %stitle="%s" style="float: right" data-base-target="bp-overlay">%s</a>',
$url,
$target,
$view->escape($title),
$view->icon($icon)
);
}
public function renderLink($view)
{
return '<a href="#">' . ($this->hasAlias() ? $this->getAlias() : $this->name) . '</a>';
}
public function getIcons($view)
{
$icons = array();
if ($this->isInDowntime()) {
$icons[] = $view->icon('moon');
}
if ($this->isAcknowledged()) {
$icons[] = $view->icon('ok');
}
return $icons;
return Link::create($this->getAlias(), '#');
}
public function operatorHtml()
@ -473,13 +336,18 @@ abstract class Node
return '';
}
public function __toString()
public function getName()
{
return $this->name;
}
public function __toString()
{
return $this->getName();
}
public function __destruct()
{
$this->parents = array();
unset($this->parents);
}
}

View file

@ -2,21 +2,21 @@
namespace Icinga\Module\Businessprocess\Renderer;
use Icinga\Date\DateFormatter;
use Icinga\Exception\ProgrammingError;
use Icinga\Module\Businessprocess\BpNode;
use Icinga\Module\Businessprocess\BusinessProcess;
use Icinga\Module\Businessprocess\Html\Container;
use Icinga\Module\Businessprocess\Html\Element;
use Icinga\Module\Businessprocess\Html\Html;
use Icinga\Module\Businessprocess\Html\HtmlString;
use Icinga\Module\Businessprocess\Html\Text;
use Icinga\Module\Businessprocess\Node;
use Icinga\Module\Businessprocess\Web\Url;
use Icinga\Web\View;
use Icinga\Web\Request;
abstract class Renderer extends Html
{
/** @var View */
protected $view;
/** @var BusinessProcess */
protected $bp;
@ -35,15 +35,13 @@ abstract class Renderer extends Html
/**
* Renderer constructor.
*
* @param View $view
* @param BusinessProcess $bp
* @param BpNode|null $parent
*/
public function __construct(View $view, BusinessProcess $bp, BpNode $parent = null)
public function __construct(BusinessProcess $bp, BpNode $parent = null)
{
$this->bp = $bp;
$this->parent = $parent;
$this->view = $view;
}
/**
@ -117,7 +115,6 @@ abstract class Renderer extends Html
)
)->setContent($cnt)
);
}
return $container;
@ -213,6 +210,40 @@ abstract class Renderer extends Html
$this->locked = false;
return $this;
}
public function timeSince($time, $timeOnly = false)
{
if (! $time) {
return HtmlString::create('');
}
return Element::create(
'span',
array(
'class' => array('relative-time', 'time-since'),
'title' => DateFormatter::formatDateTime($time),
)
)->setContent(DateFormatter::timeSince($time, $timeOnly));
}
protected function createUnboundParent(BusinessProcess $bp)
{
$unbound = $bp->getUnboundNodes();
$parent = new BpNode($bp, (object) array(
'name' => '__unbound__',
'operator' => '|',
'child_names' => array_keys($unbound)
));
$parent->getState();
$parent->setMissing()
->setDowntime(false)
->setAck(false)
->setAlias('Unbound nodes');
return $parent;
}
/**
* Just to be on the safe side
*/
@ -220,6 +251,5 @@ abstract class Renderer extends Html
{
unset($this->parent);
unset($this->bp);
unset($this->view);
}
}

View file

@ -39,6 +39,12 @@ class TileRenderer extends Renderer
$this->add(new NodeTile($this, $name, $node, $path));
}
$unbound = $this->createUnboundParent($bp);
if ($unbound->hasChildren()) {
$name = $unbound->getAlias();
$this->add($this->add(new NodeTile($this, $name, $unbound)));
}
$nodesDiv->addContent($this->getContent());
$this->setContent($nodesDiv);

View file

@ -0,0 +1,211 @@
<?php
namespace Icinga\Module\Businessprocess\Renderer;
use Icinga\Module\Businessprocess\BpNode;
use Icinga\Module\Businessprocess\BusinessProcess;
use Icinga\Module\Businessprocess\Html\Container;
use Icinga\Module\Businessprocess\Html\Element;
use Icinga\Module\Businessprocess\Html\HtmlString;
use Icinga\Module\Businessprocess\Html\Icon;
use Icinga\Module\Businessprocess\Html\Link;
use Icinga\Module\Businessprocess\Node;
use Icinga\Module\Businessprocess\Web\Url;
class TreeRenderer extends Renderer
{
/**
* @inheritdoc
*/
public function render()
{
$bp = $this->bp;
$this->add(Container::create(
array(
'id' => $bp->getHtmlId(),
'class' => 'bp'
),
HtmlString::create($this->renderBp($bp))
));
return parent::render();
}
/**
* @param BusinessProcess $bp
* @return string
*/
public function renderBp(BusinessProcess $bp)
{
$html = '';
foreach ($bp->getRootNodes() as $name => $node) {
$html .= $this->renderNode($bp, $node);
}
return $html;
}
/**
* @param Node $node
* @param $path
* @return string
*/
protected function getId(Node $node, $path)
{
return md5(implode(';', $path) . (string) $node);
}
protected function getStateClassNames(Node $node)
{
$state = strtolower($node->getStateName());
if ($node->isMissing()) {
return array('missing');
} elseif ($state === 'ok') {
if ($node->hasMissingChildren()) {
return array('ok', 'missing-children');
} else {
return array('ok');
}
} else {
return array('problem', $state);
}
}
/**
* @param Node $node
* @return Icon[]
*/
public function getNodeIcons(Node $node)
{
$icons = array();
if ($node->isInDowntime()) {
$icons[] = Icon::create('moon');
}
if ($node->isAcknowledged()) {
$icons[] = Icon::create('ok');
}
return $icons;
}
/**
* @param Node $node
* @return string
*/
public function renderNode(BusinessProcess $bp, Node $node, $path = array())
{
$table = Element::create(
'table',
array(
'id' => $this->getId($node, $path),
'class' => array(
'bp',
$node->getObjectClassName()
)
)
);
$attributes = $table->attributes();
$attributes->add('class', $this->getStateClassNames($node));
if ($node->isHandled()) {
$attributes->add('class', 'handled');
}
if ($node->hasChildren()) {
$attributes->add('class', 'operator');
} else {
$attributes->add('class', 'node');
}
$tbody = $table->createElement('tbody');
$tr = $tbody->createElement('tr');
if ($node->hasChildren()) {
$tr->createElement(
'th',
array(
'rowspan' => $node->countChildren() + 1
)
)->createElement(
'span',
array('class' => 'op')
)->setContent($node->operatorHtml());
}
$td = $tr->createElement('td');
$td->addContent($this->getActionIcons($bp, $node));
if ($node->hasInfoUrl()) {
$td->add($this->createInfoAction($node));
}
if (! $this->bp->isLocked()) {
$td->addContent($this->getActionIcons($bp, $node));
}
$link = $node->getLink();
$link->addContent($this->getNodeIcons($node));
$link->addContent($this->timeSince($node->getLastStateChange()));
$td->addContent($link);
foreach ($node->getChildren() as $name => $child) {
$tbody->createElement('tr')->createElement('td')->setContent(
$this->renderNode($bp, $child, $this->getCurrentPath())
);
}
return $table;
}
protected function getActionIcons(BusinessProcess $bp, Node $node)
{
if ($node instanceof BpNode) {
return $this->createEditAction($bp, $node);
} else {
return $this->createSimulationAction($bp, $node);
}
}
protected function createEditAction(BusinessProcess $bp, BpNode $node)
{
return $this->actionIcon(
'wrench',
Url::fromPath('businessprocess/node/edit', array(
'config' => $bp->getName(),
'node' => $node->getName()
)),
$this->translate('Modify this node')
);
}
protected function createSimulationAction(BusinessProcess $bp, Node $node)
{
return $this->actionIcon(
'magic',
Url::fromPath('businessprocess/process/show?addSimulation&unlocked', array(
'config' => $bp->getName(),
'node' => $node->getName()
)),
$this->translate('Simulate a specific state')
);
}
protected function createInfoAction(BpNode $node)
{
$url = $node->getInfoUrl();
return $this->actionIcon(
'help',
$url,
sprintf('%s: %s', $this->translate('More information'), $url)
);
}
protected function actionIcon($icon, $url, $title)
{
return Link::create(
Icon::create($icon),
$url,
null,
array(
'title' => $title,
'style' => 'float: right',
)
);
}
}

View file

@ -2,7 +2,6 @@
namespace Icinga\Module\Businessprocess;
use Icinga\Module\Businessprocess\Html\Link;
use Icinga\Module\Businessprocess\Web\Url;
class ServiceNode extends MonitoredNode
@ -26,28 +25,6 @@ class ServiceNode extends MonitoredNode
}
}
protected function getActionIcons($view)
{
$icons = array();
if (! $this->bp->isLocked()) {
$url = Url::fromPath('businessprocess/node/simulate', array(
'config' => $this->bp->getName(),
'node' => $this->name
));
$icons[] = $this->actionIcon(
$view,
'magic',
$url,
'Simulation'
);
}
return $icons;
}
public function getHostname()
{
return $this->hostname;
@ -76,13 +53,4 @@ class ServiceNode extends MonitoredNode
return Url::fromPath('monitoring/service/show', $params);
}
public function renderLink($view)
{
if ($this->isMissing()) {
return '<span class="missing">' . $view->escape($this->getAlias()) . '</span>';
}
return $this->getLink()->render();
}
}