Make WordPress Core

Changeset 60906


Ignore:
Timestamp:
10/06/2025 08:11:21 PM (5 weeks ago)
Author:
westonruter
Message:

Posts, Post Types: Short-circuit wp_post_delete() when $post_id arg is not above zero after casting to int.

The casting to int ensures that the action callbacks for post deletion can safely use the int type hint for the $post_id argument, as otherwise a fatal error occurs when an integer string is passed. This function also originally had casting of the argument to an integer, going back to at least WP 1.5.0, since it was passed directly into an SQL query. The casting was removed in [6180] with the introduction of prepared SQL statements.

The wp_delete_post() function had $post_id = 0 defined as its argument, also going back at least to WP 1.5.0, perhaps as a way to indicate the type of the argument as being an integer before there was PHPDoc. Unlike with functions like get_post() which have $post = null as the default argument to fall back to getting the global post, no such fallback logic was added to wp_delete_post(), meaning that passing no argument would always result in a DB query to locate the post with an ID of 0, which will never happen. So this introduces a _doing_it_wrong() in case 0 is passed, and yet the default value of 0 is not removed from the function signature to not introduce a fatal error in case any existing code is not supplying the $post_id parameter (however unlikely this may be).

Unit tests have been fleshed out for wp_delete_post() to add coverage for what was previously missing.

Props SirLouen, kkmuffme, fakhriaz, sajjad67, siliconforks, peterwilsoncc, westonruter.
Fixes #63975.

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/post.php

    r60792 r60906  
    37443744 * @see wp_trash_post()
    37453745 *
    3746  * @param int  $post_id      Optional. Post ID. Default 0.
     3746 * @param int  $post_id      Post ID. (The default of 0 is for historical reasons; providing it is incorrect.)
    37473747 * @param bool $force_delete Optional. Whether to bypass Trash and force deletion.
    37483748 *                           Default false.
     
    37513751function wp_delete_post( $post_id = 0, $force_delete = false ) {
    37523752    global $wpdb;
     3753
     3754    $post_id = (int) $post_id;
     3755    if ( $post_id <= 0 ) {
     3756        _doing_it_wrong( __FUNCTION__, __( 'The post ID must be greater than 0.' ), '6.9.0' );
     3757        return false;
     3758    }
    37533759
    37543760    $post = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID = %d", $post_id ) );
     
    37763782     * @since 4.4.0
    37773783     *
    3778      * @param WP_Post|false|null $delete       Whether to go forward with deletion.
     3784     * @param WP_Post|false|null $check        Whether to go forward with deletion. Anything other than null will short-circuit deletion.
    37793785     * @param WP_Post            $post         Post object.
    37803786     * @param bool               $force_delete Whether to bypass the Trash.
  • trunk/tests/phpunit/tests/post.php

    r60792 r60906  
    503503    }
    504504
    505     public function test_wp_delete_post_reassign_hierarchical_post_type() {
    506         $grandparent_page_id = self::factory()->post->create( array( 'post_type' => 'page' ) );
    507         $parent_page_id      = self::factory()->post->create(
    508             array(
    509                 'post_type'   => 'page',
    510                 'post_parent' => $grandparent_page_id,
    511             )
    512         );
    513         $page_id             = self::factory()->post->create(
    514             array(
    515                 'post_type'   => 'page',
    516                 'post_parent' => $parent_page_id,
    517             )
    518         );
    519 
    520         $this->assertSame( $parent_page_id, get_post( $page_id )->post_parent );
    521 
    522         wp_delete_post( $parent_page_id, true );
    523         $this->assertSame( $grandparent_page_id, get_post( $page_id )->post_parent );
    524 
    525         wp_delete_post( $grandparent_page_id, true );
    526         $this->assertSame( 0, get_post( $page_id )->post_parent );
    527     }
    528 
    529505    /**
    530506     * Test ensuring that the post_slug can be filtered with a custom value short circuiting the built in
  • trunk/tests/phpunit/tests/post/wpInsertPost.php

    r57680 r60906  
    567567
    568568    /**
    569      * "When I delete a future post using wp_delete_post( $post->ID ) it does not update the cron correctly."
    570      *
    571      * @ticket 5364
    572      * @covers ::wp_delete_post
    573      */
    574     public function test_delete_future_post_cron() {
    575         $future_date = strtotime( '+1 day' );
    576 
    577         $data = array(
    578             'post_status'  => 'publish',
    579             'post_content' => 'content',
    580             'post_title'   => 'title',
    581             'post_date'    => date_format( date_create( "@{$future_date}" ), 'Y-m-d H:i:s' ),
    582         );
    583 
    584         // Insert a post and make sure the ID is OK.
    585         $post_id = wp_insert_post( $data );
    586 
    587         // Check that there's a publish_future_post job scheduled at the right time.
    588         $this->assertSame( $future_date, $this->next_schedule_for_post( 'publish_future_post', $post_id ) );
    589 
    590         // Now delete the post and make sure the cron entry is removed.
    591         wp_delete_post( $post_id );
    592 
    593         $this->assertFalse( $this->next_schedule_for_post( 'publish_future_post', $post_id ) );
    594     }
    595 
    596     /**
    597569     * Bug: permalink doesn't work if post title is empty.
    598570     *
Note: See TracChangeset for help on using the changeset viewer.