From 75f5c806b1cc7bb6da3c5286ec81e99f2c365b9b Mon Sep 17 00:00:00 2001 From: John Parris Date: Wed, 15 Nov 2023 11:28:34 -0500 Subject: [PATCH] MERL-1270: Do not rewrite links in the post editor (#1625) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: do not rewrite links in the post editor When Faust’s “Enable Post and Category URL rewrites” is enabled, this has been causing URLs to be rewritten in the editor to contain the front-end URL instead of the WP URL, which causes them to be saved to the database this way. Instead, we want the WP URL saved to the database. * fix: don't rewrite links in `wp-link-ajax` ajax requests * fix: do not rewrite links on permalink generation requests * test: confirm post_link filtering behavior. Confirms links are not rewritten on post-new.php pages when $_POST is empty. Also confirms Ajax requests to generate sample permalinks are not rewritten. These checks prevent the incorrect guid from being written to the database. Confirms `wp-link-ajax` Ajax requests are not rewritten. This is used by the Classic Editor when linking content. chore: update `enable_rewrites` values in tests to be `1` instead of `true`, for consistency. * add changeset * refactor: extract conditional logic to functions --- .changeset/yellow-foxes-complain.md | 5 ++ .../includes/replacement/callbacks.php | 22 +++++++++ .../includes/replacement/functions.php | 21 ++++++++ .../integration/ReplacementCallbacksTests.php | 49 +++++++++++++++++-- 4 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 .changeset/yellow-foxes-complain.md diff --git a/.changeset/yellow-foxes-complain.md b/.changeset/yellow-foxes-complain.md new file mode 100644 index 000000000..98ec986b2 --- /dev/null +++ b/.changeset/yellow-foxes-complain.md @@ -0,0 +1,5 @@ +--- +'@faustwp/wordpress-plugin': patch +--- + +Fixed a bug where links were rewritten to the Faust Front-end Site URL when using the post editor, resulting in those rewritten links being saved to the post content and guid fields when they shouldn't be. These links are now saved with the URL pointing to the WP site, as they should be. They are still rewritten at runtime to link to the Front-end Site URL when appropriate. diff --git a/plugins/faustwp/includes/replacement/callbacks.php b/plugins/faustwp/includes/replacement/callbacks.php index 0115469f2..9cf215124 100644 --- a/plugins/faustwp/includes/replacement/callbacks.php +++ b/plugins/faustwp/includes/replacement/callbacks.php @@ -234,13 +234,35 @@ function post_preview_link( $link, $post ) { * @return string URL used for the post. */ function post_link( $link ) { + global $pagenow; + $target_pages = array( 'admin-ajax.php', 'index.php', 'edit.php', 'post.php', 'post-new.php', 'upload.php', 'media-new.php' ); + + // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in `is_ajax_generate_permalink_request()` and `is_wp_link_ajax_request()`. + if ( empty( $_POST ) && 'post-new.php' === $pagenow ) { + return $link; + } + + // Ajax requests to generate permalink. + if ( in_array( $pagenow, $target_pages, true ) + && is_ajax_generate_permalink_request() + ) { + return $link; + } + if ( ! is_rewrites_enabled() || ( function_exists( 'is_graphql_request' ) && is_graphql_request() ) + // Block editor makes REST requests on these pages to query content. + || ( in_array( $pagenow, $target_pages, true ) && current_user_can( 'edit_posts' ) && defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { return $link; } + // Check for wp-link-ajax requests. Used by Classic Editor when linking content. + if ( is_wp_link_ajax_request() ) { + return $link; + } + return equivalent_frontend_url( $link ); } diff --git a/plugins/faustwp/includes/replacement/functions.php b/plugins/faustwp/includes/replacement/functions.php index 84768450a..056a932b7 100644 --- a/plugins/faustwp/includes/replacement/functions.php +++ b/plugins/faustwp/includes/replacement/functions.php @@ -110,3 +110,24 @@ function has_file_extension( $string ) { } } +/** + * Determines if an AJAX request to generate permalinks is in progress. + * + * @return boolean + */ +function is_ajax_generate_permalink_request(): bool { + return ( ! empty( $_POST['samplepermalinknonce'] ) && check_ajax_referer( 'samplepermalink', 'samplepermalinknonce' ) ); +} + +/** + * Determines if a wp-link-ajax request is in progress. + * + * @return boolean + */ +function is_wp_link_ajax_request(): bool { + return ( wp_doing_ajax() + && ! empty( $_POST['_ajax_linking_nonce'] ) + && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_ajax_linking_nonce'] ) ), 'internal-linking' ) + && ! empty( $_POST['action'] ) + && 'wp-link-ajax' === $_POST['action'] ); +} diff --git a/plugins/faustwp/tests/integration/ReplacementCallbacksTests.php b/plugins/faustwp/tests/integration/ReplacementCallbacksTests.php index de3f4be75..6ad1c77a5 100644 --- a/plugins/faustwp/tests/integration/ReplacementCallbacksTests.php +++ b/plugins/faustwp/tests/integration/ReplacementCallbacksTests.php @@ -11,7 +11,8 @@ content_replacement, post_preview_link, image_source_replacement, - image_source_srcset_replacement + image_source_srcset_replacement, + post_link }; use function WPE\FaustWP\Settings\faustwp_update_setting; @@ -159,11 +160,51 @@ public function test_post_link_returns_unfiltered_link_when_content_replacement_ */ public function test_post_link_returns_filtered_link_when_content_replacement_is_enabled() { faustwp_update_setting( 'frontend_uri', 'http://moo' ); - faustwp_update_setting( 'enable_rewrites', true ); + faustwp_update_setting( 'enable_rewrites', '1' ); $this->assertSame( 'http://moo/?p=' . $this->post_id, get_permalink( $this->post_id ) ); } + public function test_post_link_returns_unfiltered_link_when_on_post_new_page(): void { + global $pagenow; + $pagenow = 'post-new.php'; + self::assertSame( 'http://example.org/hello-world', post_link( 'http://example.org/hello-world' ) ); + } + + public function test_post_link_returns_unfiltered_link_on_ajax_requests_to_generate_permalinks_using_samplepermalinknonce(): void { + global $pagenow, $_REQUEST, $_POST; + $pagenow = 'admin-ajax.php'; + wp_set_current_user( 1 ); + faustwp_update_setting( 'frontend_uri', 'http://moo' ); + faustwp_update_setting( 'enable_rewrites', '1' ); + $_REQUEST['samplepermalinknonce'] = wp_create_nonce( 'samplepermalink' ); + $_POST['samplepermalinknonce'] = $_REQUEST['samplepermalinknonce']; + + self::assertSame( 'http://example.org/hello-world', post_link( 'http://example.org/hello-world' ) ); + + unset( $_REQUEST['samplepermalinknonce'], $_POST['samplepermalinknonce'] ); + unset( $pagenow ); + wp_set_current_user( null ); + } + + public function test_post_link_returns_unfiltered_link_on_ajax_requests_to_generate_permalinks_using_ajax_linking_nonce(): void { + global $pagenow, $_POST; + $pagenow = 'admin-ajax.php'; + wp_set_current_user( 1 ); + faustwp_update_setting( 'frontend_uri', 'http://moo' ); + faustwp_update_setting( 'enable_rewrites', '1' ); + add_filter( 'wp_doing_ajax', '__return_true' ); + $_POST['_ajax_linking_nonce'] = wp_create_nonce( 'internal-linking' ); + $_POST['action'] = 'wp-link-ajax'; + + self::assertSame( 'http://example.org/hello-world', post_link( 'http://example.org/hello-world' ) ); + + unset( $_POST['_ajax_linking_nonce'], $_POST['action'] ); + unset( $pagenow ); + remove_filter( 'wp_doing_ajax', '__return_true' ); + wp_set_current_user( null ); + } + /** * Tests get_preview_post_link() returns rewritten value. */ @@ -203,7 +244,7 @@ public function test_post_preview_link_uses_frontend_uri_scheme() { public function test_custom_post_type_post_preview_link_returns_filtered_link_when_content_replacement_is_enabled() { faustwp_update_setting( 'frontend_uri', 'http://moo' ); - faustwp_update_setting( 'enable_rewrites', true ); + faustwp_update_setting( 'enable_rewrites', '1' ); $post_id = $this->getCustomPostType(); $this->assertSame( 'http://moo/?document=' . $post_id . '&preview=true&previewPathname=' . rawurlencode( wp_make_link_relative( get_permalink( $post_id ) ) ) . '&p=' . $post_id . '&typeName=Document', get_preview_post_link( $post_id ) ); faustwp_update_setting( 'frontend_uri', null ); @@ -216,7 +257,7 @@ public function test_custom_post_type_post_preview_link_returns_filtered_link_wh public function test_custom_post_type_post_link_returns_unfiltered_link_when_content_replacement_is_enabled() { faustwp_update_setting( 'frontend_uri', 'http://moo' ); - faustwp_update_setting( 'enable_rewrites', true ); + faustwp_update_setting( 'enable_rewrites', '1' ); $post_id = $this->getCustomPostType(); $this->assertSame( 'http://example.org/?document=' . $post_id, get_permalink($post_id) ); faustwp_update_setting( 'frontend_uri', null );