If a constraint validator set on an entity field (a string product "sku" field, for example) adds a violation, the following code in WidgetBase::flagErrors() triggers:
$violations_by_delta = array();
foreach ($violations as $violation) {
// Separate violations by delta.
$property_path = explode('.', $violation->getPropertyPath());
$delta = array_shift($property_path);
// Violations at the ItemList level are not associated to any delta,
// we file them under $delta NULL.
$delta = is_numeric($delta) ? $delta : NULL;
$violations_by_delta[$delta][] = $violation;
$violation->arrayPropertyPath = $property_path;
}
The $delta is set to NULL in this case, since $property_path is empty.
The PHP manual says:
Null will be cast to the empty string, i.e. the key null will actually be stored under "".
So our $delta key gets converted back from NULL to an empty string. Further down there is this piece of code:
foreach ($violations_by_delta as $delta => $delta_violations) {
// Pass violations to the main element:
// - if this is a multiple-value widget,
// - or if the violations are at the ItemList level.
if ($handles_multiple || $delta === NULL) {
$delta_element = $element;
}
The $delta === NULL check fails, and the system crashes.
We need to either do the NULL cast further down the line, or replace the strict NULL check with an is_numeric check.
Comments
Comment #1
bojanz commentedSomething like this perhaps.
Does anyone know where the test should live?
Comment #2
pcambraHere's a failing test and the patch fix.
Comment #4
penyaskitoThe fix itself looks good, and nice test coverage!
Some nitpicking.
copypasted?
Too much spacing.
Bad indentation.
Comment #5
undertext commentedComment #6
dawehnerHaving a proper test for this is great! Let's fix the two small bits.
Wow, it is cool that it is possible to validate via API . drupal_process_form() can be directly replaced by \Drupal::formBuilder()->processForm
Let's adapt this one line description as well.
Comment #7
tim bozeman commentedReroll of #5.
I changed
drupal_process_form('field_test_entity_form', $form, $form_state);to
\Drupal::formBuilder()->processForm('field_test_entity_form', $form, $form_state);And changed the comment to
Defines the test entity class for testing entity constraint violations.Comment #8
tim bozeman commentedWhoops. Last patch was missing a file.
Comment #9
bojanz commentedThanks, Tim.
This one should be ready to go once the tests come back green.
Comment #11
alexpottCommitted 62edf52 and pushed to 8.0.x. Thanks!
Fixed on commit. DrupalUnitTestBase is deprecated and everything else was not used.
Comment #14
amateescu commentedSadly, this patch did not fix the issue entirely, see #2784015-11: Widget validation crashes on ItemList violations for widgets with a custom errorElement() implementation.