Make WordPress Core

Changeset 40676 for trunk


Ignore:
Timestamp:
05/16/2017 05:36:25 AM (9 years ago)
Author:
westonruter
Message:

Customize: Keep alive auto-drafts created for page/post stubs when parent changeset is updated, and delete when changeset is garbage-collected.

Props utkarshpatel, westonruter.
See #31089.
Fixes #39715.

Location:
trunk
Files:
5 edited

Legend:

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

    r40631 r40676  
    326326add_action( 'delete_term',                '_wp_delete_tax_menu_item',   10, 3 );
    327327add_action( 'transition_post_status',     '_wp_auto_add_pages_to_menu', 10, 3 );
     328add_action( 'delete_post',                '_wp_delete_customize_changeset_dependent_auto_drafts' );
    328329
    329330// Post Thumbnail CSS class filtering
    … …  
    401402add_action( 'admin_enqueue_scripts', '_wp_customize_loader_settings' );
    402403add_action( 'delete_attachment', '_delete_attachment_theme_mod' );
     404add_action( 'transition_post_status', '_wp_keep_alive_customize_changeset_dependent_auto_drafts', 20, 3 );
    403405
    404406// Calendar widget cache
  • trunk/src/wp-includes/nav-menu.php

    r39638 r40676  
    979979        }
    980980}
     981
     982/**
     983 * Delete auto-draft posts associated with the supplied changeset.
     984 *
     985 * @since 4.8.0
     986 * @access private
     987 *
     988 * @param int $post_id Post ID for the customize_changeset.
     989 */
     990function _wp_delete_customize_changeset_dependent_auto_drafts( $post_id ) {
     991        $post = get_post( $post_id );
     992
     993        if ( ! $post || 'customize_changeset' !== $post->post_type ) {
     994                return;
     995        }
     996
     997        $data = json_decode( $post->post_content, true );
     998        if ( empty( $data['nav_menus_created_posts']['value'] ) ) {
     999                return;
     1000        }
     1001        remove_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' );
     1002        foreach ( $data['nav_menus_created_posts']['value'] as $post_id ) {
     1003                if ( ! empty( $post_id ) && 'auto-draft' === get_post_status( $post_id ) ) {
     1004                        wp_delete_post( $post_id, true );
     1005                }
     1006        }
     1007        add_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' );
     1008}
  • trunk/src/wp-includes/theme.php

    r40300 r40676  
    30603060        return ( $wp_customize instanceof WP_Customize_Manager ) && $wp_customize->is_preview();
    30613061}
     3062
     3063/**
     3064 * Make sure that auto-draft posts get their post_date bumped to prevent premature garbage-collection.
     3065 *
     3066 * When a changeset is updated but remains an auto-draft, ensure the post_date
     3067 * for the auto-draft posts remains the same so that it will be
     3068 * garbage-collected at the same time by `wp_delete_auto_drafts()`. Otherwise,
     3069 * if the changeset is updated to be a draft then update the posts
     3070 * to have a far-future post_date so that they will never be garbage collected
     3071 * unless the changeset post itself is deleted.
     3072 *
     3073 * @since 4.8.0
     3074 * @access private
     3075 * @see wp_delete_auto_drafts()
     3076 *
     3077 * @param string   $new_status Transition to this post status.
     3078 * @param string   $old_status Previous post status.
     3079 * @param \WP_Post $post       Post data.
     3080 * @global wpdb $wpdb
     3081 */
     3082function _wp_keep_alive_customize_changeset_dependent_auto_drafts( $new_status, $old_status, $post ) {
     3083        global $wpdb;
     3084        unset( $old_status );
     3085
     3086        // Short-circuit if not a changeset or if the changeset was published.
     3087        if ( 'customize_changeset' !== $post->post_type || 'publish' === $new_status ) {
     3088                return;
     3089        }
     3090
     3091        if ( 'auto-draft' === $new_status ) {
     3092                /*
     3093                 * Keep the post date for the post matching the changeset
     3094                 * so that it will not be garbage-collected before the changeset.
     3095                 */
     3096                $new_post_date = $post->post_date;
     3097        } else {
     3098                /*
     3099                 * Since the changeset no longer has an auto-draft (and it is not published)
     3100                 * it is now a persistent changeset, a long-lived draft, and so any
     3101                 * associated auto-draft posts should have their dates
     3102                 * pushed out very far into the future to prevent them from ever
     3103                 * being garbage-collected.
     3104                 */
     3105                $new_post_date = gmdate( 'Y-m-d H:i:d', strtotime( '+100 years' ) );
     3106        }
     3107
     3108        $data = json_decode( $post->post_content, true );
     3109        if ( empty( $data['nav_menus_created_posts']['value'] ) ) {
     3110                return;
     3111        }
     3112        foreach ( $data['nav_menus_created_posts']['value'] as $post_id ) {
     3113                if ( empty( $post_id ) || 'auto-draft' !== get_post_status( $post_id ) ) {
     3114                        continue;
     3115                }
     3116                $wpdb->update(
     3117                        $wpdb->posts,
     3118                        array( 'post_date' => $new_post_date ), // Note wp_delete_auto_drafts() only looks at this this date.
     3119                        array( 'ID' => $post_id )
     3120                );
     3121                clean_post_cache( $post_id );
     3122        }
     3123}
  • trunk/tests/phpunit/tests/post/nav-menu.php

    r38945 r40676  
    524524                $this->assertNotContains( 'menu-item-home', $classes );
    525525        }
     526
     527        /**
     528         * Test _wp_delete_customize_changeset_dependent_auto_drafts.
     529         *
     530         * @covers _wp_delete_customize_changeset_dependent_auto_drafts()
     531         */
     532        function test_wp_delete_customize_changeset_dependent_auto_drafts() {
     533                $nav_created_post_ids = $this->factory()->post->create_many(2, array(
     534                        'post_status' => 'auto-draft',
     535                ) );
     536                $data = array(
     537                        'nav_menus_created_posts' => array(
     538                                'value' => $nav_created_post_ids,
     539                        ),
     540                );
     541                wp_set_current_user( self::factory()->user->create( array(
     542                        'role' => 'administrator',
     543                ) ) );
     544                require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
     545                $wp_customize = new WP_Customize_Manager();
     546                do_action( 'customize_register', $wp_customize );
     547                $wp_customize->save_changeset_post( array(
     548                        'data' => $data,
     549                ) );
     550                $this->assertInstanceOf( 'WP_Post', get_post( $nav_created_post_ids[0] ) );
     551                $this->assertInstanceOf( 'WP_Post', get_post( $nav_created_post_ids[1] ) );
     552                wp_delete_post( $wp_customize->changeset_post_id(), true );
     553                $this->assertNotInstanceOf( 'WP_Post', get_post( $nav_created_post_ids[0] ) );
     554                $this->assertNotInstanceOf( 'WP_Post', get_post( $nav_created_post_ids[1] ) );
     555        }
    526556}
  • trunk/tests/phpunit/tests/theme.php

    r40524 r40676  
    310310                $this->assertEquals($style, get_stylesheet());
    311311        }
     312
     313        /**
     314         * Test _wp_keep_alive_customize_changeset_dependent_auto_drafts.
     315         *
     316         * @covers _wp_keep_alive_customize_changeset_dependent_auto_drafts()
     317         */
     318        function test_wp_keep_alive_customize_changeset_dependent_auto_drafts() {
     319                $nav_created_post_ids = $this->factory()->post->create_many(2, array(
     320                        'post_status' => 'auto-draft',
     321                ) );
     322                $data = array(
     323                        'nav_menus_created_posts' => array(
     324                                'value' => $nav_created_post_ids,
     325                        ),
     326                );
     327                wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
     328                require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
     329                $wp_customize = new WP_Customize_Manager();
     330                do_action( 'customize_register', $wp_customize );
     331                $wp_customize->save_changeset_post( array(
     332                        'data' => $data,
     333                ) );
     334                $this->assertEquals( get_post( $nav_created_post_ids[0] )->post_date, get_post( $wp_customize->changeset_post_id() )->post_date );
     335                $this->assertEquals( get_post( $nav_created_post_ids[1] )->post_date, get_post( $wp_customize->changeset_post_id() )->post_date );
     336                $wp_customize->save_changeset_post( array(
     337                        'status' => 'draft',
     338                        'data' => $data,
     339                ) );
     340                $expected_year = date( 'Y' ) + 100;
     341                $this->assertEquals( $expected_year, date( 'Y', strtotime( get_post( $nav_created_post_ids[0] )->post_date ) ) );
     342                $this->assertEquals( $expected_year, date( 'Y', strtotime( get_post( $nav_created_post_ids[1] )->post_date ) ) );
     343        }
    312344}
Note: See TracChangeset for help on using the changeset viewer.