Skip to content

Conversation

@LAPSrj
Copy link

@LAPSrj LAPSrj commented Nov 26, 2025

This is my proposed fix for ticket 64314, where a fatal error happens when trying to save a post if you have enabled revision for a post meta that is an array.

In this proposed fix I'm using serialize to make any type of variable a string. I've chosen that because:

  • The smallest number of changes to the code
  • The same line of code will work for any type of variable
  • Is the way how WP saves arrays in the database, so seamed like a good choice.

Trac ticket: 64314


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

Drafted Commit Message

Revisions: Prevent fatal error in PHP 8+ when saving a post revision with revisioned non-scalar post meta.

Developed in https://github.com/WordPress/wordpress-develop/pull/10560

Follow-up to [56714].

Props LAPSrj, manhphucofficial, westonruter.
See #20299.
Fixes #64314.

@github-actions
Copy link

Hi @LAPSrj! 👋

Thank you for your contribution to WordPress! 💖

It looks like this is your first pull request to wordpress-develop. Here are a few things to be aware of that may help you out!

No one monitors this repository for new pull requests. Pull requests must be attached to a Trac ticket to be considered for inclusion in WordPress Core. To attach a pull request to a Trac ticket, please include the ticket's full URL in your pull request description.

Pull requests are never merged on GitHub. The WordPress codebase continues to be managed through the SVN repository that this GitHub repository mirrors. Please feel free to open pull requests to work on any contribution you are making.

More information about how GitHub pull requests can be used to contribute to WordPress can be found in the Core Handbook.

Please include automated tests. Including tests in your pull request is one way to help your patch be considered faster. To learn about WordPress' test suites, visit the Automated Testing page in the handbook.

If you have not had a chance, please review the Contribute with Code page in the WordPress Core Handbook.

The Developer Hub also documents the various coding standards that are followed:

Thank you,
The WordPress Project

@github-actions
Copy link

github-actions bot commented Nov 26, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props lapsrj, westonruter.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions
Copy link

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

LAPSrj and others added 3 commits November 30, 2025 22:00
Co-authored-by: Weston Ruter <[email protected]>
* trunk: (44 commits)
  I18N: Use `wp_get_list_item_separator()` as list separator for the states of sites, posts, and media.
  Tests: Use `assertSame()` in some newly introduced tests.
  Export: Update `export_wp()` to handle `get_comment()` returning `null` due to filter.
  I18N: Add missing translation functions for REST API app login.
  Tests: Use `assertSame()` in some newly introduced tests.
  Networks and Sites: Ensure the Site Address field renders in correct order when RTL locale is active.
  Tests: Use `assertSame()` in some newly introduced tests.
  Add: Unit test to validate core abilities schemas only include valid properties.
  Docs: Improve specificity of types in `WP_Script_Modules` and `script-modules.php` functions.
  I18N: add border.radiusSizes key to theme-i18n.json
  Posts, Post Types: Only set default title for custom post types if they have title support.
  Site Health: Include value of `EMPTY_TRASH_DAYS` constant in debug data.
  Docs: Improve accuracy for types in phpdoc for `WP_Dependencies`, `_WP_Dependency`, `WP_Scripts`, and `WP_Styles`.
  Script Loader: Re-target release for missing dependency notices from 7.0.0 to 6.9.1.
  Docs: Add missing parameter descriptions in `wp-admin/install.php`.
  Site Health: Add common HTTP response headers for page cache detection.
  Docs: Update `@since x.y.z` with actual version number.
  Plugins: Restore line break between the filter links row and the plugin cards in the Featured view.
  Mail: Add missing `embeds` key for the `wp_mail_succeeded` action's `$mail_data` param.
  Upgrade/Install: Add missing file to the `$_old_files` array.
  ...
@westonruter
Copy link
Member

Gemini's review of all the changes, including the new test:

Here's my review of the changes:

Changes in src/wp-includes/revision.php:

The core change is the introduction of maybe_serialize() before normalize_whitespace():

--- a/src/wp-includes/revision.php
+++ b/src/wp-includes/revision.php
@@ -187,7 +187,7 @@ function wp_save_post_revision( $post_id ) {
                        $post_has_changed = false;
 
                        foreach ( array_keys( _wp_post_revision_fields( $post ) ) as $field ) {
-                               if ( normalize_whitespace( $post->$field ) !== normalize_whitespace( $latest_revision->$field ) ) {
+                               if ( normalize_whitespace( maybe_serialize( $post->$field ) ) !== normalize_whitespace( maybe_serialize( $latest_revision->$field ) ) ) {
                                        $post_has_changed = true;
                                        break;
                                }
  • Reasoning: This is an excellent change to address a potential TypeError in PHP 8.0+ when normalize_whitespace() (which internally uses preg_replace()) receives a non-string value (like an array or object). By using maybe_serialize(), any non-scalar values will be converted to a string representation before whitespace normalization, preventing a crash and allowing for consistent comparison.
  • Coding Standards: The change adheres to WordPress coding standards regarding formatting and function usage. maybe_serialize() is an idiomatic WordPress function for handling data that might need serialization for storage or comparison.
  • PHP 7.2 Compatibility: This change is fully compatible with PHP 7.2 and proactively prevents issues that arise in PHP 8.0+.

Changes in tests/phpunit/tests/post/revisions.php:

A new test method test_wp_save_post_revision_with_array_post_meta() has been added.

  • @ticket and @covers Tags: Correctly uses @ticket 64314 and @covers ::wp_save_post_revision.
  • Comprehensive Setup: The test cleverly sets up the scenario by:
    • Explicitly setting wp_save_post_revision_check_for_changes to true to ensure change detection is active.
    • Using the wp_post_revision_meta_keys filter to ensure that the custom favorite_things meta key is saved with each revision. This is crucial for the latest_revision to have the correct data for comparison.
    • Using the _wp_post_revision_fields filter to inform wp_save_post_revision that favorite_things should be considered a revisionable field, allowing WP_Post::__get to retrieve the meta value.
  • Clear Assertions:
    • The test sets an initial array value, saves a revision, and asserts that the revision was created and that the array was correctly saved to the revision's meta.
    • It then updates the array value, saves a second revision, and asserts that this second revision was successfully created (proving that the change was detected) and that the updated array was saved to its meta.
  • Relevance to Fix: This test directly validates the fix by introducing an array into a revisioned field and confirming that wp_save_post_revision works as expected without errors and with proper change detection.
  • Nitpicks: The use of anonymous functions for filters is acceptable in unit tests, as WP_UnitTestCase typically cleans up filters between tests. No explicit remove_filter or remove_all_filters is strictly necessary at the end of the test method in this context for robustness.

Conclusion:

Both the code change in src/wp-includes/revision.php and the accompanying unit test in tests/phpunit/tests/post/revisions.php are well-executed. The change is a robust fix for a compatibility issue, and the test provides excellent coverage for the scenario, demonstrating adherence to best practices for extending WordPress revision functionality with custom array-based meta.

The overall quality of the proposed changes is high.

pento pushed a commit that referenced this pull request Dec 12, 2025
…with revisioned non-scalar post meta.

Developed in #10560

Follow-up to [56714].

Props LAPSrj, manhphucofficial, westonruter.
See #20299.
Fixes #64314.


git-svn-id: https://develop.svn.wordpress.org/trunk@61372 602fd350-edb4-49c9-b593-d223f7449a82
markjaquith pushed a commit to markjaquith/WordPress that referenced this pull request Dec 12, 2025
github-actions bot pushed a commit to gilzow/wordpress-performance that referenced this pull request Dec 12, 2025
@westonruter
Copy link
Member

Committed in r61372 (48b2b65)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants