Problem/Motivation

Follow-up from #196972: How does hook_views_tabs() work?.

From #2614250-14: Number widget validation can break AJAX actions by amateescu:

\Drupal\Core\Field\WidgetBase::flagErrors(), line 423, $violation->getPropertyPath() returns an empty string, which means that $delta_element = $element; below will be $element[0]['value'] instead of just $element['value'], and that's why the call to $this->errorElement() below will send the wrong form array structure.

This probably causes the following major bugs:

Proposed resolution

Let's add the $sub_property_path of a validation violation to the errorElement() method of widgets, so they can be easily used when mapping them to elements. Probably, we can also default to 1:1 mapping between violated properties and elements.

Right, now those sub property path is already calculated and available via the undocumented $violation->arrayPropertyPath property.

Remaining tasks

User interface changes

API changes

Data model changes

CommentFileSizeAuthor
#87 2027059-nr-bot.txt132 bytesneeds-review-queue-bot
#75 2027059-75.patch759 bytessteveoliver
#62 drupal-2027059-62-test-only.patch1.87 KBDane Powell
#62 drupal-2027059-62.patch3.12 KBDane Powell
#55 2027059-55-test-only.patch1.86 KBandypost
#55 2027059-55.patch3.11 KBandypost
#7 2027059-7-fix-widgetbase-error-element.patch10.74 KBbojanz
#9 2027059-9-fix-widgetbase-error-element.patch10.74 KBbojanz
#11 2027059-11-fix-widgetbase-error-element.patch10.86 KBbojanz
#15 2027059-15-fix-widgetbase-error-element.patch5.06 KBdbolinovski
#18 2027059-18-fix-widgetbase-error-element.patch5.12 KBdbolinovski
#22 2027059-22-fix-widgetbase-error-element.patch24.65 KBdbolinovski
#26 interdiff-2027059-22-26.txt2.87 KBnlisgo
#26 pass_validation-2027059-26.patch24.68 KBnlisgo
#29 interdiff-2027059-26-29.txt892 bytesnlisgo
#29 pass_validation-2027059-29.patch40.78 KBnlisgo
#34 2027059-34-fix-widgetbase-error-element.patch23.92 KBdbolinovski
#35 2027059-35-fix-widgetbase-error-element.patch23.91 KBdbolinovski
#36 interdiff-2027059-34-35.txt15.92 KBdbolinovski
#38 interdiff-2027059-35-38.txt1.05 KBdbolinovski
#38 2027059-38-fix-widgetbase-error-element.patch23.91 KBdbolinovski
#39 interdiff-2027059-35-39.txt1.05 KBdbolinovski
#39 2027059-39-fix-widgetbase-error-element.patch23.91 KBdbolinovski
#45 2027059-45.patch3.13 KBswentel
#45 2027059-45-test-only.patch1.88 KBswentel
#45 2027059-45-interdiff.txt1.25 KBswentel
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

fago’s picture

Status: Postponed » Active
fago’s picture

Issue summary: View changes
Status: Active » Closed (duplicate)

This is getting handled as part from #2095195: Remove deprecated field_attach_form_*() now.

yched’s picture

@fago: Is it ? I'm afk, bit iirc that other patch just paases ViolationList objects directly as a param to widget::flagErrors() instead of passing it through $form_state, but otherwise doesn't change anything regarding error paths ?

fago’s picture

Status: Closed (duplicate) » Active

True - looks like I confused that :/ Thanks, re-opening.

tim.plunkett’s picture

Priority: Normal » Major
tim.plunkett’s picture

Issue tags: +blocker
bojanz’s picture

Status: Active » Needs review
FileSize
10.74 KB

Wow, so $violation->arrayPropertyPath doesn't actually exist on the violation object, we just randomly assign it there in WidgetBase.
Didn't even know PHP allowed that.

Here's an initial patch. It stops passing $violation->arrayPropertyPath, and introduces a new method argument instead.
It also returns the correct error element.
No test work yet.

Status: Needs review » Needs work

The last submitted patch, 7: 2027059-7-fix-widgetbase-error-element.patch, failed testing.

bojanz’s picture

Status: Needs work » Needs review
FileSize
10.74 KB

Friday afternoon intelligence. This time without the syntax error.

Status: Needs review » Needs work

The last submitted patch, 9: 2027059-9-fix-widgetbase-error-element.patch, failed testing.

bojanz’s picture

Status: Needs work » Needs review
FileSize
10.86 KB

$error and $violation were inconsistently used in the method signature, and I made it worse. Now fixed.

This one should be green, but we'll want to introduce additional test coverage.

yched’s picture

Then we should stop assigning $violation->arrayPropertyPath altogether, rather than assigning it and then unassigning it a couple lines below ?

Would mean building $violations_by_delta as

[delta] => [ 
  ['violation' => $violation, 'property_path" => $property_path],
  ['violation' => ..., 'property_path' => ...],
  ...
]  

rather than

[delta] => [
  $violation_with_a_temp_arrayPropertyPath,
  $violation_with_a_temp_arrayPropertyPath,
  ...
]
yched’s picture

But more generally, it feels weird to have a method with params :
- $property_path (as an array skipping the delta)
- $violation that has a getPropertyPath() method that returns something slightly different (a string, starting with the delta)

Maybe we could remove the new param, and instead provide a dedicated helper method in WidgetBase, $this->getLocalErrorPath($violation), that implementations of errorElement($violation) would call ?

tim.plunkett’s picture

Sorry for letting this slip. Just wanted to also point out that we cannot dereference arrayPropertyPath/propertyPath, since it is somethings empty.
#2553983: Required textarea with summary breaks ajax events for other fields.

dbolinovski’s picture

Removed $violation->arrayPropertyPath and added WidgetBase::getLocalErrorPath(ConstraintViolationInterface $violation).
Included fix from https://www.drupal.org/node/2553983.

Status: Needs review » Needs work

The last submitted patch, 15: 2027059-15-fix-widgetbase-error-element.patch, failed testing.

The last submitted patch, 15: 2027059-15-fix-widgetbase-error-element.patch, failed testing.

dbolinovski’s picture

Status: Needs work » Needs review
FileSize
5.12 KB
dawehner’s picture

Ideally we would have test coverage for some of the following cases: a) a widget handling multiple form elements b) a widget on a field with single cardinality b) a widget on a field with multiple cardinality, so we are sure that its passed along properly to all of them.

yched’s picture

Agreed with #19, otherwise patch looks good to me :-)

bojanz’s picture

dbolinovski has started work on tests, I've told him to upload his progress the next time he's online.

dbolinovski’s picture

TextareaWithSummaryWidget::errorElement() changes. Added test cases.

Status: Needs review » Needs work

The last submitted patch, 22: 2027059-22-fix-widgetbase-error-element.patch, failed testing.

swentel’s picture

  1. +++ b/core/modules/system/src/Tests/Validation/WidgetBaseErrorElementTest.php
    @@ -0,0 +1,224 @@
    + * Definition of Drupal\system\Tests\Validation\WidgetBaseErrorElementTest.
    

    Should be 'Contains \Drupal ...'

  2. +++ b/core/modules/system/src/Tests/Validation/WidgetBaseErrorElementTest.php
    @@ -0,0 +1,224 @@
    + * Tests if the validation violation property paths are properly passed on to widgets.
    

    80 chars

  3. +++ b/core/modules/system/src/Tests/Validation/WidgetBaseErrorElementTest.php
    @@ -0,0 +1,224 @@
    +    // Post 3 email addresses, set errorneous email address in second field and check form errors.
    

    80 chars

  4. +++ b/core/modules/system/src/Tests/Validation/WidgetBaseErrorElementTest.php
    @@ -0,0 +1,224 @@
    +    // Now set errorneous email address in first and third fields and check form errors.
    

    80 chars

nlisgo’s picture

Assigned: Unassigned » nlisgo

I will address feedback in #24.

nlisgo’s picture

Assigned: nlisgo » Unassigned
Status: Needs work » Needs review
FileSize
2.87 KB
24.68 KB
bojanz’s picture

 /**
  * @file
- * Definition of Drupal\system\Tests\Validation\WidgetBaseErrorElementTest.
+ * Definition of \Drupal\system\Tests\Validation\WidgetBaseErrorElementTest.
  */

"Definition of" still needs to become "Contains" :)

+ * Tests if the validation violation property paths are properly passed on to
+ * widgets.
  *
  * @group address
  */

We can go with something shorter perhaps. "Tests the validation violation property paths."
And the @group is clearly bogus.

dbolinovski was unsure about the test location and naming, would appreciate a comment there.

Status: Needs review » Needs work

The last submitted patch, 26: pass_validation-2027059-26.patch, failed testing.

nlisgo’s picture

Status: Needs work » Needs review
FileSize
892 bytes
40.78 KB

Feedback from #27 has been addressed except for the invitation to comment on the location and name of the test.

Status: Needs review » Needs work

The last submitted patch, 29: pass_validation-2027059-29.patch, failed testing.

The last submitted patch, 22: 2027059-22-fix-widgetbase-error-element.patch, failed testing.

The last submitted patch, 26: pass_validation-2027059-26.patch, failed testing.

The last submitted patch, 29: pass_validation-2027059-29.patch, failed testing.

dbolinovski’s picture

Status: Needs work » Needs review
FileSize
23.92 KB
dbolinovski’s picture

dbolinovski’s picture

FileSize
15.92 KB

Addressing Bojan’s feedback, changed variable names to snake_case, removed assertion from setUp(), plugin annotation changes.

yched’s picture

Status: Needs review » Needs work

Drupal\system\Tests\Validation is not ideal IMO, the tests in there are about our validation API, this is about field API widgets.
So I'd suggest putting it in Drupal\system\Tests\Field\Widget.

Other than that, looks good :-)

dbolinovski’s picture

Addressing #37, test moved in Drupal\system\Tests\Field\Widget.

dbolinovski’s picture

Status: Needs work » Needs review
FileSize
1.05 KB
23.91 KB

Addressing #37, test moved in Drupal\system\Tests\Field\Widget.

yched’s picture

Status: Needs review » Needs work

Wait, actually this is wrong :

+++ b/core/lib/Drupal/Core/Field/WidgetBase.php
@@ -425,7 +425,6 @@ public function flagErrors(FieldItemListInterface $items, ConstraintViolationLis
           $property_path = explode('.', $violation->getPropertyPath());
           $delta = array_shift($property_path);
           $violations_by_delta[$delta][] = $violation;
-          $violation->arrayPropertyPath = $property_path;

@@ -500,10 +498,25 @@ public function settingsSummary() {
+  protected function getLocalErrorPath(ConstraintViolationInterface $violation) {
+    return array_filter(explode('.', $violation->getPropertyPath()));
+  }

Wait, actually that is wrong :)

The code in HEAD does an array_unshift(), which removes the "delta" part of the property path, so that the widget for delta N works with actual local path (that does not start with the delta).

The new code skips that, and getLocalErrorPath() will return a path that begins with "delta".

Mulling on that a bit.

yched’s picture

Discussed with @tim.plunkett in Barcelona.

Initially this issue was opened as a task to cleanup a @todo for a not-too-nice but minor and internal hack (how WidgetBase::flagErrors() communicates violation paths that are local to each widget)

This was then risen to a major bug as it was thought to block #2509268: Inline errors repeated on child elements in module uninstall form, which had fails around that code area in WidgetBase, and that code area had a @todo pointing here.

- Fixing that @todo would however not actually fix the fails over there, which have more to do with how the specific UriWidget decides to implement its errorElement() logic (by just keeping the parent implementation), and the patch here wouldn't actually change that.

- The patch here would also be an API break at this point (WidgetInterface::errorElement() implementations couldn't rely on $violation->arrayPropertyPath as they currently do).

- Plus, the patch is currently broken, as it doesn't handle the deltas correctly :-)

So I'm very inclined to "won't fix" this at this point - thus, I'll temptatively do that. Feel free to argue otherwise :-)

yched’s picture

Status: Needs work » Closed (won't fix)

So I'm very inclined to "won't fix" this at this point - thus, I'll temptatively do that. Feel free to argue otherwise :-)

And actually doing it...

bojanz’s picture

Status: Closed (won't fix) » Needs work

I understand yched's argumentation, the widget should be responsible for mapping errors to elements because the form structure is not guaranteed to match the property path.

However, this is not obvious at all from the current code, and should be documented.

amateescu’s picture

This problem started to show up more an more with various widgets and people keep trying to "fix" it by changing the errorElement() method of each widget :/

swentel’s picture

Ok let's see if this works.

Completely new approach which isn't API breaking at all. Added the test from #2614250: Number widget validation can break AJAX actions as test only, full patch and interdiff (which is just the "fix"). Not sure how the rest of the tests will react on this.

The last submitted patch, 45: 2027059-45-test-only.patch, failed testing.

The last submitted patch, 45: 2027059-45.patch, failed testing.

swentel’s picture

Ok, looks that was a little naieve, but also kind of impossible to figure out anyway after some more local testing ..

swentel’s picture

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

xjm’s picture

Title: Pass validation violation property paths on to widgets » Widgets are missing validation violation property paths, resulting in AJAX validation errors
Category: Task » Bug report
Issue summary: View changes
Issue tags: +Needs issue summary update
Related issues: +#2509268: Inline errors repeated on child elements in module uninstall form

I tried to summarize why this is a major bug based on the two related issues. Probably could use a more complete summary update.

It makes sense for this to be major if indeed multiple widgets fail validation and cause fatals with AJAX because of it.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

DuaelFr’s picture

This issue is easily reproductible with the paragraphs module.

  1. Create a paragraph type with a simple field
  2. Add a paragraph field on your content type
  3. Add a required number field on the same content type
  4. While creating a content of this type, try to add a paragraph

Expected: paragraph type form is embedded in the content type creation form
Current: AjaX error

andypost’s picture

andypost’s picture

The last submitted patch, 55: 2027059-55.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 55: 2027059-55-test-only.patch, failed testing.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

geerlingguy’s picture

I hit this just with the core number and core image field:

  1. Add a file upload field (not required).
  2. Add a numeric field (required) without a default value.
  3. Create a node with these two fields.
  4. Upload a file.
  5. Observe that something goes wrong, ajax error in console, and fatal error in watchdog/syslog.

Luckily, in my case, the file still uploads/attaches properly, but it looks strange on the front end/admin UI.

xjm’s picture

Issue tags: +Triaged core major

The core committers and entity and field maintainers discussed this issue awhile back and agreed that it is major on account of the exceptions being triggered through the user interface. #2614250: Number widget validation can break AJAX actions is a specific case of this, also major, and currently postponed on this issue.

Thanks @geerlingguy for confirming the issue.

Dane Powell’s picture

Version: 8.4.x-dev » 8.3.x-dev
Status: Needs work » Needs review

I've confirmed that #55 resolves this as well as #2614250: Number widget validation can break AJAX actions. It seems that the failing tests are unrelated to this particular patch.

Moving back to "needs review" to re-run tests, and also bumping target version back to 8.3.x since this should not be a disruptive fix.

Dane Powell’s picture

The last submitted patch, 62: drupal-2027059-62.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 62: drupal-2027059-62-test-only.patch, failed testing.

Dane Powell’s picture

Oh yeah, the patch in #45/55/62 really is broken. It "fixes" the immediate issue but goes too far and removes legitimate validation (allowing you to e.g. create blocks with duplicate descriptions). Hence the failing tests.

jdleonard’s picture

Title: Widgets are missing validation violation property paths, resulting in AJAX validation errors » Widgets are missing validation violation property paths, resulting in AJAX validation errors & and inability to set error on a field from an entity constraint validator
Version: 8.3.x-dev » 8.4.x-dev
Issue summary: View changes
Related issues: +#2714347: No way to set error on a field from an entity constraint validator

@Dane Powell: Moving this to 8.4.x-dev per my reading of the Backport Policy. Feel free to reset if I have misinterpreted. Also, hello/JIBA!

I believe the proposed fix in this issue will resolve the issue I just ran into, first reported by someone else in #2714347: No way to set error on a field from an entity constraint validator. Updating title to reflect increased impact of this fix (maybe someone can devise a more concise title) and updating the issue summary to reflect the additional major bug this will address.

Dane Powell’s picture

Makes sense. When we finally get this merged, do I get to say that Jones Wins Again? :)

joe_carvajal’s picture

We're actually blocked into this issue too.

We reproduced the issue following the steps in #59, but the image in our case cannot be uploaded.
The casuistry to reproduce this issue is quite probable (only needs an entity with a file and a numeric field), and the issue prevents users to upload files when this happens. Shouldn't this issue be triaged as critical instead?

josephdpurcell’s picture

I am blocked on this issue as well. I can confirm that with Drupal 8.3.5 and address module 8.x-1.0 that the "AddressFormatConstraintValidator" is not properly throwing violations, even though it correctly calls core's buildViolation().

I have tested patch #62 with no success.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Pascal-’s picture

There's a really easy work around here, just make the Number (Integer) fields not-required and it instantly works again.
Not sure if other Number fields affect this.

amateescu’s picture

Title: Widgets are missing validation violation property paths, resulting in AJAX validation errors & and inability to set error on a field from an entity constraint validator » Improve the documentation of WidgetBase::errorElement() for mapping violation property paths to form elements
Category: Bug report » Task
Priority: Major » Normal
Status: Needs work » Active
Issue tags: -blocker, -Contributed project blocker, -Triaged core major
Related issues: -#2614250: Number widget validation can break AJAX actions, -#2798115: Required Number field with a Paragraph field on Content Type causes AJAX Error, -#2714347: No way to set error on a field from an entity constraint validator

I'm sorry that my comment from #44 derailed the initial purpose of this issue :/

I've opened a separate issue with a concise summary of the problem that has been discussed in the latest comments and a proposed fix: #2901943: Content entity form validation does not respect the #limit_validation_errors property from field widgets, so let's get this issue back to what it was about before my comment. That would be @bojanz's request from #43 to improve the documentation of \Drupal\Core\Field\WidgetBase::errorElement().

Note that the "inability to set error on a field from an entity constraint validator" part of the current issue title was already fixed by #2894634: Allow entity-level validations to flag errors on form elements.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

steveoliver’s picture

I've read through this and all these related issues, and while we are making progress with documentation, and this issue does address the issue of setting the correct violation path, it still seems like the underlying issue is that the "if ($error_element !== FALSE) {" check in WidgetBase:L451 ends up letting NULL values through to the '$form_state->setError()' call on the next line.

Shouldn't we make sure that all implementations of errorElement actually return a valid element or FALSE? And/or change the "if ($error_element !== FALSE) {" check to "if ($error_element) {" to prevent NULL values from coming through, e.g. when an error element path can't be determined?

I'm trying to figure out which of all these issues to use to propose a new patch.

steveoliver’s picture

Making sure $error_element is actually an array, instead of just !== FALSE.

Let's see what testbot says.

steveoliver’s picture

Status: Active » Needs review
bahuma20’s picture

#75 works for me :)

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
FileSize
132 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.