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. See #30937. Fixes #38943. git-svn-id: https://develop.svn.wordpress.org/trunk@39409 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
6a7883ffcf
commit
3e9a2d5a5a
|
@ -1961,10 +1961,6 @@ final class WP_Customize_Manager {
|
|||
}
|
||||
|
||||
$changeset_post_id = $this->changeset_post_id();
|
||||
if ( $changeset_post_id && in_array( get_post_status( $changeset_post_id ), array( 'publish', 'trash' ) ) ) {
|
||||
wp_send_json_error( 'changeset_already_published' );
|
||||
}
|
||||
|
||||
if ( empty( $changeset_post_id ) ) {
|
||||
if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->create_posts ) ) {
|
||||
wp_send_json_error( 'cannot_create_changeset_post' );
|
||||
|
@ -1999,13 +1995,8 @@ final class WP_Customize_Manager {
|
|||
wp_send_json_error( 'bad_customize_changeset_status', 400 );
|
||||
}
|
||||
$is_publish = ( 'publish' === $changeset_status || 'future' === $changeset_status );
|
||||
if ( $is_publish ) {
|
||||
if ( ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ) ) {
|
||||
wp_send_json_error( 'changeset_publish_unauthorized', 403 );
|
||||
}
|
||||
if ( false === has_action( 'transition_post_status', '_wp_customize_publish_changeset' ) ) {
|
||||
wp_send_json_error( 'missing_publish_callback', 500 );
|
||||
}
|
||||
if ( $is_publish && ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->publish_posts ) ) {
|
||||
wp_send_json_error( 'changeset_publish_unauthorized', 403 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2034,20 +2025,6 @@ final class WP_Customize_Manager {
|
|||
}
|
||||
$changeset_date_gmt = gmdate( 'Y-m-d H:i:s', $timestamp );
|
||||
}
|
||||
$now = gmdate( 'Y-m-d H:i:59' );
|
||||
|
||||
$is_future_dated = ( mysql2date( 'U', $changeset_date_gmt, false ) > mysql2date( 'U', $now, false ) );
|
||||
if ( ! $is_future_dated ) {
|
||||
wp_send_json_error( 'not_future_date', 400 ); // Only future dates are allowed.
|
||||
}
|
||||
|
||||
if ( ! $this->is_theme_active() && ( 'future' === $changeset_status || $is_future_dated ) ) {
|
||||
wp_send_json_error( 'cannot_schedule_theme_switches', 400 ); // This should be allowed in the future, when theme is a regular setting.
|
||||
}
|
||||
$will_remain_auto_draft = ( ! $changeset_status && ( ! $changeset_post_id || 'auto-draft' === get_post_status( $changeset_post_id ) ) );
|
||||
if ( $changeset_date && $will_remain_auto_draft ) {
|
||||
wp_send_json_error( 'cannot_supply_date_for_auto_draft_changeset', 400 );
|
||||
}
|
||||
}
|
||||
|
||||
$r = $this->save_changeset_post( array(
|
||||
|
@ -2057,7 +2034,15 @@ final class WP_Customize_Manager {
|
|||
'data' => $input_changeset_data,
|
||||
) );
|
||||
if ( is_wp_error( $r ) ) {
|
||||
$response = $r->get_error_data();
|
||||
$response = array(
|
||||
'message' => $r->get_error_message(),
|
||||
'code' => $r->get_error_code(),
|
||||
);
|
||||
if ( is_array( $r->get_error_data() ) ) {
|
||||
$response = array_merge( $response, $r->get_error_data() );
|
||||
} else {
|
||||
$response['data'] = $r->get_error_data();
|
||||
}
|
||||
} else {
|
||||
$response = $r;
|
||||
|
||||
|
@ -2132,9 +2117,43 @@ final class WP_Customize_Manager {
|
|||
$changeset_post_id = $this->changeset_post_id();
|
||||
$existing_changeset_data = array();
|
||||
if ( $changeset_post_id ) {
|
||||
$existing_status = get_post_status( $changeset_post_id );
|
||||
if ( 'publish' === $existing_status || 'trash' === $existing_status ) {
|
||||
return new WP_Error( 'changeset_already_published' );
|
||||
}
|
||||
|
||||
$existing_changeset_data = $this->get_changeset_post_data( $changeset_post_id );
|
||||
}
|
||||
|
||||
// Fail if attempting to publish but publish hook is missing.
|
||||
if ( 'publish' === $args['status'] && false === has_action( 'transition_post_status', '_wp_customize_publish_changeset' ) ) {
|
||||
return new WP_Error( 'missing_publish_callback' );
|
||||
}
|
||||
|
||||
// Validate date.
|
||||
$now = gmdate( 'Y-m-d H:i:59' );
|
||||
if ( $args['date_gmt'] ) {
|
||||
$is_future_dated = ( mysql2date( 'U', $args['date_gmt'], false ) > mysql2date( 'U', $now, false ) );
|
||||
if ( ! $is_future_dated ) {
|
||||
return new WP_Error( 'not_future_date' ); // Only future dates are allowed.
|
||||
}
|
||||
|
||||
if ( ! $this->is_theme_active() && ( 'future' === $args['status'] || $is_future_dated ) ) {
|
||||
return new WP_Error( 'cannot_schedule_theme_switches' ); // This should be allowed in the future, when theme is a regular setting.
|
||||
}
|
||||
$will_remain_auto_draft = ( ! $args['status'] && ( ! $changeset_post_id || 'auto-draft' === get_post_status( $changeset_post_id ) ) );
|
||||
if ( $will_remain_auto_draft ) {
|
||||
return new WP_Error( 'cannot_supply_date_for_auto_draft_changeset' );
|
||||
}
|
||||
} elseif ( $changeset_post_id && 'future' === $args['status'] ) {
|
||||
|
||||
// Fail if the new status is future but the existing post's date is not in the future.
|
||||
$changeset_post = get_post( $changeset_post_id );
|
||||
if ( mysql2date( 'U', $changeset_post->post_date_gmt, false ) <= mysql2date( 'U', $now, false ) ) {
|
||||
return new WP_Error( 'not_future_date' );
|
||||
}
|
||||
}
|
||||
|
||||
// The request was made via wp.customize.previewer.save().
|
||||
$update_transactionally = (bool) $args['status'];
|
||||
$allow_revision = (bool) $args['status'];
|
||||
|
@ -2347,7 +2366,12 @@ final class WP_Customize_Manager {
|
|||
if ( $args['status'] ) {
|
||||
$post_array['post_status'] = $args['status'];
|
||||
}
|
||||
if ( $args['date_gmt'] ) {
|
||||
|
||||
// Reset post date to now if we are publishing, otherwise pass post_date_gmt and translate for post_date.
|
||||
if ( 'publish' === $args['status'] ) {
|
||||
$post_array['post_date_gmt'] = '0000-00-00 00:00:00';
|
||||
$post_array['post_date'] = '0000-00-00 00:00:00';
|
||||
} elseif ( $args['date_gmt'] ) {
|
||||
$post_array['post_date_gmt'] = $args['date_gmt'];
|
||||
$post_array['post_date'] = get_date_from_gmt( $args['date_gmt'] );
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ class Tests_Ajax_CustomizeManager extends WP_Ajax_UnitTestCase {
|
|||
$wp_customize->save_changeset_post( array( 'status' => 'publish' ) );
|
||||
$this->make_ajax_call( 'customize_save' );
|
||||
$this->assertFalse( $this->_last_response_parsed['success'] );
|
||||
$this->assertEquals( 'changeset_already_published', $this->_last_response_parsed['data'] );
|
||||
$this->assertEquals( 'changeset_already_published', $this->_last_response_parsed['data']['code'] );
|
||||
wp_update_post( array( 'ID' => $wp_customize->changeset_post_id(), 'post_status' => 'auto-draft' ) );
|
||||
|
||||
// User cannot edit.
|
||||
|
@ -213,7 +213,7 @@ class Tests_Ajax_CustomizeManager extends WP_Ajax_UnitTestCase {
|
|||
$_POST['customize_changeset_date'] = '2010-01-01 00:00:00';
|
||||
$this->make_ajax_call( 'customize_save' );
|
||||
$this->assertFalse( $this->_last_response_parsed['success'] );
|
||||
$this->assertEquals( 'not_future_date', $this->_last_response_parsed['data'] );
|
||||
$this->assertEquals( 'not_future_date', $this->_last_response_parsed['data']['code'] );
|
||||
$_POST['customize_changeset_date'] = ( gmdate( 'Y' ) + 1 ) . '-01-01 00:00:00';
|
||||
$this->make_ajax_call( 'customize_save' );
|
||||
$this->assertTrue( $this->_last_response_parsed['success'] );
|
||||
|
@ -307,4 +307,80 @@ class Tests_Ajax_CustomizeManager extends WP_Ajax_UnitTestCase {
|
|||
$this->assertEquals( 'New Site Title', get_option( 'blogname' ) );
|
||||
$this->assertEquals( 'Published', get_post( $post_id )->post_title );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WP_Customize_Manager::save().
|
||||
*
|
||||
* @ticket 38943
|
||||
* @covers WP_Customize_Manager::save()
|
||||
*/
|
||||
function test_success_save_post_date() {
|
||||
$uuid = wp_generate_uuid4();
|
||||
$post_id = $this->factory()->post->create( array(
|
||||
'post_name' => $uuid,
|
||||
'post_title' => 'Original',
|
||||
'post_type' => 'customize_changeset',
|
||||
'post_status' => 'auto-draft',
|
||||
'post_content' => wp_json_encode( array(
|
||||
'blogname' => array(
|
||||
'value' => 'New Site Title',
|
||||
),
|
||||
) ),
|
||||
) );
|
||||
$wp_customize = $this->set_up_valid_state( $uuid );
|
||||
|
||||
// Success future schedule date.
|
||||
$future_date = ( gmdate( 'Y' ) + 1 ) . '-01-01 00:00:00';
|
||||
$_POST['customize_changeset_status'] = 'future';
|
||||
$_POST['customize_changeset_title'] = 'Future date';
|
||||
$_POST['customize_changeset_date'] = $future_date;
|
||||
$this->make_ajax_call( 'customize_save' );
|
||||
$this->assertTrue( $this->_last_response_parsed['success'] );
|
||||
$changeset_post_schedule = get_post( $post_id );
|
||||
$this->assertEquals( $future_date, $changeset_post_schedule->post_date );
|
||||
|
||||
// Success future changeset change to draft keeping existing date.
|
||||
unset( $_POST['customize_changeset_date'] );
|
||||
$_POST['customize_changeset_status'] = 'draft';
|
||||
$this->make_ajax_call( 'customize_save' );
|
||||
$this->assertTrue( $this->_last_response_parsed['success'] );
|
||||
$changeset_post_draft = get_post( $post_id );
|
||||
$this->assertEquals( $future_date, $changeset_post_draft->post_date );
|
||||
|
||||
// Success if date is not passed with schedule changeset and stored changeset have future date.
|
||||
$_POST['customize_changeset_status'] = 'future';
|
||||
$this->make_ajax_call( 'customize_save' );
|
||||
$this->assertTrue( $this->_last_response_parsed['success'] );
|
||||
$changeset_post_schedule = get_post( $post_id );
|
||||
$this->assertEquals( $future_date, $changeset_post_schedule->post_date );
|
||||
// Success if draft with past date.
|
||||
$now = current_time( 'mysql' );
|
||||
wp_update_post( array(
|
||||
'ID' => $post_id,
|
||||
'post_status' => 'draft',
|
||||
'post_date' => $now,
|
||||
'post_date_gmt' => get_gmt_from_date( $now ),
|
||||
) );
|
||||
|
||||
// Fail if future request and existing date is past.
|
||||
$_POST['customize_changeset_status'] = 'future';
|
||||
unset( $_POST['customize_changeset_date'] );
|
||||
$this->make_ajax_call( 'customize_save' );
|
||||
$this->assertFalse( $this->_last_response_parsed['success'] );
|
||||
$this->assertEquals( 'not_future_date', $this->_last_response_parsed['data']['code'] );
|
||||
|
||||
// Success publish changeset reset date to current.
|
||||
wp_update_post( array(
|
||||
'ID' => $post_id,
|
||||
'post_status' => 'future',
|
||||
'post_date' => $future_date,
|
||||
'post_date_gmt' => get_gmt_from_date( $future_date ),
|
||||
) );
|
||||
unset( $_POST['customize_changeset_date'] );
|
||||
$_POST['customize_changeset_status'] = 'publish';
|
||||
$this->make_ajax_call( 'customize_save' );
|
||||
$this->assertTrue( $this->_last_response_parsed['success'] );
|
||||
$changeset_post_publish = get_post( $post_id );
|
||||
$this->assertNotEquals( $future_date, $changeset_post_publish->post_date );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -627,10 +627,11 @@ class Tests_WP_Customize_Manager extends WP_UnitTestCase {
|
|||
'custom' => 'something',
|
||||
),
|
||||
);
|
||||
$date = ( gmdate( 'Y' ) + 1 ) . '-12-01 00:00:00';
|
||||
$r = $manager->save_changeset_post( array(
|
||||
'status' => 'auto-draft',
|
||||
'title' => 'Auto Draft',
|
||||
'date_gmt' => '2010-01-01 00:00:00',
|
||||
'date_gmt' => $date,
|
||||
'data' => $pre_saved_data,
|
||||
) );
|
||||
$this->assertInternalType( 'array', $r );
|
||||
|
@ -651,7 +652,7 @@ class Tests_WP_Customize_Manager extends WP_UnitTestCase {
|
|||
}
|
||||
$this->assertEquals( 'Auto Draft', get_post( $post_id )->post_title );
|
||||
$this->assertEquals( 'auto-draft', get_post( $post_id )->post_status );
|
||||
$this->assertEquals( '2010-01-01 00:00:00', get_post( $post_id )->post_date_gmt );
|
||||
$this->assertEquals( $date, get_post( $post_id )->post_date_gmt );
|
||||
$this->assertNotEquals( 'Changeset Title', get_option( 'blogname' ) );
|
||||
$this->assertArrayHasKey( 'setting_validities', $r );
|
||||
|
||||
|
|
Loading…
Reference in New Issue