getRequest()->getActionName() !== 'sets') { $this->assertPermission('director/' . $this->getPluralBaseType()); } } /** * @return $this */ protected function addObjectsTabs() { $tabName = $this->getRequest()->getActionName(); if (substr($this->getType(), -5) === 'Group') { $tabName = 'groups'; } $this->tabs(new ObjectsTabs($this->getBaseType(), $this->Auth())) ->activate($tabName); return $this; } public function indexAction() { if ($this->getRequest()->isApiRequest()) { try { $this->streamJsonResult(); } catch (\Exception $e) { echo $e->getTraceAsString(); exit; } return; } $type = $this->getType(); $this ->addObjectsTabs() ->setAutorefreshInterval(10) ->addTitle($this->translate(ucfirst(strtolower($type)) . 's')) ->actions(new ObjectsActionBar($type, $this->url())); if ($type === 'command' && $this->params->get('type') === 'external_object') { $this->tabs()->activate('external'); } // Hint: might be used in controllers extending this $this->table = $this->getTable(); $this->table->renderTo($this); } protected function streamJsonResult() { $connection = $this->db(); Benchmark::measure('aha'); $db = $connection->getDbAdapter(); $query = $this->getTable() ->getQuery() ->reset(ZfSelect::COLUMNS) ->columns('*') ->reset(ZfSelect::LIMIT_COUNT) ->reset(ZfSelect::LIMIT_OFFSET); echo '{ "objects": [ '; $cnt = 0; $objects = []; $dummy = IcingaObject::createByType($this->getType(), [], $connection); $dummy->prefetchAllRelatedTypes(); Benchmark::measure('Prefetching'); PrefetchCache::initialize($this->db()); Benchmark::measure('Ready to query'); $stmt = $db->query($query); $this->getResponse()->sendHeaders(); if (! ob_get_level()) { ob_start(); } $resolved = (bool) $this->params->get('resolved', false); $first = true; $flushes = 0; while ($row = $stmt->fetch()) { /** @var IcingaObject $object */ if ($first) { Benchmark::measure('First row'); } $object = $dummy::fromDbRow($row, $connection); $objects[] = json_encode($object->toPlainObject($resolved, true), JSON_PRETTY_PRINT); if ($first) { Benchmark::measure('Got first row'); $first = false; } $cnt++; if ($cnt === 100) { if ($flushes > 0) { echo ', '; } echo implode(', ', $objects); $cnt = 0; $objects = []; $flushes++; ob_end_flush(); ob_start(); } } if ($cnt > 0) { if ($flushes > 0) { echo ', '; } echo implode(', ', $objects); } if ($this->params->get('benchmark')) { echo "],\n"; Benchmark::measure('All done'); echo '"benchmark_string": ' . json_encode(Benchmark::renderToText()); } else { echo '] '; } echo "}\n"; if (ob_get_level()) { ob_end_flush(); } // TODO: can we improve this? exit; } protected function getTable() { return ObjectsTable::create($this->getType(), $this->db()) ->setAuth($this->getAuth()); } public function editAction() { $type = ucfirst($this->getType()); if (empty($this->multiEdit)) { throw new NotFoundError('Cannot edit multiple "%s" instances', $type); } $objects = $this->loadMultiObjectsFromParams(); $formName = 'icinga' . $type; $form = IcingaMultiEditForm::load() ->setObjects($objects) ->pickElementsFrom($this->loadForm($formName), $this->multiEdit); if ($type === 'Service') { $form->setListUrl('director/services'); } elseif ($type === 'Host') { $form->setListUrl('director/hosts'); } $form->handleRequest(); $this ->addSingleTab($this->translate('Multiple objects')) ->addTitle( $this->translate('Modify %d objects'), count($objects) )->content()->add($form); } /** * Loads the TemplatesTable or the TemplateTreeRenderer * * Passing render=tree switches to the tree view. */ public function templatesAction() { $type = $this->getType(); $shortType = IcingaObject::createByType($type)->getShortTableName(); $this ->assertPermission('director/admin') ->addObjectsTabs() ->setAutorefreshInterval(10) ->addTitle( $this->translate('All your %s Templates'), $this->translate(ucfirst($type)) ) ->actions(new TemplateActionBar($shortType, $this->url())); $this->params->get('render') === 'tree' ? TemplateTreeRenderer::showType($shortType, $this, $this->db()) : TemplatesTable::create($shortType, $this->db())->renderTo($this); } protected function assertApplyRulePermission() { return $this->assertPermission('director/admin'); } public function applyrulesAction() { $type = $this->getType(); $tType = $this->translate(ucfirst($type)); $this ->assertApplyRulePermission() ->addObjectsTabs() ->setAutorefreshInterval(10) ->addTitle( $this->translate('All your %s Apply Rules'), $tType ); $this->actions()/*->add( $this->getBackToDashboardLink() )*/->add( Link::create( $this->translate('Add'), "director/$type/add", ['type' => 'apply'], [ 'title' => sprintf( $this->translate('Create a new %s Apply Rule'), $tType ), 'class' => 'icon-plus', 'data-base-target' => '_next' ] ) ); $table = new ApplyRulesTable($this->db()); $table->setType($this->getType()); $table->renderTo($this); } public function setsAction() { $type = $this->getType(); $tType = $this->translate(ucfirst($type)); $this ->assertPermission('director/' . $this->getBaseType() . '_sets') ->addObjectsTabs() ->requireSupportFor('Sets') ->setAutorefreshInterval(10) ->addTitle( $this->translate('Icinga %s Sets'), $tType ); $this->actions()->add( Link::create( $this->translate('Add'), "director/${type}set/add", null, [ 'title' => sprintf( $this->translate('Create a new %s Set'), $tType ), 'class' => 'icon-plus', 'data-base-target' => '_next' ] ) ); ObjectSetTable::create($type, $this->db())->renderTo($this); } protected function loadMultiObjectsFromParams() { $filter = Filter::fromQueryString($this->params->toString()); $type = $this->getType(); $objects = array(); $db = $this->db(); /** @var $filter FilterChain */ foreach ($filter->filters() as $sub) { /** @var $sub FilterChain */ foreach ($sub->filters() as $ex) { /** @var $ex FilterChain|FilterExpression */ $col = $ex->getColumn(); if ($ex->isExpression()) { if ($col === 'name') { $name = $ex->getExpression(); $objects[$name] = IcingaObject::loadByType($type, $name, $db); } elseif ($col === 'id') { $name = $ex->getExpression(); $objects[$name] = IcingaObject::loadByType($type, ['id' => $name], $db); } } } } return $objects; } /** * @param $feature * @return $this * @throws NotFoundError */ protected function requireSupportFor($feature) { if ($this->supports($feature) !== true) { throw new NotFoundError( '%s does not support %s', $this->getType(), $feature ); } return $this; } protected function supports($feature) { $func = "supports$feature"; return IcingaObject::createByType($this->getType())->$func(); } protected function getBaseType() { $type = $this->getType(); if (substr($type, -5) === 'Group') { return substr($type, 0, -5); } else { return $type; } } protected function getType() { // Strip final 's' and upcase an eventual 'group' return preg_replace( array('/group$/', '/period$/', '/argument$/', '/apiuser$/'), array('Group', 'Period', 'Argument', 'ApiUser'), str_replace( 'template', '', substr($this->getRequest()->getControllerName(), 0, -1) ) ); } protected function getPluralType() { return $this->getType() . 's'; } protected function getPluralBaseType() { return $this->getBaseType() . 's'; } }