diff --git a/models/monitor.php b/models/monitor.php index 17768ddf..8b1d577e 100644 --- a/models/monitor.php +++ b/models/monitor.php @@ -34,7 +34,7 @@ public function __construct( array $options ) { // Only monitor if permalinks enabled if ( get_option( 'permalink_structure' ) !== false ) { add_action( 'pre_post_update', array( $this, 'pre_post_update' ), 10, 2 ); - add_action( 'post_updated', array( $this, 'post_updated' ), 11, 3 ); + add_action( 'wp_after_insert_post', array( $this, 'post_after_insert' ), 11, 4 ); add_action( 'redirection_remove_existing', array( $this, 'remove_existing_redirect' ) ); add_filter( 'redirection_permalink_changed', array( $this, 'has_permalink_changed' ), 10, 3 ); @@ -83,6 +83,27 @@ public function can_monitor_post( ?WP_Post $post, ?WP_Post $post_before ): bool return true; } + /** + * Called after a post and its terms have been inserted or updated. This hook + * fires after term assignment in both the classic editor and the REST/block + * editor flows, so the new permalink is always available when we compare it + * against the one captured in `pre_post_update`. + * + * @param int $post_id + * @param WP_Post|null $post + * @param bool $update + * @param WP_Post|null $post_before + * @return void + */ + public function post_after_insert( int $post_id, ?WP_Post $post, bool $update, ?WP_Post $post_before ): void { + // A slug cannot change on insertion, so skip brand-new posts. + if ( ! $update ) { + return; + } + + $this->post_updated( $post_id, $post, $post_before ); + } + /** * Called when a post has been updated - check if the slug has changed * diff --git a/tests/integration/models/test-monitor.php b/tests/integration/models/test-monitor.php index 5decd3cf..989c7572 100644 --- a/tests/integration/models/test-monitor.php +++ b/tests/integration/models/test-monitor.php @@ -228,7 +228,7 @@ public function testPostUpdatedWithNullPostExitsCleanly() { public function testNoHooks() { $monitor = new Red_Monitor( array( 'monitor_post' => 0, 'monitor_types' => array() ) ); - $this->assertFalse( has_action( 'post_updated', array( $monitor, 'post_updated' ) ) ); + $this->assertFalse( has_action( 'wp_after_insert_post', array( $monitor, 'post_after_insert' ) ) ); $this->assertFalse( has_action( 'edit_form_advanced', array( $monitor, 'insert_old_post' ) ) ); $this->assertFalse( has_action( 'edit_page_form', array( $monitor, 'insert_old_post' ) ) ); } @@ -236,7 +236,7 @@ public function testNoHooks() { public function testHasHooks() { $monitor = new Red_Monitor( $this->getActiveOptions() ); - $this->assertEquals( 11, has_action( 'post_updated', array( $monitor, 'post_updated' ) ) ); + $this->assertEquals( 11, has_action( 'wp_after_insert_post', array( $monitor, 'post_after_insert' ) ) ); $this->assertEquals( 10, has_action( 'pre_post_update', array( $monitor, 'pre_post_update' ) ) ); }