summaryrefslogtreecommitdiffstats
path: root/application/controllers/SuggestController.php
diff options
context:
space:
mode:
Diffstat (limited to 'application/controllers/SuggestController.php')
-rw-r--r--application/controllers/SuggestController.php415
1 files changed, 415 insertions, 0 deletions
diff --git a/application/controllers/SuggestController.php b/application/controllers/SuggestController.php
new file mode 100644
index 0000000..659c48c
--- /dev/null
+++ b/application/controllers/SuggestController.php
@@ -0,0 +1,415 @@
+<?php
+
+namespace Icinga\Module\Director\Controllers;
+
+use Icinga\Module\Director\Restriction\HostgroupRestriction;
+use ipl\Html\Html;
+use Icinga\Exception\NotFoundError;
+use Icinga\Module\Director\Hook\ImportSourceHook;
+use Icinga\Module\Director\Objects\IcingaHost;
+use Icinga\Module\Director\Objects\IcingaService;
+use Icinga\Module\Director\Objects\ImportSource;
+use Icinga\Module\Director\Web\Controller\ActionController;
+use Icinga\Data\Filter\Filter;
+use Icinga\Module\Director\Objects\HostApplyMatches;
+
+class SuggestController extends ActionController
+{
+ protected function checkDirectorPermissions()
+ {
+ }
+
+ public function indexAction()
+ {
+ // TODO: Using some temporarily hardcoded methods, should use DataViews later on
+ $context = $this->getRequest()->getPost('context');
+ $key = null;
+
+ if (strpos($context, '!') !== false) {
+ list($context, $key) = preg_split('~!~', $context, 2);
+ }
+
+ $func = 'suggest' . ucfirst($context);
+ if (method_exists($this, $func)) {
+ if (! empty($key)) {
+ $all = $this->$func($key);
+ } else {
+ $all = $this->$func();
+ }
+ } else {
+ $all = array();
+ }
+ // TODO: also get cursor position and eventually add an asterisk in the middle
+ // tODO: filter also when fetching, eventually limit somehow
+ $search = $this->getRequest()->getPost('value');
+ $begins = array();
+ $matches = array();
+ $begin = Filter::expression('value', '=', $search . '*');
+ $middle = Filter::expression('value', '=', '*' . $search . '*')->setCaseSensitive(false);
+ $prefixes = array();
+ foreach ($all as $str) {
+ if (false !== ($pos = strrpos($str, '.'))) {
+ $prefix = substr($str, 0, $pos) . '.';
+ $prefixes[$prefix] = $prefix;
+ }
+ if (strlen($search)) {
+ $row = (object) array('value' => $str);
+ if ($begin->matches($row)) {
+ $begins[] = $this->highlight($str, $search);
+ } elseif ($middle->matches($row)) {
+ $matches[] = $this->highlight($str, $search);
+ }
+ } else {
+ $matches[] = Html::escape($str);
+ }
+ }
+
+ $containing = array_slice(array_merge($begins, $matches), 0, 100);
+ $suggestions = $containing;
+
+ if ($func === 'suggestHostFilterColumns' || $func === 'suggestHostaddresses') {
+ ksort($prefixes);
+
+ if (count($suggestions) < 5) {
+ $suggestions = array_merge($suggestions, array_keys($prefixes));
+ }
+ }
+ $this->view->suggestions = $suggestions;
+ }
+
+ /**
+ * One more dummy helper for tests
+ *
+ * TODO: Should not remain here
+ *
+ * @return array
+ * @throws \Icinga\Exception\ConfigurationError
+ * @throws \Icinga\Security\SecurityException
+ */
+ protected function suggestLocations()
+ {
+ $this->assertPermission('director/hosts');
+ $db = $this->db()->getDbAdapter();
+ $query = $db->select()
+ ->distinct()
+ ->from('icinga_host_var', 'varvalue')
+ ->where('varname = ?', 'location')
+ ->order('varvalue');
+ return $db->fetchCol($query);
+ }
+
+ protected function suggestHostnames($type = 'object')
+ {
+ $this->assertPermission('director/hosts');
+ $db = $this->db()->getDbAdapter();
+ $query = $db->select()
+ ->from('icinga_host', 'object_name')
+ ->order('object_name');
+
+ if ($type !== null) {
+ $query->where('object_type = ?', $type);
+ }
+ $restriction = new HostgroupRestriction($this->db(), $this->Auth());
+ $restriction->filterHostsQuery($query);
+
+ return $db->fetchCol($query);
+ }
+
+ protected function suggestHostsAndTemplates()
+ {
+ return $this->suggestHostnames(null);
+ }
+
+ protected function suggestServicenames()
+ {
+ $r=array();
+ $this->assertPermission('director/services');
+ $db = $this->db()->getDbAdapter();
+ $for_host = $this->getRequest()->getPost('for_host');
+ if (!empty($for_host)) {
+ $tmp_host = IcingaHost::load($for_host, $this->db());
+ }
+
+ $query = $db->select()->distinct()
+ ->from('icinga_service', 'object_name')
+ ->order('object_name')
+ ->where("object_type IN ('object','apply')");
+ if (!empty($tmp_host)) {
+ $query->where('host_id = ?', $tmp_host->id);
+ }
+ $r = array_merge($r, $db->fetchCol($query));
+ if (!empty($tmp_host)) {
+ $resolver = $tmp_host->templateResolver();
+ foreach ($resolver->fetchResolvedParents() as $template_obj) {
+ $query = $db->select()->distinct()
+ ->from('icinga_service', 'object_name')
+ ->order('object_name')
+ ->where("object_type IN ('object','apply')")
+ ->where('host_id = ?', $template_obj->id);
+ $r = array_merge($r, $db->fetchCol($query));
+ }
+
+ $matcher = HostApplyMatches::prepare($tmp_host);
+ foreach ($this->getAllApplyRules() as $rule) {
+ if ($matcher->matchesFilter($rule->filter)) { //TODO
+ $r[]=$rule->name;
+ }
+ }
+ }
+ natcasesort($r);
+ return $r;
+ }
+
+ protected function suggestHosttemplates()
+ {
+ $this->assertPermission('director/hosts');
+ return $this->fetchTemplateNames('icinga_host', 'template_choice_id IS NULL');
+ }
+
+ protected function suggestServicetemplates()
+ {
+ $this->assertPermission('director/services');
+ return $this->fetchTemplateNames('icinga_service', 'template_choice_id IS NULL');
+ }
+
+ protected function suggestNotificationtemplates()
+ {
+ $this->assertPermission('director/notifications');
+ return $this->fetchTemplateNames('icinga_notification');
+ }
+
+ protected function suggestCommandtemplates()
+ {
+ $this->assertPermission('director/commands');
+ $db = $this->db()->getDbAdapter();
+ $query = $db->select()
+ ->from('icinga_command', 'object_name')
+ ->order('object_name');
+ return $db->fetchCol($query);
+ }
+
+ protected function suggestUsertemplates()
+ {
+ $this->assertPermission('director/users');
+ return $this->fetchTemplateNames('icinga_user');
+ }
+
+ /**
+ * @return array
+ * @throws \Icinga\Security\SecurityException
+ * @codingStandardsIgnoreStart
+ */
+ protected function suggestScheduled_downtimetemplates()
+ {
+ // @codingStandardsIgnoreEnd
+ $this->assertPermission('director/scheduled-downtimes');
+ return $this->fetchTemplateNames('icinga_scheduled_downtime');
+ }
+
+ protected function suggestCheckcommandnames()
+ {
+ $db = $this->db()->getDbAdapter();
+ $query = $db->select()
+ ->from('icinga_command', 'object_name')
+ ->where('object_type != ?', 'template')
+ ->order('object_name');
+
+ return $db->fetchCol($query);
+ }
+
+ protected function fetchTemplateNames($table, $where = null)
+ {
+ $db = $this->db()->getDbAdapter();
+ $query = $db->select()
+ ->from($table, 'object_name')
+ ->where('object_type = ?', 'template')
+ ->order('object_name');
+
+ if ($where !== null) {
+ $query->where('template_choice_id IS NULL');
+ }
+
+ return $db->fetchCol($query);
+ }
+
+ protected function suggestHostgroupnames()
+ {
+ $db = $this->db()->getDbAdapter();
+ $query = $db->select()->from('icinga_hostgroup', 'object_name')->order('object_name');
+ return $db->fetchCol($query);
+ }
+
+ protected function suggestHostaddresses()
+ {
+ $db = $this->db()->getDbAdapter();
+ $query = $db->select()->from('icinga_host', 'address')->order('address');
+ return $db->fetchCol($query);
+ }
+
+ protected function suggestHostFilterColumns()
+ {
+ return $this->getFilterColumns('host.', [
+ $this->translate('Host properties'),
+ $this->translate('Custom variables')
+ ]);
+ }
+
+ protected function suggestServiceFilterColumns()
+ {
+ return $this->getFilterColumns('service.', [
+ $this->translate('Service properties'),
+ $this->translate('Host properties'),
+ $this->translate('Host Custom variables'),
+ $this->translate('Custom variables')
+ ]);
+ }
+
+ protected function suggestDataListValuesForListId($id)
+ {
+ $db = $this->db()->getDbAdapter();
+ $select = $db->select()
+ ->from('director_datalist_entry', ['entry_name', 'entry_value'])
+ ->where('list_id = ?', $id)
+ ->order('entry_value ASC');
+
+ $result = $db->fetchPairs($select);
+ if ($result) {
+ return $result;
+ } else {
+ return [];
+ }
+ }
+
+ protected function suggestDataListValues($field = null)
+ {
+ if ($field === null) {
+ // field is required!
+ return [];
+ }
+
+ $datalistType = 'Icinga\\Module\\Director\\DataType\\DataTypeDatalist';
+ $db = $this->db()->getDbAdapter();
+
+ $query = $db->select()
+ ->from(['f' =>'director_datafield'], [])
+ ->join(
+ ['sid' => 'director_datafield_setting'],
+ 'sid.datafield_id = f.id AND sid.setting_name = \'datalist_id\'',
+ []
+ )
+ ->join(
+ ['l' => 'director_datalist'],
+ 'l.id = sid.setting_value',
+ []
+ )
+ ->join(
+ ['e' => 'director_datalist_entry'],
+ 'e.list_id = l.id',
+ ['entry_name', 'entry_value']
+ )
+ ->where('datatype = ?', $datalistType)
+ ->where('varname = ?', $field)
+ ->order('entry_value');
+
+
+ // TODO: respect allowed_roles
+ /* this implementation from DataTypeDatalist is broken
+ $roles = array_map('json_encode', Acl::instance()->listRoleNames());
+
+ if (empty($roles)) {
+ $query->where('allowed_roles IS NULL');
+ } else {
+ $query->where('(allowed_roles IS NULL OR allowed_roles IN (?))', $roles);
+ }
+ */
+
+ $data = [];
+ foreach ($db->fetchPairs($query) as $key => $label) {
+ // TODO: find a better solution here
+ // $data[] = sprintf("%s [%s]", $label, $key);
+ $data[] = $key;
+ }
+ return $data;
+ }
+
+ protected function getFilterColumns($prefix, $keys)
+ {
+ if ($prefix === 'host.') {
+ $all = IcingaHost::enumProperties($this->db(), $prefix);
+ } else {
+ $all = IcingaService::enumProperties($this->db(), $prefix);
+ }
+ $res = [];
+ foreach ($keys as $key) {
+ if (array_key_exists($key, $all)) {
+ $res = array_merge($res, array_keys($all[$key]));
+ }
+ }
+
+ natsort($res);
+ return $res;
+ }
+
+ protected function suggestDependencytemplates()
+ {
+ $this->assertPermission('director/hosts');
+ return $this->fetchTemplateNames('icinga_dependency');
+ }
+
+ protected function highlight($val, $search)
+ {
+ $search = ($search);
+ $val = Html::escape($val);
+ return preg_replace(
+ '/(' . preg_quote($search, '/') . ')/i',
+ '<strong>\1</strong>',
+ $val
+ );
+ }
+
+ protected function getAllApplyRules()
+ {
+ $allApplyRules=$this->fetchAllApplyRules();
+ foreach ($allApplyRules as $rule) {
+ $rule->filter = Filter::fromQueryString($rule->assign_filter);
+ }
+
+ return $allApplyRules;
+ }
+
+ protected function fetchAllApplyRules()
+ {
+ $db = $this->db()->getDbAdapter();
+ $query = $db->select()->from(
+ array('s' => 'icinga_service'),
+ array(
+ 'id' => 's.id',
+ 'name' => 's.object_name',
+ 'assign_filter' => 's.assign_filter',
+ )
+ )->where('object_type = ? AND assign_filter IS NOT NULL', 'apply');
+
+ return $db->fetchAll($query);
+ }
+
+ protected function suggestImportsourceproperties($sourceId = null)
+ {
+ if ($sourceId === null) {
+ return [];
+ }
+
+ try {
+ $importSource = ImportSource::loadWithAutoIncId($sourceId, $this->db());
+ $source = ImportSourceHook::loadByName($importSource->get('source_name'), $this->db());
+
+ $columns = array_merge(
+ $source->listColumns(),
+ $importSource->listProperties()
+ );
+
+ return array_combine($columns, $columns);
+ } catch (NotFoundError $e) {
+ return [];
+ }
+ }
+}