mirror of
https://github.com/Icinga/icingaweb2-module-director.git
synced 2025-07-28 08:14:04 +02:00
parent
83dc9dc6c3
commit
f871e0bd7d
@ -12,6 +12,7 @@ use Icinga\Module\Director\Db;
|
||||
use Icinga\Module\Director\DirectorObject\Automation\Basket;
|
||||
use Icinga\Module\Director\DirectorObject\Automation\BasketSnapshot;
|
||||
use Icinga\Module\Director\DirectorObject\Automation\BasketSnapshotFieldResolver;
|
||||
use Icinga\Module\Director\Forms\AddToBasketForm;
|
||||
use Icinga\Module\Director\Forms\BasketCreateSnapshotForm;
|
||||
use Icinga\Module\Director\Forms\BasketForm;
|
||||
use Icinga\Module\Director\Forms\RestoreBasketForm;
|
||||
@ -64,6 +65,18 @@ class BasketController extends ActionController
|
||||
);
|
||||
}
|
||||
|
||||
public function addAction()
|
||||
{
|
||||
$this->addSingleTab($this->translate('Add to Basket'));
|
||||
$this->addTitle($this->translate('Add chosen objects to a Configuration Basket'));
|
||||
$form = new AddToBasketForm();
|
||||
$form->setDb($this->db())
|
||||
->setType($this->params->getRequired('type'))
|
||||
->setNames($this->url()->getParams()->getValues('names'))
|
||||
->handleRequest();
|
||||
$this->content()->add($form);
|
||||
}
|
||||
|
||||
public function createAction()
|
||||
{
|
||||
$this->actions()->add(
|
||||
|
@ -2,9 +2,11 @@
|
||||
|
||||
namespace Icinga\Module\Director\Controllers;
|
||||
|
||||
use dipl\Web\Url;
|
||||
use Icinga\Data\Filter\Filter;
|
||||
use Icinga\Data\Filter\FilterChain;
|
||||
use Icinga\Data\Filter\FilterExpression;
|
||||
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
|
||||
use Icinga\Module\Director\Forms\IcingaAddServiceForm;
|
||||
use Icinga\Module\Director\Forms\IcingaAddServiceSetForm;
|
||||
use Icinga\Module\Director\Objects\IcingaHost;
|
||||
@ -47,6 +49,31 @@ class HostsController extends ObjectsController
|
||||
));
|
||||
}
|
||||
|
||||
public function edittemplatesAction()
|
||||
{
|
||||
parent::editAction();
|
||||
|
||||
$objects = $this->loadMultiObjectsFromParams();
|
||||
$names = [];
|
||||
/** @var ExportInterface $object */
|
||||
foreach ($objects as $object) {
|
||||
$names[] = $object->getUniqueIdentifier();
|
||||
}
|
||||
|
||||
$url = Url::fromPath('director/basket/add', [
|
||||
'type' => 'HostTemplate',
|
||||
]);
|
||||
|
||||
$url->getParams()->addValues('names', $names);
|
||||
|
||||
$this->actions()->add(Link::create(
|
||||
$this->translate('Add to Basket'),
|
||||
$url,
|
||||
null,
|
||||
['class' => 'icon-tag']
|
||||
));
|
||||
}
|
||||
|
||||
public function addserviceAction()
|
||||
{
|
||||
$this->addSingleTab($this->translate('Add Service'));
|
||||
|
@ -49,6 +49,17 @@ class ImportsourceController extends ActionController
|
||||
$this->actions(new AutomationObjectActionBar(
|
||||
$this->getRequest()
|
||||
));
|
||||
$source = $this->getImportSource();
|
||||
|
||||
$this->actions()->add(Link::create(
|
||||
$this->translate('Add to Basket'),
|
||||
'director/basket/add',
|
||||
[
|
||||
'type' => 'ImportSource',
|
||||
'names' => $source->getUniqueIdentifier()
|
||||
],
|
||||
['class' => 'icon-tag']
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Director\Controllers;
|
||||
|
||||
use dipl\Html\Link;
|
||||
use Icinga\Module\Director\Forms\DirectorJobForm;
|
||||
use Icinga\Module\Director\Web\Controller\ActionController;
|
||||
use Icinga\Module\Director\Objects\DirectorJob;
|
||||
@ -19,6 +20,7 @@ class JobController extends ActionController
|
||||
$this
|
||||
->addJobTabs($job, 'show')
|
||||
->addTitle($this->translate('Job: %s'), $job->get('job_name'))
|
||||
->addToBasketLink()
|
||||
->content()->add(new JobDetails($job));
|
||||
}
|
||||
|
||||
@ -50,6 +52,7 @@ class JobController extends ActionController
|
||||
$this
|
||||
->addJobTabs($job, 'edit')
|
||||
->addTitle($this->translate('Job: %s'), $job->get('job_name'))
|
||||
->addToBasketLink()
|
||||
->content()->add($form);
|
||||
}
|
||||
|
||||
@ -63,6 +66,27 @@ class JobController extends ActionController
|
||||
return DirectorJob::loadWithAutoIncId((int) $this->params->getRequired('id'), $this->db());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
* @throws \Icinga\Exception\MissingParameterException
|
||||
* @throws \Icinga\Exception\NotFoundError
|
||||
*/
|
||||
protected function addToBasketLink()
|
||||
{
|
||||
$job = $this->requireJob();
|
||||
$this->actions()->add(Link::create(
|
||||
$this->translate('Add to Basket'),
|
||||
'director/basket/add',
|
||||
[
|
||||
'type' => 'DirectorJob',
|
||||
'names' => $job->getUniqueIdentifier()
|
||||
],
|
||||
['class' => 'icon-tag']
|
||||
));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function addJobTabs(DirectorJob $job, $active)
|
||||
{
|
||||
$id = $job->get('id');
|
||||
|
@ -45,6 +45,15 @@ class SyncruleController extends ActionController
|
||||
$this->addPropertyHint($rule);
|
||||
return;
|
||||
}
|
||||
$this->actions()->add(Link::create(
|
||||
$this->translate('Add to Basket'),
|
||||
'director/basket/add',
|
||||
[
|
||||
'type' => 'SyncRule',
|
||||
'names' => $rule->getUniqueIdentifier()
|
||||
],
|
||||
['class' => 'icon-tag']
|
||||
));
|
||||
|
||||
if (! $run) {
|
||||
$this->warning($this->translate('This Sync Rule has never been run before.'));
|
||||
@ -159,6 +168,15 @@ class SyncruleController extends ActionController
|
||||
['class' => 'icon-paste']
|
||||
)
|
||||
);
|
||||
$this->actions()->add(Link::create(
|
||||
$this->translate('Add to Basket'),
|
||||
'director/basket/add',
|
||||
[
|
||||
'type' => 'SyncRule',
|
||||
'names' => $rule->getUniqueIdentifier()
|
||||
],
|
||||
['class' => 'icon-tag']
|
||||
));
|
||||
|
||||
if (! $rule->hasSyncProperties()) {
|
||||
$this->addPropertyHint($rule);
|
||||
|
131
application/forms/AddToBasketForm.php
Normal file
131
application/forms/AddToBasketForm.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Forms;
|
||||
|
||||
use dipl\Html\Html;
|
||||
use dipl\Html\HtmlDocument;
|
||||
use dipl\Html\Link;
|
||||
use Icinga\Exception\NotFoundError;
|
||||
use Icinga\Module\Director\DirectorObject\Automation\Basket;
|
||||
use Icinga\Module\Director\Web\Form\DirectorForm;
|
||||
|
||||
class AddToBasketForm extends DirectorForm
|
||||
{
|
||||
/** @var Basket */
|
||||
private $basket;
|
||||
|
||||
private $type = '(has not been set)';
|
||||
|
||||
private $names = [];
|
||||
|
||||
/**
|
||||
* @throws \Zend_Form_Exception
|
||||
* @throws \Icinga\Exception\NotFoundError
|
||||
*/
|
||||
public function setup()
|
||||
{
|
||||
$baskets = Basket::loadAll($this->getDb());
|
||||
$enum = [];
|
||||
foreach ($baskets as $basket) {
|
||||
$enum[$basket->get('basket_name')] = $basket->get('basket_name');
|
||||
}
|
||||
|
||||
$names = [];
|
||||
$basket = null;
|
||||
if ($this->hasBeenSent()) {
|
||||
$basketName = $this->getSentValue('basket');
|
||||
if ($basketName) {
|
||||
$basket = Basket::load($basketName, $this->getDb());
|
||||
}
|
||||
}
|
||||
$count = 0;
|
||||
$type = $this->type;
|
||||
foreach ($this->names as $name) {
|
||||
if (! empty($names)) {
|
||||
$names[] = ', ';
|
||||
}
|
||||
if ($basket && $basket->hasObject($type, $name)) {
|
||||
$names[] = Html::tag('span', [
|
||||
'style' => 'text-decoration: line-through'
|
||||
], $name);
|
||||
} else {
|
||||
$count++;
|
||||
$names[] = $name;
|
||||
}
|
||||
}
|
||||
$this->addHtmlHint((new HtmlDocument())->add([
|
||||
'The following objects will be added: ',
|
||||
$names
|
||||
]));
|
||||
$this->addElement('select', 'basket', [
|
||||
'label' => $this->translate('Basket'),
|
||||
'multiOptions' => $this->optionalEnum($enum),
|
||||
'required' => true,
|
||||
'class' => 'autosubmit',
|
||||
]);
|
||||
|
||||
if ($count > 0) {
|
||||
$this->setSubmitLabel(sprintf(
|
||||
$this->translate('Add %s objects'),
|
||||
$count
|
||||
));
|
||||
} else {
|
||||
$this->setSubmitLabel($this->translate('Add'));
|
||||
$this->addSubmitButtonIfSet();
|
||||
$this->getElement($this->submitButtonName)->setAttrib('disabled', true);
|
||||
}
|
||||
}
|
||||
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setNames($names)
|
||||
{
|
||||
$this->names = $names;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Icinga\Exception\NotFoundError
|
||||
* @throws \Icinga\Module\Director\Exception\DuplicateKeyException
|
||||
*/
|
||||
public function onSuccess()
|
||||
{
|
||||
$type = $this->type;
|
||||
$basket = Basket::load($this->getValue('basket'), $this->getDb());
|
||||
$basketName = $basket->get('basket_name');
|
||||
|
||||
if (empty($this->names)) {
|
||||
$this->getElement('basket')->addErrorMessage($this->translate(
|
||||
'No object has been chosen'
|
||||
));
|
||||
}
|
||||
if ($basket->supportsCustomSelectionFor($type)) {
|
||||
$basket->addObjects($type, $this->names);
|
||||
$basket->store();
|
||||
$this->setSuccessMessage(sprintf($this->translate(
|
||||
'Configuration objects have been added to the chosen basket "%s"'
|
||||
), $basketName));
|
||||
return parent::onSuccess();
|
||||
} else {
|
||||
$this->addHtmlHint(Html::tag('p', [
|
||||
'class' => 'error'
|
||||
], Html::sprintf($this->translate(
|
||||
'Please check your Basket configuration, %s does not support'
|
||||
. ' single "%s" configuration objects'
|
||||
), Link::create(
|
||||
$basketName,
|
||||
'director/basket',
|
||||
['name' => $basketName],
|
||||
['data-base-target' => '_next']
|
||||
), $type)));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -8,13 +8,13 @@ class BasketDashlet extends Dashlet
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->translate('Object Basket');
|
||||
return $this->translate('Configuration Baskets');
|
||||
}
|
||||
|
||||
public function getSummary()
|
||||
{
|
||||
return $this->translate(
|
||||
'Preserve specific objects in a specific state'
|
||||
'Preserve specific configuration objects in a specific state'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,16 @@ class Basket extends DbObject
|
||||
|
||||
protected function onLoadFromDb()
|
||||
{
|
||||
$this->chosenObjects = Json::decode($this->get('objects'));
|
||||
$this->chosenObjects = (array) Json::decode($this->get('objects'));
|
||||
}
|
||||
|
||||
public function supportsCustomSelectionFor($type)
|
||||
{
|
||||
if (! array_key_exists($type, $this->chosenObjects)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_array($this->chosenObjects[$type]);
|
||||
}
|
||||
|
||||
public function setObjects($objects)
|
||||
@ -81,17 +90,28 @@ class Basket extends DbObject
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a weird method, as it is required to deal with raw form data
|
||||
*
|
||||
* @param $type
|
||||
* @param ExportInterface[]|bool $objects
|
||||
*/
|
||||
public function addObjects($type, $objects = true)
|
||||
{
|
||||
BasketSnapshot::assertValidType($type);
|
||||
|
||||
// '1' -> from Form!
|
||||
if ($objects === 'ALL') {
|
||||
$objects = true;
|
||||
} elseif ($objects === null || $objects === 'IGNORE') {
|
||||
return;
|
||||
} elseif ($objects === '[]') {
|
||||
if (isset($this->chosenObjects[$type])) {
|
||||
if (! is_array($this->chosenObjects[$type])) {
|
||||
$this->chosenObjects[$type] = [];
|
||||
}
|
||||
} else {
|
||||
$this->chosenObjects[$type] = [];
|
||||
}
|
||||
$objects = [];
|
||||
}
|
||||
|
||||
@ -112,14 +132,42 @@ class Basket extends DbObject
|
||||
$this->reallySet('objects', Json::encode($this->chosenObjects));
|
||||
}
|
||||
|
||||
public function hasObject($type, $object)
|
||||
{
|
||||
if (! $this->hasType($type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->chosenObjects[$type] === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($object instanceof ExportInterface) {
|
||||
$object = $object->getUniqueIdentifier();
|
||||
}
|
||||
|
||||
if (is_array($this->chosenObjects[$type])) {
|
||||
return in_array($object, $this->chosenObjects[$type]);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @param string $object
|
||||
*/
|
||||
public function addObject($type, $object)
|
||||
{
|
||||
// TODO: make sure array exists - and is not boolean
|
||||
if (is_array($this->chosenObjects[$type])) {
|
||||
$this->chosenObjects[$type][] = $object;
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'The Basket "%s" has not been configured for single objects of type "%s"',
|
||||
$this->get('basket_name'),
|
||||
$type
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function hasType($type)
|
||||
|
@ -8,11 +8,29 @@ use Icinga\Module\Director\Data\Db\DbObject;
|
||||
use Icinga\Module\Director\Objects\DirectorDatafield;
|
||||
use Icinga\Module\Director\Objects\IcingaCommand;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Zend_Db_Adapter_Abstract as ZfDbAdapter;
|
||||
|
||||
class BasketSnapshot extends DbObject
|
||||
{
|
||||
protected static $typeClasses = [
|
||||
'Datafield' => '\\Icinga\\Module\\Director\\Objects\\DirectorDatafield',
|
||||
'Command' => '\\Icinga\\Module\\Director\\Objects\\IcingaCommand',
|
||||
'HostGroup' => '\\Icinga\\Module\\Director\\Objects\\IcingaHostGroup',
|
||||
'IcingaTemplateChoiceHost' => '\\Icinga\\Module\\Director\\Objects\\IcingaTemplateChoiceHost',
|
||||
'HostTemplate' => '\\Icinga\\Module\\Director\\Objects\\IcingaHost',
|
||||
'ServiceGroup' => '\\Icinga\\Module\\Director\\Objects\\IcingaServiceGroup',
|
||||
'IcingaTemplateChoiceService' => '\\Icinga\\Module\\Director\\Objects\\IcingaTemplateChoiceService',
|
||||
'ServiceTemplate' => '\\Icinga\\Module\\Director\\Objects\\IcingaService',
|
||||
'ServiceSet' => '\\Icinga\\Module\\Director\\Objects\\IcingaServiceSet',
|
||||
'Notification' => '\\Icinga\\Module\\Director\\Objects\\IcingaNotification',
|
||||
'Dependency' => '\\Icinga\\Module\\Director\\Objects\\IcingaDependency',
|
||||
'ImportSource' => '\\Icinga\\Module\\Director\\Objects\\ImportSource',
|
||||
'SyncRule' => '\\Icinga\\Module\\Director\\Objects\\SyncRule',
|
||||
'DirectorJob' => '\\Icinga\\Module\\Director\\Objects\\DirectorJob',
|
||||
'Basket' => '\\Icinga\\Module\\Director\\DirectorObject\\Automation\\Automation',
|
||||
];
|
||||
|
||||
protected $objects = [];
|
||||
|
||||
protected $content;
|
||||
@ -47,27 +65,23 @@ class BasketSnapshot extends DbObject
|
||||
'ts_create' => null,
|
||||
];
|
||||
|
||||
public static function supports($type)
|
||||
{
|
||||
return isset(self::$typeClasses[$type]);
|
||||
}
|
||||
|
||||
public static function assertValidType($type)
|
||||
{
|
||||
if (! static::supports($type)) {
|
||||
throw new InvalidArgumentException("Basket does not support '$type'");
|
||||
}
|
||||
}
|
||||
|
||||
public static function getClassForType($type)
|
||||
{
|
||||
$types = [
|
||||
'Datafield' => '\\Icinga\\Module\\Director\\Objects\\DirectorDatafield',
|
||||
'Command' => '\\Icinga\\Module\\Director\\Objects\\IcingaCommand',
|
||||
'HostGroup' => '\\Icinga\\Module\\Director\\Objects\\IcingaHostGroup',
|
||||
'IcingaTemplateChoiceHost' => '\\Icinga\\Module\\Director\\Objects\\IcingaTemplateChoiceHost',
|
||||
'HostTemplate' => '\\Icinga\\Module\\Director\\Objects\\IcingaHost',
|
||||
'ServiceGroup' => '\\Icinga\\Module\\Director\\Objects\\IcingaServiceGroup',
|
||||
'IcingaTemplateChoiceService' => '\\Icinga\\Module\\Director\\Objects\\IcingaTemplateChoiceService',
|
||||
'ServiceTemplate' => '\\Icinga\\Module\\Director\\Objects\\IcingaService',
|
||||
'ServiceSet' => '\\Icinga\\Module\\Director\\Objects\\IcingaServiceSet',
|
||||
'Notification' => '\\Icinga\\Module\\Director\\Objects\\IcingaNotification',
|
||||
'Dependency' => '\\Icinga\\Module\\Director\\Objects\\IcingaDependency',
|
||||
'ImportSource' => '\\Icinga\\Module\\Director\\Objects\\ImportSource',
|
||||
'SyncRule' => '\\Icinga\\Module\\Director\\Objects\\SyncRule',
|
||||
'DirectorJob' => '\\Icinga\\Module\\Director\\Objects\\DirectorJob',
|
||||
'Basket' => '\\Icinga\\Module\\Director\\DirectorObject\\Automation\\Automation',
|
||||
];
|
||||
static::assertValidType($type);
|
||||
|
||||
return $types[$type];
|
||||
return self::$typeClasses[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,21 +203,36 @@ class BasketSnapshot extends DbObject
|
||||
$new = $class::import($object, $connection, $replace);
|
||||
if ($new->hasBeenModified()) {
|
||||
if ($new instanceof IcingaObject && $new->supportsImports()) {
|
||||
$changed[$new->getObjectName()] = $new;
|
||||
/** @var ExportInterface $new */
|
||||
$changed[$new->getUniqueIdentifier()] = $new;
|
||||
} else {
|
||||
$new->store();
|
||||
}
|
||||
}
|
||||
|
||||
// Linking fields right now, as we're not in $changed
|
||||
if ($new instanceof IcingaObject) {
|
||||
$fieldResolver->relinkObjectFields($new, $object);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No modification on the object, still, fields might have
|
||||
// been changed
|
||||
if ($new instanceof IcingaObject) {
|
||||
$fieldResolver->relinkObjectFields($new, $object);
|
||||
}
|
||||
}
|
||||
$allObjects[spl_object_hash($new)] = $object;
|
||||
}
|
||||
|
||||
/** @var IcingaObject $object */
|
||||
foreach ($changed as $object) {
|
||||
$this->recursivelyStore($object, $changed);
|
||||
}
|
||||
foreach ($changed as $key => $new) {
|
||||
// Store related fields. As objects might have formerly been
|
||||
// unstored, let's to it right here
|
||||
if ($new instanceof IcingaObject) {
|
||||
$fieldResolver->relinkObjectFields($new, $objects[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$db->commit();
|
||||
@ -302,9 +331,11 @@ class BasketSnapshot extends DbObject
|
||||
if ($dummy instanceof IcingaCommand) {
|
||||
$select = $db->select()->from($dummy->getTableName())
|
||||
->where('object_type != ?', 'external_object');
|
||||
} else {
|
||||
} elseif (! $dummy->isGroup()) {
|
||||
$select = $db->select()->from($dummy->getTableName())
|
||||
->where('object_type = ?', 'template');
|
||||
} else {
|
||||
$select = $db->select()->from($dummy->getTableName());
|
||||
}
|
||||
$all = $class::loadAll($this->getConnection(), $select);
|
||||
} else {
|
||||
|
@ -6,6 +6,7 @@ use Icinga\Data\Db\DbConnection;
|
||||
use Icinga\Exception\NotFoundError;
|
||||
use Icinga\Module\Director\Data\PropertiesFilter;
|
||||
use Icinga\Module\Director\Db;
|
||||
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
|
||||
use Icinga\Module\Director\Exception\DuplicateKeyException;
|
||||
use Icinga\Module\Director\IcingaConfig\IcingaConfig;
|
||||
use Icinga\Module\Director\IcingaConfig\IcingaLegacyConfigHelper as c1;
|
||||
@ -13,7 +14,7 @@ use Icinga\Module\Director\Objects\Extension\FlappingSupport;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
class IcingaHost extends IcingaObject
|
||||
class IcingaHost extends IcingaObject implements ExportInterface
|
||||
{
|
||||
use FlappingSupport;
|
||||
|
||||
|
@ -7,6 +7,7 @@ use Icinga\Exception\IcingaException;
|
||||
use Icinga\Module\Director\Data\PropertiesFilter;
|
||||
use Icinga\Module\Director\Db;
|
||||
use Icinga\Module\Director\Db\Cache\PrefetchCache;
|
||||
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
|
||||
use Icinga\Module\Director\Exception\DuplicateKeyException;
|
||||
use Icinga\Module\Director\IcingaConfig\IcingaConfig;
|
||||
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
|
||||
@ -16,7 +17,7 @@ use Icinga\Module\Director\Resolver\HostServiceBlacklist;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
class IcingaService extends IcingaObject
|
||||
class IcingaService extends IcingaObject implements ExportInterface
|
||||
{
|
||||
use FlappingSupport;
|
||||
|
||||
|
@ -6,6 +6,7 @@ use Icinga\Exception\IcingaException;
|
||||
use Icinga\Exception\InvalidPropertyException;
|
||||
use Icinga\Exception\NotFoundError;
|
||||
use Icinga\Module\Director\Deployment\DeploymentInfo;
|
||||
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
|
||||
use Icinga\Module\Director\Forms\DeploymentLinkForm;
|
||||
use Icinga\Module\Director\Forms\IcingaCloneObjectForm;
|
||||
use Icinga\Module\Director\Forms\IcingaObjectFieldForm;
|
||||
@ -79,6 +80,9 @@ abstract class ObjectController extends ActionController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
if (! $this->getRequest()->isApiRequest()) {
|
||||
@ -111,6 +115,9 @@ abstract class ObjectController extends ActionController
|
||||
$this->content()->add($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
public function editAction()
|
||||
{
|
||||
$object = $this->requireObject();
|
||||
@ -118,9 +125,14 @@ abstract class ObjectController extends ActionController
|
||||
$this->addObjectTitle()
|
||||
->addObjectForm($object)
|
||||
->addActionClone()
|
||||
->addActionUsage();
|
||||
->addActionUsage()
|
||||
->addActionBasket();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
* @throws \Icinga\Security\SecurityException
|
||||
*/
|
||||
public function renderAction()
|
||||
{
|
||||
$this->assertTypePermission()
|
||||
@ -133,6 +145,9 @@ abstract class ObjectController extends ActionController
|
||||
$preview->renderTo($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
public function cloneAction()
|
||||
{
|
||||
$this->assertTypePermission();
|
||||
@ -151,6 +166,10 @@ abstract class ObjectController extends ActionController
|
||||
->content()->add($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
* @throws \Icinga\Security\SecurityException
|
||||
*/
|
||||
public function fieldsAction()
|
||||
{
|
||||
$this->assertPermission('director/admin');
|
||||
@ -187,6 +206,10 @@ abstract class ObjectController extends ActionController
|
||||
$table->renderTo($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
* @throws \Icinga\Security\SecurityException
|
||||
*/
|
||||
public function historyAction()
|
||||
{
|
||||
$this
|
||||
@ -206,6 +229,9 @@ abstract class ObjectController extends ActionController
|
||||
->renderTo($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
public function membershipAction()
|
||||
{
|
||||
$object = $this->requireObject();
|
||||
@ -224,6 +250,10 @@ abstract class ObjectController extends ActionController
|
||||
->renderTo($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
protected function addObjectTitle()
|
||||
{
|
||||
$object = $this->requireObject();
|
||||
@ -271,6 +301,37 @@ abstract class ObjectController extends ActionController
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
protected function addActionBasket()
|
||||
{
|
||||
if ($this->hasBasketSupport()) {
|
||||
$object = $this->object;
|
||||
if ($object instanceof ExportInterface) {
|
||||
if ($object->isTemplate()) {
|
||||
$type = $this->getType() . 'Template';
|
||||
} elseif ($object->isGroup()) {
|
||||
$type = ucfirst($this->getType());
|
||||
} else {
|
||||
// Command? Sure?
|
||||
$type = ucfirst($this->getType());
|
||||
}
|
||||
$this->actions()->add(Link::create(
|
||||
$this->translate('Add to Basket'),
|
||||
'director/basket/add',
|
||||
[
|
||||
'type' => $type,
|
||||
'names' => $object->getUniqueIdentifier()
|
||||
],
|
||||
['class' => 'icon-tag']
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function addTemplate()
|
||||
{
|
||||
$this->assertPermission('director/admin');
|
||||
@ -450,10 +511,20 @@ abstract class ObjectController extends ActionController
|
||||
return $form;
|
||||
}
|
||||
|
||||
protected function hasBasketSupport()
|
||||
{
|
||||
return $this->object->isTemplate() || $this->object->isGroup();
|
||||
}
|
||||
|
||||
protected function onObjectFormLoaded(DirectorObjectForm $form)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IcingaObject
|
||||
* @throws NotFoundError
|
||||
* @throws \Zend_Controller_Response_Exception
|
||||
*/
|
||||
protected function requireObject()
|
||||
{
|
||||
if (! $this->object) {
|
||||
|
@ -56,7 +56,6 @@ abstract class ObjectsController extends ActionController
|
||||
|
||||
/**
|
||||
* @return IcingaObjectsHandler
|
||||
* @throws \Icinga\Exception\ConfigurationError
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
protected function apiRequestHandler()
|
||||
@ -82,7 +81,6 @@ abstract class ObjectsController extends ActionController
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Icinga\Exception\ConfigurationError
|
||||
* @throws \Icinga\Exception\Http\HttpNotFoundException
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
@ -124,7 +122,6 @@ abstract class ObjectsController extends ActionController
|
||||
|
||||
/**
|
||||
* @return ObjectsTable
|
||||
* @throws \Icinga\Exception\ConfigurationError
|
||||
*/
|
||||
protected function getTable()
|
||||
{
|
||||
@ -134,9 +131,24 @@ abstract class ObjectsController extends ActionController
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
* @throws \Icinga\Exception\ConfigurationError
|
||||
*/
|
||||
public function edittemplatesAction()
|
||||
{
|
||||
$this->commonForEdit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
public function editAction()
|
||||
{
|
||||
$this->commonForEdit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
public function commonForEdit()
|
||||
{
|
||||
$type = ucfirst($this->getType());
|
||||
|
||||
@ -293,7 +305,7 @@ abstract class ObjectsController extends ActionController
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \Icinga\Exception\ConfigurationError
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
protected function loadMultiObjectsFromParams()
|
||||
{
|
||||
@ -341,7 +353,6 @@ abstract class ObjectsController extends ActionController
|
||||
/**
|
||||
* @param ZfQueryBasedTable $table
|
||||
* @return ZfQueryBasedTable
|
||||
* @throws \Icinga\Exception\ConfigurationError
|
||||
* @throws NotFoundError
|
||||
*/
|
||||
protected function eventuallyFilterCommand(ZfQueryBasedTable $table)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Director\Web\Controller;
|
||||
|
||||
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
use Icinga\Module\Director\Web\Controller\Extension\DirectorDb;
|
||||
use Icinga\Module\Director\Web\Table\ApplyRulesTable;
|
||||
@ -115,6 +116,18 @@ abstract class TemplateController extends CompatController
|
||||
['class' => 'icon-edit']
|
||||
)
|
||||
]);
|
||||
if ($template instanceof ExportInterface) {
|
||||
$this->actions()->add(Link::create(
|
||||
$this->translate('Add to Basket'),
|
||||
'director/basket/add',
|
||||
[
|
||||
'type' => ucfirst($this->getType()) . 'Template',
|
||||
'names' => $template->getUniqueIdentifier()
|
||||
],
|
||||
['class' => 'icon-tag']
|
||||
));
|
||||
}
|
||||
|
||||
$list = new UnorderedList([], [
|
||||
'class' => 'vertical-action-list'
|
||||
]);
|
||||
|
@ -29,8 +29,7 @@ class ObjectPreview
|
||||
|
||||
/**
|
||||
* @param ControlsAndContent $cc
|
||||
* @throws \Icinga\Exception\IcingaException
|
||||
* @throws \Icinga\Exception\ProgrammingError
|
||||
* @throws \Icinga\Exception\NotFoundError
|
||||
*/
|
||||
public function renderTo(ControlsAndContent $cc)
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Director\Web\Table;
|
||||
|
||||
use dipl\Web\Table\Extension\MultiSelect;
|
||||
use Icinga\Authentication\Auth;
|
||||
use Icinga\Data\Filter\Filter;
|
||||
use Icinga\Module\Director\Db;
|
||||
@ -17,6 +18,8 @@ use Zend_Db_Select as ZfSelect;
|
||||
|
||||
class TemplatesTable extends ZfQueryBasedTable
|
||||
{
|
||||
use MultiSelect;
|
||||
|
||||
protected $searchColumns = ['o.object_name'];
|
||||
|
||||
private $type;
|
||||
@ -28,6 +31,16 @@ class TemplatesTable extends ZfQueryBasedTable
|
||||
return $table;
|
||||
}
|
||||
|
||||
protected function assemble()
|
||||
{
|
||||
$type = $this->type;
|
||||
$this->enableMultiSelect(
|
||||
"director/${type}s/edittemplates",
|
||||
"director/${type}template",
|
||||
['name']
|
||||
);
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
|
Loading…
x
Reference in New Issue
Block a user