mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-25 06:44:33 +02:00
Merge pull request #3862 from Icinga/feature/config-form-events-hook-3768
Provide ConfigFormEventsHook
This commit is contained in:
commit
0a55df0fcf
@ -4,9 +4,10 @@
|
|||||||
namespace Icinga\Forms;
|
namespace Icinga\Forms;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Icinga\Exception\ConfigurationError;
|
|
||||||
use Zend_Form_Decorator_Abstract;
|
use Zend_Form_Decorator_Abstract;
|
||||||
use Icinga\Application\Config;
|
use Icinga\Application\Config;
|
||||||
|
use Icinga\Application\Hook\ConfigFormEventsHook;
|
||||||
|
use Icinga\Exception\ConfigurationError;
|
||||||
use Icinga\Web\Form;
|
use Icinga\Web\Form;
|
||||||
use Icinga\Web\Notification;
|
use Icinga\Web\Notification;
|
||||||
|
|
||||||
@ -52,9 +53,21 @@ class ConfigForm extends Form
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function isValid($formData)
|
||||||
* {@inheritdoc}
|
{
|
||||||
*/
|
$valid = parent::isValid($formData);
|
||||||
|
|
||||||
|
if ($valid && ConfigFormEventsHook::runIsValid($this) === false) {
|
||||||
|
foreach (ConfigFormEventsHook::getLastErrors() as $msg) {
|
||||||
|
$this->error($msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
public function onSuccess()
|
public function onSuccess()
|
||||||
{
|
{
|
||||||
$sections = array();
|
$sections = array();
|
||||||
@ -72,11 +85,15 @@ class ConfigForm extends Form
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ConfigFormEventsHook::runOnSuccess($this) === false) {
|
||||||
|
Notification::error($this->translate(
|
||||||
|
'Configuration successfully stored. Though, one or more module hooks failed to run.'
|
||||||
|
. ' See logs for details'
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function onRequest()
|
public function onRequest()
|
||||||
{
|
{
|
||||||
$values = array();
|
$values = array();
|
||||||
|
Binary file not shown.
@ -1,5 +1,5 @@
|
|||||||
# Icinga Web 2 - Head for multiple monitoring backends.
|
# Icinga Web 2 - Head for multiple monitoring backends.
|
||||||
# Copyright (C) 2018 Icinga Development Team
|
# Copyright (C) 2019 Icinga Development Team
|
||||||
# This file is distributed under the same license as Icinga Web 2.
|
# This file is distributed under the same license as Icinga Web 2.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
#
|
#
|
||||||
@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Icinga Web 2 (None)\n"
|
"Project-Id-Version: Icinga Web 2 (None)\n"
|
||||||
"Report-Msgid-Bugs-To: dev@icinga.com\n"
|
"Report-Msgid-Bugs-To: dev@icinga.com\n"
|
||||||
"POT-Creation-Date: 2018-07-11 14:17+0000\n"
|
"POT-Creation-Date: 2019-07-12 12:08-0700\n"
|
||||||
"PO-Revision-Date: 2018-07-11 16:30+0200\n"
|
"PO-Revision-Date: 2019-07-12 14:10+0200\n"
|
||||||
"Last-Translator: Markus Frosch <markus.frosch@icinga.com>\n"
|
"Last-Translator: Markus Frosch <markus.frosch@icinga.com>\n"
|
||||||
"Language: de_DE\n"
|
"Language: de_DE\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -17,7 +17,7 @@ msgstr ""
|
|||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"X-Poedit-Basepath: .\n"
|
"X-Poedit-Basepath: .\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"X-Generator: Poedit 2.0.6\n"
|
"X-Generator: Poedit 2.2.3\n"
|
||||||
"X-Poedit-SearchPath-0: .\n"
|
"X-Poedit-SearchPath-0: .\n"
|
||||||
|
|
||||||
#: ../../../../library/Icinga/Web/Form/Validator/InArray.php:16
|
#: ../../../../library/Icinga/Web/Form/Validator/InArray.php:16
|
||||||
@ -534,6 +534,14 @@ msgstr "Komma separierte Liste von Nutzern, die dieser Rolle zugewiesen werden"
|
|||||||
msgid "Configuration"
|
msgid "Configuration"
|
||||||
msgstr "Konfiguration"
|
msgstr "Konfiguration"
|
||||||
|
|
||||||
|
#: ../../../../application/forms/ConfigForm.php:89
|
||||||
|
msgid ""
|
||||||
|
"Configuration successfully stored. Though, one or more module hooks failed "
|
||||||
|
"to run. See logs for details"
|
||||||
|
msgstr ""
|
||||||
|
"Konfiguration erfolgreich gespeichert. Es sind jedoch einer oder mehrere "
|
||||||
|
"Modul-Hooks fehlgeschlagen. Bitte die Logs prüfen"
|
||||||
|
|
||||||
#: ../../../../application/controllers/RoleController.php:155
|
#: ../../../../application/controllers/RoleController.php:155
|
||||||
#: ../../../../application/controllers/UserController.php:320
|
#: ../../../../application/controllers/UserController.php:320
|
||||||
#: ../../../../application/controllers/GroupController.php:369
|
#: ../../../../application/controllers/GroupController.php:369
|
||||||
|
49
doc/60-Hooks.md
Normal file
49
doc/60-Hooks.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Hooks
|
||||||
|
|
||||||
|
## ConfigFormEventsHook
|
||||||
|
|
||||||
|
The `ConfigFormEventsHook` allows developers to hook into the handling of configuration forms. It provides three methods:
|
||||||
|
|
||||||
|
* `appliesTo()`
|
||||||
|
* `isValid()`
|
||||||
|
* `onSuccess()`
|
||||||
|
|
||||||
|
`appliesTo()` determines whether the hook should run for a given configuration form.
|
||||||
|
Developers should use `instanceof` checks in order to decide whether the hook should run or not.
|
||||||
|
If `appliesTo()` returns `false`, `isValid()` and `onSuccess()` won't get called for this hook.
|
||||||
|
|
||||||
|
`isValid()` is called after the configuration form has been validated successfully.
|
||||||
|
An exception thrown here indicates form errors and prevents the config from being stored.
|
||||||
|
The exception's error message is shown in the frontend automatically.
|
||||||
|
If there are multiple hooks indicating errors, every error will be displayed.
|
||||||
|
|
||||||
|
`onSuccess()` is called after the configuration has been stored successfully.
|
||||||
|
Form handling can't be interrupted here. Any exception will be caught, logged and notified.
|
||||||
|
|
||||||
|
Hook example:
|
||||||
|
|
||||||
|
```php
|
||||||
|
namespace Icinga\Module\Acme\ProvidedHook;
|
||||||
|
|
||||||
|
use Icinga\Application\Hook\ConfigFormEventsHook;
|
||||||
|
use Icinga\Forms\ConfigForm;
|
||||||
|
use Icinga\Forms\Security\RoleForm;
|
||||||
|
|
||||||
|
class ConfigFormEvents extends ConfigFormEventsHook
|
||||||
|
{
|
||||||
|
public function appliesTo(ConfigForm $form)
|
||||||
|
{
|
||||||
|
return $form instanceof RoleForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onSuccess(ConfigForm $form)
|
||||||
|
{
|
||||||
|
$this->updateMyModuleConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function updateMyModuleConfig()
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
137
library/Icinga/Application/Hook/ConfigFormEventsHook.php
Normal file
137
library/Icinga/Application/Hook/ConfigFormEventsHook.php
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2019 Icinga GmbH | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Application\Hook;
|
||||||
|
|
||||||
|
use Icinga\Application\Hook;
|
||||||
|
use Icinga\Application\Logger;
|
||||||
|
use Icinga\Exception\IcingaException;
|
||||||
|
use Icinga\Forms\ConfigForm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for config form event hooks
|
||||||
|
*/
|
||||||
|
abstract class ConfigFormEventsHook
|
||||||
|
{
|
||||||
|
/** @var array Array of errors found while processing the form event hooks */
|
||||||
|
private static $lastErrors = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the hook applies to the given config form
|
||||||
|
*
|
||||||
|
* @param ConfigForm $form
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function appliesTo(ConfigForm $form)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isValid event hook
|
||||||
|
*
|
||||||
|
* Implement this method in order to run code after the form has been validated successfully.
|
||||||
|
* Throw an exception here if either the form is not valid or you want interrupt the form handling.
|
||||||
|
* The exception's message will be automatically added as form error message so that it will be
|
||||||
|
* displayed in the frontend.
|
||||||
|
*
|
||||||
|
* @param ConfigForm $form
|
||||||
|
*
|
||||||
|
* @throws \Exception If either the form is not valid or to interrupt the form handling
|
||||||
|
*/
|
||||||
|
public function isValid(ConfigForm $form)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onSuccess event hook
|
||||||
|
*
|
||||||
|
* Implement this method in order to run code after the configuration form has been stored successfully.
|
||||||
|
* You can't interrupt the form handling here. Any exception will be caught, logged and notified.
|
||||||
|
*
|
||||||
|
* @param ConfigForm $form
|
||||||
|
*/
|
||||||
|
public function onSuccess(ConfigForm $form)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an array of errors found while processing the form event hooks
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
final public static function getLastErrors()
|
||||||
|
{
|
||||||
|
return static::$lastErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run all isValid hooks
|
||||||
|
*
|
||||||
|
* @param ConfigForm $form
|
||||||
|
*
|
||||||
|
* @return bool Returns false if any hook threw an exception
|
||||||
|
*/
|
||||||
|
final public static function runIsValid(ConfigForm $form)
|
||||||
|
{
|
||||||
|
return self::runEventMethod('isValid', $form);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run all onSuccess hooks
|
||||||
|
*
|
||||||
|
* @param ConfigForm $form
|
||||||
|
*
|
||||||
|
* @return bool Returns false if any hook threw an exception
|
||||||
|
*/
|
||||||
|
final public static function runOnSuccess(ConfigForm $form)
|
||||||
|
{
|
||||||
|
return self::runEventMethod('onSuccess', $form);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function runEventMethod($eventMethod, ConfigForm $form)
|
||||||
|
{
|
||||||
|
static::$lastErrors = [];
|
||||||
|
|
||||||
|
if (! Hook::has('ConfigFormEvents')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$success = true;
|
||||||
|
|
||||||
|
foreach (Hook::all('ConfigFormEvents') as $hook) {
|
||||||
|
/** @var self $hook */
|
||||||
|
if (! $hook->runAppliesTo($form)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$hook->$eventMethod($form);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
static::$lastErrors[] = $e->getMessage();
|
||||||
|
|
||||||
|
Logger::error("%s\n%s", $e, IcingaException::getConfidentialTraceAsString($e));
|
||||||
|
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function runAppliesTo(ConfigForm $form)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$appliesTo = $this->appliesTo($form);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Don't save exception to last errors because we do not want to disturb the user for messed up
|
||||||
|
// appliesTo checks
|
||||||
|
Logger::error("%s\n%s", $e, IcingaException::getConfidentialTraceAsString($e));
|
||||||
|
|
||||||
|
$appliesTo = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $appliesTo === true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user