diff --git a/includes/classes/API/SubscriptionsController.php b/includes/classes/API/SubscriptionsController.php index fba277a00..1f84f92b3 100644 --- a/includes/classes/API/SubscriptionsController.php +++ b/includes/classes/API/SubscriptionsController.php @@ -257,15 +257,19 @@ public function receive_item( $request ) { return $response; } - wp_update_post( - [ - 'ID' => $request['post_id'], - 'post_title' => $request['post_data']['title'], - 'post_content' => $content, - 'post_excerpt' => $request['post_data']['excerpt'], - 'post_name' => $request['post_data']['slug'], - ] - ); + $post_update = [ + 'ID' => $request['post_id'], + 'post_title' => $request['post_data']['title'], + 'post_content' => $content, + 'post_excerpt' => $request['post_data']['excerpt'], + 'post_name' => $request['post_data']['slug'], + ]; + + if ( isset( $request['post_data']['status'] ) ) { + $post_update['post_status'] = $request['post_data']['status']; + } + + wp_update_post( $post_update ); /** * We check if each of these exist since the API removes empty arrays from requests diff --git a/includes/classes/Authentications/WordPressDotcomOauth2Authentication.php b/includes/classes/Authentications/WordPressDotcomOauth2Authentication.php index 57ad3f625..023b02d7b 100644 --- a/includes/classes/Authentications/WordPressDotcomOauth2Authentication.php +++ b/includes/classes/Authentications/WordPressDotcomOauth2Authentication.php @@ -81,10 +81,10 @@ public static function credentials_form( $args = array() ) { // Calculate the redirect_uri to use for authorization (the current admin url & query vars). $redirect_uri = esc_url( ( is_ssl() ? 'https://' : 'http://' ) . - sanitize_text_field( isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '' ) . // Input var okay. WPCS: CSRF ok. - sanitize_text_field( isset( $_SERVER['SCRIPT_NAME'] ) ? $_SERVER['SCRIPT_NAME'] : '' ) . // WPCS: input var ok. + sanitize_text_field( isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '' ) . + sanitize_text_field( isset( $_SERVER['SCRIPT_NAME'] ) ? $_SERVER['SCRIPT_NAME'] : '' ) . '?' . - sanitize_text_field( isset( $_SERVER['QUERY_STRING'] ) ? $_SERVER['QUERY_STRING'] : '' ) // WPCS: input var ok. + sanitize_text_field( isset( $_SERVER['QUERY_STRING'] ) ? $_SERVER['QUERY_STRING'] : '' ) ); $args[ self::API_REDIRECT_URI ] = $redirect_uri; diff --git a/includes/classes/InternalConnections/NetworkSiteConnection.php b/includes/classes/InternalConnections/NetworkSiteConnection.php index 0c330206f..eb7634802 100644 --- a/includes/classes/InternalConnections/NetworkSiteConnection.php +++ b/includes/classes/InternalConnections/NetworkSiteConnection.php @@ -76,7 +76,7 @@ public function push( $post_id, $args = array() ) { 'post_excerpt' => $post->post_excerpt, 'post_type' => $post->post_type, 'post_author' => isset( $post->post_author ) ? $post->post_author : get_current_user_id(), - 'post_status' => 'publish', + 'post_status' => Utils\can_distribute_post_status() ? $post->post_status : 'publish', ); $post = Utils\prepare_post( $post ); @@ -97,8 +97,7 @@ public function push( $post_id, $args = array() ) { } if ( empty( $args['post_status'] ) ) { - if ( isset( $new_post_args['ID'] ) ) { - + if ( isset( $new_post_args['ID'] ) && ! Utils\can_distribute_post_status() ) { // Avoid updating the status of previously distributed posts. $existing_status = get_post_status( (int) $new_post_args['ID'] ); if ( $existing_status ) { diff --git a/includes/subscriptions.php b/includes/subscriptions.php index 5ad798113..847baf47e 100644 --- a/includes/subscriptions.php +++ b/includes/subscriptions.php @@ -287,6 +287,10 @@ function send_notifications( $post ) { } } + if ( Utils\can_distribute_post_status() ) { + $post_body['post_data']['status'] = $post->post_status; + } + $request = wp_remote_post( untrailingslashit( $target_url ) . '/wp/v2/dt_subscription/receive', [ diff --git a/includes/utils.php b/includes/utils.php index 1b59fe1ff..7e1f3094c 100644 --- a/includes/utils.php +++ b/includes/utils.php @@ -974,6 +974,23 @@ function get_processed_content( $post_content ) { return $post_content; } +/** + * Check if post status can be distributed. + * + * @return bool + */ +function can_distribute_post_status() { + /** + * Filter whether Distributor should update post statuses when the origin post status changes. + * + * False by default, return true to have post statuses distributed. + * + * @since 2.0.0 + * @hook dt_distribute_post_status + */ + return apply_filters( 'dt_distribute_post_status', false ); +} + /** * Gets the REST URL for a post. * diff --git a/tests/test-plugins/auto-publish-pulled-posts/auto-publish-pulled-posts.php b/tests/test-plugins/auto-publish-pulled-posts/auto-publish-pulled-posts.php new file mode 100644 index 000000000..fbc4c7624 --- /dev/null +++ b/tests/test-plugins/auto-publish-pulled-posts/auto-publish-pulled-posts.php @@ -0,0 +1,20 @@ +loginAs( 'wpsnapshots' ); - self::assertPostFieldContains( 40, 'post_title', 'Test Post' ); + // Don't test in block editor. + $editor_has_blocks = $this->editorHasBlocks( $I ); + if ( $editor_has_blocks ) { + return; + } - return; + self::assertPostFieldContains( 40, 'post_title', 'Test Post' ); // Distribute post $post_info = $this->pushPost( $I, 40, 2 ); @@ -65,12 +69,12 @@ public function testDistributedFrom() { $I->waitUntilElementVisible( 'body.post-php' ); - $editor_has_blocks = $this->editorHasBlocks( $I ); + $editor_has_blocks = $this->editorHasBlocks( $I, true ); // Make sure we see distributed time in publish box if ( $editor_has_blocks ) { $I->seeText( 'Distributed on:', '#distributed-from' ); } else { - $I->seeText( 'Distributed on', '#syndicate-time' ); + $I->seeText( 'Distributed on:', '#syndicate-time' ); } // Make sure we see distributed status admin notice and that it shows as linked @@ -102,4 +106,89 @@ public function testDistributedFrom() { $this->assertTrue( ( false !== strpos( $source, 'click( $element ); + $I->waitUntilElementVisible( '#message' ); + } + } catch ( \Exception $e ) {} + $I->click( '[data-slug="auto-publish-pulled-posts"] .activate a' ); + $I->waitUntilElementVisible( '#message' ); + $I->moveTo( $to_blog_slug . 'wp-admin/admin.php?page=pull' ); if ( $use_connection ) { $I->checkOptions( '#pull_connections', $use_connection ); + $I->executeJavaScript(' + jQuery("#pull_connections").find("option").filter(function(){ + return jQuery(this).text() == "' . $use_connection . '"; + }).prop("selected", true).trigger("change"); + '); $I->waitUntilElementVisible( '.wp-list-table #cb-select-' . $original_post_id ); } @@ -148,9 +164,19 @@ protected function pullPost( \WPAcceptance\PHPUnit\Actor $I, $original_post_id, * * Must be called from the edit page. * - * @param \WPAcceptance\PHPUnit\Actor $actor The actor. + * @param \WPAcceptance\PHPUnit\Actor $actor The actor. + * @param bool $on_edit_page We detect the block editor using a body class + * of post edit page so we need to navigate to + * that page before checking. */ - protected function editorHasBlocks ( $actor ) { + + protected function editorHasBlocks ( $actor, $on_edit_page = false ) { + + if ( ! $on_edit_page ) { + $actor->moveTo( '/wp-admin/post.php?post=40&action=edit' ); + $actor->waitUntilElementVisible( 'body.post-php' );; + } + $body = $actor->getElement( 'body' ); $msg = $actor->elementToString( $body ); return ( strpos( $msg, 'block-editor-page' ) ); @@ -169,6 +195,89 @@ protected function dismissNUXTip( $actor ) { } catch ( \Exception $e ) {} } + /** + * Test status distribution. + * + * @param Object $post_info Information about the distributed post. + * @param \WPAcceptance\PHPUnit\Actor $actor The Actor instance. + */ + protected function statusDistributionTest( $post_info, $actor ) { + + // TEST SCENARIO: with 'dt_distribute_post_status' false (DEFAULT). + // Deactivate the plugin? + $actor->moveTo( '/wp-admin/plugins.php' ); + usleep( 300 ); + + // Check the distributed post state. + $actor->moveTo( $post_info['distributed_edit_url'] ); + $actor->waitUntilElementVisible( 'body.post-php' ); + + // The remote post should start in a Published post status. + $actor->seeText( 'Published', '#post-status-display' ); + + // Go back to the origin post. + $actor->moveTo( $post_info['original_edit_url'] ); + $actor->waitUntilElementVisible( 'body.post-php' ); + + // The origin post should be in a published post status. + $actor->seeText( 'Published', '#post-status-display' ); + + // Change the origin post status to draft. + $actor->click( '.edit-post-status' ); + $actor->waitUntilElementVisible( '#post_status' ); + $actor->selectOptionByValue( '#post_status', 'draft' ); + $actor->click( '.save-post-status' ); + usleep( 200 ); + $actor->click( '#publish' ); // Click the 'Update' button. + $actor->waitUntilElementVisible( '#wpadminbar' ); + + // The remote post will still be in a published status, the post status is not distributed. + $actor->moveTo( $post_info['distributed_edit_url'] ); + $actor->waitUntilElementVisible( 'body.post-php' ); + $actor->seeText( 'Published', '#post-status-display' ); + + // TEST SCENARIO: with 'dt_distribute_post_status' true - activate the helper plugin. + $actor->moveTo( '/wp-admin/plugins.php' ); + $actor->click( '[data-slug="enable-post-status-distribution"] .activate a' ); + $actor->waitUntilElementVisible( '#message' ); + + // Update the origin post + $actor->moveTo( $post_info['original_edit_url'] ); + $actor->waitUntilElementVisible( 'body.post-php' ); + + // The origin post should be in a draft state. + $actor->seeText( 'Draft', '#post-status-display' ); + + // Change the remote post title and update. + $actor->typeInField( '#title', 'Updated test title' ); + $actor->click( '#save-post' ); + $actor->waitUntilElementVisible( '#wpadminbar' ); + + // The remote post should now in a draft status, the post status is distributed. + $actor->moveTo( $post_info['distributed_edit_url'] ); + $actor->waitUntilElementVisible( 'body.post-php' ); + $actor->seeText( 'Draft', '#post-status-display' ); + } + + /** + * Create an external connection. + * + * @param \WPAcceptance\PHPUnit\Actor $actor The Actor instance. + */ + protected function createExternalConnection( $actor, $from = '', $to = 'two' ) { + $connection_url = $this->getWPHomeUrl() . '/wp-json'; + if ( $to ) { + $connection_url = $this->getWPHomeUrl() . "/{$to}/wp-json"; + } + $actor->moveTo( "{$from}/wp-admin/post-new.php?post_type=dt_ext_connection" ); + $actor->typeInField( '#title', 'Test External Connection' ); + $actor->typeInField( '#dt_username', 'wpsnapshots' ); + $actor->typeInField( '#dt_password', 'password' ); + $actor->typeInField( '#dt_external_connection_url', $connection_url ); + $actor->pressEnterKey( '#create-connection' ); + $actor->waitUntilElementVisible( '.notice-success' ); + } + /** * Disable new default fullscreen mode in WP 5.4. * diff --git a/wpacceptance.json b/wpacceptance.json index 6d79be2b6..79f3830ef 100644 --- a/wpacceptance.json +++ b/wpacceptance.json @@ -9,5 +9,9 @@ ], "enforce_clean_db": true, "bootstrap": "tests\/wpacceptance\/bootstrap.php", - "repository": "10up" + "repository": "10up", + "before_scripts" : [ + "mv tests/test-plugins/* ../" + ], + "project_path": "%WP_ROOT%/wp-content" }