Make WordPress Core


Ignore:
Timestamp:
10/12/2017 04:00:15 AM (7 years ago)
Author:
westonruter
Message:

Customize: Add changeset locking in Customizer to prevent users from overriding each other's changes.

  • Customization locking is checked when changesets are saved and when heartbeat ticks.
  • Lock is lifted immediately upon a user closing the Customizer.
  • Heartbeat is introduced into Customizer.
  • Changes made to user after it was locked by another user are stored as an autosave revision for restoration.
  • Lock notification displays link to preview the other user's changes on the frontend.
  • A user loading a locked Customizer changeset will be presented with an option to take over.
  • Autosave revisions attached to a published changeset are converted into auto-drafts so that they will be presented to users for restoration.
  • Focus constraining is improved in overlay notifications.
  • Escape key is stopped from propagating in overlay notifications, and it dismisses dismissible overlay notifications.
  • Introduces changesetLocked state which is used to disable the Save button and suppress the AYS dialog when leaving the Customizer.
  • Fixes bug where users could be presented with each other's autosave revisions.

Props sayedwp, westonruter, melchoyce.
See #31436, #31897, #39896.
Fixes #42024.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/ajax/CustomizeManager.php

    r41667 r41839  
    517517     *
    518518     * @ticket 39896
    519      * @covers WP_Customize_Manager::handle_dismiss_autosave_request()
     519     * @covers WP_Customize_Manager::handle_dismiss_autosave_or_lock_request()
    520520     * @covers WP_Customize_Manager::dismiss_user_auto_draft_changesets()
    521521     */
    522     public function test_handle_dismiss_autosave_request() {
     522    public function test_handle_dismiss_autosave_or_lock_request() {
    523523        $uuid = wp_generate_uuid4();
    524524        $wp_customize = $this->set_up_valid_state( $uuid );
    525525
    526         $this->make_ajax_call( 'customize_dismiss_autosave' );
     526        $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    527527        $this->assertFalse( $this->_last_response_parsed['success'] );
    528528        $this->assertEquals( 'invalid_nonce', $this->_last_response_parsed['data'] );
    529529
    530         $nonce = wp_create_nonce( 'customize_dismiss_autosave' );
     530        $nonce = wp_create_nonce( 'customize_dismiss_autosave_or_lock' );
    531531        $_POST['nonce'] = $_GET['nonce'] = $_REQUEST['nonce'] = $nonce;
    532         $this->make_ajax_call( 'customize_dismiss_autosave' );
     532
     533        $_POST['dismiss_lock'] = $_GET['dismiss_lock'] = $_REQUEST['dismiss_lock'] = true;
     534        $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
     535        $this->assertFalse( $this->_last_response_parsed['success'] );
     536        $this->assertEquals( 'no_changeset_to_dismiss_lock', $this->_last_response_parsed['data'] );
     537
     538        $_POST['dismiss_autosave'] = $_GET['dismiss_autosave'] = $_REQUEST['dismiss_autosave'] = true;
     539        $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    533540        $this->assertFalse( $this->_last_response_parsed['success'] );
    534541        $this->assertEquals( 'no_auto_draft_to_delete', $this->_last_response_parsed['data'] );
     
    560567            $this->assertFalse( (bool) get_post_meta( $post_id, '_customize_restore_dismissed', true ) );
    561568        }
    562         $this->make_ajax_call( 'customize_dismiss_autosave' );
     569        $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    563570        $this->assertTrue( $this->_last_response_parsed['success'] );
    564571        $this->assertEquals( 'auto_draft_dismissed', $this->_last_response_parsed['data'] );
     
    573580
    574581        // Subsequent test results in none dismissed.
    575         $this->make_ajax_call( 'customize_dismiss_autosave' );
     582        $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    576583        $this->assertFalse( $this->_last_response_parsed['success'] );
    577584        $this->assertEquals( 'no_auto_draft_to_delete', $this->_last_response_parsed['data'] );
     
    586593            'status' => 'draft',
    587594        ) );
     595
     596        $_POST['dismiss_autosave'] = $_GET['dismiss_autosave'] = $_REQUEST['dismiss_autosave'] = false;
     597        $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
     598        $this->assertTrue( $this->_last_response_parsed['success'] );
     599        $this->assertEquals( 'changeset_lock_dismissed', $this->_last_response_parsed['data'] );
     600
     601        $_POST['dismiss_autosave'] = $_GET['dismiss_autosave'] = $_REQUEST['dismiss_autosave'] = true;
    588602        $this->assertNotInstanceOf( 'WP_Error', $r );
    589603        $this->assertFalse( wp_get_post_autosave( $wp_customize->changeset_post_id() ) );
     
    591605
    592606        // Since no autosave yet, confirm no action.
    593         $this->make_ajax_call( 'customize_dismiss_autosave' );
     607        $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    594608        $this->assertFalse( $this->_last_response_parsed['success'] );
    595609        $this->assertEquals( 'no_autosave_revision_to_delete', $this->_last_response_parsed['data'] );
     
    611625
    612626        // Confirm autosave gets deleted.
    613         $this->make_ajax_call( 'customize_dismiss_autosave' );
     627        $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    614628        $this->assertTrue( $this->_last_response_parsed['success'] );
    615629        $this->assertEquals( 'autosave_revision_deleted', $this->_last_response_parsed['data'] );
     
    617631
    618632        // Since no autosave yet, confirm no action.
    619         $this->make_ajax_call( 'customize_dismiss_autosave' );
     633        $this->make_ajax_call( 'customize_dismiss_autosave_or_lock' );
    620634        $this->assertFalse( $this->_last_response_parsed['success'] );
    621635        $this->assertEquals( 'no_autosave_revision_to_delete', $this->_last_response_parsed['data'] );
Note: See TracChangeset for help on using the changeset viewer.