diff options
Diffstat (limited to 'library/Cube/Cube.php')
-rw-r--r-- | library/Cube/Cube.php | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/library/Cube/Cube.php b/library/Cube/Cube.php new file mode 100644 index 0000000..1e688f0 --- /dev/null +++ b/library/Cube/Cube.php @@ -0,0 +1,341 @@ +<?php + +// Icinga Web 2 Cube Module | (c) 2016 Icinga GmbH | GPLv2 + +namespace Icinga\Module\Cube; + +use Icinga\Application\Modules\Module; +use Icinga\Exception\IcingaException; +use Icinga\Module\Cube\ProvidedHook\Icingadb\IcingadbSupport; +use Icinga\Web\View; + +abstract class Cube +{ + /** @var ?string Prefix for slice params */ + public const SLICE_PREFIX = null; + + /** @var ?bool Whether the icingadb backend is in use */ + public const IS_USING_ICINGADB = null; + + /** @var array<string, Dimension> Available dimensions */ + protected $availableDimensions; + + /** @var array Fact names */ + protected $chosenFacts; + + /** @var Dimension[] */ + protected $dimensions = array(); + + protected $slices = array(); + + protected $renderer; + + abstract public function fetchAll(); + + /** + * Get whether the icingadb backend is in use + * + * @return bool + */ + public static function isUsingIcingaDb(): bool + { + return static::IS_USING_ICINGADB + ?? (Module::exists('icingadb') && IcingadbSupport::useIcingaDbAsBackend()); + } + + public function removeDimension($name) + { + unset($this->dimensions[$name]); + unset($this->slices[$name]); + return $this; + } + + /** + * @return CubeRenderer + * @throws IcingaException + */ + public function getRenderer() + { + throw new IcingaException('Got no cube renderer'); + } + + public function getPathLabel() + { + $dimensions = $this->getDimensionsLabel(); + $slices = $this->getSlicesLabel(); + $parts = array(); + if ($dimensions !== null) { + $parts[] = $dimensions; + } + + if ($slices !== null) { + $parts[] = $slices; + } + + return implode(', ', $parts); + } + + public function getDimensionsLabel() + { + $dimensions = $this->listDimensions(); + if (empty($dimensions)) { + return null; + } + + return implode(' -> ', array_map(function ($d) { + return $d->getLabel(); + }, $dimensions)); + } + + public function getSlicesLabel() + { + $parts = array(); + + $slices = $this->getSlices(); + if (empty($slices)) { + return null; + } + foreach ($slices as $key => $value) { + $parts[] = sprintf('%s = %s', $this->getDimension($key)->getLabel(), $value); + } + + return implode(', ', $parts); + } + + /** + * Create a new dimension + * + * @param string $name + * @return Dimension + */ + abstract public function createDimension($name); + + protected function registerAvailableDimensions() + { + if ($this->availableDimensions !== null) { + return; + } + + $this->availableDimensions = []; + foreach ($this->listAvailableDimensions() as $name => $label) { + if (! isset($this->availableDimensions[$name])) { + $this->availableDimensions[$name] = $this->createDimension($name)->setLabel($label); + } else { + $this->availableDimensions[$name]->addLabel($label); + } + } + } + + public function listAdditionalDimensions() + { + $this->registerAvailableDimensions(); + + $list = []; + foreach ($this->availableDimensions as $name => $dimension) { + if (! $this->hasDimension($name)) { + $list[$name] = $dimension->getLabel(); + } + } + + return $list; + } + + abstract public function listAvailableDimensions(); + + public function getDimensionAfter($name) + { + $found = false; + $after = null; + + foreach ($this->listDimensions() as $k => $d) { + if ($found) { + $after = $d; + break; + } + + if ($k === $name) { + $found = true; + } + } + + return $after; + } + + public function listDimensionsUpTo($name) + { + $res = array(); + foreach ($this->listDimensions() as $d => $_) { + $res[] = $d; + if ($d === $name) { + break; + } + } + + return $res; + } + + public function moveDimensionUp($name) + { + $last = $found = null; + $positions = array_keys($this->dimensions); + + foreach ($positions as $k => $v) { + if ($v === $name) { + $found = $k; + break; + } + + $last = $k; + } + + if ($found !== null) { + $this->flipPositions($positions, $last, $found); + } + + $this->reOrderDimensions($positions); + return $this; + } + + public function moveDimensionDown($name) + { + $next = $found = null; + $positions = array_keys($this->dimensions); + + foreach ($positions as $k => $v) { + if ($found !== null) { + $next = $k; + break; + } + + if ($v === $name) { + $found = $k; + } + } + + if ($next !== null) { + $this->flipPositions($positions, $next, $found); + } + + $this->reOrderDimensions($positions); + return $this; + } + + protected function flipPositions(&$array, $pos1, $pos2) + { + list( + $array[$pos1], + $array[$pos2] + ) = array( + $array[$pos2], + $array[$pos1] + ); + } + + protected function reOrderDimensions($positions) + { + $dimensions = array(); + foreach ($positions as $pos => $key) { + $dimensions[$key] = $this->dimensions[$key]; + } + + $this->dimensions = $dimensions; + } + + public function addDimension(Dimension $dimension) + { + $name = $dimension->getName(); + if ($this->hasDimension($name)) { + throw new IcingaException('Cannot add dimension "%s" twice', $name); + } + + $this->dimensions[$name] = $dimension; + return $this; + } + + public function slice($key, $value) + { + if ($this->hasDimension($key)) { + $this->slices[$key] = $value; + } else { + throw new IcingaException('Got no such dimension: "%s"', $key); + } + + return $this; + } + + public function hasDimension($name) + { + return array_key_exists($name, $this->dimensions); + } + + public function hasSlice($name) + { + return array_key_exists($name, $this->slices); + } + + public function listSlices() + { + return array_keys($this->slices); + } + + public function getSlices() + { + return $this->slices; + } + + public function hasFact($name) + { + return array_key_exists($name, $this->chosenFacts); + } + + public function getDimension($name) + { + return $this->dimensions[$name]; + } + + /** + * Return a list of chosen facts + * + * @return array + */ + public function listFacts() + { + return $this->chosenFacts; + } + + /** + * Choose a list of facts + * + * @param array $facts + * @return $this + */ + public function chooseFacts(array $facts) + { + $this->chosenFacts = $facts; + return $this; + } + + public function listDimensions() + { + return array_diff_key($this->dimensions, $this->slices); + } + + public function listColumns() + { + return array_merge(array_keys($this->listDimensions()), $this->listFacts()); + } + + /** + * @param View $view + * @param CubeRenderer $renderer + * @return string + */ + public function render(View $view, CubeRenderer $renderer = null) + { + if ($renderer === null) { + $renderer = $this->getRenderer(); + } + + return $renderer->render($view); + } +} |