diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php
index e2ddbaf47fdaf..50f4b661273fc 100644
--- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php
+++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php
@@ -47,6 +47,7 @@ public function getFunctions()
new TwigFunction('form_widget', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))),
new TwigFunction('form_errors', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))),
new TwigFunction('form_label', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))),
+ new TwigFunction('form_help', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))),
new TwigFunction('form_row', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))),
new TwigFunction('form_rest', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))),
new TwigFunction('form', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))),
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig
index d6b08f76375c4..b082d9236b927 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig
@@ -23,10 +23,15 @@ col-sm-2
{# Rows #}
{% block form_row -%}
+ {%- set widget_attr = {} -%}
+ {%- if help is not empty -%}
+ {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
+ {%- endif -%}
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
index 0e198aa517cae..f8d230d5fa223 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
@@ -89,9 +89,14 @@
{# Rows #}
{% block form_row -%}
+ {%- set widget_attr = {} -%}
+ {%- if help is not empty -%}
+ {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
+ {%- endif -%}
{{- form_label(form) -}}
- {{- form_widget(form) -}}
+ {{- form_widget(form, widget_attr) -}}
+ {{- form_help(form) -}}
{{- form_errors(form) -}}
{%- endblock form_row %}
@@ -149,3 +154,17 @@
{% if form is not rootform %}{% else %}{% endif %}
{%- endif %}
{%- endblock form_errors %}
+
+{# Help #}
+
+{% block form_help -%}
+ {%- if help is not empty -%}
+
+ {%- if translation_domain is same as(false) -%}
+ {{- help -}}
+ {%- else -%}
+ {{- help|trans({}, translation_domain) -}}
+ {%- endif -%}
+
+ {%- endif -%}
+{%- endblock form_help %}
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig
index e23e6f8a29d09..ca40981ec8524 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig
@@ -24,21 +24,31 @@ col-sm-2
{%- if expanded is defined and expanded -%}
{{ block('fieldset_form_row') }}
{%- else -%}
+ {%- set widget_attr = {} -%}
+ {%- if help is not empty -%}
+ {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
+ {%- endif -%}
{%- endif -%}
{%- endblock form_row %}
{% block fieldset_form_row -%}
+ {%- set widget_attr = {} -%}
+ {%- if help is not empty -%}
+ {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
+ {%- endif -%}
{{- form_label(form) -}}
- {{- form_widget(form) -}}
+ {{- form_widget(form, widget_attr) -}}
+ {{- form_help(form) -}}
{##}
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig
index 2acd7086b0c7e..b8aa6b8cd189e 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig
@@ -257,9 +257,14 @@
{%- if compound is defined and compound -%}
{%- set element = 'fieldset' -%}
{%- endif -%}
+ {%- set widget_attr = {} -%}
+ {%- if help is not empty -%}
+ {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
+ {%- endif -%}
<{{ element|default('div') }} class="form-group">
{{- form_label(form) -}}
- {{- form_widget(form) -}}
+ {{- form_widget(form, widget_attr) -}}
+ {{- form_help(form) -}}
{{ element|default('div') }}>
{%- endblock form_row %}
@@ -276,3 +281,17 @@
{%- endif %}
{%- endblock form_errors %}
+
+{# Help #}
+
+{% block form_help -%}
+ {%- if help is not empty -%}
+
+ {%- if translation_domain is same as(false) -%}
+ {{- help -}}
+ {%- else -%}
+ {{- help|trans({}, translation_domain) -}}
+ {%- endif -%}
+
+ {%- endif -%}
+{%- endblock form_help %}
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
index 583583e189997..11d5783dd59f5 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
@@ -287,6 +287,20 @@
{%- block button_label -%}{%- endblock -%}
+{# Help #}
+
+{% block form_help -%}
+ {%- if help is not empty -%}
+
+ {%- if translation_domain is same as(false) -%}
+ {{- help -}}
+ {%- else -%}
+ {{- help|trans({}, translation_domain) -}}
+ {%- endif -%}
+
+ {%- endif -%}
+{%- endblock form_help %}
+
{# Rows #}
{%- block repeated_row -%}
@@ -298,10 +312,15 @@
{%- endblock repeated_row -%}
{%- block form_row -%}
+ {%- set widget_attr = {} -%}
+ {%- if help is not empty -%}
+ {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
+ {%- endif -%}
{{- form_label(form) -}}
{{- form_errors(form) -}}
- {{- form_widget(form) -}}
+ {{- form_widget(form, widget_attr) -}}
+ {{- form_help(form) -}}
{%- endblock form_row -%}
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig
index 39274c6c8d058..10eaf566d097d 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_table_layout.html.twig
@@ -1,13 +1,18 @@
{% use "form_div_layout.html.twig" %}
{%- block form_row -%}
+ {%- set widget_attr = {} -%}
+ {%- if help is not empty -%}
+ {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
+ {%- endif -%}
{{- form_label(form) -}}
{{- form_errors(form) -}}
- {{- form_widget(form) -}}
+ {{- form_widget(form, widget_attr) -}}
+ {{- form_help(form) -}}
{%- endblock form_row -%}
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig
index 3035689cc9dff..9e1261e3adafb 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig
@@ -267,11 +267,16 @@
{# Rows #}
{% block form_row -%}
+ {%- set widget_attr = {} -%}
+ {%- if help is not empty -%}
+ {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
+ {%- endif -%}
- {{ form_label(form) }}
- {{ form_widget(form) }}
- {{ form_errors(form) }}
+ {{- form_label(form) -}}
+ {{- form_widget(form, widget_attr) -}}
+ {{- form_help(form) -}}
+ {{- form_errors(form) -}}
{%- endblock form_row %}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php
index e5ee8903efe4a..9c9ea12ab2b97 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php
@@ -69,6 +69,11 @@ protected function renderLabel(FormView $view, $label = null, array $vars = arra
return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
+ protected function renderHelp(FormView $view)
+ {
+ return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ }
+
protected function renderErrors(FormView $view)
{
return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
index 5e872b83eb67d..e99c1e6fc7622 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
@@ -89,6 +89,11 @@ protected function renderLabel(FormView $view, $label = null, array $vars = arra
return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
+ protected function renderHelp(FormView $view)
+ {
+ return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ }
+
protected function renderErrors(FormView $view)
{
return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php
index 063edd889aed4..8ad680710a588 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php
@@ -70,6 +70,11 @@ protected function renderLabel(FormView $view, $label = null, array $vars = arra
return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
+ protected function renderHelp(FormView $view)
+ {
+ return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ }
+
protected function renderErrors(FormView $view)
{
return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php
index d8cbde1017345..c34e6e3f32389 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php
@@ -92,6 +92,11 @@ protected function renderLabel(FormView $view, $label = null, array $vars = arra
return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
+ protected function renderHelp(FormView $view)
+ {
+ return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ }
+
protected function renderErrors(FormView $view)
{
return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
index 22a1413f38cbc..ddf4e389ebfa6 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
@@ -179,6 +179,11 @@ protected function renderLabel(FormView $view, $label = null, array $vars = arra
return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
+ protected function renderHelp(FormView $view)
+ {
+ return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ }
+
protected function renderErrors(FormView $view)
{
return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
index 5119480d90e4c..99d29f717b335 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
@@ -90,6 +90,11 @@ protected function renderLabel(FormView $view, $label = null, array $vars = arra
return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
}
+ protected function renderHelp(FormView $view)
+ {
+ return (string) $this->renderer->searchAndRenderBlock($view, 'help');
+ }
+
protected function renderErrors(FormView $view)
{
return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
diff --git a/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php b/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php
index 77c78ce38f530..9c550a05c5c93 100644
--- a/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php
+++ b/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php
@@ -34,6 +34,7 @@ class UndefinedCallableHandler
'form_widget' => 'form',
'form_errors' => 'form',
'form_label' => 'form',
+ 'form_help' => 'form',
'form_row' => 'form',
'form_rest' => 'form',
'form' => 'form',
diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json
index 402c4ed9a8020..14c80b21a33e2 100644
--- a/src/Symfony/Bridge/Twig/composer.json
+++ b/src/Symfony/Bridge/Twig/composer.json
@@ -23,7 +23,7 @@
"symfony/asset": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/finder": "~3.4|~4.0",
- "symfony/form": "^3.4.7|^4.0.7",
+ "symfony/form": "^4.1",
"symfony/http-foundation": "~3.4|~4.0",
"symfony/http-kernel": "~3.4|~4.0",
"symfony/polyfill-intl-icu": "~1.0",
@@ -41,7 +41,7 @@
"symfony/workflow": "~3.4|~4.0"
},
"conflict": {
- "symfony/form": "<3.4.7|<4.0.7,>=4.0",
+ "symfony/form": "<4.1",
"symfony/console": "<3.4"
},
"suggest": {
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_help.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_help.html.php
new file mode 100644
index 0000000000000..6113c00dea9b1
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_help.html.php
@@ -0,0 +1,3 @@
+
+ escape(false !== $translation_domain ? $view['translator']->trans($help, array(), $translation_domain) : $help); ?>
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_row.html.php
index a4f86d0223184..ba81f45b5d576 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_row.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/form_row.html.php
@@ -1,5 +1,7 @@
- label($form) ?>
- errors($form) ?>
- widget($form) ?>
+ array('aria-describedby' => $id.'_help')); ?>
+ label($form); ?>
+ errors($form); ?>
+ widget($form, $widgetAttr); ?>
+ help($form); ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php
index 41c0cc7bfe8ba..1626a9cc63ff5 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php
@@ -1,3 +1,3 @@
id="escape($id) ?>" name="escape($full_name) ?>" disabled="disabled"
required="required"
-block($form, 'attributes') : '' ?>
+block($form, 'attributes') : '' ?>
\ No newline at end of file
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php
index e2f03ff2b7064..71d606c3d4b42 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php
@@ -1,9 +1,11 @@
+ array('aria-describedby' => $id.'_help')); ?>
label($form); ?>
errors($form); ?>
- widget($form); ?>
+ widget($form, $widgetAttr); ?>
+ help($form); ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php
index 0ad1ff85b24a5..378be904ef78c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php
@@ -169,6 +169,18 @@ public function label(FormView $view, $label = null, array $variables = array())
return $this->renderer->searchAndRenderBlock($view, 'label', $variables);
}
+ /**
+ * Renders the help of the given view.
+ *
+ * @param FormView $view The parent view
+ *
+ * @return string The HTML markup
+ */
+ public function help(FormView $view): string
+ {
+ return $this->renderer->searchAndRenderBlock($view, 'help');
+ }
+
/**
* Renders the errors of the given view.
*
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php
index b86d54b78cdb4..3507729c79f5b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php
@@ -91,6 +91,11 @@ protected function renderLabel(FormView $view, $label = null, array $vars = arra
return (string) $this->engine->get('form')->label($view, $label, $vars);
}
+ protected function renderHelp(FormView $view)
+ {
+ return (string) $this->engine->get('form')->help($view);
+ }
+
protected function renderErrors(FormView $view)
{
return (string) $this->engine->get('form')->errors($view);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php
index 8dd6fffa79f41..dcec5b300245c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php
@@ -92,6 +92,11 @@ protected function renderLabel(FormView $view, $label = null, array $vars = arra
return (string) $this->engine->get('form')->label($view, $label, $vars);
}
+ protected function renderHelp(FormView $view)
+ {
+ return (string) $this->engine->get('form')->help($view);
+ }
+
protected function renderErrors(FormView $view)
{
return (string) $this->engine->get('form')->errors($view);
diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json
index 1272f8d07c260..f91fb24f9691a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/composer.json
+++ b/src/Symfony/Bundle/FrameworkBundle/composer.json
@@ -39,7 +39,7 @@
"symfony/dom-crawler": "~3.4|~4.0",
"symfony/polyfill-intl-icu": "~1.0",
"symfony/security": "~3.4|~4.0",
- "symfony/form": "~3.4|~4.0",
+ "symfony/form": "^4.1",
"symfony/expression-language": "~3.4|~4.0",
"symfony/process": "~3.4|~4.0",
"symfony/security-core": "~3.4|~4.0",
@@ -65,7 +65,7 @@
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0",
"symfony/asset": "<3.4",
"symfony/console": "<3.4",
- "symfony/form": "<3.4",
+ "symfony/form": "<4.1",
"symfony/property-info": "<3.4",
"symfony/serializer": "<4.1",
"symfony/stopwatch": "<3.4",
diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php
index 1beb6ab806f86..3f671d8216e38 100644
--- a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php
+++ b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php
@@ -89,6 +89,7 @@ public function buildView(FormView $view, FormInterface $form, array $options)
'required' => $form->isRequired(),
'size' => null,
'label_attr' => $options['label_attr'],
+ 'help' => $options['help'],
'compound' => $formConfig->getCompound(),
'method' => $formConfig->getMethod(),
'action' => $formConfig->getAction(),
@@ -178,10 +179,12 @@ public function configureOptions(OptionsResolver $resolver)
'attr' => array(),
'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.',
'upload_max_size_message' => $uploadMaxSizeMessage, // internal
+ 'help' => null,
));
$resolver->setAllowedTypes('label_attr', 'array');
$resolver->setAllowedTypes('upload_max_size_message', array('callable'));
+ $resolver->setAllowedTypes('help', array('string', 'null'));
}
/**
diff --git a/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php
index 4764117964b61..6fa45e69e13ed 100644
--- a/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php
+++ b/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php
@@ -102,6 +102,23 @@ public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly
);
}
+ public function testHelp()
+ {
+ $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array(
+ 'help' => 'Help text test!',
+ ));
+ $view = $form->createView();
+ $html = $this->renderHelp($view);
+
+ $this->assertMatchesXpath($html,
+'/span
+ [@id="name_help"]
+ [@class="help-block"]
+ [.="[trans]Help text test![/trans]"]
+'
+ );
+ }
+
public function testErrors()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
diff --git a/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php
index beabaa21cdb1a..f7784927941ee 100644
--- a/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php
+++ b/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php
@@ -151,6 +151,23 @@ public function testLegendOnExpandedType()
);
}
+ public function testHelp()
+ {
+ $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array(
+ 'help' => 'Help text test!',
+ ));
+ $view = $form->createView();
+ $html = $this->renderHelp($view);
+
+ $this->assertMatchesXpath($html,
+'/small
+ [@id="name_help"]
+ [@class="form-text text-muted"]
+ [.="[trans]Help text test![/trans]"]
+'
+ );
+ }
+
public function testErrors()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
@@ -178,7 +195,7 @@ public function testErrors()
public function testErrorWithNoLabel()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', array('label'=>false));
+ $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', array('label' => false));
$form->addError(new FormError('[trans]Error 1[/trans]'));
$view = $form->createView();
$html = $this->renderLabel($view);
diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php
index be295a302efe8..93a9f25d357b0 100644
--- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php
+++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\Form\Tests;
+use PHPUnit\Framework\SkippedTestError;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
@@ -113,6 +114,11 @@ abstract protected function renderForm(FormView $view, array $vars = array());
abstract protected function renderLabel(FormView $view, $label = null, array $vars = array());
+ protected function renderHelp(FormView $view)
+ {
+ $this->markTestSkipped(sprintf('%s::renderHelp() is not implemented.', get_class($this)));
+ }
+
abstract protected function renderErrors(FormView $view);
abstract protected function renderWidget(FormView $view, array $vars = array());
@@ -408,6 +414,66 @@ public function testLabelFormatOnButtonId()
);
}
+ public function testHelp()
+ {
+ $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array(
+ 'help' => 'Help text test!',
+ ));
+ $view = $form->createView();
+ $html = $this->renderHelp($view);
+
+ $this->assertMatchesXpath($html,
+'/p
+ [@id="name_help"]
+ [@class="help-text"]
+ [.="[trans]Help text test![/trans]"]
+'
+ );
+ }
+
+ public function testHelpNotSet()
+ {
+ $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
+ $view = $form->createView();
+ $html = $this->renderHelp($view);
+
+ $this->assertMatchesXpath($html, '/p', 0);
+ }
+
+ public function testHelpSetLinkFromWidget()
+ {
+ $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array(
+ 'help' => 'Help text test!',
+ ));
+ $view = $form->createView();
+ $html = $this->renderRow($view);
+
+ // Test if renderHelp method is implemented (throw SkippedTestError if not)
+ $this->renderHelp($view);
+
+ $this->assertMatchesXpath($html,
+'//input
+ [@aria-describedby="name_help"]
+'
+ );
+ }
+
+ public function testHelpNotSetNotLinkedFromWidget()
+ {
+ $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
+ $view = $form->createView();
+ $html = $this->renderRow($view);
+
+ // Test if renderHelp method is implemented (throw SkippedTestError if not)
+ $this->renderHelp($view);
+
+ $this->assertMatchesXpath($html,
+'//input
+ [not(@aria-describedby)]
+'
+ );
+ }
+
public function testErrors()
{
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json
index acbb82aa8fe49..444033593219d 100644
--- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json
+++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json
@@ -33,6 +33,7 @@
"by_reference",
"data",
"disabled",
+ "help",
"inherit_data",
"label",
"label_attr",
diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt
index 6d698a6171f15..3a0a452fd45cd 100644
--- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt
+++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt
@@ -14,9 +14,10 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice")
choices by_reference csrf_token_manager
expanded data
group_by disabled
- multiple inherit_data
- placeholder label
- preferred_choices label_attr
+ multiple help
+ placeholder inherit_data
+ preferred_choices label
+ label_attr
label_format
mapped
method
diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.json
index bdefb5c946626..b0735e7248687 100644
--- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.json
+++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.json
@@ -14,6 +14,7 @@
"disabled",
"empty_data",
"error_bubbling",
+ "help",
"inherit_data",
"label",
"label_attr",
diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.txt
index 72b13dfef75aa..78a4db0e684f7 100644
--- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.txt
+++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.txt
@@ -16,6 +16,7 @@ Symfony\Component\Form\Extension\Core\Type\FormType (Block prefix: "form")
disabled
empty_data
error_bubbling
+ help
inherit_data
label
label_attr
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy