summaryrefslogtreecommitdiffstats
path: root/application/controllers/DataController.php
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--application/controllers/DataController.php406
1 files changed, 406 insertions, 0 deletions
diff --git a/application/controllers/DataController.php b/application/controllers/DataController.php
new file mode 100644
index 0000000..ae4bbcf
--- /dev/null
+++ b/application/controllers/DataController.php
@@ -0,0 +1,406 @@
+<?php
+
+namespace Icinga\Module\Director\Controllers;
+
+use gipfl\Web\Widget\Hint;
+use Icinga\Exception\NotFoundError;
+use Icinga\Module\Director\Forms\DirectorDatalistEntryForm;
+use Icinga\Module\Director\Forms\DirectorDatalistForm;
+use Icinga\Module\Director\Forms\IcingaServiceDictionaryMemberForm;
+use Icinga\Module\Director\Objects\DirectorDatalist;
+use Icinga\Module\Director\Objects\IcingaHost;
+use Icinga\Module\Director\Objects\IcingaObject;
+use Icinga\Module\Director\Objects\IcingaService;
+use Icinga\Module\Director\PlainObjectRenderer;
+use Icinga\Module\Director\Web\Controller\ActionController;
+use Icinga\Module\Director\Web\Form\IcingaObjectFieldLoader;
+use Icinga\Module\Director\Web\Table\CustomvarTable;
+use Icinga\Module\Director\Web\Table\DatafieldCategoryTable;
+use Icinga\Module\Director\Web\Table\DatafieldTable;
+use Icinga\Module\Director\Web\Table\DatalistEntryTable;
+use Icinga\Module\Director\Web\Table\DatalistTable;
+use Icinga\Module\Director\Web\Tabs\DataTabs;
+use gipfl\IcingaWeb2\Link;
+use InvalidArgumentException;
+use ipl\Html\Html;
+use ipl\Html\Table;
+
+class DataController extends ActionController
+{
+ public function listsAction()
+ {
+ $this->addTitle($this->translate('Data lists'));
+ $this->actions()->add(
+ Link::create($this->translate('Add'), 'director/data/list', null, [
+ 'class' => 'icon-plus',
+ 'data-base-target' => '_next'
+ ])
+ );
+
+ $this->tabs(new DataTabs())->activate('datalist');
+ (new DatalistTable($this->db()))->renderTo($this);
+ }
+
+ /**
+ * @throws \Icinga\Exception\MissingParameterException
+ * @throws \Icinga\Exception\NotFoundError
+ */
+ public function listAction()
+ {
+ $form = DirectorDatalistForm::load()
+ ->setSuccessUrl('director/data/lists')
+ ->setDb($this->db());
+
+ if ($name = $this->params->get('name')) {
+ $list = $this->requireList('name');
+ $form->setObject($list);
+ $this->addListActions($list);
+ $this->addTitle(
+ $this->translate('Data List: %s'),
+ $list->get('list_name')
+ )->addListTabs($name, 'list');
+ } else {
+ $this
+ ->addTitle($this->translate('Add a new Data List'))
+ ->addSingleTab($this->translate('Data List'));
+ }
+
+ $this->content()->add($form->handleRequest());
+ }
+
+ public function fieldsAction()
+ {
+ $this->setAutorefreshInterval(10);
+ $this->tabs(new DataTabs())->activate('datafield');
+ $this->addTitle($this->translate('Data Fields'));
+ $this->actions()->add(Link::create(
+ $this->translate('Add'),
+ 'director/datafield/add',
+ null,
+ [
+ 'class' => 'icon-plus',
+ 'data-base-target' => '_next',
+ ]
+ ));
+
+ (new DatafieldTable($this->db()))->renderTo($this);
+ }
+
+ public function fieldcategoriesAction()
+ {
+ $this->setAutorefreshInterval(10);
+ $this->tabs(new DataTabs())->activate('datafieldcategory');
+ $this->addTitle($this->translate('Data Field Categories'));
+ $this->actions()->add(Link::create(
+ $this->translate('Add'),
+ 'director/datafieldcategory/add',
+ null,
+ [
+ 'class' => 'icon-plus',
+ 'data-base-target' => '_next',
+ ]
+ ));
+
+ (new DatafieldCategoryTable($this->db()))->renderTo($this);
+ }
+
+ public function varsAction()
+ {
+ $this->tabs(new DataTabs())->activate('customvars');
+ $this->addTitle($this->translate('Custom Vars - Overview'));
+ (new CustomvarTable($this->db()))->renderTo($this);
+ }
+
+ /**
+ * @throws \Icinga\Exception\MissingParameterException
+ * @throws \Icinga\Exception\NotFoundError
+ */
+ public function listentryAction()
+ {
+ $entryName = $this->params->get('entry_name');
+ $list = $this->requireList('list');
+ $this->addListActions($list);
+ $listId = $list->get('id');
+ $listName = $list->get('list_name');
+ $title = $title = $this->translate('List Entries') . ': ' . $listName;
+ $this->addTitle($title);
+
+ $form = DirectorDatalistEntryForm::load()
+ ->setSuccessUrl('director/data/listentry', ['list' => $listName])
+ ->setList($list);
+
+ if (null !== $entryName) {
+ $form->loadObject([
+ 'list_id' => $listId,
+ 'entry_name' => $entryName
+ ]);
+ $this->actions()->add(Link::create(
+ $this->translate('back'),
+ 'director/data/listentry',
+ ['list' => $listName],
+ ['class' => 'icon-left-big']
+ ));
+ }
+ $form->handleRequest();
+
+ $this->addListTabs($listName, 'entries');
+
+ $table = new DatalistEntryTable($this->db());
+ $table->getAttributes()->set('data-base-target', '_self');
+ $table->setList($list);
+ $this->content()->add([$form, $table]);
+ }
+
+ public function dictionaryAction()
+ {
+ $connection = $this->db();
+ $this->addSingleTab('Nested Dictionary');
+ $varName = $this->params->get('varname');
+ $instance = $this->url()->getParam('instance');
+ $action = $this->url()->getParam('action');
+ $object = $this->requireObject();
+
+ if ($instance || $action) {
+ $this->actions()->add(
+ Link::create($this->translate('Back'), $this->url()->without(['action', 'instance']), null, [
+ 'class' => 'icon-edit'
+ ])
+ );
+ } else {
+ $this->actions()->add(
+ Link::create($this->translate('Add'), $this->url(), [
+ 'action' => 'add'
+ ], [
+ 'class' => 'icon-edit'
+ ])
+ );
+ }
+ $subjects = $this->prepareSubjectsLabel($object, $varName);
+ $fieldLoader = new IcingaObjectFieldLoader($object);
+ $instances = $this->getCurrentInstances($object, $varName);
+
+ if (empty($instances)) {
+ $this->content()->add(Hint::info(sprintf(
+ $this->translate('No %s have been created yet'),
+ $subjects
+ )));
+ } else {
+ $this->content()->add($this->prepareInstancesTable($instances));
+ }
+
+ $field = $this->getFieldByName($fieldLoader, $varName);
+ $template = $object::load([
+ 'object_name' => $field->getSetting('template_name')
+ ], $connection);
+
+ $form = new IcingaServiceDictionaryMemberForm();
+ $form->setDb($connection);
+ if ($instance) {
+ $instanceObject = $object::create([
+ 'imports' => [$template],
+ 'object_name' => $instance,
+ 'vars' => $instances[$instance]
+ ], $connection);
+ $form->setObject($instanceObject);
+ } elseif ($action === 'add') {
+ $form->presetImports([$template->getObjectName()]);
+ } else {
+ return;
+ }
+ if ($instance) {
+ if (! isset($instances[$instance])) {
+ throw new NotFoundError("There is no such instance: $instance");
+ }
+ $subTitle = sprintf($this->translate('Modify instance: %s'), $instance);
+ } else {
+ $subTitle = $this->translate('Add a new instance');
+ }
+
+ $this->content()->add(Html::tag('h2', ['style' => 'margin-top: 2em'], $subTitle));
+ $form->handleRequest($this->getRequest());
+ $this->content()->add($form);
+ if ($form->succeeded()) {
+ $virtualObject = $form->getObject();
+ $name = $virtualObject->getObjectName();
+ $params = $form->getObject()->getVars();
+ $instances[$name] = $params;
+ if ($name !== $instance) { // Has been renamed
+ unset($instances[$instance]);
+ }
+ ksort($instances);
+ $object->set("vars.$varName", (object)$instances);
+ $object->store();
+ $this->redirectNow($this->url()->without(['instance', 'action']));
+ } elseif ($form->shouldBeDeleted()) {
+ unset($instances[$instance]);
+ if (empty($instances)) {
+ $object->set("vars.$varName", null)->store();
+ } else {
+ $object->set("vars.$varName", (object)$instances)->store();
+ }
+ $this->redirectNow($this->url()->without(['instance', 'action']));
+ }
+ }
+
+ protected function requireObject()
+ {
+ $connection = $this->db();
+ $hostName = $this->params->getRequired('host');
+ $serviceName = $this->params->get('service');
+ if ($serviceName) {
+ $host = IcingaHost::load($hostName, $connection);
+ $object = IcingaService::load([
+ 'host_id' => $host->get('id'),
+ 'object_name' => $serviceName,
+ ], $connection);
+ } else {
+ $object = IcingaHost::load($hostName, $connection);
+ }
+
+ if (! $object->isObject()) {
+ throw new InvalidArgumentException(sprintf(
+ 'Only single objects allowed, %s is a %s',
+ $object->getObjectName(),
+ $object->get('object_type')
+ ));
+ }
+ return $object;
+ }
+
+ protected function shorten($string, $maxLen)
+ {
+ if (strlen($string) <= $maxLen) {
+ return $string;
+ }
+
+ return substr($string, 0, $maxLen) . '...';
+ }
+
+ protected function getFieldByName(IcingaObjectFieldLoader $loader, $name)
+ {
+ foreach ($loader->getFields() as $field) {
+ if ($field->get('varname') === $name) {
+ return $field;
+ }
+ }
+
+ throw new InvalidArgumentException("Found no configured field for '$name'");
+ }
+
+ /**
+ * @param IcingaObject $object
+ * @param $varName
+ * @return array
+ */
+ protected function getCurrentInstances(IcingaObject $object, $varName)
+ {
+ $currentVars = $object->getVars();
+ if (isset($currentVars->$varName)) {
+ $currentValue = $currentVars->$varName;
+ } else {
+ $currentValue = (object)[];
+ }
+ if (is_object($currentValue)) {
+ $currentValue = (array)$currentValue;
+ } else {
+ throw new InvalidArgumentException(sprintf(
+ '"%s" is not a valid Dictionary',
+ json_encode($currentValue)
+ ));
+ }
+ return $currentValue;
+ }
+
+ /**
+ * @param array $currentValue
+ * @param $subjects
+ * @return Hint|Table
+ */
+ protected function prepareInstancesTable(array $currentValue)
+ {
+ $table = new Table();
+ $table->addAttributes([
+ 'class' => 'common-table table-row-selectable'
+ ]);
+ $table->getHeader()->add(
+ Table::row([
+ $this->translate('Key / Instance'),
+ $this->translate('Properties')
+ ], ['style' => 'text-align: left'], 'th')
+ );
+ foreach ($currentValue as $key => $item) {
+ $table->add(Table::row([
+ Link::create($key, $this->url()->with('instance', $key)),
+ str_replace("\n", ' ', $this->shorten(PlainObjectRenderer::render($item), 512))
+ ]));
+ }
+
+ return $table;
+ }
+
+ /**
+ * @param IcingaObject $object
+ * @param $varName
+ * @return string
+ */
+ protected function prepareSubjectsLabel(IcingaObject $object, $varName)
+ {
+ if ($object instanceof IcingaService) {
+ $hostName = $object->get('host');
+ $subjects = $object->getObjectName() . " ($varName)";
+ } else {
+ $hostName = $object->getObjectName();
+ $subjects = sprintf(
+ $this->translate('%s instances'),
+ $varName
+ );
+ }
+ $this->addTitle(sprintf(
+ $this->translate('%s on %s'),
+ $subjects,
+ $hostName
+ ));
+ return $subjects;
+ }
+
+ protected function addListActions(DirectorDatalist $list)
+ {
+ $this->actions()->add(
+ Link::create(
+ $this->translate('Add to Basket'),
+ 'director/basket/add',
+ [
+ 'type' => 'DataList',
+ 'names' => $list->getUniqueIdentifier()
+ ],
+ ['class' => 'icon-tag']
+ )
+ );
+ }
+
+ /**
+ * @param $paramName
+ * @return DirectorDatalist
+ * @throws \Icinga\Exception\MissingParameterException
+ * @throws \Icinga\Exception\NotFoundError
+ */
+ protected function requireList($paramName)
+ {
+ return DirectorDatalist::load($this->params->getRequired($paramName), $this->db());
+ }
+
+ protected function addListTabs($name, $activate)
+ {
+ $this->tabs()->add('list', [
+ 'url' => 'director/data/list',
+ 'urlParams' => ['name' => $name],
+ 'label' => $this->translate('Edit list'),
+ ])->add('entries', [
+ 'url' => 'director/data/listentry',
+ 'urlParams' => ['list' => $name],
+ 'label' => $this->translate('List entries'),
+ ])->activate($activate);
+
+ return $this;
+ }
+}