Commit 5c91d3ac59 for wordpress.org
commit 5c91d3ac5934540a3d437873d987776b413141f0
Author: jorbin <jorbin@git.wordpress.org>
Date: Tue Nov 3 20:35:58 2026 +0000
Rewrites: Avoid fatal errors when flushing rules for random content.
`wp_random_content_flush_rewrite_rules_for_post()` runs on the `wp_after_insert_post` and `after_delete_post` actions, which third-party code may fire with a missing or incorrectly typed `$post`. Also make the `$post` parameter of `_update_posts_count_on_delete()` optional for the same single-argument `after_delete_post` calls.
Developed in: https://github.com/WordPress/wordpress-develop/pull/14356
Follow-up to r64402.
Props jorbin, bradshawtm, therssoftware.
Fixes #64498.
Built from https://develop.svn.wordpress.org/trunk@65250
git-svn-id: http://core.svn.wordpress.org/trunk@64399 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/ms-blogs.php b/wp-includes/ms-blogs.php
index adb20da267..d791dd2f45 100644
--- a/wp-includes/ms-blogs.php
+++ b/wp-includes/ms-blogs.php
@@ -889,12 +889,13 @@ function _update_blog_date_on_post_delete( $post_id ) {
*
* @since 4.0.0
* @since 6.2.0 Added the `$post` parameter.
+ * @since 7.2.0 The `$post` parameter isn't always guaranteed to be provided.
*
- * @param int $post_id Post ID.
- * @param WP_Post $post Post object.
+ * @param int $post_id Post ID.
+ * @param WP_Post|null $post Optional. Post object. Default null.
*/
-function _update_posts_count_on_delete( $post_id, $post ) {
- if ( ! $post || 'publish' !== $post->post_status || 'post' !== $post->post_type ) {
+function _update_posts_count_on_delete( $post_id, $post = null ) {
+ if ( ! $post instanceof WP_Post || 'publish' !== $post->post_status || 'post' !== $post->post_type ) {
return;
}
diff --git a/wp-includes/query.php b/wp-includes/query.php
index 4cafca3d7c..40a9a285c9 100644
--- a/wp-includes/query.php
+++ b/wp-includes/query.php
@@ -1513,6 +1513,12 @@ function wp_random_content_redirect(): void {
* unpublished, renamed, moved or deleted.
*
* Runs on the {@see 'wp_after_insert_post'} and {@see 'after_delete_post'} actions.
+ * Third-party code may fire these actions with unexpected values, so the parameters are
+ * not type declared. When `$post` is omitted it is looked up from `$post_id`. Passing
+ * anything other than a `WP_Post` as `$post`, or a post that cannot be looked up, is
+ * incorrect usage and nothing is flushed. `$post_before` is only considered on
+ * `wp_after_insert_post`, where passing anything other than a `WP_Post` or null is
+ * incorrect usage and the value is ignored.
*
* @since 7.2.0
*
@@ -1520,21 +1526,59 @@ function wp_random_content_redirect(): void {
* @global WP_Rewrite $wp_rewrite WordPress rewrite component.
*
* @param int $post_id Post ID.
- * @param WP_Post $post Post object.
+ * @param WP_Post|null $post Optional. Post object. Looked up from `$post_id` when null. Default null.
* @param bool $update Optional. Whether this is an existing post being updated. Default false.
* @param WP_Post|null $post_before Optional. Post object before the update, null for new posts. Default null.
*/
-function wp_random_content_flush_rewrite_rules_for_post( int $post_id, WP_Post $post, bool $update = false, ?WP_Post $post_before = null ): void {
+function wp_random_content_flush_rewrite_rules_for_post( $post_id, $post = null, $update = false, $post_before = null ): void {
global $wp_rewrite;
+ // Only look up a real ID: get_post() falls back to the global post for an empty value.
+ if ( null === $post && (int) $post_id > 0 ) {
+ $post = get_post( (int) $post_id );
+ }
+
+ if ( ! $post instanceof WP_Post ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: 1: $post, 2: WP_Post */
+ __( 'The %1$s argument must be a %2$s object.' ),
+ '<code>$post</code>',
+ '<code>WP_Post</code>'
+ ),
+ '7.2.0'
+ );
+ return;
+ }
+
+ $posts = array( $post );
+
+ // Only wp_after_insert_post passes the previous post object, which matters when it was renamed or moved.
+ if ( 'wp_after_insert_post' === current_action() ) {
+ if ( $post_before instanceof WP_Post ) {
+ $posts[] = $post_before;
+ } elseif ( null !== $post_before ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: 1: $post_before, 2: WP_Post */
+ __( 'The %1$s argument must be a %2$s object or null.' ),
+ '<code>$post_before</code>',
+ '<code>WP_Post</code>'
+ ),
+ '7.2.0'
+ );
+ }
+ }
+
if ( ! $wp_rewrite->using_permalinks() || ! wp_is_random_content_redirect_enabled() ) {
return;
}
- foreach ( array( $post, $post_before ) as $page ) {
+ foreach ( $posts as $page ) {
if (
- $page instanceof WP_Post
- && $wp_rewrite->get_random_base() === $page->post_name
+ $wp_rewrite->get_random_base() === $page->post_name
&& (
( 'page' === $page->post_type && 0 === (int) $page->post_parent )
|| ( 'post' === $page->post_type && $wp_rewrite->post_permalinks_share_random_base() )
diff --git a/wp-includes/version.php b/wp-includes/version.php
index ff06770a58..3c3d36e029 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-beta4-65249';
+$wp_version = '7.2-beta4-65250';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.