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 -%}
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