diff --git a/src/wp-includes/link-template.php b/src/wp-includes/link-template.php index e454ecebe0..9f3d9a97ee 100644 --- a/src/wp-includes/link-template.php +++ b/src/wp-includes/link-template.php @@ -2431,6 +2431,9 @@ function get_pagenum_link( $pagenum = 1, $escape = true ) { $qs_regex = '|\?.*?$|'; preg_match( $qs_regex, $request, $qs_match ); + $parts = array(); + $parts[] = untrailingslashit( get_bloginfo( 'url' ) ); + if ( ! empty( $qs_match[0] ) ) { $query_string = $qs_match[0]; $request = preg_replace( $qs_regex, '', $request ); @@ -2442,17 +2445,21 @@ function get_pagenum_link( $pagenum = 1, $escape = true ) { $request = preg_replace( '|^' . preg_quote( $wp_rewrite->index, '|' ) . '|i', '', $request ); $request = ltrim( $request, '/' ); - $base = trailingslashit( get_bloginfo( 'url' ) ); - if ( $wp_rewrite->using_index_permalinks() && ( $pagenum > 1 || '' !== $request ) ) { - $base .= $wp_rewrite->index . '/'; + $parts[] = $wp_rewrite->index; } + $parts[] = untrailingslashit( $request ); + if ( $pagenum > 1 ) { - $request = ( ( ! empty( $request ) ) ? trailingslashit( $request ) : $request ) . user_trailingslashit( $wp_rewrite->pagination_base . '/' . $pagenum, 'paged' ); + $parts[] = $wp_rewrite->pagination_base; + $parts[] = $pagenum; } - $result = $base . $request . $query_string; + $result = user_trailingslashit( implode( '/', array_filter( $parts ) ), 'paged' ); + if ( ! empty( $query_string ) ) { + $result .= $query_string; + } } /** diff --git a/tests/phpunit/tests/link.php b/tests/phpunit/tests/link.php index f3216c17ee..d05a6b210f 100644 --- a/tests/phpunit/tests/link.php +++ b/tests/phpunit/tests/link.php @@ -4,28 +4,6 @@ */ class Tests_Link extends WP_UnitTestCase { - public function get_pagenum_link_cb( $url ) { - return $url . '/WooHoo'; - } - - /** - * @ticket 8847 - */ - public function test_get_pagenum_link_case_insensitivity() { - $old_req_uri = $_SERVER['REQUEST_URI']; - - $this->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' ); - - add_filter( 'home_url', array( $this, 'get_pagenum_link_cb' ) ); - $_SERVER['REQUEST_URI'] = '/woohoo'; - $paged = get_pagenum_link( 2 ); - - remove_filter( 'home_url', array( $this, 'get_pagenum_link_cb' ) ); - $this->assertSame( $paged, home_url( '/WooHoo/page/2/' ) ); - - $_SERVER['REQUEST_URI'] = $old_req_uri; - } - public function test_wp_get_shortlink() { $post_id = self::factory()->post->create(); $post_id2 = self::factory()->post->create(); diff --git a/tests/phpunit/tests/link/getPagenumLink.php b/tests/phpunit/tests/link/getPagenumLink.php new file mode 100644 index 0000000000..9c81cc8454 --- /dev/null +++ b/tests/phpunit/tests/link/getPagenumLink.php @@ -0,0 +1,199 @@ +set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' ); + + add_filter( 'home_url', array( $this, 'get_pagenum_link_cb' ) ); + $_SERVER['REQUEST_URI'] = '/woohoo'; + $paged = get_pagenum_link( 2 ); + + remove_filter( 'home_url', array( $this, 'get_pagenum_link_cb' ) ); + $this->assertSame( $paged, home_url( '/WooHoo/page/2/' ) ); + } + + /** + * Appends '/WooHoo' to the provided URL. + * + * Callback for the 'home_url' filter hook. + * + * @param string $url The base URL. + * @return string The base URL with '/WooHoo' appended. + */ + public function get_pagenum_link_cb( $url ) { + return $url . '/WooHoo'; + } + + /** + * Tests that a trailing slash is not added to the link. + * + * @ticket 2877 + * + * @dataProvider data_get_pagenum_link_plain_permalinks + * @dataProvider data_get_pagenum_link + * + * @param string $permalink_structure The structure to use for permalinks. + * @param string $request_uri The value for `$_SERVER['REQUEST_URI']`. + * @param int $pagenum The page number to get the link for. + * @param string $expected The expected relative URL. + */ + public function test_get_pagenum_link_should_not_add_trailing_slash( $permalink_structure, $request_uri, $pagenum, $expected ) { + $this->set_permalink_structure( $permalink_structure ); + $_SERVER['REQUEST_URI'] = $request_uri; + $paged = get_pagenum_link( $pagenum ); + + $this->assertSame( home_url( $expected ), $paged ); + } + + /** + * Data provider. + * + * @return array[] + */ + public function data_get_pagenum_link_plain_permalinks() { + return array( + 'page 1 and plain permalinks' => array( + 'permalink_structure' => '', + 'request_uri' => '/?paged=2', + 'pagenum' => 1, + 'expected' => '/', + ), + 'page 2 and plain permalinks' => array( + 'permalink_structure' => '', + 'request_uri' => '/', + 'pagenum' => 2, + 'expected' => '/?paged=2', + ), + ); + } + + /** + * Tests that a trailing slash is added to the link when a trailing slash + * exists in the permalink structure. + * + * @ticket 2877 + * + * @dataProvider data_get_pagenum_link + * + * @param string $permalink_structure The structure to use for permalinks. + * @param string $request_uri The value for `$_SERVER['REQUEST_URI']`. + * @param int $pagenum The page number to get the link for. + * @param string $expected The expected relative URL. + */ + public function test_get_pagenum_link_should_add_trailing_slash( $permalink_structure, $request_uri, $pagenum, $expected ) { + // Ensure the permalink structure has a trailing slash. + $permalink_structure = trailingslashit( $permalink_structure ); + + // Ensure the expected value has a trailing slash at the appropriate position. + if ( str_contains( $expected, '?' ) ) { + // Contains query args. + $parts = explode( '?', $expected, 2 ); + $expected = trailingslashit( $parts[0] ) . '?' . $parts[1]; + } else { + $expected = trailingslashit( $expected ); + } + + $this->set_permalink_structure( $permalink_structure ); + $_SERVER['REQUEST_URI'] = $request_uri; + $paged = get_pagenum_link( $pagenum ); + + $this->assertSame( home_url( $expected ), $paged ); + } + + /** + * Data provider. + * + * @return array[] + */ + public function data_get_pagenum_link() { + return array( + 'page 1 and index.php' => array( + 'permalink_structure' => '/index.php/%year%/%monthnum%/%day%/%postname%', + 'request_uri' => '/index.php/woohoo/page/2/', + 'pagenum' => 1, + 'expected' => '/index.php/woohoo', + ), + 'page 2 and index.php' => array( + 'permalink_structure' => '/index.php/%year%/%monthnum%/%day%/%postname%', + 'request_uri' => '/index.php/woohoo/page/2/', + 'pagenum' => 2, + 'expected' => '/index.php/woohoo/page/2', + ), + 'page 1 with date-based permalinks' => array( + 'permalink_structure' => '/%year%/%monthnum%/%day%/%postname%', + 'request_uri' => '/woohoo/page/2/', + 'pagenum' => 1, + 'expected' => '/woohoo', + ), + 'page 2 with date-based permalinks' => array( + 'permalink_structure' => '/%year%/%monthnum%/%day%/%postname%', + 'request_uri' => '/woohoo', + 'pagenum' => 2, + 'expected' => '/woohoo/page/2', + ), + 'page 1 with postname-based permalinks' => array( + 'permalink_structure' => '/%postname%', + 'request_uri' => '/woohoo/page/2', + 'pagenum' => 1, + 'expected' => '/woohoo', + ), + 'page 2 with postname-based permalinks' => array( + 'permalink_structure' => '/%postname%', + 'request_uri' => '/woohoo', + 'pagenum' => 2, + 'expected' => '/woohoo/page/2', + ), + 'page 1 with postname-based permalinks and query args' => array( + 'permalink_structure' => '/%postname%', + 'request_uri' => '/woohoo/page/2?test=1234', + 'pagenum' => 1, + 'expected' => '/woohoo?test=1234', + ), + 'page 2 with postname-based permalinks and query args' => array( + 'permalink_structure' => '/%postname%', + 'request_uri' => '/woohoo?test=1234', + 'pagenum' => 2, + 'expected' => '/woohoo/page/2?test=1234', + ), + ); + } +}