Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8dbe258

Browse filesBrowse files
committed
[Form] The trace of form errors is now displayed in the profiler
1 parent 541f889 commit 8dbe258
Copy full SHA for 8dbe258

File tree

Expand file treeCollapse file tree

9 files changed

+103
-25
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+103
-25
lines changed

‎src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig
+21-7Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -473,14 +473,28 @@
473473
{% endif %}
474474
</td>
475475
<td>
476-
{% if error.cause is empty %}
477-
<em>Unknown.</em>
478-
{% elseif error.cause.root is defined %}
479-
<strong>Constraint Violation</strong><br/>
480-
<pre>{{ error.cause.root }}{% if error.cause.path is not empty %}{% if error.cause.path|first != '[' %}.{% endif %}{{ error.cause.path }}{% endif %} = {{ error.cause.value }}</pre>
476+
{% for trace in error.trace %}
477+
{% if not loop.first %}
478+
<br/>Caused by:<br/><br/>
479+
{% endif %}
480+
{% if trace.root is defined %}
481+
<strong>{{ trace.class }}</strong><br/>
482+
<pre>
483+
{{- trace.root -}}
484+
{%- if trace.path is not empty -%}
485+
{%- if trace.path|first != '[' %}.{% endif -%}
486+
{{- trace.path -}}
487+
{%- endif %} = {{ trace.value -}}
488+
</pre>
489+
{% elseif trace.message is defined %}
490+
<strong>{{ trace.class }}</strong><br/>
491+
<pre>{{ trace.message }}</pre>
492+
{% else %}
493+
<pre>{{ trace }}</pre>
494+
{% endif %}
481495
{% else %}
482-
<pre>{{ error.cause }}</pre>
483-
{% endif %}
496+
<em>Unknown.</em>
497+
{% endfor %}
484498
</td>
485499
</tr>
486500
{% endfor %}

‎src/Symfony/Component/Form/Button.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Button.php
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,15 @@ public function isSynchronized()
344344
return true;
345345
}
346346

347+
/**
348+
* Unsupported method.
349+
*
350+
* @return null Always returns null
351+
*/
352+
public function getTransformationFailure()
353+
{
354+
}
355+
347356
/**
348357
* Unsupported method.
349358
*

‎src/Symfony/Component/Form/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ CHANGELOG
2121
* ObjectChoiceList now compares choices by their value, if a value path is
2222
given
2323
* you can now pass interface names in the "data_class" option
24+
* [BC BREAK] added `FormInterface::getTransformationFailure()`
2425

2526
2.4.0
2627
-----

‎src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php
+29-8Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,18 +115,39 @@ public function extractSubmittedData(FormInterface $form)
115115
'origin' => is_object($error->getOrigin())
116116
? spl_object_hash($error->getOrigin())
117117
: null,
118+
'trace' => array(),
118119
);
119120

120121
$cause = $error->getCause();
121122

122-
if ($cause instanceof ConstraintViolationInterface) {
123-
$errorData['cause'] = array(
124-
'root' => $this->valueExporter->exportValue($cause->getRoot()),
125-
'path' => $this->valueExporter->exportValue($cause->getPropertyPath()),
126-
'value' => $this->valueExporter->exportValue($cause->getInvalidValue()),
127-
);
128-
} else {
129-
$errorData['cause'] = null !== $cause ? $this->valueExporter->exportValue($cause) : null;
123+
while (null !== $cause) {
124+
if ($cause instanceof ConstraintViolationInterface) {
125+
$errorData['trace'][] = array(
126+
'class' => $this->valueExporter->exportValue(get_class($cause)),
127+
'root' => $this->valueExporter->exportValue($cause->getRoot()),
128+
'path' => $this->valueExporter->exportValue($cause->getPropertyPath()),
129+
'value' => $this->valueExporter->exportValue($cause->getInvalidValue()),
130+
);
131+
132+
$cause = method_exists($cause, 'getCause') ? $cause->getCause() : null;
133+
134+
continue;
135+
}
136+
137+
if ($cause instanceof \Exception) {
138+
$errorData['trace'][] = array(
139+
'class' => $this->valueExporter->exportValue(get_class($cause)),
140+
'message' => $this->valueExporter->exportValue($cause->getMessage()),
141+
);
142+
143+
$cause = $cause->getPrevious();
144+
145+
continue;
146+
}
147+
148+
$errorData['trace'][] = $cause;
149+
150+
break;
130151
}
131152

132153
$data['errors'][] = $errorData;

‎src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public function validate($form, Constraint $constraint)
103103
->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')))
104104
->setInvalidValue($form->getViewData())
105105
->setCode(Form::ERR_INVALID)
106+
->setCause($form->getTransformationFailure())
106107
->addViolation();
107108
}
108109
}

‎src/Symfony/Component/Form/Form.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Form.php
+13-7Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,10 @@ class Form implements \IteratorAggregate, FormInterface
121121
private $extraData = array();
122122

123123
/**
124-
* Whether the data in model, normalized and view format is
125-
* synchronized. Data may not be synchronized if transformation errors
126-
* occur.
127-
* @var bool
124+
* Returns the transformation failure generated during submission, if any
125+
* @var TransformationFailedException|null
128126
*/
129-
private $synchronized = true;
127+
private $transformationFailure;
130128

131129
/**
132130
* Whether the form's data has been initialized.
@@ -634,7 +632,7 @@ public function submit($submittedData, $clearMissing = true)
634632
$viewData = $this->normToView($normData);
635633
}
636634
} catch (TransformationFailedException $e) {
637-
$this->synchronized = false;
635+
$this->transformationFailure = $e;
638636

639637
// If $viewData was not yet set, set it to $submittedData so that
640638
// the erroneous data is accessible on the form.
@@ -711,7 +709,15 @@ public function isBound()
711709
*/
712710
public function isSynchronized()
713711
{
714-
return $this->synchronized;
712+
return null === $this->transformationFailure;
713+
}
714+
715+
/**
716+
* {@inheritdoc}
717+
*/
718+
public function getTransformationFailure()
719+
{
720+
return $this->transformationFailure;
715721
}
716722

717723
/**

‎src/Symfony/Component/Form/FormInterface.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/FormInterface.php
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\Form;
1313

14+
use Symfony\Component\Form\Exception\TransformationFailedException;
15+
1416
/**
1517
* A form group bundling multiple forms in a hierarchical structure.
1618
*
@@ -230,10 +232,20 @@ public function isEmpty();
230232
/**
231233
* Returns whether the data in the different formats is synchronized.
232234
*
235+
* If the data is not synchronized, you can get the transformation failure
236+
* by calling {@link getTransformationFailure()}.
237+
*
233238
* @return bool
234239
*/
235240
public function isSynchronized();
236241

242+
/**
243+
* Returns the data transformation failure, if any.
244+
*
245+
* @return TransformationFailedException|null The transformation failure
246+
*/
247+
public function getTransformationFailure();
248+
237249
/**
238250
* Initializes the form tree.
239251
*

‎src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.php
+8-3Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ public function testExtractSubmittedDataStoresErrors()
319319
'norm' => "'Foobar'",
320320
),
321321
'errors' => array(
322-
array('message' => 'Invalid!', 'origin' => null, 'cause' => null),
322+
array('message' => 'Invalid!', 'origin' => null, 'trace' => array()),
323323
),
324324
'synchronized' => 'true',
325325
), $this->dataExtractor->extractSubmittedData($form));
@@ -340,7 +340,7 @@ public function testExtractSubmittedDataStoresErrorOrigin()
340340
'norm' => "'Foobar'",
341341
),
342342
'errors' => array(
343-
array('message' => 'Invalid!', 'origin' => spl_object_hash($form), 'cause' => null),
343+
array('message' => 'Invalid!', 'origin' => spl_object_hash($form), 'trace' => array()),
344344
),
345345
'synchronized' => 'true',
346346
), $this->dataExtractor->extractSubmittedData($form));
@@ -360,7 +360,12 @@ public function testExtractSubmittedDataStoresErrorCause()
360360
'norm' => "'Foobar'",
361361
),
362362
'errors' => array(
363-
array('message' => 'Invalid!', 'origin' => null, 'cause' => 'object(Exception)'),
363+
array('message' => 'Invalid!', 'origin' => null, 'trace' => array(
364+
array(
365+
'class' => "'Exception'",
366+
'message' => "''",
367+
),
368+
)),
364369
),
365370
'synchronized' => 'true',
366371
), $this->dataExtractor->extractSubmittedData($form));

‎src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,14 @@ function () { throw new TransformationFailedException(); }
225225

226226
$this->validator->validate($form, new Form());
227227

228+
$is2Dot4Api = Validation::API_VERSION_2_4 === $this->getApiVersion();
229+
228230
$this->buildViolation('invalid_message_key')
229231
->setParameter('{{ value }}', 'foo')
230232
->setParameter('{{ foo }}', 'bar')
231233
->setInvalidValue('foo')
232234
->setCode(Form::ERR_INVALID)
235+
->setCause($is2Dot4Api ? null : $form->getTransformationFailure())
233236
->assertRaised();
234237
}
235238

@@ -259,11 +262,14 @@ function () { throw new TransformationFailedException(); }
259262

260263
$this->validator->validate($form, new Form());
261264

265+
$is2Dot4Api = Validation::API_VERSION_2_4 === $this->getApiVersion();
266+
262267
$this->buildViolation('invalid_message_key')
263268
->setParameter('{{ value }}', 'foo')
264269
->setParameter('{{ foo }}', 'bar')
265270
->setInvalidValue('foo')
266271
->setCode(Form::ERR_INVALID)
272+
->setCause($is2Dot4Api ? null : $form->getTransformationFailure())
267273
->assertRaised();
268274
}
269275

@@ -293,10 +299,13 @@ function () { throw new TransformationFailedException(); }
293299

294300
$this->validator->validate($form, new Form());
295301

302+
$is2Dot4Api = Validation::API_VERSION_2_4 === $this->getApiVersion();
303+
296304
$this->buildViolation('invalid_message_key')
297305
->setParameter('{{ value }}', 'foo')
298306
->setInvalidValue('foo')
299307
->setCode(Form::ERR_INVALID)
308+
->setCause($is2Dot4Api ? null : $form->getTransformationFailure())
300309
->assertRaised();
301310
}
302311

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.