Commit f7f55f9b30 for wordpress.org

commit f7f55f9b308531a5702cc3f540c26807369247a5
Author: jorbin <jorbin@git.wordpress.org>
Date:   Tue Oct 6 14:51:12 2026 +0000

    Posts, Post Types: Fire dynamic status transition hooks only for registered statuses and post types.

    Props xknown, jorbin, westonruter, lancewillett.

    Built from https://develop.svn.wordpress.org/trunk@64131


    git-svn-id: http://core.svn.wordpress.org/trunk@63287 1a063a9b-81f0-0310-95a4-ce76da25c4cd

diff --git a/wp-includes/post.php b/wp-includes/post.php
index a651afd41b..10bb778bbd 100644
--- a/wp-includes/post.php
+++ b/wp-includes/post.php
@@ -6003,63 +6003,71 @@ function wp_transition_post_status( $new_status, $old_status, $post ) {
 	 */
 	do_action( 'transition_post_status', $new_status, $old_status, $post );

-	/**
-	 * Fires when a post is transitioned from one status to another.
-	 *
-	 * The dynamic portions of the hook name, `$new_status` and `$old_status`,
-	 * refer to the old and new post statuses, respectively.
-	 *
-	 * Possible hook names include:
-	 *
-	 *  - `draft_to_publish`
-	 *  - `publish_to_trash`
-	 *  - `pending_to_draft`
-	 *
-	 * @since 2.3.0
-	 *
-	 * @param WP_Post $post Post object.
-	 */
-	do_action( "{$old_status}_to_{$new_status}", $post );
+	$new_status_object = get_post_status_object( $new_status );
+	$old_status_valid  = get_post_status_object( $old_status ) || 'new' === $old_status;
+	$post_type_object  = get_post_type_object( $post->post_type );

-	/**
-	 * Fires when a post is transitioned from one status to another.
-	 *
-	 * The dynamic portions of the hook name, `$new_status` and `$post->post_type`,
-	 * refer to the new post status and post type, respectively.
-	 *
-	 * Possible hook names include:
-	 *
-	 *  - `draft_post`
-	 *  - `future_post`
-	 *  - `pending_post`
-	 *  - `private_post`
-	 *  - `publish_post`
-	 *  - `trash_post`
-	 *  - `draft_page`
-	 *  - `future_page`
-	 *  - `pending_page`
-	 *  - `private_page`
-	 *  - `publish_page`
-	 *  - `trash_page`
-	 *  - `publish_attachment`
-	 *  - `trash_attachment`
-	 *
-	 * Please note: When this action is hooked using a particular post status (like
-	 * 'publish', as `publish_{$post->post_type}`), it will fire both when a post is
-	 * first transitioned to that status from something else, as well as upon
-	 * subsequent post updates (old and new status are both the same).
-	 *
-	 * Therefore, if you are looking to only fire a callback when a post is first
-	 * transitioned to a status, use the {@see 'transition_post_status'} hook instead.
-	 *
-	 * @since 2.3.0
-	 * @since 5.9.0 Added `$old_status` parameter.
-	 *
-	 * @param int     $post_id    Post ID.
-	 * @param WP_Post $post       Post object.
-	 * @param string  $old_status Old post status.
-	 */
-	do_action( "{$new_status}_{$post->post_type}", $post->ID, $post, $old_status );
+	if ( $new_status_object && $old_status_valid ) {
+		/**
+		 * Fires when a post is transitioned from one status to another.
+		 *
+		 * The dynamic portions of the hook name, `$new_status` and `$old_status`,
+		 * refer to the old and new post statuses, respectively.
+		 *
+		 * Possible hook names include:
+		 *
+		 *  - `draft_to_publish`
+		 *  - `publish_to_trash`
+		 *  - `pending_to_draft`
+		 *
+		 * @since 2.3.0
+		 *
+		 * @param WP_Post $post Post object.
+		 */
+		do_action( "{$old_status}_to_{$new_status}", $post );
+	}
+
+	if ( $new_status_object && $post_type_object ) {
+		/**
+		 * Fires when a post is transitioned from one status to another.
+		 *
+		 * The dynamic portions of the hook name, `$new_status` and `$post->post_type`,
+		 * refer to the new post status and post type, respectively.
+		 *
+		 * Possible hook names include:
+		 *
+		 *  - `draft_post`
+		 *  - `future_post`
+		 *  - `pending_post`
+		 *  - `private_post`
+		 *  - `publish_post`
+		 *  - `trash_post`
+		 *  - `draft_page`
+		 *  - `future_page`
+		 *  - `pending_page`
+		 *  - `private_page`
+		 *  - `publish_page`
+		 *  - `trash_page`
+		 *  - `publish_attachment`
+		 *  - `trash_attachment`
+		 *
+		 * Please note: When this action is hooked using a particular post status (like
+		 * 'publish', as `publish_{$post->post_type}`), it will fire both when a post is
+		 * first transitioned to that status from something else, as well as upon
+		 * subsequent post updates (old and new status are both the same).
+		 *
+		 * Therefore, if you are looking to only fire a callback when a post is first
+		 * transitioned to a status, use the {@see 'transition_post_status'} hook instead.
+		 *
+		 * @since 2.3.0
+		 * @since 5.9.0 Added `$old_status` parameter.
+		 *
+		 * @param int     $post_id    Post ID.
+		 * @param WP_Post $post       Post object.
+		 * @param string  $old_status Old post status.
+		 */
+		do_action( "{$new_status}_{$post->post_type}", $post->ID, $post, $old_status );
+	}
 }

 /**
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 58bea66223..d675119f78 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '7.2-alpha-64130';
+$wp_version = '7.2-alpha-64131';

 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.