From bfeffa332d2fd73a49320fb853b59862e194e696 Mon Sep 17 00:00:00 2001 From: Igor Rozum Date: Tue, 10 Nov 2026 11:21:05 -0500 Subject: [PATCH] Twenty Twenty-One: Respect custom text of the more tag in the continue reading link --- .../inc/template-functions.php | 28 ++++- .../twentyTwentyOneContinueReadingLink.php | 110 ++++++++++++++++++ 2 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 tests/phpunit/tests/theme/twentyTwentyOneContinueReadingLink.php diff --git a/src/wp-content/themes/twentytwentyone/inc/template-functions.php b/src/wp-content/themes/twentytwentyone/inc/template-functions.php index b7cbb1c6b12c2..27126bc75e4d8 100644 --- a/src/wp-content/themes/twentytwentyone/inc/template-functions.php +++ b/src/wp-content/themes/twentytwentyone/inc/template-functions.php @@ -163,19 +163,39 @@ function twenty_twenty_one_continue_reading_link_excerpt() { // Filter the excerpt more link. add_filter( 'excerpt_more', 'twenty_twenty_one_continue_reading_link_excerpt' ); +/** + * Checks whether the current post sets its own text for the more link. + * + * @return bool True if the post content has a `` tag. + */ +function twenty_twenty_one_has_custom_more_text() { + return 1 === preg_match( '//', (string) get_post_field( 'post_content', get_the_ID() ), $matches ) && '' !== trim( $matches[1] ); +} + /** * Creates the continue reading link. * * @since Twenty Twenty-One 1.0 + * + * @param string $more_link_element Read More link element. + * @param string $more_link_text Read More text. + * @return string|void The link markup, or nothing in the admin. */ -function twenty_twenty_one_continue_reading_link() { - if ( ! is_admin() ) { - return ''; +function twenty_twenty_one_continue_reading_link( $more_link_element = '', $more_link_text = '' ) { + if ( is_admin() ) { + return; } + + $link_text = twenty_twenty_one_continue_reading_text(); + if ( twenty_twenty_one_has_custom_more_text() ) { + $link_text = esc_html( $more_link_text ) . the_title( ' ', '', false ); + } + + return ''; } // Filter the content more link. -add_filter( 'the_content_more_link', 'twenty_twenty_one_continue_reading_link' ); +add_filter( 'the_content_more_link', 'twenty_twenty_one_continue_reading_link', 10, 2 ); if ( ! function_exists( 'twenty_twenty_one_post_title' ) ) { /** diff --git a/tests/phpunit/tests/theme/twentyTwentyOneContinueReadingLink.php b/tests/phpunit/tests/theme/twentyTwentyOneContinueReadingLink.php new file mode 100644 index 0000000000000..9694b6c479e73 --- /dev/null +++ b/tests/phpunit/tests/theme/twentyTwentyOneContinueReadingLink.php @@ -0,0 +1,110 @@ + + */ + private array $original_globals = array(); + + public function set_up() { + parent::set_up(); + + // `backupGlobals` is disabled for the suite, so these have to be restored by hand. + foreach ( $this->global_names as $global_name ) { + if ( array_key_exists( $global_name, $GLOBALS ) ) { + $this->original_globals[ $global_name ] = $GLOBALS[ $global_name ]; + } + } + + $template_functions = WP_CONTENT_DIR . '/themes/twentytwentyone/inc/template-functions.php'; + if ( ! file_exists( $template_functions ) ) { + $this->markTestSkipped( 'The Twenty Twenty-One theme is not installed.' ); + } + require_once $template_functions; + } + + public function tear_down() { + foreach ( $this->global_names as $global_name ) { + if ( array_key_exists( $global_name, $this->original_globals ) ) { + $GLOBALS[ $global_name ] = $this->original_globals[ $global_name ]; + } else { + unset( $GLOBALS[ $global_name ] ); + } + } + + parent::tear_down(); + } + + private function set_up_post( string $content ): void { + $post_id = self::factory()->post->create( array( 'post_content' => $content ) ); + + $GLOBALS['post'] = get_post( $post_id ); + setup_postdata( $GLOBALS['post'] ); + } + + /** + * @ticket 52683 + */ + public function test_uses_custom_more_text_when_set() { + $this->set_up_post( 'TeaserRest' ); + + $link = twenty_twenty_one_continue_reading_link( '', 'Read the full story' ); + + $this->assertStringContainsString( '>Read the full story ', $link ); + $this->assertStringNotContainsString( 'Continue reading', $link ); + } + + /** + * @ticket 52683 + */ + public function test_uses_theme_text_without_custom_more_text() { + $this->set_up_post( 'TeaserRest' ); + + $link = twenty_twenty_one_continue_reading_link( '', twenty_twenty_one_continue_reading_text() ); + + $this->assertStringContainsString( 'Continue reading', $link ); + $this->assertStringContainsString( 'class="more-link"', $link ); + } + + /** + * @ticket 52683 + */ + public function test_escapes_custom_more_text() { + $this->set_up_post( 'TeaserRest' ); + + $link = twenty_twenty_one_continue_reading_link( '', 'Tom & Jerry' ); + + $this->assertStringContainsString( 'Tom & Jerry', $link ); + } + + /** + * @ticket 52683 + */ + public function test_the_content_shows_custom_more_text() { + add_filter( 'the_content_more_link', 'twenty_twenty_one_continue_reading_link', 10, 2 ); + $GLOBALS['more'] = 0; + $this->set_up_post( 'TeaserRest' ); + + $content = get_the_content( twenty_twenty_one_continue_reading_text() ); + + $this->assertStringContainsString( 'Read the full story', $content ); + $this->assertStringContainsString( 'more-link-container', $content ); + } +}