diff options
Diffstat (limited to 'application')
-rw-r--r-- | application/controllers/IntegrationsController.php | 118 | ||||
-rw-r--r-- | application/forms/Config/TtsIntegrationConfigForm.php | 249 | ||||
-rw-r--r-- | application/views/scripts/integrations/index.phtml | 56 | ||||
-rw-r--r-- | application/views/scripts/integrations/new.phtml | 6 | ||||
-rw-r--r-- | application/views/scripts/integrations/remove.phtml | 6 | ||||
-rw-r--r-- | application/views/scripts/integrations/update.phtml | 6 |
6 files changed, 441 insertions, 0 deletions
diff --git a/application/controllers/IntegrationsController.php b/application/controllers/IntegrationsController.php new file mode 100644 index 0000000..340e15d --- /dev/null +++ b/application/controllers/IntegrationsController.php @@ -0,0 +1,118 @@ +<?php + +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Generictts\Controllers; + +use Icinga\Exception\NotFoundError; +use Icinga\Forms\ConfirmRemovalForm; +use Icinga\Module\Generictts\Forms\Config\TtsIntegrationConfigForm; +use Icinga\Web\Controller; +use Icinga\Web\Notification; + +/** + * Manage trouble ticket system integrations + */ +class IntegrationsController extends Controller +{ + /** + * List trouble ticket system integrations + */ + public function indexAction() + { + $this->getTabs()->add('integrations', array( + 'active' => true, + 'label' => $this->translate('Integrations'), + 'url' => $this->getRequest()->getUrl() + )); + $this->view->integrations = $this->Config(); + } + + /** + * Integrate a new trouble ticket system + */ + public function newAction() + { + $this->getTabs()->add('new-integration', array( + 'active' => true, + 'label' => $this->translate('New Integration'), + 'url' => $this->getRequest()->getUrl() + )); + + $integrations = new TtsIntegrationConfigForm(); + $integrations + ->setIniConfig($this->Config()) + ->setRedirectUrl('generictts/integrations') + ->handleRequest(); + + $this->view->form = $integrations; + } + + /** + * Remove a trouble ticket system integration + */ + public function removeAction() + { + $integration = $this->params->getRequired('integration'); + + $this->getTabs()->add('remove-integration', array( + 'active' => true, + 'label' => $this->translate('Remove Integration'), + 'url' => $this->getRequest()->getUrl() + )); + + $integrations = new TtsIntegrationConfigForm(); + try { + $integrations + ->setIniConfig($this->Config()) + ->bind($integration); + } catch (NotFoundError $e) { + $this->httpNotFound($e->getMessage()); + } + + $confirmation = new ConfirmRemovalForm(array( + 'onSuccess' => function (ConfirmRemovalForm $confirmation) use ($integration, $integrations) { + $integrations->remove($integration); + if ($integrations->save()) { + Notification::success(mt('generictts', 'TTS integration removed')); + return true; + } + return false; + } + )); + $confirmation + ->setRedirectUrl('generictts/integrations') + ->setSubmitLabel($this->translate('Remove Integration')) + ->handleRequest(); + + $this->view->form = $confirmation; + } + + /** + * Update a trouble ticket system integration + */ + public function updateAction() + { + $integration = $this->params->getRequired('integration'); + + $this->getTabs()->add('update-integration', array( + 'active' => true, + 'label' => $this->translate('Update Integration'), + 'url' => $this->getRequest()->getUrl() + )); + + $integrations = new TtsIntegrationConfigForm(); + try { + $integrations + ->setIniConfig($this->Config()) + ->bind($integration); + } catch (NotFoundError $e) { + $this->httpNotFound($e->getMessage()); + } + $integrations + ->setRedirectUrl('generictts/integrations') + ->handleRequest(); + + $this->view->form = $integrations; + } +} diff --git a/application/forms/Config/TtsIntegrationConfigForm.php b/application/forms/Config/TtsIntegrationConfigForm.php new file mode 100644 index 0000000..2bdb562 --- /dev/null +++ b/application/forms/Config/TtsIntegrationConfigForm.php @@ -0,0 +1,249 @@ +<?php + +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Generictts\Forms\Config; + +use Zend_Validate_Callback; +use Icinga\Exception\AlreadyExistsException; +use Icinga\Exception\IcingaException; +use Icinga\Exception\NotFoundError; +use Icinga\Forms\ConfigForm; +use Icinga\Web\Form\Validator\UrlValidator; +use Icinga\Web\Notification; + +/** + * Form for managing trouble ticket system integrations + */ +class TtsIntegrationConfigForm extends ConfigForm +{ + /** + * Name of the integration if the form is bound to one + * + * @var string + */ + protected $boundIntegration; + + /** + * {@inheritdoc} + */ + public function init() + { + $this->setName('form_config_generictts_tts_integrations'); + } + + /** + * {@inheritdoc} + */ + public function createElements(array $formData) + { + $this->addElement( + 'text', + 'name', + array( + 'description' => $this->translate('The name of the TTS integration'), + 'label' => $this->translate('Name'), + 'required' => true + ) + ); + + $patternValidator = new Zend_Validate_Callback(function ($value) { + return @preg_match($value, '') !== false; + }); + $patternValidator->setMessage( + $this->translate('"%value%" is not a valid regular expression.'), + Zend_Validate_Callback::INVALID_VALUE + ); + $this->addElement( + 'text', + 'pattern', + array( + 'value' => '/this-will-not-match(\d{3-6})/', + 'label' => $this->translate('Ticket Pattern'), + 'description' => $this->translate( + 'The pattern to extract ticket IDs from comments.' + . ' The ticket pattern must be a valid regular expression' + ), + 'required' => true, + 'validators' => array($patternValidator) + ) + ); + + $urlValidator = new Zend_Validate_Callback(function ($value) { + return strpos($value, '$1') !== false; + }); + $urlValidator->setMessage( + $this->translate('The URL must contain the placeholder $1 to be substituted with a ticket ID.'), + Zend_Validate_Callback::INVALID_VALUE + ); + $this->addElement( + 'text', + 'url', + array( + 'value' => 'http://no-such-domain.example.com/ticket?id=$1', + 'label' => $this->translate('TTS Ticket URL'), + 'description' => $this->translate( + 'The URL pointing to the TTS with $1 as the placeholder for the ticket ID' + ), + 'required' => true, + 'validators' => array($urlValidator, new UrlValidator()) + ) + ); + } + + /** + * {@inheritdoc} + */ + public function getSubmitLabel() + { + if (($submitLabel = parent::getSubmitLabel()) === null) { + if ($this->boundIntegration === null) { + $submitLabel = $this->translate('Integrate'); + } else { + $submitLabel = $this->translate('Update Integration'); + } + } + return $submitLabel; + } + + /** + * {@inheritdoc} + */ + public function onRequest() + { + // The base class implementation does not make sense here. We're not populating the whole configuration but + // only a section + return; + } + + /** + * {@inheritdoc} + */ + public function onSuccess() + { + $name = $this->getElement('name')->getValue(); + $values = array( + 'pattern' => $this->getElement('pattern')->getValue(), + 'url' => $this->getElement('url')->getValue() + ); + if ($this->boundIntegration === null) { + $successNotification = $this->translate('TTS integrated'); + try { + $this->add($name, $values); + } catch (AlreadyExistsException $e) { + $this->addError($e->getMessage()); + return false; + } + } else { + $successNotification = $this->translate('TTS integration updated'); + try { + $this->update($name, $values, $this->boundIntegration); + } catch (IcingaException $e) { + // Exception may be AlreadyExistsException or NotFoundError + $this->addError($e->getMessage()); + return false; + } + } + if ($this->save()) { + Notification::success($successNotification); + return true; + } + return false; + } + + /** + * Add a TTS integration + * + * @param string $name The name of the integration + * @param array $values + * + * @return $this + * + * @throws AlreadyExistsException If the integration to add already exists + */ + public function add($name, array $values) + { + if ($this->config->hasSection($name)) { + throw new AlreadyExistsException( + $this->translate('Can\'t add integration \'%s\'. Integration already exists'), + $name + ); + } + $this->config->setSection($name, $values); + return $this; + } + + /** + * Bind integration to this form + * + * @param string $name The name of the integration + * + * @return $this + * + * @throws NotFoundError If the given integration does not exist + */ + public function bind($name) + { + if (! $this->config->hasSection($name)) { + throw new NotFoundError( + $this->translate('Can\'t load integration \'%s\'. Integration does not exist'), + $name + ); + } + $this->boundIntegration = $name; + $integration = $this->config->getSection($name)->toArray(); + $integration['name'] = $name; + $this->populate($integration); + return $this; + } + + /** + * Remove a TTS integration + * + * @param string $name The name of the integration + * + * @return $this + * + * @throws NotFoundError If the role does not exist + */ + public function remove($name) + { + if (! $this->config->hasSection($name)) { + throw new NotFoundError( + $this->translate('Can\'t remove integration \'%s\'. Integration does not exist'), + $name + ); + } + $this->config->removeSection($name); + return $this; + } + + /** + * Update a TTS integration + * + * @param string $name The possibly new name of the integration + * @param array $values + * @param string $oldName The name of the integration to update + * + * @return $this + * + * @throws NotFoundError If the integration to update does not exist + */ + public function update($name, array $values, $oldName) + { + if ($name !== $oldName) { + // The integration got a new name + $this->remove($oldName); + $this->add($name, $values); + } else { + if (! $this->config->hasSection($name)) { + throw new NotFoundError( + $this->translate('Can\'t update integration \'%s\'. Integration does not exist'), + $name + ); + } + $this->config->setSection($name, $values); + } + return $this; + } +} diff --git a/application/views/scripts/integrations/index.phtml b/application/views/scripts/integrations/index.phtml new file mode 100644 index 0000000..0f657ce --- /dev/null +++ b/application/views/scripts/integrations/index.phtml @@ -0,0 +1,56 @@ +<div class="controls"> + <?= $tabs ?> + <?= $this->qlink( + $this->translate('Integrate New Ticket System') , + 'generictts/integrations/new', + null, + array( + 'class' => 'action-link', + 'data-base-target' => '_next', + 'icon' => 'plus', + 'title' => $this->translate('Integrate a new trouble ticket system') + ) + ) ?> +</div> +<div class="content"> +<?php /** @var \Icinga\Application\Config $integrations */ if ($integrations->isEmpty()): ?> + <p><?= $this->translate('No ticket system has been integrated yet.') ?></p> +<?php return; endif ?> + <table class="tts-integrations-table common-table table-row-selectable" data-base-target="_next"> + <thead> + <tr> + <th><?= $this->translate('Name') ?></th> + <th><?= $this->translate('Pattern') ?></th> + <th><?= $this->translate('URL') ?></th> + </tr> + </thead> + <tbody> + <?php foreach ($integrations as $name => $integration): /** @var object $role */ ?> + <tr> + <td> + <?= $this->qlink( + $name, + 'generictts/integrations/update', + array('integration' => $name), + array('title' => sprintf($this->translate('Update integration %s'), $name)) + ) ?> + </td> + <td><?= $this->escape($integration->pattern) ?></td> + <td><?= $this->escape($integration->url) ?></td> + <td class="icon-col text-right"> + <?= $this->qlink( + '', + 'generictts/integrations/remove', + array('integration' => $name), + array( + 'class' => 'action-link', + 'icon' => 'cancel', + 'title' => sprintf($this->translate('Remove integration %s'), $name) + ) + ) ?> + </td> + </tr> + <?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/integrations/new.phtml b/application/views/scripts/integrations/new.phtml new file mode 100644 index 0000000..13a8ed9 --- /dev/null +++ b/application/views/scripts/integrations/new.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?= $form ?> +</div> diff --git a/application/views/scripts/integrations/remove.phtml b/application/views/scripts/integrations/remove.phtml new file mode 100644 index 0000000..13a8ed9 --- /dev/null +++ b/application/views/scripts/integrations/remove.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?= $form ?> +</div> diff --git a/application/views/scripts/integrations/update.phtml b/application/views/scripts/integrations/update.phtml new file mode 100644 index 0000000..13a8ed9 --- /dev/null +++ b/application/views/scripts/integrations/update.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?= $form ?> +</div> |