diff --git a/src/wp-includes/date.php b/src/wp-includes/date.php index ea2b4a60a2..0a789337ad 100644 --- a/src/wp-includes/date.php +++ b/src/wp-includes/date.php @@ -815,16 +815,59 @@ class WP_Date_Query { * @since 3.7.0 * @access public * - * @param string|array $datetime An array of parameters or a strotime() string - * @param string $default_to Controls what values default to if they are missing from $datetime. Pass "min" or "max". + * @param string|array $datetime An array of parameters or a strotime() string + * @param bool $default_to_max Whether to round up incomplete dates. Supported by values + * of $datetime that are arrays, or string values that are a + * subset of MySQL date format ('Y', 'Y-m', 'Y-m-d', 'Y-m-d H:i'). + * Default: false. * @return string|false A MySQL format date/time or false on failure */ public function build_mysql_datetime( $datetime, $default_to_max = false ) { $now = current_time( 'timestamp' ); if ( ! is_array( $datetime ) ) { - // @todo Timezone issues here possibly - return gmdate( 'Y-m-d H:i:s', strtotime( $datetime, $now ) ); + + /* + * Try to parse some common date formats, so we can detect + * the level of precision and support the 'inclusive' parameter. + */ + if ( preg_match( '/^(\d{4})$/', $datetime, $matches ) ) { + // Y + $datetime = array( + 'year' => intval( $matches[1] ), + ); + + } else if ( preg_match( '/^(\d{4})\-(\d{2})$/', $datetime, $matches ) ) { + // Y-m + $datetime = array( + 'year' => intval( $matches[1] ), + 'month' => intval( $matches[2] ), + ); + + } else if ( preg_match( '/^(\d{4})\-(\d{2})\-(\d{2})$/', $datetime, $matches ) ) { + // Y-m-d + $datetime = array( + 'year' => intval( $matches[1] ), + 'month' => intval( $matches[2] ), + 'day' => intval( $matches[3] ), + ); + + } else if ( preg_match( '/^(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2})$/', $datetime, $matches ) ) { + // Y-m-d H:i + $datetime = array( + 'year' => intval( $matches[1] ), + 'month' => intval( $matches[2] ), + 'day' => intval( $matches[3] ), + 'hour' => intval( $matches[4] ), + 'minute' => intval( $matches[5] ), + ); + } + + // If no match is found, we don't support default_to_max. + if ( ! is_array( $datetime ) ) { + // @todo Timezone issues here possibly + return gmdate( 'Y-m-d H:i:s', strtotime( $datetime, $now ) ); + } } $datetime = array_map( 'absint', $datetime ); diff --git a/tests/phpunit/tests/query/dateQuery.php b/tests/phpunit/tests/query/dateQuery.php index 676d860ce9..7570d7b8ac 100644 --- a/tests/phpunit/tests/query/dateQuery.php +++ b/tests/phpunit/tests/query/dateQuery.php @@ -271,6 +271,378 @@ class Tests_Query_DateQuery extends WP_UnitTestCase { $this->assertEquals( $expected_dates, wp_list_pluck( $posts, 'post_date' ) ); } + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_Y() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 13:00:00', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2007-05-07 13:00:00', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008', + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2007', + ), + ) ); + + $this->assertEquals( array( $p2 ), $before_posts ); + $this->assertEquals( array( $p1 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_Y_inclusive() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 13:00:00', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2007-05-07 13:00:00', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008', + 'inclusive' => true, + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2007', + 'inclusive' => true, + ), + ) ); + + $this->assertEqualSets( array( $p1, $p2 ), $before_posts ); + $this->assertEqualSets( array( $p1, $p2 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_Ym() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 13:00:00', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2008-04-07 13:00:00', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008-05', + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2008-04', + ), + ) ); + + $this->assertEquals( array( $p2 ), $before_posts ); + $this->assertEquals( array( $p1 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_Ym_inclusive() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 13:00:00', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2008-04-07 13:00:00', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008-05', + 'inclusive' => true, + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2008-04', + 'inclusive' => true, + ), + ) ); + + $this->assertEqualSets( array( $p1, $p2 ), $before_posts ); + $this->assertEqualSets( array( $p1, $p2 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_Ymd() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 13:00:00', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2008-05-05 13:00:00', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008-05-06', + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2008-05-05', + ), + ) ); + + $this->assertEquals( array( $p2 ), $before_posts ); + $this->assertEquals( array( $p1 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_Ymd_inclusive() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 13:00:00', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2008-05-05 13:00:00', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008-05-06', + 'inclusive' => true, + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2008-05-05', + 'inclusive' => true, + ), + ) ); + + $this->assertEqualSets( array( $p1, $p2 ), $before_posts ); + $this->assertEqualSets( array( $p1, $p2 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_YmdHi() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:05:00', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:04:00', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008-05-06 14:05', + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2008-05-06 14:04', + ), + ) ); + + $this->assertEquals( array( $p2 ), $before_posts ); + $this->assertEquals( array( $p1 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_YmdHi_inclusive() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:05:00', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:04:00', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008-05-06 14:05', + 'inclusive' => true, + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2008-05-06 14:04', + 'inclusive' => true, + ), + ) ); + + $this->assertEqualSets( array( $p1, $p2 ), $before_posts ); + $this->assertEqualSets( array( $p1, $p2 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_YmdHis() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:05:15', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:05:14', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008-05-06 14:05:15', + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2008-05-06 14:05:14', + ), + ) ); + + $this->assertEquals( array( $p2 ), $before_posts ); + $this->assertEquals( array( $p1 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_YmdHis_inclusive() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:04:15', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:04:14', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => '2008-05-06 14:04:15', + 'inclusive' => true, + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => '2008-05-06 14:04:14', + 'inclusive' => true, + ), + ) ); + + $this->assertEqualSets( array( $p1, $p2 ), $before_posts ); + $this->assertEqualSets( array( $p1, $p2 ), $after_posts ); + } + + /** + * @ticket 29908 + */ + public function test_beforeafter_with_date_string_non_parseable() { + $p1 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:05:15', + ) ); + $p2 = $this->factory->post->create( array( + 'post_date' => '2008-05-06 14:05:14', + ) ); + + $before_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'before' => 'June 12, 2008', + ), + ) ); + + $after_posts = $this->_get_query_result( array( + 'fields' => 'ids', + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'date_query' => array( + 'after' => 'June 12, 2007', + ), + ) ); + + $this->assertEquals( array( $p1, $p2 ), $before_posts ); + } + public function test_date_query_year_expecting_results() { $this->create_posts();