s method only generates debug notices for these cases. * * @since 4.1.0 * * @param array $date_query The date_query array. * @return bool True if all values in the query are valid, false if one or more fail. */ public function validate_date_values( $date_query = array() ) { if ( empty( $date_query ) ) { return false; } $valid = true; /* * Validate 'before' and 'after' up front, then let the * validation routine continue to be sure that all invalid * values generate errors too. */ if ( array_key_exists( 'before', $date_query ) && is_array( $date_query['before'] ) ) { $valid = $this->validate_date_values( $date_query['before'] ); } if ( array_key_exists( 'after', $date_query ) && is_array( $date_query['after'] ) ) { $valid = $this->validate_date_values( $date_query['after'] ); } // Array containing all min-max checks. $min_max_checks = array(); // Days per year. if ( array_key_exists( 'year', $date_query ) ) { /* * If a year exists in the date query, we can use it to get the days. * If multiple years are provided (as in a BETWEEN), use the first one. */ if ( is_array( $date_query['year'] ) ) { $_year = reset( $date_query['year'] ); } else { $_year = $date_query['year']; } $max_days_of_year = gmdate( 'z', mktime( 0, 0, 0, 12, 31, $_year ) ) + 1; } else { // Otherwise we use the max of 366 (leap-year). $max_days_of_year = 366; } $min_max_checks['dayofyear'] = array( 'min' => 1, 'max' => $max_days_of_year, ); // Days per week. $min_max_checks['dayofweek'] = array( 'min' => 1, 'max' => 7, ); // Days per week. $min_max_checks['dayofweek_iso'] = array( 'min' => 1, 'max' => 7, ); // Months per year. $min_max_checks['month'] = array( 'min' => 1, 'max' => 12, ); // Weeks per year. if ( isset( $_year ) ) { /* * If we have a specific year, use it to calculate number of weeks. * Note: the number of weeks in a year is the date in which Dec 28 appears. */ $week_count = gmdate( 'W', mktime( 0, 0, 0, 12, 28, $_year ) ); } else { // Otherwise set the week-count to a maximum of 53. $week_count = 53; } $min_max_checks['week'] = array( 'min' => 1, 'max' => $week_count, ); // Days per month. $min_max_checks['day'] = array( 'min' => 1, 'max' => 31, ); // Hours per day. $min_max_checks['hour'] = array( 'min' => 0, 'max' => 23, ); // Minutes per hour. $min_max_checks['minute'] = array( 'min' => 0, 'max' => 59, ); // Seconds per minute. $min_max_checks['second'] = array( 'min' => 0, 'max' => 59, ); // Concatenate and throw a notice for each invalid value. foreach ( $min_max_checks as $key => $check ) { if ( ! array_key_exists( $key, $date_query ) ) { continue; } // Throw a notice for each failing value. foreach ( (array) $date_query[ $key ] as $_value ) { $is_between = $_value >= $check['min'] && $_value <= $check['max']; if ( ! is_numeric( $_value ) || ! $is_between ) { $error = sprintf( /* translators: Date query invalid date message. 1: Invalid value, 2: Type of value, 3: Minimum valid value, 4: Maximum valid value. */ __( 'Invalid value %1$s for %2$s. Expected value should be between %3$s and %4$s.' ), '' . esc_html( $_value ) . '', '' . esc_html( $key ) . '', '' . esc_html( $check['min'] ) . '', '' . esc_html( $check['max'] ) . '' ); _doing_it_wrong( __CLASS__, $error, '4.1.0' ); $valid = false; } } } // If we already have invalid date messages, don't bother running through checkdate(). if ( ! $valid ) { return $valid; } $day_month_year_error_msg = ''; $day_exists = array_key_exists( 'day', $date_query ) && is_numeric( $date_query['day'] ); $month_exists = array_key_exists( 'month', $date_query ) && is_numeric( $date_query['month'] ); $year_exists = array_key_exists( 'year', $date_query ) && is_numeric( $date_query['year'] ); if ( $day_exists && $month_exists && $year_exists ) { // 1. Checking day, month, year combination. 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'] ) ) ) { $day_month_year_error_msg = sprintf( /* translators: 1: Year, 2: Month, 3: Day of month. */ __( 'The following values do not describe a valid date: year %1$s, month %2$s, day %3$s.' ), '' . esc_html( $date_query['year'] ) . '', '' . esc_html( $date_query['month'] ) . '', '' . esc_html( $date_query['day'] ) . '' ); $valid = false; } } elseif ( $day_exists && $month_exists ) { /* * 2. checking day, month combination * We use 2012 because, as a leap year, it's the most permissive. */ if ( ! wp_checkdate( $date_query['month'], $date_query['day'], 2012, sprintf( '2012-%s-%s', $date_query['month'], $date_query['day'] ) ) ) { $day_month_year_error_msg = sprintf( /* translators: 1: Month, 2: Day of month. */ __( 'The following values do not describe a valid date: month %1$s, day %2$s.' ), '' . esc_html( $date_query['month'] ) . '', '' . esc_html( $date_query['day'] ) . '' ); $valid = false; } } if ( ! empty( $day_month_year_error_msg ) ) { _doing_it_wrong( __CLASS__, $day_month_year_error_msg, '4.1.0' ); } return $valid; } /** * Validates a column name parameter. * * Column names without a table prefix (like 'post_date') are checked against a list of * allowed and known tables, and then, if found, have a table prefix (such as 'wp_posts.') * prepended. Prefixed column names (such as 'wp_posts.post_date') bypass this allowed * check, and are only sanitized to remove illegal characters. * * @since 3.7.0 * * @global wpdb $wpdb WordPress database abstraction object. * * @param string $column The user-supplied column name. * @return string A validated column name value. */ public function validate_column( $column ) { global $wpdb; $valid_columns = array( 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt', 'comment_date', 'comment_date_gmt', 'user_registered', 'registered', 'last_updated', ); // Attempt to detect a table prefix. if ( ! str_contains( $column, '.' ) ) { /** * Filters the list of valid date query columns. * * @since 3.7.0 * @since 4.1.0 Added 'user_registered' to the default recognized columns. * @since 4.6.0 Added 'registered' and 'last_updated' to the default recognized columns. * * @param string[] $valid_columns An array of valid date query columns. Defaults * are 'post_date', 'post_date_gmt', 'post_modified', * 'post_modified_gmt', 'comment_date', 'comment_date_gmt', * 'user_registered', 'registered', 'last_updated'. */ if ( ! in_array( $column, apply_filters( 'date_query_valid_columns', $valid_columns ), true ) ) { $column = 'post_date'; } $known_columns = array( $wpdb->posts => array( 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt', ), $wpdb->comments => array( 'comment_date', 'comment_date_gmt', ), $wpdb->users => array( 'user_registered', ), $wpdb->blogs => array( 'registered', 'last_updated', ), ); // If it's a known column name, add the appropriate table prefix. foreach ( $known_columns as $table_name => $table_columns ) { if ( in_array( $column, $table_columns, true ) ) { $column = $table_name . '.' . $column; break; } } } // Remove unsafe characters. return preg_replace( '/[^a-zA-Z0-9_$\.]/', '', $column ); } /** * Generates WHERE clause to be appended to a main query. * * @since 3.7.0 * * @return string MySQL WHERE clause. */ public function get_sql() { $sql = $this->get_sql_clauses(); $where = $sql['where']; /** * Filters the date query WHERE clause. * * @since 3.7.0 * * @param string $where WHERE clause of the date query. * @param WP_Date_Query $query The WP_Date_Query instance. */ return apply_filters( 'get_date_sql', $where, $this ); } /** * Generates SQL clauses to be appended to a main query. * * Called by the public WP_Date_Query::get_sql(), this method is abstracted * out to maintain parity with the other Query classes. * * @since 4.1.0 * * @return string[] { * Array containing JOIN and WHERE SQL clauses to append to the main query. * * @type string $join SQL fragment to append to the main JOIN clause. * @type string $where SQL fragment to append to the main WHERE clause. * } */ protected function get_sql_clauses() { $sql = $this->get_sql_for_query( $this->queries ); if ( ! empty( $sql['where'] ) ) { $sql['where'] = ' AND ' . $sql['where']; } return $sql; } /** * Generates SQL clauses for a single query array. * * If nested subqueries are found, this method recurses the tree to * produce the properly nested SQL. * * @since 4.1.0 * * @param array $query Query to parse. * @param int $depth Optional. Number of tree levels deep we currently are. * Used to calculate indentation. Default 0. * @return array { * Array containing JOIN and WHERE SQL clauses to append to a single query array. * * @type string $join SQL fragment to append to the main JOIN clause. * @type string $where SQL fragment to append to the main WHERE clause. * } */ protected function get_sql_for_query( $query, $depth = 0 ) { $sql_chunks = array( 'join' => array(), 'where' => array(), ); $sql = array( 'join' => '', 'where' => '', ); $indent = ''; for ( $i = 0; $i < $depth; $i++ ) { $indent .= ' '; } foreach ( $query as $key => $clause ) { if ( 'relation' === $key ) { $relation = $query['relation']; } elseif ( is_array( $clause ) ) { // This is a first-order clause. if ( $this->is_first_order_clause( $clause ) ) { $clause_sql = $this->get_sql_for_clause( $clause, $query ); $where_count = count( $clause_sql['where'] ); if ( ! $where_count ) { $sql_chunks['where'][] = ''; } elseif ( 1 === $where_count ) { $sql_chunks['where'][] = $clause_sql['where'][0]; } else { $sql_chunks['where'][] = '( ' . implode( ' AND ', $clause_sql['where'] ) . ' )'; } $sql_chunks['join'] = array_merge( $sql_chunks['join'], $clause_sql['join'] ); // This is a subquery, so we recurse. } else { $clause_sql = $this->get_sql_for_query( $clause, $depth + 1 ); $sql_chunks['where'][] = $clause_sql['where']; $sql_chunks['join'][] = $clause_sql['join']; } } } // Filter to remove empties. $sql_chunks['join'] = array_filter( $sql_chunks['join'] ); $sql_chunks['where'] = array_filter( $sql_chunks['where'] ); if ( empty( $relation ) ) { $relation = 'AND'; } // Filter duplicate JOIN clauses and combine into a single string. if ( ! empty( $sql_chunks['join'] ) ) { $sql['join'] = implode( ' ', array_unique( $sql_chunks['join'] ) ); } // Generate a single WHERE clause with proper brackets and indentation. if ( ! empty( $sql_chunks['where'] ) ) { $sql['where'] = '( ' . "\n " . $indent . implode( ' ' . "\n " . $indent . $relation . ' ' . "\n " . $indent, $sql_chunks['where'] ) . "\n" . $indent . ')'; } return $sql; } /** * Turns a single date clause into pieces for a WHERE clause. * * A wrapper for get_sql_for_clause(), included here for backward * compatibility while retaining the naming convention across Query classes. * * @since 3.7.0 * * @param array $query Date query arguments. * @return array { * Array containing JOIN and WHERE SQL clauses to append to the main query. * * @type string[] $join Array of SQL fragments to append to the main JOIN clause. * @type string[] $where Array of SQL fragments to append to the main WHERE clause. * } */ protected function get_sql_for_subquery( $query ) { return $this->get_sql_for_clause( $query, '' ); } /** * Turns a first-order date query into SQL for a WHERE clause. * * @since 4.1.0 * * @global wpdb $wpdb WordPress database abstraction object. * * @param array $query Date query clause. * @param array $parent_query Parent query of the current date query. * @return array { * Array containing JOIN and WHERE SQL clauses to append to the main query. * * @type string[] $join Array of SQL fragments to append to the main JOIN clause. * @type string[] $where Array of SQL fragments to append to the main WHERE clause. * } */ protected function get_sql_for_clause( $query, $parent_query ) { global $wpdb; // The sub-parts of a $where part. $where_parts = array(); $column = ( ! empty( $query['column'] ) ) ? esc_sql( $query['column'] ) : $this->column; $column = $this->validate_column( $column ); $compare = $this->get_compare( $query ); $inclusive = ! empty( $query['inclusive'] ); // Assign greater- and less-than values. $lt = '<'; $gt = '>'; if ( $inclusive ) { $lt .= '='; $gt .= '='; } // Range queries. if ( ! empty( $query['after'] ) ) { $where_parts[] = $wpdb->prepare( "$column $gt %s", $this->build_mysql_datetime( $query['after'], ! $inclusive ) ); } if ( ! empty( $query['before'] ) ) { $where_parts[] = $wpdb->prepare( "$column $lt %s", $this->build_mysql_datetime( $query['before'], $inclusive ) ); } // Specific value queries. $date_units = array( 'YEAR' => array( 'year' ), 'MONTH' => array( 'month', 'monthnum' ), '_wp_mysql_week' => array( 'week', 'w' ), 'DAYOFYEAR' => array( 'dayofyear' ), 'DAYOFMONTH' => array( 'day' ), 'DAYOFWEEK' => array( 'dayofweek' ), 'WEEKDAY' => array( 'dayofweek_iso' ), ); // Check of the possible date units and add them to the query. foreach ( $date_units as $sql_part => $query_parts ) { foreach ( $query_parts as $query_part ) { if ( isset( $query[ $query_part ] ) ) { $value = $this->build_value( $compare, $query[ $query_part ] ); if ( $value ) { switch ( $sql_part ) { case '_wp_mysql_week': $where_parts[] = _wp_mysql_week( $column ) . " $compare $value"; break; case 'WEEKDAY': $where_parts[] = "$sql_part( $column ) + 1 $compare $value"; break; default: $where_parts[] = "$sql_part( $column ) $compare $value"; } break; } } } } if ( isset( $query['hour'] ) || isset( $query['minute'] ) || isset( $query['second'] ) ) { // Avoid notices. foreach ( array( 'hour', 'minute', 'second' ) as $unit ) { if ( ! isset( $query[ $unit ] ) ) { $query[ $unit ] = null; } } $time_query = $this->build_time_query( $column, $compare, $query['hour'], $query['minute'], $query['second'] ); if ( $time_query ) { $where_parts[] = $time_query; } } /* * Return an array of 'join' and 'where' for compatibility * with other query classes. */ return array( 'where' => $where_parts, 'join' => array(), ); } /** * Builds and validates a value string based on the comparison operator. * * @since 3.7.0 * * @param string $compare The compare operator to use. * @param string|array $value The value. * @return string|false|int The value to be used in SQL or false on error. */ public function build_value( $compare, $value ) { if ( ! isset( $value ) ) { return false; } switch ( $compare ) { case 'IN': case 'NOT IN': $value = (array) $value; // Remove non-numeric values. $value = array_filter( $value, 'is_numeric' ); if ( empty( $value ) ) { return false; } return '(' . implode( ',', array_map( 'intval', $value ) ) . ')'; case 'BETWEEN': case 'NOT BETWEEN': if ( ! is_array( $value ) || 2 !== count( $value ) ) { $value = array( $value, $value ); } else { $value = array_values( $value ); } // If either value is non-numeric, bail. foreach ( $value as $v ) { if ( ! is_numeric( $v ) ) { return false; } } $value = array_map( 'intval', $value ); return $value[0] . ' AND ' . $value[1]; default: if ( ! is_numeric( $value ) ) { return false; } return (int) $value; } } /** * Builds a MySQL format date/time based on some query parameters. * * You can pass an array of values (year, month, etc.) with missing parameter values being defaulted to * either the maximum or minimum values (controlled by the $default_to parameter). Alternatively you can * pass a string that will be passed to date_create(). * * @since 3.7.0 * * @param string|array $datetime An array of parameters or a strtotime() 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 ) { if ( ! is_array( $datetime ) ) { /* * 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' => (int) $matches[1], ); } elseif ( preg_match( '/^(\d{4})\-(\d{2})$/', $datetime, $matches ) ) { // Y-m $datetime = array( 'year' => (int) $matches[1], 'month' => (int) $matches[2], ); } elseif ( preg_match( '/^(\d{4})\-(\d{2})\-(\d{2})$/', $datetime, $matches ) ) { // Y-m-d $datetime = array( 'year' => (int) $matches[1], 'month' => (int) $matches[2], 'day' => (int) $matches[3], ); } elseif ( preg_match( '/^(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2})$/', $datetime, $matches ) ) { // Y-m-d H:i $datetime = array( 'year' => (int) $matches[1], 'month' => (int) $matches[2], 'day' => (int) $matches[3], 'hour' => (int) $matches[4], 'minute' => (int) $matches[5], ); } // If no match is found, we don't support default_to_max. if ( ! is_array( $datetime ) ) { $wp_timezone = wp_timezone(); // Assume local timezone if not provided. $dt = date_create( $datetime, $wp_timezone ); if ( false === $dt ) { return gmdate( 'Y-m-d H:i:s', false ); } return $dt->setTimezone( $wp_timezone )->format( 'Y-m-d H:i:s' ); } } $datetime = array_map( 'absint', $datetime ); if ( ! isset( $datetime['year'] ) ) { $datetime['year'] = current_time( 'Y' ); } if ( ! isset( $datetime['month'] ) ) { $datetime['month'] = ( $default_to_max ) ? 12 : 1; } if ( ! isset( $datetime['day'] ) ) { $datetime['day'] = ( $default_to_max ) ? (int) gmdate( 't', mktime( 0, 0, 0, $datetime['month'], 1, $datetime['year'] ) ) : 1; } if ( ! isset( $datetime['hour'] ) ) { $datetime['hour'] = ( $default_to_max ) ? 23 : 0; } if ( ! isset( $datetime['minute'] ) ) { $datetime['minute'] = ( $default_to_max ) ? 59 : 0; } if ( ! isset( $datetime['second'] ) ) { $datetime['second'] = ( $default_to_max ) ? 59 : 0; } return sprintf( '%04d-%02d-%02d %02d:%02d:%02d', $datetime['year'], $datetime['month'], $datetime['day'], $datetime['hour'], $datetime['minute'], $datetime['second'] ); } /** * Builds a query string for comparing time values (hour, minute, second). * * If just hour, minute, or second is set than a normal comparison will be done. * However if multiple values are passed, a pseudo-decimal time will be created * in order to be able to accurately compare against. * * @since 3.7.0 * * @global wpdb $wpdb WordPress database abstraction object. * * @param string $column The column to query against. Needs to be pre-validated! * @param string $compare The comparison operator. Needs to be pre-validated! * @param int|null $hour Optional. An hour value (0-23). * @param int|null $minute Optional. A minute value (0-59). * @param int|null $second Optional. A second value (0-59). * @return string|false A query part or false on failure. */ public function build_time_query( $column, $compare, $hour = null, $minute = null, $second = null ) { global $wpdb; // Have to have at least one. if ( ! isset( $hour ) && ! isset( $minute ) && ! isset( $second ) ) { return false; } // Complex combined queries aren't supported for multi-value queries. if ( in_array( $compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ), true ) ) { $return = array(); $value = $this->build_value( $compare, $hour ); if ( false !== $value ) { $return[] = "HOUR( $column ) $compare $value"; } $value = $this->build_value( $compare, $minute ); if ( false !== $value ) { $return[] = "MINUTE( $column ) $compare $value"; } $value = $this->build_value( $compare, $second ); if ( false !== $value ) { $return[] = "SECOND( $column ) $compare $value"; } return implode( ' AND ', $return ); } // Cases where just one unit is set. if ( isset( $hour ) && ! isset( $minute ) && ! isset( $second ) ) { $value = $this->build_value( $compare, $hour ); if ( false !== $value ) { return "HOUR( $column ) $compare $value"; } } elseif ( ! isset( $hour ) && isset( $minute ) && ! isset( $second ) ) { $value = $this->build_value( $compare, $minute ); if ( false !== $value ) { return "MINUTE( $column ) $compare $value"; } } elseif ( ! isset( $hour ) && ! isset( $minute ) && isset( $second ) ) { $value = $this->build_value( $compare, $second ); if ( false !== $value ) { return "SECOND( $column ) $compare $value"; } } // Single units were already handled. Since hour & second isn't allowed, minute must to be set. if ( ! isset( $minute ) ) { return false; } $format = ''; $time = ''; // Hour. if ( null !== $hour ) { $format .= '%H.'; $time .= sprintf( '%02d', $hour ) . '.'; } else { $format .= '0.'; $time .= '0.'; } // Minute. $format .= '%i'; $time .= sprintf( '%02d', $minute ); if ( isset( $second ) ) { $format .= '%s'; $time .= sprintf( '%02d', $second ); } return $wpdb->prepare( "DATE_FORMAT( $column, %s ) $compare %f", $format, $time ); } /** * Sanitizes a 'relation' operator. * * @since 6.0.3 * * @param string $relation Raw relation key from the query argument. * @return string Sanitized relation. Either 'AND' or 'OR'. */ public function sanitize_relation( $relation ) { if ( 'OR' === strtoupper( $relation ) ) { return 'OR'; } else { return 'AND'; } } } es, videos, JavaScript, and arbitrary HTML. * * Supported providers: * * | Provider | Flavor | Since | * | ------------ | ----------------------------------------- | ------- | * | Dailymotion | dailymotion.com | 2.9.0 | * | Flickr | flickr.com | 2.9.0 | * | Scribd | scribd.com | 2.9.0 | * | Vimeo | vimeo.com | 2.9.0 | * | WordPress.tv | wordpress.tv | 2.9.0 | * | YouTube | youtube.com/watch | 2.9.0 | * | Crowdsignal | polldaddy.com | 3.0.0 | * | SmugMug | smugmug.com | 3.0.0 | * | YouTube | youtu.be | 3.0.0 | * | Twitter | twitter.com | 3.4.0 | * | Slideshare | slideshare.net | 3.5.0 | * | SoundCloud | soundcloud.com | 3.5.0 | * | Dailymotion | dai.ly | 3.6.0 | * | Flickr | flic.kr | 3.6.0 | * | Spotify | spotify.com | 3.6.0 | * | Imgur | imgur.com | 3.9.0 | * | Animoto | animoto.com | 4.0.0 | * | Animoto | video214.com | 4.0.0 | * | Issuu | issuu.com | 4.0.0 | * | Mixcloud | mixcloud.com | 4.0.0 | * | Crowdsignal | poll.fm | 4.0.0 | * | TED | ted.com | 4.0.0 | * | YouTube | youtube.com/playlist | 4.0.0 | * | Tumblr | tumblr.com | 4.2.0 | * | Kickstarter | kickstarter.com | 4.2.0 | * | Kickstarter | kck.st | 4.2.0 | * | Cloudup | cloudup.com | 4.3.0 | * | ReverbNation | reverbnation.com | 4.4.0 | * | VideoPress | videopress.com | 4.4.0 | * | Reddit | reddit.com | 4.4.0 | * | Speaker Deck | speakerdeck.com | 4.4.0 | * | Twitter | twitter.com/timelines | 4.5.0 | * | Twitter | twitter.com/moments | 4.5.0 | * | Twitter | twitter.com/user | 4.7.0 | * | Twitter | twitter.com/likes | 4.7.0 | * | Twitter | twitter.com/lists | 4.7.0 | * | Screencast | screencast.com | 4.8.0 | * | Amazon | amazon.com (com.mx, com.br, ca) | 4.9.0 | * | Amazon | amazon.de (fr, it, es, in, nl, ru, co.uk) | 4.9.0 | * | Amazon | amazon.co.jp (com.au) | 4.9.0 | * | Amazon | amazon.cn | 4.9.0 | * | Amazon | a.co | 4.9.0 | * | Amazon | amzn.to (eu, in, asia) | 4.9.0 | * | Amazon | z.cn | 4.9.0 | * | Someecards | someecards.com | 4.9.0 | * | Someecards | some.ly | 4.9.0 | * | Crowdsignal | survey.fm | 5.1.0 | * | TikTok | tiktok.com | 5.4.0 | * | Pinterest | pinterest.com | 5.9.0 | * | WolframCloud | wolframcloud.com | 5.9.0 | * | Pocket Casts | pocketcasts.com | 6.1.0 | * | Crowdsignal | crowdsignal.net | 6.2.0 | * | Anghami | anghami.com | 6.3.0 | * * No longer supported providers: * * | Provider | Flavor | Since | Removed | * | ------------ | -------------------- | --------- | --------- | * | Qik | qik.com | 2.9.0 | 3.9.0 | * | Viddler | viddler.com | 2.9.0 | 4.0.0 | * | Revision3 | revision3.com | 2.9.0 | 4.2.0 | * | Blip | blip.tv | 2.9.0 | 4.4.0 | * | Rdio | rdio.com | 3.6.0 | 4.4.1 | * | Rdio | rd.io | 3.6.0 | 4.4.1 | * | Vine | vine.co | 4.1.0 | 4.9.0 | * | Photobucket | photobucket.com | 2.9.0 | 5.1.0 | * | Funny or Die | funnyordie.com | 3.0.0 | 5.1.0 | * | CollegeHumor | collegehumor.com | 4.0.0 | 5.3.1 | * | Hulu | hulu.com | 2.9.0 | 5.5.0 | * | Instagram | instagram.com | 3.5.0 | 5.5.2 | * | Instagram | instagr.am | 3.5.0 | 5.5.2 | * | Instagram TV | instagram.com | 5.1.0 | 5.5.2 | * | Instagram TV | instagr.am | 5.1.0 | 5.5.2 | * | Facebook | facebook.com | 4.7.0 | 5.5.2 | * | Meetup.com | meetup.com | 3.9.0 | 6.0.1 | * | Meetup.com | meetu.ps | 3.9.0 | 6.0.1 | * * @see wp_oembed_add_provider() * * @since 2.9.0 * * @param array[] $providers An array of arrays containing data about popular oEmbed providers. */ $this->providers = apply_filters( 'oembed_providers', $providers ); // Fix any embeds that contain new lines in the middle of the HTML which breaks wpautop(). add_filter( 'oembed_dataparse', array( $this, '_strip_newlines' ), 10, 3 ); } /** * Exposes private/protected methods for backward compatibility. * * @since 4.0.0 * * @param string $name Method to call. * @param array $arguments Arguments to pass when calling. * @return mixed|false Return value of the callback, false otherwise. */ public function __call( $name, $arguments ) { if ( in_array( $name, $this->compat_methods, true ) ) { return $this->$name( ...$arguments ); } return false; } /** * Takes a URL and returns the corresponding oEmbed provider's URL, if there is one. * * @since 4.0.0 * * @see WP_oEmbed::discover() * * @param string $url The URL to the content. * @param string|array $args { * Optional. Additional provider arguments. Default empty. * * @type bool $discover Optional. Determines whether to attempt to discover link tags * at the given URL for an oEmbed provider when the provider URL * is not found in the built-in providers list. Default true. * } * @return string|false The oEmbed provider URL on success, false on failure. */ public function get_provider( $url, $args = '' ) { $args = wp_parse_args( $args ); $provider = false; if ( ! isset( $args['discover'] ) ) { $args['discover'] = true; } foreach ( $this->providers as $matchmask => $data ) { list( $providerurl, $regex ) = $data; // Turn the asterisk-type provider URLs into regex. if ( ! $regex ) { $matchmask = '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $matchmask ), '#' ) ) . '#i'; $matchmask = preg_replace( '|^#http\\\://|', '#https?\://', $matchmask ); } if ( preg_match( $matchmask, $url ) ) { $provider = str_replace( '{format}', 'json', $providerurl ); // JSON is easier to deal with than XML. break; } } if ( ! $provider && $args['discover'] ) { $provider = $this->discover( $url ); } return $provider; } /** * Adds an oEmbed provider. * * The provider is added just-in-time when wp_oembed_add_provider() is called before * the {@see 'plugins_loaded'} hook. * * The just-in-time addition is for the benefit of the {@see 'oembed_providers'} filter. * * @since 4.0.0 * * @see wp_oembed_add_provider() * * @param string $format Format of URL that this provider can handle. You can use * asterisks as wildcards. * @param string $provider The URL to the oEmbed provider.. * @param bool $regex Optional. Whether the $format parameter is in a regex format. * Default false. */ public static function _add_provider_early( $format, $provider, $regex = false ) { if ( empty( self::$early_providers['add'] ) ) { self::$early_providers['add'] = array(); } self::$early_providers['add'][ $format ] = array( $provider, $regex ); } /** * Removes an oEmbed provider. * * The provider is removed just-in-time when wp_oembed_remove_provider() is called before * the {@see 'plugins_loaded'} hook. * * The just-in-time removal is for the benefit of the {@see 'oembed_providers'} filter. * * @since 4.0.0 * * @see wp_oembed_remove_provider() * * @param string $format The format of URL that this provider can handle. You can use * asterisks as wildcards. */ public static function _remove_provider_early( $format ) { if ( empty( self::$early_providers['remove'] ) ) { self::$early_providers['remove'] = array(); } self::$early_providers['remove'][] = $format; } /** * Takes a URL and attempts to return the oEmbed data. * * @see WP_oEmbed::fetch() * * @since 4.8.0 * * @param string $url The URL to the content that should be attempted to be embedded. * @param string|array $args Optional. Additional arguments for retrieving embed HTML. * See wp_oembed_get() for accepted arguments. Default empty. * @return object|false The result in the form of an object on success, false on failure. */ public function get_data( $url, $args = '' ) { $args = wp_parse_args( $args ); $provider = $this->get_provider( $url, $args ); if ( ! $provider ) { return false; } $data = $this->fetch( $provider, $url, $args ); if ( false === $data ) { return false; } return $data; } /** * The do-it-all function that takes a URL and attempts to return the HTML. * * @see WP_oEmbed::fetch() * @see WP_oEmbed::data2html() * * @since 2.9.0 * * @param string $url The URL to the content that should be attempted to be embedded. * @param string|array $args Optional. Additional arguments for retrieving embed HTML. * See wp_oembed_get() for accepted arguments. Default empty. * @return string|false The UNSANITIZED (and potentially unsafe) HTML that should be used to embed * on success, false on failure. */ public function get_html( $url, $args = '' ) { /** * Filters the oEmbed result before any HTTP requests are made. * * This allows one to short-circuit the default logic, perhaps by * replacing it with a routine that is more optimal for your setup. * * Returning a non-null value from the filter will effectively short-circuit retrieval * and return the passed value instead. * * @since 4.5.3 * * @param null|string $result The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. * Default null to continue retrieving the result. * @param string $url The URL to the content that should be attempted to be embedded. * @param string|array $args Optional. Additional arguments for retrieving embed HTML. * See wp_oembed_get() for accepted arguments. Default empty. */ $pre = apply_filters( 'pre_oembed_result', null, $url, $args ); if ( null !== $pre ) { return $pre; } $data = $this->get_data( $url, $args ); if ( false === $data ) { return false; } /** * Filters the HTML returned by the oEmbed provider. * * @since 2.9.0 * * @param string|false $data The returned oEmbed HTML (false if unsafe). * @param string $url URL of the content to be embedded. * @param string|array $args Optional. Additional arguments for retrieving embed HTML. * See wp_oembed_get() for accepted arguments. Default empty. */ return apply_filters( 'oembed_result', $this->data2html( $data, $url ), $url, $args ); } /** * Attempts to discover link tags at the given URL for an oEmbed provider. * * @since 2.9.0 * * @param string $url The URL that should be inspected for discovery `` tags. * @return string|false The oEmbed provider URL on success, false on failure. */ public function discover( $url ) { $providers = array(); $args = array( 'limit_response_size' => 153600, // 150 KB ); /** * Filters oEmbed remote get arguments. * * @since 4.0.0 * * @see WP_Http::request() * * @param array $args oEmbed remote get arguments. * @param string $url URL to be inspected. */ $args = apply_filters( 'oembed_remote_get_args', $args, $url ); // Fetch URL content. $request = wp_safe_remote_get( $url, $args ); $html = wp_remote_retrieve_body( $request ); if ( $html ) { /** * Filters the link types that contain oEmbed provider URLs. * * @since 2.9.0 * * @param string[] $format Array of oEmbed link types. Accepts 'application/json+oembed', * 'text/xml+oembed', and 'application/xml+oembed' (incorrect, * used by at least Vimeo). */ $linktypes = apply_filters( 'oembed_linktypes', array( 'application/json+oembed' => 'json', 'text/xml+oembed' => 'xml', 'application/xml+oembed' => 'xml', ) ); // Strip . $html_head_end = stripos( $html, '' ); if ( $html_head_end ) { $html = substr( $html, 0, $html_head_end ); } // Do a quick check. $tagfound = false; foreach ( $linktypes as $linktype => $format ) { if ( stripos( $html, $linktype ) ) { $tagfound = true; break; } } if ( $tagfound && preg_match_all( '#]+)/?>#iU', $html, $links ) ) { foreach ( $links[1] as $link ) { $atts = shortcode_parse_atts( $link ); if ( ! empty( $atts['type'] ) && ! empty( $linktypes[ $atts['type'] ] ) && ! empty( $atts['href'] ) ) { $providers[ $linktypes[ $atts['type'] ] ] = htmlspecialchars_decode( $atts['href'] ); // Stop here if it's JSON (that's all we need). if ( 'json' === $linktypes[ $atts['type'] ] ) { break; } } } } } // JSON is preferred to XML. if ( ! empty( $providers['json'] ) ) { return $providers['json']; } elseif ( ! empty( $providers['xml'] ) ) { return $providers['xml']; } else { return false; } } /** * Connects to an oEmbed provider and returns the result. * * @since 2.9.0 * * @param string $provider The URL to the oEmbed provider. * @param string $url The URL to the content that is desired to be embedded. * @param string|array $args Optional. Additional arguments for retrieving embed HTML. * See wp_oembed_get() for accepted arguments. Default empty. * @return object|false The result in the form of an object on success, false on failure. */ public function fetch( $provider, $url, $args = '' ) { $args = wp_parse_args( $args, wp_embed_defaults( $url ) ); $provider = add_query_arg( 'maxwidth', (int) $args['width'], $provider ); $provider = add_query_arg( 'maxheight', (int) $args['height'], $provider ); $provider = add_query_arg( 'url', urlencode( $url ), $provider ); $provider = add_query_arg( 'dnt', 1, $provider ); /** * Filters the oEmbed URL to be fetched. * * @since 2.9.0 * @since 4.9.0 The `dnt` (Do Not Track) query parameter was added to all oEmbed provider URLs. * * @param string $provider URL of the oEmbed provider. * @param string $url URL of the content to be embedded. * @param array $args Optional. Additional arguments for retrieving embed HTML. * See wp_oembed_get() for accepted arguments. Default empty. */ $provider = apply_filters( 'oembed_fetch_url', $provider, $url, $args ); foreach ( array( 'json', 'xml' ) as $format ) { $result = $this->_fetch_with_format( $provider, $format ); if ( is_wp_error( $result ) && 'not-implemented' === $result->get_error_code() ) { continue; } return ( $result && ! is_wp_error( $result ) ) ? $result : false; } return false; } /** * Fetches result from an oEmbed provider for a specific format and complete provider URL * * @since 3.0.0 * * @param string $provider_url_with_args URL to the provider with full arguments list (url, maxheight, etc.) * @param string $format Format to use. * @return object|false|WP_Error The result in the form of an object on success, false on failure. */ private function _fetch_with_format( $provider_url_with_args, $format ) { $provider_url_with_args = add_query_arg( 'format', $format, $provider_url_with_args ); /** This filter is documented in wp-includes/class-wp-oembed.php */ $args = apply_filters( 'oembed_remote_get_args', array(), $provider_url_with_args ); $response = wp_safe_remote_get( $provider_url_with_args, $args ); if ( 501 === wp_remote_retrieve_response_code( $response ) ) { return new WP_Error( 'not-implemented' ); } $body = wp_remote_retrieve_body( $response ); if ( ! $body ) { return false; } $parse_method = "_parse_$format"; return $this->$parse_method( $body ); } /** * Parses a json response body. * * @since 3.0.0 * * @param string $response_body * @return object|false */ private function _parse_json( $response_body ) { $data = json_decode( trim( $response_body ) ); return ( $data && is_object( $data ) ) ? $data : false; } /** * Parses an XML response body. * * @since 3.0.0 * * @param string $response_body * @return object|false */ private function _parse_xml( $response_body ) { if ( ! function_exists( 'libxml_disable_entity_loader' ) ) { return false; } if ( PHP_VERSION_ID < 80000 ) { /* * This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading * is disabled by default, so this function is no longer needed to protect against XXE attacks. */ $loader = libxml_disable_entity_loader( true ); } $errors = libxml_use_internal_errors( true ); $return = $this->_parse_xml_body( $response_body ); libxml_use_internal_errors( $errors ); if ( PHP_VERSION_ID < 80000 && isset( $loader ) ) { // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.libxml_disable_entity_loaderDeprecated libxml_disable_entity_loader( $loader ); } return $return; } /** * Serves as a helper function for parsing an XML response body. * * @since 3.6.0 * * @param string $response_body * @return stdClass|false */ private function _parse_xml_body( $response_body ) { if ( ! function_exists( 'simplexml_import_dom' ) || ! class_exists( 'DOMDocument', false ) ) { return false; } $dom = new DOMDocument(); $success = $dom->loadXML( $response_body ); if ( ! $success ) { return false; } if ( isset( $dom->doctype ) ) { return false; } foreach ( $dom->childNodes as $child ) { if ( XML_DOCUMENT_TYPE_NODE === $child->nodeType ) { return false; } } $xml = simplexml_import_dom( $dom ); if ( ! $xml ) { return false; } $return = new stdClass(); foreach ( $xml as $key => $value ) { $return->$key = (string) $value; } return $return; } /** * Converts a data object from WP_oEmbed::fetch() and returns the HTML. * * @since 2.9.0 * * @param object $data A data object result from an oEmbed provider. * @param string $url The URL to the content that is desired to be embedded. * @return string|false The HTML needed to embed on success, false on failure. */ public function data2html( $data, $url ) { if ( ! is_object( $data ) || empty( $data->type ) ) { return false; } $return = false; switch ( $data->type ) { case 'photo': if ( empty( $data->url ) || empty( $data->width ) || empty( $data->height ) ) { break; } if ( ! is_string( $data->url ) || ! is_numeric( $data->width ) || ! is_numeric( $data->height ) ) { break; } $title = ! empty( $data->title ) && is_string( $data->title ) ? $data->title : ''; $return = '' . esc_attr( $title ) . ''; break; case 'video': case 'rich': if ( ! empty( $data->html ) && is_string( $data->html ) ) { $return = $data->html; } break; case 'link': if ( ! empty( $data->title ) && is_string( $data->title ) ) { $return = '' . esc_html( $data->title ) . ''; } break; default: $return = false; } /** * Filters the returned oEmbed HTML. * * Use this filter to add support for custom data types, or to filter the result. * * @since 2.9.0 * * @param string $return The returned oEmbed HTML. * @param object $data A data object result from an oEmbed provider. * @param string $url The URL of the content to be embedded. */ return apply_filters( 'oembed_dataparse', $return, $data, $url ); } /** * Strips any new lines from the HTML. * * @since 2.9.0 as strip_scribd_newlines() * @since 3.0.0 * * @param string $html Existing HTML. * @param object $data Data object from WP_oEmbed::data2html() * @param string $url The original URL passed to oEmbed. * @return string Possibly modified $html */ public function _strip_newlines( $html, $data, $url ) { if ( ! str_contains( $html, "\n" ) ) { return $html; } $count = 1; $found = array(); $token = '__PRE__'; $search = array( "\t", "\n", "\r", ' ' ); $replace = array( '__TAB__', '__NL__', '__CR__', '__SPACE__' ); $tokenized = str_replace( $search, $replace, $html ); preg_match_all( '#(]*>.+?)#i', $tokenized, $matches, PREG_SET_ORDER ); foreach ( $matches as $i => $match ) { $tag_html = str_replace( $replace, $search, $match[0] ); $tag_token = $token . $i; $found[ $tag_token ] = $tag_html; $html = str_replace( $tag_html, $tag_token, $html, $count ); } $replaced = str_replace( $replace, $search, $html ); $stripped = str_replace( array( "\r\n", "\n" ), '', $replaced ); $pre = array_values( $found ); $tokens = array_keys( $found ); return str_replace( $tokens, $pre, $stripped ); } }
Fatal error: require_once(): Failed opening required '/var/www/html/helitower.com.br/web/wp-content/plugins/revslider/includes/output.sr7.class.php' (include_path='.:/usr/share/pear') in /var/www/html/helitower.com.br/web/wp-content/plugins/revslider/revslider.php on line 111