| 1 |
<?php |
| 2 |
/** |
| 3 |
* Support date query integration |
| 4 |
* |
| 5 |
* @package elasticpress |
| 6 |
* @since 1.3 |
| 7 |
*/ |
| 8 |
|
| 9 |
namespace ElasticPress\Indexable\Post; |
| 10 |
|
| 11 |
use \WP_Date_Query as WP_Date_Query; |
| 12 |
|
| 13 |
if ( ! defined( 'ABSPATH' ) ) { |
| 14 |
// @codeCoverageIgnoreStart |
| 15 |
exit; // Exit if accessed directly. |
| 16 |
// @codeCoverageIgnoreEnd |
| 17 |
} |
| 18 |
|
| 19 |
/** |
| 20 |
* Date query class |
| 21 |
*/ |
| 22 |
class DateQuery extends WP_Date_Query { |
| 23 |
/** |
| 24 |
* Like WP_Date_Query::get_sql |
| 25 |
* takes WP_Date_Query class queries and returns ES filter arrays |
| 26 |
* |
| 27 |
* @since 0.1.4 |
| 28 |
* @return array |
| 29 |
*/ |
| 30 |
public function get_es_filter() { |
| 31 |
$filter = $this->get_es_filter_for_clauses(); |
| 32 |
|
| 33 |
return $filter; |
| 34 |
} |
| 35 |
|
| 36 |
/** |
| 37 |
* Like WP_Date_Query::get_sql_for_clauses |
| 38 |
* takes all queries in WP_Date_Query object and gets ES filters for each |
| 39 |
* |
| 40 |
* @since 0.1.4 |
| 41 |
* @return array |
| 42 |
*/ |
| 43 |
protected function get_es_filter_for_clauses() { |
| 44 |
$filter = $this->get_es_filter_for_query( $this->queries ); |
| 45 |
|
| 46 |
return $filter; |
| 47 |
} |
| 48 |
|
| 49 |
/** |
| 50 |
* Get Elaticsearch formatted filters |
| 51 |
* |
| 52 |
* @param array $query array of date query clauses. |
| 53 |
* @param int $depth unused but may be necessary if we do nested date queries. |
| 54 |
* @since 0.1.4 |
| 55 |
* @return array |
| 56 |
*/ |
| 57 |
protected function get_es_filter_for_query( $query, $depth = 0 ) { |
| 58 |
$filter_chunks = array( |
| 59 |
'filters' => [], |
| 60 |
); |
| 61 |
|
| 62 |
$filter_array = []; |
| 63 |
|
| 64 |
foreach ( $query as $key => $clause ) { |
| 65 |
if ( 'relation' === $key ) { |
| 66 |
$relation = $query['relation']; |
| 67 |
} elseif ( is_array( $clause ) ) { |
| 68 |
|
| 69 |
// This is a first-order clause. |
| 70 |
if ( $this->is_first_order_clause( $clause ) ) { |
| 71 |
|
| 72 |
$clause_filter = $this->get_es_filter_for_clause( $clause, $query ); |
| 73 |
|
| 74 |
$filter_count = count( $clause_filter ); |
| 75 |
if ( $filter_count ) { |
| 76 |
$filter_chunks['filters'][] = $clause_filter; |
| 77 |
} |
| 78 |
|
| 79 |
// This is a subquery, so we recurse. |
| 80 |
} |
| 81 |
} |
| 82 |
} |
| 83 |
|
| 84 |
// @todo implement OR filter relationships. |
| 85 |
if ( empty( $relation ) ) { |
| 86 |
$relation = 'AND'; |
| 87 |
} |
| 88 |
|
| 89 |
if ( 'AND' === $relation ) { |
| 90 |
$filter_array['and'] = []; |
| 91 |
|
| 92 |
$range_filters = []; |
| 93 |
$term_filters = []; |
| 94 |
foreach ( $filter_chunks['filters'] as $key => $filter ) { |
| 95 |
$filter_type = key( $filter ); |
| 96 |
if ( 'date_terms' === $filter_type ) { |
| 97 |
$term_filters[] = $filter['date_terms']; |
| 98 |
} elseif ( 'range_filters' === $filter_type ) { |
| 99 |
$range_filters[] = $filter['range_filters']; |
| 100 |
} |
| 101 |
} |
| 102 |
|
| 103 |
if ( $range_filters ) { |
| 104 |
$filter_array['and'] = array( |
| 105 |
'bool' => $this->build_es_range_filter( $range_filters ), |
| 106 |
); |
| 107 |
} |
| 108 |
|
| 109 |
if ( $term_filters ) { |
| 110 |
$filter_array['and'] = array( |
| 111 |
'bool' => $this->build_es_date_term_filter( $term_filters ), |
| 112 |
); |
| 113 |
} |
| 114 |
} |
| 115 |
|
| 116 |
return $filter_array; |
| 117 |
} |
| 118 |
|
| 119 |
/** |
| 120 |
* Takes array of date term filters and groups them into a filter based on |
| 121 |
* relationship type |
| 122 |
* |
| 123 |
* @param array $date_term_filters Date term filters. |
| 124 |
* @param string $type type of relationship between date term filters (AND, OR). |
| 125 |
* |
| 126 |
* @since 0.1.4 |
| 127 |
* @return array |
| 128 |
*/ |
| 129 |
protected function build_es_date_term_filter( $date_term_filters = [], $type = 'AND' ) { |
| 130 |
$date_term_filter_array = array( |
| 131 |
'must' => [], |
| 132 |
'should' => [], |
| 133 |
'must_not' => [], |
| 134 |
); |
| 135 |
|
| 136 |
if ( 'AND' === $type ) { |
| 137 |
foreach ( $date_term_filters as $date_term_filter ) { |
| 138 |
$date_term_filter_array['must'] = ! empty( $date_term_filter['must'] ) ? array_merge( $date_term_filter_array['must'], $date_term_filter['must'] ) : []; |
| 139 |
$date_term_filter_array['should'] = ! empty( $date_term_filter['should'] ) ? array_merge( $date_term_filter_array['should'], $date_term_filter['should'] ) : []; |
| 140 |
$date_term_filter_array['must_not'] = ! empty( $date_term_filter['must_not'] ) ? array_merge( $date_term_filter_array['must_not'], $date_term_filter['must_not'] ) : []; |
| 141 |
} |
| 142 |
} |
| 143 |
|
| 144 |
return array_filter( $date_term_filter_array ); |
| 145 |
} |
| 146 |
|
| 147 |
/** |
| 148 |
* Takes array of range filters and groups them into a single filter |
| 149 |
* |
| 150 |
* @param array $range_filters Range filters. |
| 151 |
* |
| 152 |
* @since 0.1.4 |
| 153 |
* @return array |
| 154 |
*/ |
| 155 |
protected function build_es_range_filter( $range_filters = [] ) { |
| 156 |
$range_filter_array = array( |
| 157 |
'must' => [], |
| 158 |
'should' => [], |
| 159 |
'must_not' => [], |
| 160 |
); |
| 161 |
|
| 162 |
foreach ( $range_filters as $key => $range_filter ) { |
| 163 |
if ( 'not' === key( $range_filter ) ) { |
| 164 |
$range_filter_array['must_not'][] = array( |
| 165 |
'range' => $range_filter['not'], |
| 166 |
); |
| 167 |
} else { |
| 168 |
$range_filter_array['must'][] = array( |
| 169 |
'range' => $range_filter, |
| 170 |
); |
| 171 |
} |
| 172 |
} |
| 173 |
|
| 174 |
return array_filter( $range_filter_array ); |
| 175 |
} |
| 176 |
|
| 177 |
/** |
| 178 |
* Takes SQL query part, and translates it into an ES filter |
| 179 |
* |
| 180 |
* @param array $query SQL query piece. |
| 181 |
* @return array ES filter. |
| 182 |
*/ |
| 183 |
protected function get_es_filter_for_clause( $query ) { |
| 184 |
|
| 185 |
// The sub-parts of a $where part. |
| 186 |
$filter_parts = []; |
| 187 |
|
| 188 |
$column = ( ! empty( $query['column'] ) ) ? $query['column'] : $this->column; |
| 189 |
|
| 190 |
$compare = $this->get_compare( $query ); |
| 191 |
|
| 192 |
$inclusive = ! empty( $query['inclusive'] ) && true === $query['inclusive'] ? true : false; |
| 193 |
|
| 194 |
// Assign greater- and less-than values. |
| 195 |
$lt = 'lt'; |
| 196 |
$gt = 'gt'; |
| 197 |
|
| 198 |
if ( $inclusive ) { |
| 199 |
$lt .= 'e'; |
| 200 |
$gt .= 'e'; |
| 201 |
} |
| 202 |
|
| 203 |
// Range queries. |
| 204 |
if ( ! empty( $query['after'] ) ) { |
| 205 |
$range_filters = array( |
| 206 |
"{$column}" => array( |
| 207 |
"{$gt}" => $this->build_mysql_datetime( $query['after'] ), |
| 208 |
), |
| 209 |
); |
| 210 |
} |
| 211 |
|
| 212 |
if ( ! empty( $query['before'] ) ) { |
| 213 |
$range_filters = empty( $range_filters[ $column ] ) ? array( "{$column}" => array( "{$lt}" => [] ) ) : $range_filters; |
| 214 |
$range_filters[ $column ][ $lt ] = $this->build_mysql_datetime( $query['before'] ); |
| 215 |
} |
| 216 |
|
| 217 |
if ( ! empty( $query['after'] ) || ! empty( $query['before'] ) ) { |
| 218 |
$filter_parts['range_filters'] = $range_filters; |
| 219 |
} |
| 220 |
|
| 221 |
// Specific value queries. |
| 222 |
$date_parameters = array( |
| 223 |
'year' => ! empty( $query['year'] ) ? $query['year'] : false, |
| 224 |
'month' => ! empty( $query['month'] ) ? $query['month'] : false, |
| 225 |
'week' => ! empty( $query['week'] ) ? $query['week'] : false, |
| 226 |
'dayofyear' => ! empty( $query['dayofyear'] ) ? $query['dayofyear'] : false, |
| 227 |
'day' => ! empty( $query['day'] ) ? $query['day'] : false, |
| 228 |
'dayofweek' => ! empty( $query['dayofweek'] ) ? $query['dayofweek'] : false, |
| 229 |
'dayofweek_iso' => ! empty( $query['dayofweek_iso'] ) ? $query['dayofweek_iso'] : false, |
| 230 |
'hour' => ! empty( $query['hour'] ) ? $query['hour'] : false, |
| 231 |
'minute' => ! empty( $query['minute'] ) ? $query['minute'] : false, |
| 232 |
'second' => ! empty( $query['second'] ) ? $query['second'] : false, |
| 233 |
'm' => ! empty( $query['m'] ) ? $query['m'] : false, // yearmonth |
| 234 |
); |
| 235 |
|
| 236 |
if ( empty( $date_parameters['month'] ) && ! empty( $query['monthnum'] ) ) { |
| 237 |
$date_parameters['month'] = $query['monthnum']; |
| 238 |
} |
| 239 |
|
| 240 |
if ( empty( $date_parameters['week'] ) && ! empty( $query['w'] ) ) { |
| 241 |
$date_parameters['week'] = $query['w']; |
| 242 |
} |
| 243 |
|
| 244 |
foreach ( $date_parameters as $param => $value ) { |
| 245 |
if ( false === $value ) { |
| 246 |
unset( $date_parameters[ $param ] ); |
| 247 |
} |
| 248 |
} |
| 249 |
|
| 250 |
if ( $date_parameters ) { |
| 251 |
|
| 252 |
self::validate_date_values( $date_parameters ); |
| 253 |
|
| 254 |
$date_terms = array( |
| 255 |
'must' => [], |
| 256 |
'should' => [], |
| 257 |
'must_not' => [], |
| 258 |
); |
| 259 |
|
| 260 |
foreach ( $date_parameters as $param => $value ) { |
| 261 |
if ( '=' === $compare ) { |
| 262 |
$date_terms['must'][]['term'][ "date_terms.{$param}" ] = $value; |
| 263 |
} elseif ( '!=' === $compare ) { |
| 264 |
$date_terms['must_not'][]['term'][ "date_terms.{$param}" ] = $value; |
| 265 |
} elseif ( 'IN' === $compare ) { |
| 266 |
foreach ( $value as $in_value ) { |
| 267 |
$date_terms['should'][]['term'][ "date_terms.{$param}" ] = $in_value; |
| 268 |
} |
| 269 |
} elseif ( 'NOT IN' === $compare ) { |
| 270 |
foreach ( $value as $in_value ) { |
| 271 |
$date_terms['must_not'][]['term'][ "date_terms.{$param}" ] = $in_value; |
| 272 |
} |
| 273 |
} elseif ( 'BETWEEN' === $compare ) { |
| 274 |
$range_filter[ "date_terms.{$param}" ] = []; |
| 275 |
$range_filter[ "date_terms.{$param}" ]['gte'] = $value[0]; |
| 276 |
$range_filter[ "date_terms.{$param}" ]['lte'] = $value[1]; |
| 277 |
$filter_parts['range_filters'] = $range_filter; |
| 278 |
} elseif ( 'NOT BETWEEN' === $compare ) { |
| 279 |
$range_filter[ "date_terms.{$param}" ] = []; |
| 280 |
$range_filter[ "date_terms.{$param}" ]['gt'] = $value[0]; |
| 281 |
$range_filter[ "date_terms.{$param}" ]['lt'] = $value[1]; |
| 282 |
$filter_parts['range_filters'] = array( 'not' => $range_filter ); |
| 283 |
} elseif ( strpos( $compare, '>' ) !== false ) { |
| 284 |
$range = ( strpos( $compare, '=' ) !== false ) ? 'gte' : 'gt'; |
| 285 |
$range_filter[ "date_terms.{$param}" ] = []; |
| 286 |
$range_filter[ "date_terms.{$param}" ][ $range ] = $value; |
| 287 |
$filter_parts['range_filters'] = $range_filter; |
| 288 |
} elseif ( strpos( $compare, '<' ) !== false ) { |
| 289 |
$range = ( strpos( $compare, '=' ) !== false ) ? 'lte' : 'lt'; |
| 290 |
$range_filter[ "date_terms.{$param}" ] = []; |
| 291 |
$range_filter[ "date_terms.{$param}" ][ $range ] = $value; |
| 292 |
$filter_parts['range_filters'] = $range_filter; |
| 293 |
} |
| 294 |
} |
| 295 |
|
| 296 |
$date_terms = array_filter( $date_terms ); |
| 297 |
|
| 298 |
if ( ! empty( $date_terms ) ) { |
| 299 |
$filter_parts['date_terms'] = $date_terms; |
| 300 |
} |
| 301 |
} |
| 302 |
|
| 303 |
return $filter_parts; |
| 304 |
} |
| 305 |
|
| 306 |
/** |
| 307 |
* Takes WP_Query args, and returns ES filters for query |
| 308 |
* Support for older style WP_Query date params |
| 309 |
* |
| 310 |
* @param array $args WP_Query args. |
| 311 |
* @return array|bool |
| 312 |
*/ |
| 313 |
public static function simple_es_date_filter( $args ) { |
| 314 |
$date_parameters = array( |
| 315 |
'year' => ! empty( $args['year'] ) ? $args['year'] : false, |
| 316 |
'month' => ! empty( $args['month'] ) ? $args['month'] : false, |
| 317 |
'week' => ! empty( $args['week'] ) ? $args['week'] : false, |
| 318 |
'day' => ! empty( $args['day'] ) ? $args['day'] : false, |
| 319 |
'hour' => ! empty( $args['hour'] ) ? $args['hour'] : false, |
| 320 |
'minute' => ! empty( $args['minute'] ) ? $args['minute'] : false, |
| 321 |
'second' => ! empty( $args['second'] ) ? $args['second'] : false, |
| 322 |
'm' => ! empty( $args['m'] ) ? $args['m'] : false, // yearmonth |
| 323 |
); |
| 324 |
|
| 325 |
if ( ! $date_parameters['month'] && ! empty( $args['monthnum'] ) ) { |
| 326 |
$date_parameters['month'] = $args['monthnum']; |
| 327 |
} |
| 328 |
|
| 329 |
if ( ! $date_parameters['week'] && ! empty( $args['w'] ) ) { |
| 330 |
$date_parameters['week'] = $args['w']; |
| 331 |
} |
| 332 |
|
| 333 |
foreach ( $date_parameters as $param => $value ) { |
| 334 |
if ( false === $value ) { |
| 335 |
unset( $date_parameters[ $param ] ); |
| 336 |
} |
| 337 |
} |
| 338 |
|
| 339 |
if ( ! $date_parameters ) { |
| 340 |
return false; |
| 341 |
} |
| 342 |
|
| 343 |
$date_terms = []; |
| 344 |
foreach ( $date_parameters as $param => $value ) { |
| 345 |
$date_terms[]['term'][ "date_terms.{$param}" ] = $value; |
| 346 |
} |
| 347 |
|
| 348 |
return array( |
| 349 |
'bool' => array( |
| 350 |
'must' => $date_terms, |
| 351 |
), |
| 352 |
); |
| 353 |
} |
| 354 |
|
| 355 |
/** |
| 356 |
* Introduced in WP 4.1 added here for backwards compatibility |
| 357 |
* |
| 358 |
* @var array |
| 359 |
*/ |
| 360 |
public $time_keys = array( 'after', 'before', 'year', 'month', 'monthnum', 'week', 'w', 'dayofyear', 'day', 'dayofweek', 'dayofweek_iso', 'hour', 'minute', 'second' ); |
| 361 |
|
| 362 |
/** |
| 363 |
* Introduced in WP 4.1 added here for backwards compatibility |
| 364 |
* |
| 365 |
* @param array $query Date query array |
| 366 |
* @return boolean |
| 367 |
*/ |
| 368 |
protected function is_first_order_clause( $query ) { |
| 369 |
$time_keys = array_intersect( $this->time_keys, array_keys( $query ) ); |
| 370 |
return ! empty( $time_keys ); |
| 371 |
} |
| 372 |
|
| 373 |
/** |
| 374 |
* Introduced in WP 4.1 added here for backwards compatibility |
| 375 |
* |
| 376 |
* @param array $date_query Date query array |
| 377 |
* @return boolean |
| 378 |
*/ |
| 379 |
public function validate_date_values( $date_query = [] ) { |
| 380 |
if ( empty( $date_query ) ) { |
| 381 |
return false; |
| 382 |
} |
| 383 |
|
| 384 |
$valid = true; |
| 385 |
|
| 386 |
/* |
| 387 |
* Validate 'before' and 'after' up front, then let the |
| 388 |
* validation routine continue to be sure that all invalid |
| 389 |
* values generate errors too. |
| 390 |
*/ |
| 391 |
if ( array_key_exists( 'before', $date_query ) && is_array( $date_query['before'] ) ) { |
| 392 |
$valid = $this->validate_date_values( $date_query['before'] ); |
| 393 |
} |
| 394 |
|
| 395 |
if ( array_key_exists( 'after', $date_query ) && is_array( $date_query['after'] ) ) { |
| 396 |
$valid = $this->validate_date_values( $date_query['after'] ); |
| 397 |
} |
| 398 |
|
| 399 |
// Array containing all min-max checks. |
| 400 |
$min_max_checks = []; |
| 401 |
|
| 402 |
// Days per year. |
| 403 |
if ( array_key_exists( 'year', $date_query ) ) { |
| 404 |
/* |
| 405 |
* If a year exists in the date query, we can use it to get the days. |
| 406 |
* If multiple years are provided (as in a BETWEEN), use the first one. |
| 407 |
*/ |
| 408 |
if ( is_array( $date_query['year'] ) ) { |
| 409 |
$_year = reset( $date_query['year'] ); |
| 410 |
} else { |
| 411 |
$_year = $date_query['year']; |
| 412 |
} |
| 413 |
|
| 414 |
$max_days_of_year = date_i18n( 'z', mktime( 0, 0, 0, 12, 31, $_year ) ) + 1; |
| 415 |
} else { |
| 416 |
// otherwise we use the max of 366 (leap-year). |
| 417 |
$max_days_of_year = 366; |
| 418 |
} |
| 419 |
|
| 420 |
$min_max_checks['dayofyear'] = array( |
| 421 |
'min' => 1, |
| 422 |
'max' => $max_days_of_year, |
| 423 |
); |
| 424 |
|
| 425 |
// Days per week. |
| 426 |
$min_max_checks['dayofweek'] = array( |
| 427 |
'min' => 1, |
| 428 |
'max' => 7, |
| 429 |
); |
| 430 |
|
| 431 |
// Days per week. |
| 432 |
$min_max_checks['dayofweek_iso'] = array( |
| 433 |
'min' => 1, |
| 434 |
'max' => 7, |
| 435 |
); |
| 436 |
|
| 437 |
// Months per year. |
| 438 |
$min_max_checks['month'] = array( |
| 439 |
'min' => 1, |
| 440 |
'max' => 12, |
| 441 |
); |
| 442 |
|
| 443 |
// Weeks per year. |
| 444 |
if ( isset( $_year ) ) { |
| 445 |
// If we have a specific year, use it to calculate number of weeks. |
| 446 |
$date = new \DateTime(); |
| 447 |
$date->setISODate( $_year, 53 ); |
| 448 |
$week_count = $date->format( 'W' ) === '53' ? 53 : 52; |
| 449 |
|
| 450 |
} else { |
| 451 |
// Otherwise set the week-count to a maximum of 53. |
| 452 |
$week_count = 53; |
| 453 |
} |
| 454 |
|
| 455 |
$min_max_checks['week'] = array( |
| 456 |
'min' => 1, |
| 457 |
'max' => $week_count, |
| 458 |
); |
| 459 |
|
| 460 |
// Days per month. |
| 461 |
$min_max_checks['day'] = array( |
| 462 |
'min' => 1, |
| 463 |
'max' => 31, |
| 464 |
); |
| 465 |
|
| 466 |
// Hours per day. |
| 467 |
$min_max_checks['hour'] = array( |
| 468 |
'min' => 0, |
| 469 |
'max' => 23, |
| 470 |
); |
| 471 |
|
| 472 |
// Minutes per hour. |
| 473 |
$min_max_checks['minute'] = array( |
| 474 |
'min' => 0, |
| 475 |
'max' => 59, |
| 476 |
); |
| 477 |
|
| 478 |
// Seconds per minute. |
| 479 |
$min_max_checks['second'] = array( |
| 480 |
'min' => 0, |
| 481 |
'max' => 59, |
| 482 |
); |
| 483 |
|
| 484 |
// Concatenate and throw a notice for each invalid value. |
| 485 |
foreach ( $min_max_checks as $key => $check ) { |
| 486 |
if ( ! array_key_exists( $key, $date_query ) ) { |
| 487 |
continue; |
| 488 |
} |
| 489 |
|
| 490 |
// Throw a notice for each failing value. |
| 491 |
$is_between = true; |
| 492 |
foreach ( (array) $date_query[ $key ] as $_value ) { |
| 493 |
$is_between = $_value >= $check['min'] && $_value <= $check['max']; |
| 494 |
|
| 495 |
if ( ! is_numeric( $_value ) || ! $is_between ) { |
| 496 |
$error = sprintf( |
| 497 |
/* translators: Date query invalid date message: 1: invalid value, 2: type of value, 3: minimum valid value, 4: maximum valid value */ |
| 498 |
__( 'Invalid value %1$s for %2$s. Expected value should be between %3$s and %4$s.' ), |
| 499 |
'<code>' . esc_html( $_value ) . '</code>', |
| 500 |
'<code>' . esc_html( $key ) . '</code>', |
| 501 |
'<code>' . esc_html( $check['min'] ) . '</code>', |
| 502 |
'<code>' . esc_html( $check['max'] ) . '</code>' |
| 503 |
); |
| 504 |
|
| 505 |
_doing_it_wrong( __CLASS__, esc_html( $error ), '4.1.0' ); |
| 506 |
|
| 507 |
$valid = false; |
| 508 |
} |
| 509 |
} |
| 510 |
} |
| 511 |
|
| 512 |
// If we already have invalid date messages, don't bother running through checkdate(). |
| 513 |
if ( ! $valid ) { |
| 514 |
return $valid; |
| 515 |
} |
| 516 |
|
| 517 |
$day_month_year_error_msg = ''; |
| 518 |
|
| 519 |
$day_exists = array_key_exists( 'day', $date_query ) && is_numeric( $date_query['day'] ); |
| 520 |
$month_exists = array_key_exists( 'month', $date_query ) && is_numeric( $date_query['month'] ); |
| 521 |
$year_exists = array_key_exists( 'year', $date_query ) && is_numeric( $date_query['year'] ); |
| 522 |
|
| 523 |
if ( $day_exists && $month_exists && $year_exists ) { |
| 524 |
// 1. Checking day, month, year combination. |
| 525 |
if ( ! wp_checkdate( $date_query['month'], $date_query['day'], $date_query['year'], sprintf( '%s-%s-%s', $date_query['year'], $date_query['month'], $date_query['day'] ) ) ) { |
| 526 |
/* translators: 1: year, 2: month, 3: day of month */ |
| 527 |
$day_month_year_error_msg = sprintf( |
| 528 |
// translators: 1: Year, 2: Month, 3: Day |
| 529 |
__( 'The following values do not describe a valid date: year %1$s, month %2$s, day %3$s.' ), |
| 530 |
'<code>' . esc_html( $date_query['year'] ) . '</code>', |
| 531 |
'<code>' . esc_html( $date_query['month'] ) . '</code>', |
| 532 |
'<code>' . esc_html( $date_query['day'] ) . '</code>' |
| 533 |
); |
| 534 |
|
| 535 |
$valid = false; |
| 536 |
} |
| 537 |
} elseif ( $day_exists && $month_exists ) { |
| 538 |
/* |
| 539 |
* 2. checking day, month combination |
| 540 |
* We use 2012 because, as a leap year, it's the most permissive. |
| 541 |
*/ |
| 542 |
if ( ! wp_checkdate( $date_query['month'], $date_query['day'], 2012, sprintf( '2012-%s-%s', $date_query['month'], $date_query['day'] ) ) ) { |
| 543 |
/* translators: 1: month, 2: day of month */ |
| 544 |
$err_msg = __( 'The following values do not describe a valid date: month %1$s, day %2$s.' ); |
| 545 |
$day_month_year_error_msg = sprintf( |
| 546 |
$err_msg, |
| 547 |
'<code>' . esc_html( $date_query['month'] ) . '</code>', |
| 548 |
'<code>' . esc_html( $date_query['day'] ) . '</code>' |
| 549 |
); |
| 550 |
|
| 551 |
$valid = false; |
| 552 |
} |
| 553 |
} |
| 554 |
|
| 555 |
if ( ! empty( $day_month_year_error_msg ) ) { |
| 556 |
_doing_it_wrong( __CLASS__, esc_html( $day_month_year_error_msg ), '4.1.0' ); |
| 557 |
} |
| 558 |
|
| 559 |
return $valid; |
| 560 |
} |
| 561 |
} |
| 562 |
|