diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 244cf84e9b810..29178aa4b511d 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -1193,7 +1193,12 @@ public function parse_tax_query( &$query_vars ) { continue; // Handled further down in the $query_vars['tag'] block. } - if ( $t->query_var && ! empty( $query_vars[ $t->query_var ] ) ) { + if ( $t->query_var + && isset( $query_vars[ $t->query_var ] ) + && ( is_array( $query_vars[ $t->query_var ] ) + ? ! empty( $query_vars[ $t->query_var ] ) + : '' !== (string) $query_vars[ $t->query_var ] ) + ) { $tax_query_defaults = array( 'taxonomy' => $taxonomy, 'field' => 'slug', @@ -3998,7 +4003,7 @@ public function get_queried_object() { if ( $cat ) { $term = get_term( $cat, 'category' ); - } elseif ( $category_name ) { + } elseif ( '' !== (string) $category_name ) { $term = get_term_by( 'slug', $category_name, 'category' ); } } elseif ( $this->is_tag ) { diff --git a/src/wp-includes/class-wp.php b/src/wp-includes/class-wp.php index f1664747d4042..8292afd684797 100644 --- a/src/wp-includes/class-wp.php +++ b/src/wp-includes/class-wp.php @@ -218,7 +218,7 @@ public function parse_request( $extra_query_vars = '' ) { // Look for matches. $request_match = $requested_path; - if ( empty( $request_match ) ) { + if ( '' === $request_match ) { // An empty request could only match against ^$ regex. if ( isset( $rewrite['$'] ) ) { $this->matched_rule = '$'; diff --git a/tests/phpunit/tests/rewrite/zeroPathSegment.php b/tests/phpunit/tests/rewrite/zeroPathSegment.php new file mode 100644 index 0000000000000..6da1a73de7ab1 --- /dev/null +++ b/tests/phpunit/tests/rewrite/zeroPathSegment.php @@ -0,0 +1,113 @@ +set_permalink_structure( $structure ); + create_initial_taxonomies(); + $wp_rewrite->flush_rules(); + } + + /** + * A "0" path segment should not silently fall through to the front page. + * + * @ticket 57858 + */ + public function test_zero_path_segment_should_404_when_no_matching_category_exists() { + $this->set_category_permalink_structure( '/%category%/%postname%/' ); + + self::factory()->post->create( array( 'post_status' => 'publish' ) ); + + $this->go_to( home_url( '/0/' ) ); + + $this->assertQueryTrue( 'is_404' ); + } + + /** + * A deeper path ending in "0" should 404 rather than resolve to an archive. + * + * @ticket 57858 + */ + public function test_nested_zero_path_segment_should_404() { + $this->set_category_permalink_structure( '/%category%/%postname%/' ); + + self::factory()->post->create( array( 'post_status' => 'publish' ) ); + + $this->go_to( home_url( '/wp-content/0/' ) ); + + $this->assertTrue( is_404() ); + $this->assertFalse( is_home() ); + } + + /** + * A category whose slug is "0" should still resolve to its archive. + * + * This guards against fixing the 404 by ignoring "0" outright. + * + * @ticket 57858 + */ + public function test_category_with_zero_slug_should_resolve_to_its_archive() { + global $wpdb; + + $this->set_category_permalink_structure( '/%category%/%postname%/' ); + + $category_id = self::factory()->category->create( array( 'name' => 'Zero' ) ); + + /* + * The slug has to be forced directly, as `wp_insert_term()` discards a + * slug of "0" and falls back to one derived from the name. + */ + $wpdb->update( $wpdb->terms, array( 'slug' => '0' ), array( 'term_id' => $category_id ) ); + clean_term_cache( $category_id, 'category' ); + + self::factory()->post->create( + array( + 'post_status' => 'publish', + 'post_category' => array( $category_id ), + ) + ); + + $this->go_to( home_url( '/0/' ) ); + + $this->assertQueryTrue( 'is_archive', 'is_category' ); + $this->assertSame( $category_id, get_queried_object_id() ); + } + + /** + * The front page must keep working, since an empty request is also falsy. + * + * @ticket 57858 + */ + public function test_empty_request_still_resolves_to_the_front_page() { + $this->set_category_permalink_structure( '/%category%/%postname%/' ); + + self::factory()->post->create( array( 'post_status' => 'publish' ) ); + + $this->go_to( home_url( '/' ) ); + + $this->assertQueryTrue( 'is_home', 'is_front_page' ); + } +}