Skip to content

Change hook from post_update to wp_after_insert_post#4205

Open
obstschale wants to merge 1 commit into
johngodley:trunkfrom
obstschale:trunk
Open

Change hook from post_update to wp_after_insert_post#4205
obstschale wants to merge 1 commit into
johngodley:trunkfrom
obstschale:trunk

Conversation

@obstschale
Copy link
Copy Markdown

Detect permalink changes caused by taxonomy term updates in the block editor

Summary

When the "URL Monitor" feature is enabled for a post type whose permalink
structure includes a taxonomy placeholder (e.g. /%category%/%postname%/),
changing the assigned term in the block editor (Gutenberg) currently does
not create a redirect, even though the post's URL has effectively changed.

The same change made in the classic editor works correctly. The root cause is
the order in which WordPress fires its post and taxonomy hooks in the two save
flows.

Background

Red_Monitor in models/monitor.php records the old permalink in
pre_post_update, then compares it to get_permalink() in post_updated and
creates a 301 redirect when they differ.

In wp_insert_post() (classic editor) the relevant calls run in this order:

  1. pre_post_update action
  2. tax_input terms are written (line 4998 of wp-includes/post.php)
  3. post_updated action (line 5163)
  4. wp_after_insert_post action (line 5208)

In WP_REST_Posts_Controller::update_item() (block editor / REST) the order is
different:

  1. wp_update_post() is called, which internally fires post_updated
  2. handle_terms() writes the new terms (line 1015 of
    class-wp-rest-posts-controller.php)
  3. wp_after_insert_post action (line 1047)

In the REST flow post_updated therefore fires before the new terms are
written, so get_permalink() still returns the URL with the old term and
Red_Monitor::check_for_modified_slug() sees no difference.

Change

Switch the monitor from the post_updated action to wp_after_insert_post,
which is the only hook that fires after term assignment in both the classic
and REST flows.

The existing comparison logic in check_for_modified_slug(),
pre_post_update(), and can_monitor_post() is unchanged. A small adapter
method post_after_insert() translates the four-argument wp_after_insert_post
signature to the existing post_updated() method and skips brand-new inserts
($update === false), since a slug cannot change on insertion.

Files touched

  • models/monitor.php
    • Replace add_action( 'post_updated', ... ) with
      add_action( 'wp_after_insert_post', array( $this, 'post_after_insert' ), 11, 4 ).
    • Add post_after_insert( int $post_id, ?WP_Post $post, bool $update, ?WP_Post $post_before )
      which delegates to the existing post_updated() when $update is true.
  • tests/integration/models/test-monitor.php
    • Update the two has_action() assertions in testNoHooks and testHasHooks
      from post_updated / post_updated to
      wp_after_insert_post / post_after_insert. Tests that call
      $monitor->post_updated(...) directly are unaffected because the method
      signature is unchanged.

What this fixes

  • Saving a monitored post in the block editor while changing a taxonomy term
    that is part of the permalink structure now produces a redirect from the old
    URL to the new URL, matching the behaviour of the classic editor.

What this does not fix (out of scope)

  • Renaming a term (e.g. renaming a category) or re-parenting a term in a
    hierarchical taxonomy. These actions change the URLs of every post in that
    term but do not save the posts themselves, so neither post_updated nor
    wp_after_insert_post fires. Handling those cases would require additional
    hooks on edited_term / edited_term_taxonomy plus a UI option for selecting
    which taxonomies to monitor, and is intentionally left for a follow-up.

Compatibility

wp_after_insert_post was introduced in WordPress 5.6 (December 2020), which
is well below the plugin's supported minimum.

Testing

  • php -l on both changed files: no syntax errors.
  • Existing integration tests in tests/integration/models/test-monitor.php
    continue to exercise the same code path via the unchanged post_updated()
    method; the updated has_action() assertions verify the new hook
    registration.

Suggested manual verification

  1. Set the permalink structure to /%category%/%postname%/.
  2. Enable URL monitoring for "Posts" in Redirection → Settings.
  3. In the block editor, edit a published post and change its category.
  4. Confirm that a 301 redirect from the old URL to the new URL is created in
    the configured monitor group.
  5. Repeat step 3 in the classic editor to confirm no regression.

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.

1 participant