Make WordPress Core

Changeset 39410 for branches/4.7


Ignore:
Timestamp:
12/02/2016 12:06:59 AM (10 years ago)
Author:
westonruter
Message:

Customize: Reject a changeset update when a non-future date is provided and also ensure that a published changeset always gets set to the current date/time.

  • Also moves checks from customize_save Ajax handler to the underlying WP_Customize_Manager::save_changeset_post() call which plugins may invoke directly.
  • Ensures that customize_save_response filter is always passed an array, with error code available as code.

Props utkarshpatel, westonruter, sayedwp.
Merges [39409] into 4.7 branch.
See #30937.
Fixes #38943 for 4.7.

Location:
branches/4.7
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/4.7

  • branches/4.7/src/wp-includes/class-wp-customize-manager.php

    r39346 r39410  
    19621962
    19631963                $changeset_post_id = $this->changeset_post_id();
    1964                 if ( $changeset_post_id && in_array( get_post_status( $changeset_post_id ), array( 'publish', 'trash' ) ) ) {
    1965                         wp_send_json_error( 'changeset_already_published' );
    1966                 }
    1967 
    19681964                if ( empty( $changeset_post_id ) ) {
    19691965                        if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->create_posts ) ) {
     
    20001996                        }
    20011997                        $is_publish = ( 'publish' === $changeset_status || 'future' === $changeset_status );
    2002                         if ( $is_publish ) {
    2003                                 if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ) ) {
    2004                                         wp_send_json_error( 'changeset_publish_unauthorized', 403 );
    2005                                 }
    2006                                 if ( false === has_action( 'transition_post_status', '_wp_customize_publish_changeset' ) ) {
    2007                                         wp_send_json_error( 'missing_publish_callback', 500 );
    2008                                 }
     1998                        if ( $is_publish && ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ) ) {
     1999                                wp_send_json_error( 'changeset_publish_unauthorized', 403 );
    20092000                        }
    20102001                }
     
    20352026                                $changeset_date_gmt = gmdate( 'Y-m-d H:i:s', $timestamp );
    20362027                        }
    2037                         $now = gmdate( 'Y-m-d H:i:59' );
    2038 
    2039                         $is_future_dated = ( mysql2date( 'U', $changeset_date_gmt, false ) > mysql2date( 'U', $now, false ) );
    2040                         if ( ! $is_future_dated ) {
    2041                                 wp_send_json_error( 'not_future_date', 400 ); // Only future dates are allowed.
    2042                         }
    2043 
    2044                         if ( ! $this->is_theme_active() && ( 'future' === $changeset_status || $is_future_dated ) ) {
    2045                                 wp_send_json_error( 'cannot_schedule_theme_switches', 400 ); // This should be allowed in the future, when theme is a regular setting.
    2046                         }
    2047                         $will_remain_auto_draft = ( ! $changeset_status && ( ! $changeset_post_id || 'auto-draft' === get_post_status( $changeset_post_id ) ) );
    2048                         if ( $changeset_date && $will_remain_auto_draft ) {
    2049                                 wp_send_json_error( 'cannot_supply_date_for_auto_draft_changeset', 400 );
    2050                         }
    20512028                }
    20522029
     
    20582035                ) );
    20592036                if ( is_wp_error( $r ) ) {
    2060                         $response = $r->get_error_data();
     2037                        $response = array(
     2038                                'message' => $r->get_error_message(),
     2039                                'code' => $r->get_error_code(),
     2040                        );
     2041                        if ( is_array( $r->get_error_data() ) ) {
     2042                                $response = array_merge( $response, $r->get_error_data() );
     2043                        } else {
     2044                                $response['data'] = $r->get_error_data();
     2045                        }
    20612046                } else {
    20622047                        $response = $r;
     
    21332118                $existing_changeset_data = array();
    21342119                if ( $changeset_post_id ) {
     2120                        $existing_status = get_post_status( $changeset_post_id );
     2121                        if ( 'publish' === $existing_status || 'trash' === $existing_status ) {
     2122                                return new WP_Error( 'changeset_already_published' );
     2123                        }
     2124
    21352125                        $existing_changeset_data = $this->get_changeset_post_data( $changeset_post_id );
     2126                }
     2127
     2128                // Fail if attempting to publish but publish hook is missing.
     2129                if ( 'publish' === $args['status'] && false === has_action( 'transition_post_status', '_wp_customize_publish_changeset' ) ) {
     2130                        return new WP_Error( 'missing_publish_callback' );
     2131                }
     2132
     2133                // Validate date.
     2134                $now = gmdate( 'Y-m-d H:i:59' );
     2135                if ( $args['date_gmt'] ) {
     2136                        $is_future_dated = ( mysql2date( 'U', $args['date_gmt'], false ) > mysql2date( 'U', $now, false ) );
     2137                        if ( ! $is_future_dated ) {
     2138                                return new WP_Error( 'not_future_date' ); // Only future dates are allowed.
     2139                        }
     2140
     2141                        if ( ! $this->is_theme_active() && ( 'future' === $args['status'] || $is_future_dated ) ) {
     2142                                return new WP_Error( 'cannot_schedule_theme_switches' ); // This should be allowed in the future, when theme is a regular setting.
     2143                        }
     2144                        $will_remain_auto_draft = ( ! $args['status'] && ( ! $changeset_post_id || 'auto-draft' === get_post_status( $changeset_post_id ) ) );
     2145                        if ( $will_remain_auto_draft ) {
     2146                                return new WP_Error( 'cannot_supply_date_for_auto_draft_changeset' );
     2147                        }
     2148                } elseif ( $changeset_post_id && 'future' === $args['status'] ) {
     2149
     2150                        // Fail if the new status is future but the existing post's date is not in the future.
     2151                        $changeset_post = get_post( $changeset_post_id );
     2152                        if ( mysql2date( 'U', $changeset_post->post_date_gmt, false ) <= mysql2date( 'U', $now, false ) ) {
     2153                                return new WP_Error( 'not_future_date' );
     2154                        }
    21362155                }
    21372156
     
    23482367                        $post_array['post_status'] = $args['status'];
    23492368                }
    2350                 if ( $args['date_gmt'] ) {
     2369
     2370                // Reset post date to now if we are publishing, otherwise pass post_date_gmt and translate for post_date.
     2371                if ( 'publish' === $args['status'] ) {
     2372                        $post_array['post_date_gmt'] = '0000-00-00 00:00:00';
     2373                        $post_array['post_date'] = '0000-00-00 00:00:00';
     2374                } elseif ( $args['date_gmt'] ) {
    23512375                        $post_array['post_date_gmt'] = $args['date_gmt'];
    23522376                        $post_array['post_date'] = get_date_from_gmt( $args['date_gmt'] );
  • branches/4.7/tests/phpunit/tests/ajax/CustomizeManager.php

    r38810 r39410  
    165165                $this->make_ajax_call( 'customize_save' );
    166166                $this->assertFalse( $this->_last_response_parsed['success'] );
    167                 $this->assertEquals( 'changeset_already_published', $this->_last_response_parsed['data'] );
     167                $this->assertEquals( 'changeset_already_published', $this->_last_response_parsed['data']['code'] );
    168168                wp_update_post( array( 'ID' => $wp_customize->changeset_post_id(), 'post_status' => 'auto-draft' ) );
    169169
     
    214214                $this->make_ajax_call( 'customize_save' );
    215215                $this->assertFalse( $this->_last_response_parsed['success'] );
    216                 $this->assertEquals( 'not_future_date', $this->_last_response_parsed['data'] );
     216                $this->assertEquals( 'not_future_date', $this->_last_response_parsed['data']['code'] );
    217217                $_POST['customize_changeset_date'] = ( gmdate( 'Y' ) + 1 ) . '-01-01 00:00:00';
    218218                $this->make_ajax_call( 'customize_save' );
     
    308308                $this->assertEquals( 'Published', get_post( $post_id )->post_title );
    309309        }
     310
     311        /**
     312         * Test WP_Customize_Manager::save().
     313         *
     314         * @ticket 38943
     315         * @covers WP_Customize_Manager::save()
     316         */
     317        function test_success_save_post_date() {
     318                $uuid = wp_generate_uuid4();
     319                $post_id = $this->factory()->post->create( array(
     320                        'post_name' => $uuid,
     321                        'post_title' => 'Original',
     322                        'post_type' => 'customize_changeset',
     323                        'post_status' => 'auto-draft',
     324                        'post_content' => wp_json_encode( array(
     325                                'blogname' => array(
     326                                        'value' => 'New Site Title',
     327                                ),
     328                        ) ),
     329                ) );
     330                $wp_customize = $this->set_up_valid_state( $uuid );
     331
     332                // Success future schedule date.
     333                $future_date = ( gmdate( 'Y' ) + 1 ) . '-01-01 00:00:00';
     334                $_POST['customize_changeset_status'] = 'future';
     335                $_POST['customize_changeset_title'] = 'Future date';
     336                $_POST['customize_changeset_date'] = $future_date;
     337                $this->make_ajax_call( 'customize_save' );
     338                $this->assertTrue( $this->_last_response_parsed['success'] );
     339                $changeset_post_schedule = get_post( $post_id );
     340                $this->assertEquals( $future_date, $changeset_post_schedule->post_date );
     341
     342                // Success future changeset change to draft keeping existing date.
     343                unset( $_POST['customize_changeset_date'] );
     344                $_POST['customize_changeset_status'] = 'draft';
     345                $this->make_ajax_call( 'customize_save' );
     346                $this->assertTrue( $this->_last_response_parsed['success'] );
     347                $changeset_post_draft = get_post( $post_id );
     348                $this->assertEquals( $future_date, $changeset_post_draft->post_date );
     349
     350                // Success if date is not passed with schedule changeset and stored changeset have future date.
     351                $_POST['customize_changeset_status'] = 'future';
     352                $this->make_ajax_call( 'customize_save' );
     353                $this->assertTrue( $this->_last_response_parsed['success'] );
     354                $changeset_post_schedule = get_post( $post_id );
     355                $this->assertEquals( $future_date, $changeset_post_schedule->post_date );
     356                // Success if draft with past date.
     357                $now = current_time( 'mysql' );
     358                wp_update_post( array(
     359                        'ID' => $post_id,
     360                        'post_status' => 'draft',
     361                        'post_date' => $now,
     362                        'post_date_gmt' => get_gmt_from_date( $now ),
     363                ) );
     364
     365                // Fail if future request and existing date is past.
     366                $_POST['customize_changeset_status'] = 'future';
     367                unset( $_POST['customize_changeset_date'] );
     368                $this->make_ajax_call( 'customize_save' );
     369                $this->assertFalse( $this->_last_response_parsed['success'] );
     370                $this->assertEquals( 'not_future_date', $this->_last_response_parsed['data']['code'] );
     371
     372                // Success publish changeset reset date to current.
     373                wp_update_post( array(
     374                        'ID' => $post_id,
     375                        'post_status' => 'future',
     376                        'post_date' => $future_date,
     377                        'post_date_gmt' => get_gmt_from_date( $future_date ),
     378                ) );
     379                unset( $_POST['customize_changeset_date'] );
     380                $_POST['customize_changeset_status'] = 'publish';
     381                $this->make_ajax_call( 'customize_save' );
     382                $this->assertTrue( $this->_last_response_parsed['success'] );
     383                $changeset_post_publish = get_post( $post_id );
     384                $this->assertNotEquals( $future_date, $changeset_post_publish->post_date );
     385        }
    310386}
  • branches/4.7/tests/phpunit/tests/customize/manager.php

    r39346 r39410  
    628628                        ),
    629629                );
     630                $date = ( gmdate( 'Y' ) + 1 ) . '-12-01 00:00:00';
    630631                $r = $manager->save_changeset_post( array(
    631632                        'status' => 'auto-draft',
    632633                        'title' => 'Auto Draft',
    633                         'date_gmt' => '2010-01-01 00:00:00',
     634                        'date_gmt' => $date,
    634635                        'data' => $pre_saved_data,
    635636                ) );
     
    652653                $this->assertEquals( 'Auto Draft', get_post( $post_id )->post_title );
    653654                $this->assertEquals( 'auto-draft', get_post( $post_id )->post_status );
    654                 $this->assertEquals( '2010-01-01 00:00:00', get_post( $post_id )->post_date_gmt );
     655                $this->assertEquals( $date, get_post( $post_id )->post_date_gmt );
    655656                $this->assertNotEquals( 'Changeset Title', get_option( 'blogname' ) );
    656657                $this->assertArrayHasKey( 'setting_validities', $r );
Note: See TracChangeset for help on using the changeset viewer.