diff --git a/src/wp-includes/canonical.php b/src/wp-includes/canonical.php index 423dcc6366..0c56ba24f0 100644 --- a/src/wp-includes/canonical.php +++ b/src/wp-includes/canonical.php @@ -101,6 +101,20 @@ function redirect_canonical( $requested_url = null, $do_redirect = true ) { } } + if ( get_query_var( 'day' ) && get_query_var( 'monthnum' ) && get_query_var( 'year' ) ) { + $year = get_query_var( 'year' ); + $month = get_query_var( 'monthnum' ); + $day = get_query_var( 'day' ); + $date = sprintf( '%04d-%02d-%02d', $year, $month, $day ); + if ( ! wp_checkdate( $month, $day, $year, $date ) ) { + $redirect_url = get_month_link( $year, $month ); + $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'year', 'monthnum', 'day' ), $redirect_url ); + } + } elseif ( get_query_var( 'monthnum' ) && get_query_var( 'year' ) && 12 < get_query_var( 'monthnum' ) ) { + $redirect_url = get_year_link( get_query_var( 'year' ) ); + $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'year', 'monthnum' ), $redirect_url ); + } + if ( ! $redirect_url ) { if ( $redirect_url = redirect_guess_404_permalink() ) { $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'page', 'feed', 'p', 'page_id', 'attachment_id', 'pagename', 'name', 'post_type' ), $redirect_url ); diff --git a/src/wp-includes/query.php b/src/wp-includes/query.php index 329b8d9330..0286072738 100644 --- a/src/wp-includes/query.php +++ b/src/wp-includes/query.php @@ -1513,15 +1513,24 @@ class WP_Query { if ( $qv['day'] ) { if ( ! $this->is_date ) { - $this->is_day = true; - $this->is_date = true; + $date = sprintf( '%04d-%02d-%02d', $qv['year'], $qv['monthnum'], $qv['day'] ); + if ( $qv['monthnum'] && $qv['year'] && ! wp_checkdate( $qv['monthnum'], $qv['day'], $qv['year'], $date ) ) { + $qv['error'] = '404'; + } else { + $this->is_day = true; + $this->is_date = true; + } } } if ( $qv['monthnum'] ) { if ( ! $this->is_date ) { - $this->is_month = true; - $this->is_date = true; + if ( 12 < $qv['monthnum'] ) { + $qv['error'] = '404'; + } else { + $this->is_month = true; + $this->is_date = true; + } } } diff --git a/tests/phpunit/tests/canonical.php b/tests/phpunit/tests/canonical.php index c45da604a5..48fbab5baa 100644 --- a/tests/phpunit/tests/canonical.php +++ b/tests/phpunit/tests/canonical.php @@ -239,6 +239,9 @@ class Tests_Canonical extends WP_UnitTestCase { array( '/?year=2008', '/2008/'), + array( '/2012/13/', '/2012/'), + array( '/2012/11/51/', '/2012/11/'), + // Authors array( '/?author=%d', '/author/canonical-author/' ), // array( '/?author=%d&year=2008', '/2008/?author=3'), diff --git a/tests/phpunit/tests/query/conditionals.php b/tests/phpunit/tests/query/conditionals.php index 980180789f..57cdc4aa67 100644 --- a/tests/phpunit/tests/query/conditionals.php +++ b/tests/phpunit/tests/query/conditionals.php @@ -629,4 +629,12 @@ class Tests_Query_Conditionals extends WP_UnitTestCase { // '[0-9]{4}/[0-9]{1,2}/[0-9]{1,2}/[^/]+/attachment/([^/]+)/trackback/?$' => 'index.php?attachment=$matches[1]&tb=1', // '[0-9]{4}/[0-9]{1,2}/[0-9]{1,2}/[^/]+/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]', // '[0-9]{4}/[0-9]{1,2}/[0-9]{1,2}/[^/]+/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]', + + function test_bad_dates() { + $this->go_to( '/2013/13/13/' ); + $this->assertQueryTrue( 'is_404' ); + + $this->go_to( '/2013/11/41/' ); + $this->assertQueryTrue( 'is_404' ); + } } diff --git a/tests/phpunit/tests/query/results.php b/tests/phpunit/tests/query/results.php index 9b0978edc9..6c49e40d58 100644 --- a/tests/phpunit/tests/query/results.php +++ b/tests/phpunit/tests/query/results.php @@ -486,4 +486,51 @@ class Tests_Query_Results extends WP_UnitTestCase { $author_ids = array_unique( wp_list_pluck( $posts, 'post_author' ) ); $this->assertEqualSets( array( $author_1 ), $author_ids ); } + + /** + * @ticket 10935 + */ + function test_query_is_date() { + $this->q->query( array( + 'year' => '2007', + 'monthnum' => '01', + 'day' => '01', + ) ); + + $this->assertTrue( $this->q->is_date ); + $this->assertTrue( $this->q->is_day ); + $this->assertFalse( $this->q->is_month ); + $this->assertFalse( $this->q->is_year ); + + $this->q->query( array( + 'year' => '2007', + 'monthnum' => '01', + ) ); + + $this->assertTrue( $this->q->is_date ); + $this->assertFalse( $this->q->is_day ); + $this->assertTrue( $this->q->is_month ); + $this->assertFalse( $this->q->is_year ); + + $this->q->query( array( + 'year' => '2007', + ) ); + + $this->assertTrue( $this->q->is_date ); + $this->assertFalse( $this->q->is_day ); + $this->assertFalse( $this->q->is_month ); + $this->assertTrue( $this->q->is_year ); + + $this->q->query( array( + 'year' => '2007', + 'monthnum' => '01', + 'day' => '50', + ) ); + + $this->assertTrue( $this->q->is_404 ); + $this->assertFalse( $this->q->is_date ); + $this->assertFalse( $this->q->is_day ); + $this->assertFalse( $this->q->is_month ); + $this->assertFalse( $this->q->is_year ); + } }