From 0c633491d4084cbf49c8bd42225f1a9608b37009 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 6 Oct 2015 22:33:05 +0200 Subject: [PATCH] QuickForm: initial import, makes things easier --- .../Businessprocess/Web/Form/CsrfToken.php | 53 +++ .../Businessprocess/Web/Form/FormLoader.php | 37 ++ .../Businessprocess/Web/Form/QuickForm.php | 421 ++++++++++++++++++ 3 files changed, 511 insertions(+) create mode 100644 library/Businessprocess/Web/Form/CsrfToken.php create mode 100644 library/Businessprocess/Web/Form/FormLoader.php create mode 100644 library/Businessprocess/Web/Form/QuickForm.php diff --git a/library/Businessprocess/Web/Form/CsrfToken.php b/library/Businessprocess/Web/Form/CsrfToken.php new file mode 100644 index 0000000..ce2288f --- /dev/null +++ b/library/Businessprocess/Web/Form/CsrfToken.php @@ -0,0 +1,53 @@ +getApplicationDir('forms'); + $ns = '\\Icinga\\Web\\Forms\\'; + } else { + $basedir = $module->getFormDir(); + $ns = '\\Icinga\\Module\\' . ucfirst($module->getName()) . '\\Forms\\'; + } + if (preg_match('~^[a-z0-9/]+$~i', $name)) { + $parts = preg_split('~/~', $name); + $class = ucfirst(array_pop($parts)) . 'Form'; + $file = sprintf('%s/%s/%s.php', rtrim($basedir, '/'), implode('/', $parts), $class); + if (file_exists($file)) { + require_once($file); + $class = $ns . $class; + $options = array(); + if ($module !== null) { + $options['icingaModule'] = $module; + } + + return new $class($options); + } + } + throw new ProgrammingError(sprintf('Cannot load %s (%s), no such form', $name, $file)); + } +} diff --git a/library/Businessprocess/Web/Form/QuickForm.php b/library/Businessprocess/Web/Form/QuickForm.php new file mode 100644 index 0000000..0a5cd19 --- /dev/null +++ b/library/Businessprocess/Web/Form/QuickForm.php @@ -0,0 +1,421 @@ +handleOptions($options)); + $this->setMethod('post'); + $this->setAction(Url::fromRequest()); + $this->createIdElement(); + $this->regenerateCsrfToken(); + } + + protected function handleOptions($options = null) + { + if ($options === null) { + return $options; + } + + if (array_key_exists('icingaModule', $options)) { + $this->icingaModule = $options['icingaModule']; + $this->icingaModuleName = $this->icingaModule->getName(); + unset($options['icingaModule']); + } + + return $options; + } + + protected function addSubmitButtonIfSet() + { + if (false !== ($label = $this->getSubmitLabel())) { + $el = $this->createElement('submit', $label)->setLabel($label)->removeDecorator('Label'); + $this->submitButtonName = $el->getName(); + $this->addElement($el); + } + } + + // TODO: This is ugly, we need to defer button creation + protected function moveSubmitToBottom() + { + $name = $this->submitButtonName; + if ($name && ($submit = $this->getElement($name))) { + $this->removeElement($name); + $this->addElement($submit); + } + } + + protected function createIdElement() + { + $this->detectName(); + $this->addHidden(self::ID, $this->getName()); + $this->getElement(self::ID)->setIgnore(true); + } + + protected function getSentValue($name, $default = null) + { + $request = $this->getRequest(); + + if ($request->isPost()) { + return $request->getPost($name); + } else { + return $default; + } + } + + public function getSubmitLabel() + { + if ($this->submitLabel === null) { + return $this->translate('Submit'); + } + + return $this->submitLabel; + } + + public function setSubmitLabel($label) + { + $this->submitLabel = $label; + return $this; + } + + protected function loadForm($name, Module $module = null) + { + if ($module === null) { + $module = $this->icingaModule; + } + + return FormLoader::load($name, $module); + } + + public function regenerateCsrfToken() + { + if (! $element = $this->getElement(self::CSRF)) { + $this->addHidden(self::CSRF, CsrfToken::generate()); + $element = $this->getElement(self::CSRF); + } + $element->setIgnore(true); + + return $this; + } + + public function removeCsrfToken() + { + $this->removeElement(self::CSRF); + return $this; + } + + public function addHidden($name, $value = null) + { + $this->addElement('hidden', $name); + $el = $this->getElement($name); + $el->setDecorators(array('ViewHelper')); + if ($value !== null) { + $this->setDefault($name, $value); + $el->setValue($value); + } + + return $this; + } + + public function addHtmlHint($html, $options = array()) + { + return $this->addHtml('
' . $html . '
', $options); + } + + public function addHtml($html, $options = array()) + { + $name = '_HINT' . ++$this->hintCount; + $this->addElement('note', $name, $options); + $this->getElement($name) + ->setValue($html) + ->setIgnore(true) + ->removeDecorator('Label'); + + return $this; + } + + public function optionalEnum($enum) + { + return array( + null => $this->translate('- please choose -') + ) + $enum; + } + + public function succeeded() + { + return $this->succeeded; + } + + public function setSuccessUrl($url) + { + $this->successUrl = $url; + return $this; + } + + public function setup() + { + } + + protected function onSetup() + { + } + + public function setAction($action) + { + if ($action instanceof Url) { + $action = $action->getAbsoluteUrl('&'); + } + + return parent::setAction($action); + } + + public function setIcingaModule(Module $module) + { + $this->icingaModule = $module; + return $this; + } + + public function hasBeenSubmitted() + { + if ($this->hasBeenSubmitted === null) { + $req = $this->getRequest(); + if ($req->isPost()) { + $post = $req->getPost(); + $name = $this->submitButtonName; + + if ($name === null) { + $this->hasBeenSubmitted = $this->hasBeenSent(); + } else { + $el = $this->getElement($name); + $this->hasBeenSubmitted = array_key_exists($name, $post) + && $post[$name] === $this->getSubmitLabel(); + } + } else { + $this->hasBeenSubmitted === false; + } + } + + return $this->hasBeenSubmitted; + } + + protected function beforeValidation($data = array()) + { + } + + public function prepareElements() + { + if (! $this->didSetup) { + $this->setup(); + $this->addSubmitButtonIfSet(); + $this->onSetup(); + $this->didSetup = true; + } + + return $this; + } + + public function handleRequest(Request $request = null) + { + if ($request !== null) { + $this->setRequest($request); + } + + if ($this->hasBeenSent()) { + $post = $this->getRequest()->getPost(); + if ($this->hasBeenSubmitted()) { + $this->beforeValidation($post); + if ($this->isValid($post)) { + $this->onSuccess(); + $this->succeeded = true; + } else { + $this->onFailure(); + $this->succeeded = false; + } + } else { + $this->setDefaults($post); + } + } else { + // Well... + } + + return $this; + } + + public function translate($string) + { + if ($this->icingaModuleName === null) { + return t($string); + } else { + return mt($this->icingaModuleName, $string); + } + } + + public function onSuccess() + { + $this->redirectOnSuccess(); + } + + public function setSuccessMessage($message) + { + $this->successMessage = $message; + return $this; + } + + public function getSuccessMessage($message = null) + { + if ($message !== null) { + return $message; + } + if ($this->successMessage === null) { + return t('Form has successfully been sent'); + } + return $this->successMessage; + } + + public function redirectOnSuccess($message = null) + { + $url = $this->successUrl ?: $this->getAction(); + $this->notifySuccess($this->getSuccessMessage($message)); + $this->redirectAndExit($url); + } + + public function onFailure() + { + } + + public function notifySuccess($message = null) + { + if ($message === null) { + $message = t('Form has successfully been sent'); + } + Notification::success($message); + return $this; + } + + public function notifyError($message) + { + Notification::error($message); + return $this; + } + + protected function redirectAndExit($url) + { + Icinga::app()->getFrontController()->getResponse()->redirectAndExit($url); + } + + protected function onRequest() + { + } + + public function setRequest(Request $request) + { + if ($this->request !== null) { + throw new ProgrammingError('Unable to set request twice'); + } + + $this->request = $request; + $this->prepareElements(); + $this->onRequest(); + return $this; + } + + public function getRequest() + { + if ($this->request === null) { + $this->setRequest(Icinga::app()->getFrontController()->getRequest()); + } + return $this->request; + } + + public function hasBeenSent() + { + if ($this->hasBeenSent === null) { + $req = $this->getRequest(); + if ($req->isPost()) { + $post = $req->getPost(); + $this->hasBeenSent = array_key_exists(self::ID, $post) && + $post[self::ID] === $this->getName(); + } else { + $this->hasBeenSent === false; + } + } + + return $this->hasBeenSent; + } + + protected function detectName() + { + if ($this->formName !== null) { + $this->setName($this->formName); + } else { + $this->setName(get_class($this)); + } + } +}