Skip to content

Commit

Permalink
Merge pull request #1160 from alleyinteractive/fix/issue-1157/root-re…
Browse files Browse the repository at this point in the history
…lative-image-url-base-function

Issue-1157: Root-Relative Image URLs Use Wrong Function for Base URL
  • Loading branch information
renatonascalves authored Sep 12, 2024
2 parents 2e8f03f + 5a25146 commit 74bb65a
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 27 deletions.
2 changes: 1 addition & 1 deletion admin/apple-actions/index/class-export.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public function fetch_exporter() {
if ( ! empty( $post_thumb_url ) ) {
// If the post thumb URL is root-relative, convert it to fully-qualified.
if ( str_starts_with( $post_thumb_url, '/' ) ) {
$post_thumb_url = site_url( $post_thumb_url );
$post_thumb_url = home_url( $post_thumb_url );
}

// Compile the post_thumb object using the URL and caption from the featured image.
Expand Down
3 changes: 1 addition & 2 deletions includes/apple-exporter/class-exporter-content.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,13 @@ class Exporter_Content {
*
* @param string $url The URL to format.
*
* @access protected
* @return string The formatted URL on success, or a blank string on failure.
*/
public static function format_src_url( $url ) {

// If this is a root-relative path, make absolute.
if ( 0 === strpos( $url, '/' ) ) {
$url = site_url( $url );
$url = home_url( $url );
}

// Decode the HTML entities since the URL is from the src attribute.
Expand Down
6 changes: 3 additions & 3 deletions includes/apple-exporter/class-parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ public function parse( $html ): string {
// Fork for format.
if ( 'html' === $this->format ) {
return $this->parse_html( $html );
} else {
return $this->parse_markdown( $html );
}

return $this->parse_markdown( $html );
}

/**
Expand Down Expand Up @@ -204,7 +204,7 @@ private function remove_empty_a_tags( string $html ): string {
private function handle_root_relative_urls( string $html ): string {
return preg_replace_callback(
'/(<a[^>]+href=(["\'])\/[^\/].*?\2[^>]*>)/m',
fn( $matches ) => str_replace( 'href="/', 'href="' . get_site_url() . '/', $matches[0] ),
fn( $matches ) => str_replace( 'href="/', 'href="' . get_home_url() . '/', $matches[0] ),
$html
);
}
Expand Down
12 changes: 6 additions & 6 deletions tests/apple-exporter/components/test-class-cover.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function filter_apple_news_cover_json( $json ) {
* @return string The filtered URL, made root-relative.
*/
public function filter_wp_get_attachment_url( $url ) {
return str_replace( site_url(), '', $url );
return str_replace( home_url(), '', $url );
}

/**
Expand Down Expand Up @@ -64,10 +64,10 @@ public function test_cover_role() {
// Create test post.
$post_id = self::factory()->post->create();

// Create a new attachment and assign it as the featured image for the cover component.
set_post_thumbnail(
$post_id,
$this->get_new_attachment( 0 )
// Create a new attachment and assign it as the featured image for the cover component.
set_post_thumbnail(
$post_id,
$this->get_new_attachment( 0 )
);

// Check that the cover component's default role is 'photo'.
Expand Down Expand Up @@ -120,7 +120,7 @@ public function test_relative_url() {

// Create a post with an image with a root-relative src property and ensure its URL is expanded fully when converted to a Cover component.
$image_id_1 = $this->get_new_attachment( 0, 'Test Caption', 'Test alt text.' );
$post_id_1 = self::factory()->post->create( [ 'post_content' => str_replace( site_url(), '', $this->get_image_with_caption( $image_id_1 ) ) ] );
$post_id_1 = self::factory()->post->create( [ 'post_content' => str_replace( home_url(), '', $this->get_image_with_caption( $image_id_1 ) ) ] );
$json_1 = $this->get_json_for_post( $post_id_1 );
$this->assertEquals( wp_get_attachment_image_url( $image_id_1, 'full' ), $json_1['components'][0]['components'][0]['URL'] );

Expand Down
40 changes: 39 additions & 1 deletion tests/apple-exporter/test-class-exporter-content.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,48 @@ public function test_complete_content_with_cover_config() {
/**
* Ensure we decode the HTML entities in URLs extracted from HTML attributes.[type]
*/
public function test_format_src_url() {
public function test_format_src_url(): void {
$this->assertEquals(
'https://www.example.org/some.mp3?one=two&query=arg',
Exporter_Content::format_src_url( 'https://www.example.org/some.mp3?one=two&amp;query=arg' )
);

// Change the home URL.
update_option( 'home', 'https://www.custom-example.org' );

$this->assertEquals(
'https://www.example.org/some.mp3?one=two&query=arg',
Exporter_Content::format_src_url( 'https://www.example.org/some.mp3?one=two&amp;query=arg' )
);

$this->assertEquals(
'https://www.custom-example.org/',
Exporter_Content::format_src_url( '/' )
);

$this->assertEquals(
'https://www.custom-example.org',
Exporter_Content::format_src_url( 'https://www.custom-example.org' )
);

$this->assertNotEquals(
'https://www.custom-example.org',
Exporter_Content::format_src_url( '/' ),
'Root URL is missing a trailing slash.'
);

$this->assertEquals(
'https://www.example.org',
Exporter_Content::format_src_url( 'https://www.example.org' )
);

$this->assertNotEquals(
'https://www.example.org/', // The / here is intentional.
Exporter_Content::format_src_url( 'https://www.example.org' ),
'Root URL has a trailing slash.'
);

// Reset the home URL.
update_option( 'home', 'https://www.example.org' );
}
}
124 changes: 110 additions & 14 deletions tests/apple-exporter/test-class-parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ class Apple_News_Parser_Test extends Apple_News_Testcase {
*/
public function test_parse_markdown(): void {
// Create a basic HTML post.
$post = '<html><body><h2>A heading</h2><p><strong>This is strong.</strong><br><a href="https://www.apple.com">This is a link</a></p></body></html>';
$html = '<html><body><h2>A heading</h2><p><strong>This is strong.</strong><br><a href="https://www.apple.com">This is a link</a></p></body></html>';

// Convert to Markdown.
$parser = new Parser( 'markdown' );
$markdown = $parser->parse( $post );
$markdown = $parser->parse( $html );

// Verify.
$this->assertEquals( $markdown, "## A heading\n**This is strong.**\n[This is a link](https://www.apple.com)\n\n" );
Expand All @@ -38,10 +38,10 @@ public function test_parse_markdown(): void {
*/
public function test_parse_html(): void {
// Create a basic HTML post.
$post = '<h2 id="heading-target" class="someClass">A heading</h2><p><strong>This is strong.</strong><br><a href="https://www.apple.com" target="_blank">This is a link</a></p><div>The div tags will disappear.</div>';
$html_post = '<h2 id="heading-target" class="someClass">A heading</h2><p><strong>This is strong.</strong><br><a href="https://www.apple.com" target="_blank">This is a link</a></p><div>The div tags will disappear.</div>';

// Parse only HTML that's valid for Apple News.
$html = ( new Parser( 'html' ) )->parse( $post );
$html = ( new Parser( 'html' ) )->parse( $html_post );

// Verify.
$this->assertEquals( $html, 'A heading<p><strong>This is strong.</strong><br><a href="https://www.apple.com">This is a link</a></p>The div tags will disappear.' );
Expand All @@ -53,8 +53,6 @@ public function test_parse_html(): void {
* @see \Apple_Exporter\Parser::parse
*/
public function test_clean_html_markdown(): void {
// Create a post.
global $post;
$post_content = <<<HTML
<a href="https://www.google.com">Absolute link</a>
Expand All @@ -70,18 +68,17 @@ public function test_clean_html_markdown(): void {
<a href="thisisntarealurl">Not a real URL</a>
HTML;
$post = $this->factory->post->create_and_get( // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$article = $this->factory->post->create_and_get(
[
'post_type' => 'article',
'post_title' => 'Test Article',
'post_content' => $post_content,
]
);
$permalink = get_permalink( $post );

// Convert to Markdown.
$parser = new Parser( 'markdown' );
$markdown = $parser->parse( apply_filters( 'the_content', $post->post_content ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
$markdown = $parser->parse( apply_filters( 'the_content', $article->post_content ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound

// Verify.
$this->assertEquals(
Expand All @@ -96,14 +93,63 @@ public function test_clean_html_markdown(): void {
);
}

/**
* Test the anchor cleaning functions of the parser for Markdown.
*
* @see \Apple_Exporter\Parser::parse
*/
public function test_clean_html_markdown_with_diffent_home_url(): void {
update_option( 'home', 'https://www.custom-example.org' );

$post_content = <<<HTML
<a href="https://www.google.com">Absolute link</a>
<a href="/2018/05/03/an-92-test">Root-relative link</a>
<a id="testanchor">Test Anchor</a>
<a href="#testanchor">Anchor Link</a>
<a>Legit empty link</a>
<a href=" ">Link that trims to empty</a>
<a href="thisisntarealurl">Not a real URL</a>
HTML;
$article = $this->factory->post->create_and_get(
[
'post_type' => 'article',
'post_title' => 'Test Article',
'post_content' => $post_content,
]
);

// Convert to Markdown.
$parser = new Parser( 'markdown' );
$markdown = $parser->parse( apply_filters( 'the_content', $article->post_content ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound

// Verify.
$this->assertEquals(
'[Absolute link](https://www.google.com)'
. '[Root-relative link](https://www.custom-example.org/2018/05/03/an-92-test)'
. 'Test Anchor'
. '[Anchor Link](#testanchor)'
. 'Legit empty link'
. 'Link that trims to empty'
. 'Not a real URL',
str_replace( "\n", '', $markdown )
);

// Reset the home URL.
update_option( 'home', 'https://www.example.org' );
}

/**
* Test the anchor cleaning functions of the parser for HTML.
*
* @see \Apple_Exporter\Parser::parse
*/
public function test_clean_html(): void {
// Create a post.
global $post;
$post_content = <<<HTML
<a href="https://www.google.com">Absolute link</a>
Expand All @@ -119,18 +165,17 @@ public function test_clean_html(): void {
<a href="thisisntarealurl">Not a real URL</a>
HTML;
$post = $this->factory->post->create_and_get( // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$article = $this->factory->post->create_and_get(
[
'post_type' => 'article',
'post_title' => 'Test Article',
'post_content' => $post_content,
]
);
$permalink = get_permalink( $post );

// Parse the post with HTML content format.
$parser = new Parser( 'html' );
$parsed_html = $parser->parse( apply_filters( 'the_content', $post->post_content ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
$parsed_html = $parser->parse( apply_filters( 'the_content', $article->post_content ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound

// Verify.
$this->assertEquals(
Expand All @@ -144,4 +189,55 @@ public function test_clean_html(): void {
str_replace( "\n", '', $parsed_html )
);
}

/**
* Test the clean HTML function with a different root URL.
*
* @see \Apple_Exporter\Parser::parse
*/
public function test_clean_html_with_diffent_home_url(): void {
update_option( 'home', 'https://www.custom-example.org' );

$post_content = <<<HTML
<a href="https://www.google.com">Absolute link</a>
<a href="/2018/05/03/an-92-test">Root-relative link</a>
<a id="testanchor">Test Anchor</a>
<a href="#testanchor">Anchor Link</a>
<a>Legit empty link</a>
<a href=" ">Link that trims to empty</a>
<a href="thisisntarealurl">Not a real URL</a>
HTML;
$article = $this->factory->post->create_and_get(
[
'post_type' => 'article',
'post_title' => 'Test Article',
'post_content' => $post_content,
]
);

// Parse the post with HTML content format.
$parser = new Parser( 'html' );
$parsed_html = $parser->parse( apply_filters( 'the_content', $article->post_content ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound

// Verify.
$this->assertEquals(
'<p><a href="https://www.google.com">Absolute link</a></p>'
. '<p><a href="https://www.custom-example.org/2018/05/03/an-92-test">Root-relative link</a></p>'
. '<p>Test Anchor</p>'
. '<p><a href="#testanchor">Anchor Link</a></p>'
. '<p>Legit empty link</p>'
. '<p>Link that trims to empty</p>'
. '<p>Not a real URL</p>',
str_replace( "\n", '', $parsed_html )
);

// Reset the home URL.
update_option( 'home', 'https://www.example.org' );
}
}

0 comments on commit 74bb65a

Please sign in to comment.