diff --git a/.changeset/four-books-invent.md b/.changeset/four-books-invent.md new file mode 100644 index 000000000..21f3cec7f --- /dev/null +++ b/.changeset/four-books-invent.md @@ -0,0 +1,5 @@ +--- +'@faustwp/wordpress-plugin': patch +--- + +Fixed a bug that caused links to files in wp-content to be rewritten to the Faust Front-end site URL when they should not have been. diff --git a/plugins/faustwp/includes/replacement/callbacks.php b/plugins/faustwp/includes/replacement/callbacks.php index 82a271baa..0115469f2 100644 --- a/plugins/faustwp/includes/replacement/callbacks.php +++ b/plugins/faustwp/includes/replacement/callbacks.php @@ -10,7 +10,9 @@ use function WPE\FaustWP\Settings\{ faustwp_get_setting, is_image_source_replacement_enabled, - is_rewrites_enabled + is_rewrites_enabled, + use_wp_domain_for_media, + use_wp_domain_for_post_and_category_urls, }; use function WPE\FaustWP\Utilities\{ plugin_version, @@ -21,32 +23,49 @@ } add_filter( 'the_content', __NAMESPACE__ . '\\content_replacement' ); +add_filter( 'wpgraphql_content_blocks_resolver_content', __NAMESPACE__ . '\\content_replacement' ); /** * Callback for WordPress 'the_content' filter. * * @param string $content The post content. * * @return string The post content. - * @todo Needs work... */ function content_replacement( $content ) { - if ( ! domain_replacement_enabled() ) { + $use_wp_domain_for_permalinks = ! domain_replacement_enabled(); + $use_wp_domain_for_media = use_wp_domain_for_media(); + + if ( $use_wp_domain_for_permalinks && $use_wp_domain_for_media ) { return $content; } $replacement = faustwp_get_setting( 'frontend_uri' ); - $site_url = site_url(); - if ( ! $replacement ) { $replacement = '/'; } - $content = str_replace( "href=\"{$site_url}", "href=\"{$replacement}", $content ); + $site_url = site_url(); + $media_dir = str_replace( $site_url, '', wp_upload_dir()['baseurl'] ); + $media_url = $site_url . $media_dir; + + if ( $use_wp_domain_for_permalinks && ! $use_wp_domain_for_media ) { + $content = str_replace( $media_url, $replacement . $media_dir, $content ); + return $content; + } + + if ( ! $use_wp_domain_for_permalinks && ! $use_wp_domain_for_media ) { + $content = str_replace( $site_url, $replacement, $content ); + return $content; + } + + if ( ! $use_wp_domain_for_permalinks && $use_wp_domain_for_media ) { + $content = preg_replace( "#{$site_url}(?!{$media_dir})#", "{$replacement}", $content ); + return $content; + } - return str_replace( 'href="//', 'href="/', $content ); + return $content; } -add_filter( 'the_content', __NAMESPACE__ . '\\image_source_replacement' ); /** * Callback for WordPress 'the_content' filter to replace paths to media. * @@ -79,21 +98,36 @@ function image_source_replacement( $content ) { * @return string One or more arrays of source data. */ function image_source_srcset_replacement( $sources ) { - if ( ! is_image_source_replacement_enabled() ) { - return $sources; - } + $use_wp_domain_for_media = use_wp_domain_for_media(); + $frontend_uri = faustwp_get_setting( 'frontend_uri' ); + $site_url = site_url(); + + /** + * For urls with no domain or the frontend domain, replace with the WP site_url. + * This was the default replacement pattern until Faust 1.2, at which point this + * was adjusted to correct replacement bugs. + */ + $patterns = array( + "#^{$site_url}/#", + '#^/#', + ); - $frontend_uri = faustwp_get_setting( 'frontend_uri' ); - $site_url = site_url(); + $replacement = $frontend_uri; - if ( is_array( $sources ) ) { - // For urls with no domain or the frontend domain, replace with the wp site_url. - $patterns = array( + /** + * If using WP domain for media and a frontend URL is encountered, rewrite it to WP URL. + */ + if ( $use_wp_domain_for_media ) { + $patterns = array( "#^{$frontend_uri}/#", '#^/#', ); + $replacement = $site_url; + } + + if ( is_array( $sources ) ) { foreach ( $sources as $width => $source ) { - $sources[ $width ]['url'] = preg_replace( $patterns, "$site_url/", $sources[ $width ]['url'] ); + $sources[ $width ]['url'] = preg_replace( $patterns, "$replacement/", $source['url'] ); } } diff --git a/plugins/faustwp/includes/replacement/functions.php b/plugins/faustwp/includes/replacement/functions.php index 3a875e207..84768450a 100644 --- a/plugins/faustwp/includes/replacement/functions.php +++ b/plugins/faustwp/includes/replacement/functions.php @@ -9,7 +9,8 @@ use function WPE\FaustWP\Settings\{ faustwp_get_setting, - is_rewrites_enabled + is_rewrites_enabled, + use_wp_domain_for_post_and_category_urls, }; if ( ! defined( 'ABSPATH' ) ) { @@ -19,8 +20,6 @@ /** * Determine if domain replacement can be done. * - * Enabled if query string parameter 'replace-domain' is present. - * * @return bool True if can proceed with replacement, false if else. */ function domain_replacement_enabled() { @@ -31,7 +30,7 @@ function domain_replacement_enabled() { * * @param bool $enabled True if domain replacement is enabled, false if else. */ - return apply_filters( 'faustwp_domain_replacement_enabled', is_rewrites_enabled() ); + return apply_filters( 'faustwp_domain_replacement_enabled', ! use_wp_domain_for_post_and_category_urls() ); } /** diff --git a/plugins/faustwp/includes/replacement/graphql-callbacks.php b/plugins/faustwp/includes/replacement/graphql-callbacks.php index 8de262e10..e8397d88e 100644 --- a/plugins/faustwp/includes/replacement/graphql-callbacks.php +++ b/plugins/faustwp/includes/replacement/graphql-callbacks.php @@ -14,7 +14,6 @@ exit; } -add_filter( 'graphql_request_results', __NAMESPACE__ . '\\url_replacement' ); /** * Callback for WP GraphQL 'graphql_request_results' filter. * diff --git a/plugins/faustwp/includes/settings/functions.php b/plugins/faustwp/includes/settings/functions.php index 56aa42e89..ba2d643c1 100644 --- a/plugins/faustwp/includes/settings/functions.php +++ b/plugins/faustwp/includes/settings/functions.php @@ -29,6 +29,15 @@ function is_rewrites_enabled() { return '1' === faustwp_get_setting( 'enable_rewrites' ); } +/** + * Determines if posts and category URLs should link to the WP site. + * + * @return bool + */ +function use_wp_domain_for_post_and_category_urls() { + return ! is_rewrites_enabled(); +} + /** * Determine if themes are disabled. * @@ -47,6 +56,14 @@ function is_image_source_replacement_enabled() { return '1' === faustwp_get_setting( 'enable_image_source' ); } +/** + * Determine if sourcing images from WP domain is enabled. + * + * @return bool True if image sources from WP are enabled, false if else. + */ +function use_wp_domain_for_media() { + return is_image_source_replacement_enabled(); +} /** * Get the secret key setting. diff --git a/plugins/faustwp/tests/integration/GraphQLCallbacksTests.php b/plugins/faustwp/tests/integration/GraphQLCallbacksTests.php index 2364fca4a..8e4e57fcc 100644 --- a/plugins/faustwp/tests/integration/GraphQLCallbacksTests.php +++ b/plugins/faustwp/tests/integration/GraphQLCallbacksTests.php @@ -115,10 +115,6 @@ public function test_graphql_section_field_value() { $this->assertSame( 10, has_action( 'graphql_get_setting_section_field_value', 'WPE\FaustWP\GraphQL\filter_introspection' ) ); } - public function test_graphql_request_results_filter() { - $this->assertSame( 10, has_action( 'graphql_request_results', 'WPE\FaustWP\Replacement\url_replacement' ) ); - } - /** * Tests url_replacement() returns original data when rewrites are not enabled. */ diff --git a/plugins/faustwp/tests/integration/ReplacementCallbacksTests.php b/plugins/faustwp/tests/integration/ReplacementCallbacksTests.php index 15cbb5161..de3f4be75 100644 --- a/plugins/faustwp/tests/integration/ReplacementCallbacksTests.php +++ b/plugins/faustwp/tests/integration/ReplacementCallbacksTests.php @@ -48,10 +48,6 @@ public function test_term_link_filter() { $this->assertSame( 1000, has_action( 'term_link', 'WPE\FaustWP\Replacement\term_link' ) ); } - public function test_graphql_request_results_filter() { - $this->assertSame( 10, has_action( 'graphql_request_results', 'WPE\FaustWP\Replacement\url_replacement' ) ); - } - public function test_enqueue_preview_scripts_action() { $this->assertSame( 10, has_action( 'enqueue_block_editor_assets', 'WPE\FaustWP\Replacement\enqueue_preview_scripts' ) ); } @@ -68,6 +64,10 @@ public function test_wpseo_xml_sitemap_post_url_filter() { $this->assertSame( 10, has_action( 'wpseo_xml_sitemap_post_url', 'WPE\FaustWP\Replacement\yoast_sitemap_post_url' ) ); } + public function test_wp_calculate_image_srcset_filter(): void { + self::assertSame( 10, has_action( 'wp_calculate_image_srcset', 'WPE\FaustWP\Replacement\image_source_srcset_replacement' ) ); + } + /** * Tests content_replacement() returns original value when content replacement is not enabled. */ @@ -131,6 +131,9 @@ public function test_image_source_srcset_replacement_filters_content_when_image_ public function test_image_source_replacement_filters_content_when_image_replacement_not_enabled() { faustwp_update_setting( 'enable_image_source', '0' ); $this->assertSame( '', image_source_replacement( '' ) ); + + // Ensure unrelated domains are left alone. + $this->assertSame( '', image_source_replacement( '' ) ); } /** @@ -255,6 +258,44 @@ public function test_term_link_returns_filtered_link_when_rewrite_term_links_ena $this->assertSame( 'http://moo/?cat=' . $term_id, get_term_link( $term_id ) ); } + /** + * Tests content_replacement() handles mixed content blobs properly. + */ + public function test_content_replacement_properly_handles_a_mixed_content_blob() { + faustwp_update_setting( 'frontend_uri', 'http://moo' ); + faustwp_update_setting( 'enable_image_source', '1' ); + faustwp_update_setting( 'enable_rewrites', '1' ); + + $input = <<This is a post link.

This is a media link to a PDF file.

This is a media link to an image.

+ INPUT; + + $output = <<This is a post link.

This is a media link to a PDF file.

This is a media link to an image.

+ OUTPUT; + + self::assertSame( + $output, + content_replacement( $input ) + ); + + // Check that media URLs are rewritten when enable_image_source setting is configured to NOT use the WP domain. + faustwp_update_setting( 'enable_image_source', '0' ); + + $input = <<This is a post link.

This is a media link to a PDF file.

This is a media link to an image.

+ INPUT; + + $output = <<This is a post link.

This is a media link to a PDF file.

This is a media link to an image.

+ OUTPUT; + + self::assertSame( + $output, + content_replacement( $input ) + ); + } + private function getCustomPostType() { register_post_type('document', [ 'public' => true,