icingaweb2-module-director/library/Director/Dashboard/Dashboard.php

306 lines
7.3 KiB
PHP

<?php
namespace Icinga\Module\Director\Dashboard;
use Exception;
use gipfl\Translation\TranslationHelper;
use gipfl\IcingaWeb2\Widget\Tabs;
use ipl\Html\Html;
use ipl\Html\HtmlDocument;
use ipl\Html\HtmlString;
use Icinga\Authentication\Auth;
use Icinga\Module\Director\Objects\IcingaObject;
use Icinga\Module\Director\Restriction\HostgroupRestriction;
use Icinga\Module\Director\Dashboard\Dashlet\Dashlet;
use Icinga\Module\Director\Db;
use Icinga\Web\Widget\Tab;
use ipl\Html\ValidHtml;
use Zend_Db_Select as ZfSelect;
abstract class Dashboard extends HtmlDocument
{
use TranslationHelper;
protected $name;
/** @var Dashlet[] */
protected $dashlets;
protected $dashletNames;
/** @var Db */
protected $db;
final private function __construct()
{
}
/**
* @param $name
* @param Db $db
*
* @return self
*/
public static function loadByName($name, Db $db)
{
$class = __NAMESPACE__ . '\\' . ucfirst($name) . 'Dashboard';
$dashboard = new $class();
$dashboard->db = $db;
$dashboard->name = $name;
return $dashboard;
}
public static function exists($name)
{
return class_exists(__NAMESPACE__ . '\\' . ucfirst($name) . 'Dashboard');
}
/**
* @param $description
* @return $this
*/
protected function addDescription($description)
{
if ($description instanceof ValidHtml) {
$this->add(Html::tag('p', $description));
} elseif ($description !== null) {
$this->add(Html::tag(
'p',
null,
HtmlString::create(nl2br(Html::escape($description)))
));
}
return $this;
}
public function render()
{
$this
->setSeparator("\n")
->add(Html::tag('h1', null, $this->getTitle()))
->addDescription($this->getDescription())
->add($this->renderDashlets());
return parent::render();
}
public function renderDashlets()
{
$ul = Html::tag('ul', [
'class' => 'main-actions',
'data-base-target' => '_next'
]);
foreach ($this->dashlets() as $dashlet) {
if ($dashlet->shouldBeShown()) {
$ul->add($dashlet);
}
}
return $ul;
}
public function getName()
{
return $this->name;
}
abstract public function getTitle();
public function getDescription()
{
return null;
}
public function getTabs()
{
$lName = $this->getName();
$tabs = new Tabs();
$tabs->add($lName, new Tab([
'label' => $this->translate(ucfirst($this->getName())),
'url' => 'director/dashboard',
'urlParams' => ['name' => $lName]
]));
return $tabs;
}
protected function createTabsForDashboards($names)
{
$tabs = new Tabs();
foreach ($names as $name) {
$dashboard = Dashboard::loadByName($name, $this->getDb());
if ($dashboard->isAvailable()) {
$tabs->add($name, $this->createTabForDashboard($dashboard));
}
}
return $tabs;
}
protected function createTabForDashboard(Dashboard $dashboard)
{
$name = $dashboard->getName();
return new Tab([
'label' => $this->translate(ucfirst($name)),
'url' => 'director/dashboard',
'urlParams' => ['name' => $name]
]);
}
public function count()
{
return count($this->dashlets());
}
public function isAvailable()
{
return $this->count() > 0;
}
public function getDb()
{
return $this->db;
}
public function dashlets()
{
if ($this->dashlets === null) {
$this->loadDashlets();
$this->fetchDashletSummaries();
}
return $this->dashlets;
}
public function loadDashlets()
{
$names = $this->getDashletNames();
if (empty($names)) {
$this->dashlets = array();
} else {
$this->dashlets = Dashlet::loadByNames(
$this->dashletNames,
$this->getDb()
);
}
}
public function getDashletNames()
{
return $this->dashletNames;
}
protected function fetchDashletSummaries()
{
$types = array();
foreach ($this->dashlets as $dashlet) {
foreach ($dashlet->listRequiredStats() as $objectType) {
$types[$objectType] = $objectType;
}
}
if (empty($types)) {
return;
}
try {
$stats = $this->getObjectSummary($types);
} catch (Exception $e) {
$stats = array();
}
$failing = array();
foreach ($this->dashlets as $key => $dashlet) {
foreach ($dashlet->listRequiredStats() as $objectType) {
if (array_key_exists($objectType, $stats)) {
$dashlet->addStats($objectType, $stats[$objectType]);
} else {
$failing[] = $key;
}
}
}
foreach ($failing as $key) {
unset($this->dashlets[$key]);
}
}
public function getObjectSummary($types)
{
$queries = array();
foreach ($types as $type) {
$queries[] = $this->makeSummaryQuery($type);
}
$query = $this->db->select()->union($queries, ZfSelect::SQL_UNION_ALL);
$result = array();
foreach ($this->db->fetchAll($query) as $row) {
$result[$row->icinga_type] = $row;
}
return $result;
}
protected function makeSummaryQuery($type)
{
$columns = array(
'icinga_type' => "('" . $type . "')",
'cnt_object' => $this->getCntSql('object'),
'cnt_template' => $this->getCntSql('template'),
'cnt_external' => $this->getCntSql('external_object'),
'cnt_apply' => $this->getCntSql('apply'),
'cnt_total' => 'COUNT(*)',
);
if ($this->db->isPgsql()) {
$dummy = IcingaObject::createByType($type);
if (! $dummy->supportsApplyRules()) {
$columns['cnt_apply'] = '(0)';
}
}
$query = $this->db->getDbAdapter()->select()->from(
array('o' => 'icinga_' . $type),
$columns
);
return $this->applyRestrictions($type, $query);
}
protected function applyRestrictions($type, $query)
{
switch ($type) {
case 'host':
case 'hostgroup':
$r = new HostgroupRestriction($this->getDb(), $this->getAuth());
$r->applyToQuery($query);
break;
}
return $query;
}
protected function applyHostgroupRestrictions($query)
{
$restrictions = new HostgroupRestriction($this->getDb(), $this->getAuth());
$restrictions->applyToHostGroupsQuery($query);
}
protected function getAuth()
{
return Auth::getInstance();
}
protected function getCntSql($objectType)
{
return sprintf(
"COALESCE(SUM(CASE WHEN o.object_type = '%s' THEN 1 ELSE 0 END), 0)",
$objectType
);
}
}