Merge branch 'feature/exhaustive-form-descriptions-7947'
resolves #7947
This commit is contained in:
commit
ff6658324a
|
@ -53,7 +53,7 @@ class ExternalBackendForm extends Form
|
|||
return @preg_match($value, '') !== false;
|
||||
});
|
||||
$callbackValidator->setMessage(
|
||||
$this->translate('"%value%" is not a valid regular expression'),
|
||||
$this->translate('"%value%" is not a valid regular expression.'),
|
||||
Zend_Validate_Callback::INVALID_VALUE
|
||||
);
|
||||
$this->addElement(
|
||||
|
@ -62,9 +62,10 @@ class ExternalBackendForm extends Form
|
|||
array(
|
||||
'label' => $this->translate('Filter Pattern'),
|
||||
'description' => $this->translate(
|
||||
'The regular expression to use to strip specific parts off from usernames.'
|
||||
. ' Leave empty if you do not want to strip off anything'
|
||||
'The filter to use to strip specific parts off from usernames.'
|
||||
. ' Leave empty if you do not want to strip off anything.'
|
||||
),
|
||||
'requirement' => $this->translate('The filter pattern must be a valid regular expression.'),
|
||||
'validators' => array($callbackValidator)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -66,6 +66,7 @@ class LoggingConfigForm extends Form
|
|||
'description' => $this->translate(
|
||||
'The name of the application by which to prefix syslog messages.'
|
||||
),
|
||||
'requirement' => $this->translate('The application prefix must not contain whitespace.'),
|
||||
'value' => 'icingaweb2',
|
||||
'validators' => array(
|
||||
array(
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace Icinga\Forms\Config\Resource;
|
||||
|
||||
use Zend_Validate_Callback;
|
||||
use Icinga\Web\Form;
|
||||
|
||||
/**
|
||||
|
@ -42,13 +43,22 @@ class FileResourceForm extends Form
|
|||
'validators' => array('ReadablePathValidator')
|
||||
)
|
||||
);
|
||||
$callbackValidator = new Zend_Validate_Callback(function ($value) {
|
||||
return @preg_match($value, '') !== false;
|
||||
});
|
||||
$callbackValidator->setMessage(
|
||||
$this->translate('"%value%" is not a valid regular expression.'),
|
||||
Zend_Validate_Callback::INVALID_VALUE
|
||||
);
|
||||
$this->addElement(
|
||||
'text',
|
||||
'fields',
|
||||
array(
|
||||
'required' => true,
|
||||
'label' => $this->translate('Pattern'),
|
||||
'description' => $this->translate('The regular expression by which to identify columns')
|
||||
'description' => $this->translate('The pattern by which to identify columns.'),
|
||||
'requirement' => $this->translate('The column pattern must be a valid regular expression.'),
|
||||
'validators' => array($callbackValidator)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ class Form extends Zend_Form
|
|||
public static $defaultElementDecorators = array(
|
||||
array('ViewHelper', array('separator' => '')),
|
||||
array('Errors', array('separator' => '')),
|
||||
array('Help'),
|
||||
array('Help', array('placement' => 'PREPEND')),
|
||||
array('Label', array('separator' => '')),
|
||||
array('HtmlTag', array('tag' => 'div', 'class' => 'element'))
|
||||
);
|
||||
|
@ -622,7 +622,7 @@ class Form extends Zend_Form
|
|||
public function addSubForm(Zend_Form $form, $name = null, $order = null)
|
||||
{
|
||||
if ($form instanceof self) {
|
||||
$form->removeDecorator('Form');
|
||||
$form->setDecorators(array('FormElements')); // TODO: Makes it difficult to customise subform decorators..
|
||||
$form->setSubmitLabel('');
|
||||
$form->setTokenDisabled();
|
||||
$form->setUidDisabled();
|
||||
|
@ -743,7 +743,7 @@ class Form extends Zend_Form
|
|||
if (($cue = $this->getRequiredCue()) !== null && ($label = $element->getDecorator('label')) !== false) {
|
||||
$element->setLabel($this->getView()->escape($element->getLabel()));
|
||||
$label->setOption('escape', false);
|
||||
$label->setOption('requiredSuffix', sprintf(' <span aria-hidden="true">%s</span>', $cue));
|
||||
$label->setRequiredSuffix(sprintf(' <span aria-hidden="true">%s</span>', $cue));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,29 @@ use Icinga\Web\Form;
|
|||
*/
|
||||
class FormDescriptions extends Zend_Form_Decorator_Abstract
|
||||
{
|
||||
/**
|
||||
* A list of element class names to be ignored when detecting which message to use to describe required elements
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $blacklist;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct($options = null)
|
||||
{
|
||||
parent::__construct($options);
|
||||
$this->blacklist = array(
|
||||
'Zend_Form_Element_Hidden',
|
||||
'Zend_Form_Element_Submit',
|
||||
'Zend_Form_Element_Button',
|
||||
'Icinga\Web\Form\Element\Note',
|
||||
'Icinga\Web\Form\Element\Button',
|
||||
'Icinga\Web\Form\Element\CsrfCounterMeasure'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render form descriptions
|
||||
*
|
||||
|
@ -32,9 +55,16 @@ class FormDescriptions extends Zend_Form_Decorator_Abstract
|
|||
return $content;
|
||||
}
|
||||
|
||||
$descriptions = $form->getDescriptions();
|
||||
if (($requiredDesc = $this->getRequiredDescription($form)) !== null) {
|
||||
$descriptions[] = $requiredDesc;
|
||||
$descriptions = $this->recurseForm($form, $entirelyRequired);
|
||||
if ($entirelyRequired) {
|
||||
$descriptions[] = $form->getView()->translate(
|
||||
'All fields are required and must be filled in to complete the form.'
|
||||
);
|
||||
} elseif ($entirelyRequired === false) {
|
||||
$descriptions[] = $form->getView()->translate(sprintf(
|
||||
'Required fields are marked with %s and must be filled in to complete the form.',
|
||||
$form->getRequiredCue()
|
||||
));
|
||||
}
|
||||
|
||||
if (empty($descriptions)) {
|
||||
|
@ -60,53 +90,57 @@ class FormDescriptions extends Zend_Form_Decorator_Abstract
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the description for the given form's required elements
|
||||
* Recurse the given form and return the descriptions for it and all of its subforms
|
||||
*
|
||||
* @param Form $form
|
||||
* @param Form $form The form to recurse
|
||||
* @param mixed $entirelyRequired Set by reference, true means all elements in the hierarchy are
|
||||
* required, false only a partial subset and null none at all
|
||||
* @param bool $elementsPassed Whether there were any elements passed during the recursion until now
|
||||
*
|
||||
* @return string|null
|
||||
* @return array
|
||||
*/
|
||||
protected function getRequiredDescription(Form $form)
|
||||
protected function recurseForm(Form $form, & $entirelyRequired = null, $elementsPassed = false)
|
||||
{
|
||||
if (($cue = $form->getRequiredCue()) === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$requiredLabels = array();
|
||||
$entirelyRequired = true;
|
||||
$partiallyRequired = false;
|
||||
$blacklist = array(
|
||||
'Zend_Form_Element_Hidden',
|
||||
'Zend_Form_Element_Submit',
|
||||
'Zend_Form_Element_Button',
|
||||
'Icinga\Web\Form\Element\Note',
|
||||
'Icinga\Web\Form\Element\Button',
|
||||
'Icinga\Web\Form\Element\CsrfCounterMeasure'
|
||||
);
|
||||
foreach ($form->getElements() as $element) {
|
||||
if (! in_array($element->getType(), $blacklist)) {
|
||||
if (! $element->isRequired()) {
|
||||
$entirelyRequired = false;
|
||||
} else {
|
||||
$partiallyRequired = true;
|
||||
if (($label = $element->getDecorator('label')) !== false) {
|
||||
$requiredLabels[] = $label;
|
||||
if ($form->getRequiredCue() !== null) {
|
||||
$partiallyRequired = $partiallyOptional = false;
|
||||
foreach ($form->getElements() as $element) {
|
||||
if (! in_array($element->getType(), $this->blacklist)) {
|
||||
if (! $element->isRequired()) {
|
||||
$partiallyOptional = true;
|
||||
if ($entirelyRequired) {
|
||||
$entirelyRequired = false;
|
||||
}
|
||||
} else {
|
||||
$partiallyRequired = true;
|
||||
if (($label = $element->getDecorator('label')) !== false) {
|
||||
$requiredLabels[] = $label;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! $elementsPassed) {
|
||||
$elementsPassed = $partiallyRequired || $partiallyOptional;
|
||||
if ($entirelyRequired === null && $partiallyRequired) {
|
||||
$entirelyRequired = ! $partiallyOptional;
|
||||
}
|
||||
} elseif ($entirelyRequired === null && $partiallyRequired) {
|
||||
$entirelyRequired = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($entirelyRequired && $partiallyRequired) {
|
||||
$descriptions = array($form->getDescriptions());
|
||||
foreach ($form->getSubForms() as $subForm) {
|
||||
$descriptions[] = $this->recurseForm($subForm, $entirelyRequired, $elementsPassed);
|
||||
}
|
||||
|
||||
if ($entirelyRequired) {
|
||||
foreach ($requiredLabels as $label) {
|
||||
$label->setRequiredSuffix('');
|
||||
}
|
||||
|
||||
return $form->getView()->translate('All fields are required and must be filled in to complete the form.');
|
||||
} elseif ($partiallyRequired) {
|
||||
return $form->getView()->translate(sprintf(
|
||||
'Required fields are marked with %s and must be filled in to complete the form.',
|
||||
$cue
|
||||
));
|
||||
}
|
||||
|
||||
return call_user_func_array('array_merge', $descriptions);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,18 +76,35 @@ class Help extends Zend_Form_Decorator_Abstract
|
|||
*/
|
||||
public function render($content = '')
|
||||
{
|
||||
if ($content && ($description = $this->getElement()->getDescription()) !== null) {
|
||||
$element = $this->getElement();
|
||||
$description = $element->getDescription();
|
||||
$requirement = $element->getAttrib('requirement');
|
||||
unset($element->requirement);
|
||||
|
||||
$helpContent = '';
|
||||
if ($description || $requirement) {
|
||||
if ($this->accessible) {
|
||||
$content = '<span id="'
|
||||
$helpContent = '<span id="'
|
||||
. $this->getDescriptionId()
|
||||
. '" class="sr-only">'
|
||||
. $description
|
||||
. '</span>' . $content;
|
||||
. ($description && $requirement ? ' ' : '')
|
||||
. $requirement
|
||||
. '</span>';
|
||||
}
|
||||
|
||||
$content = $this->getView()->icon('help', $description, array('aria-hidden' => 'true')) . $content;
|
||||
$helpContent = $this->getView()->icon(
|
||||
'help',
|
||||
$description . ($description && $requirement ? ' ' : '') . $requirement,
|
||||
array('aria-hidden' => $this->accessible ? 'true' : 'false')
|
||||
) . $helpContent;
|
||||
}
|
||||
|
||||
return $content;
|
||||
switch ($this->getPlacement()) {
|
||||
case self::APPEND:
|
||||
return $content . $helpContent;
|
||||
case self::PREPEND:
|
||||
return $helpContent . $content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue