Tribe__Rewrite::parse_request( string $url, array $extra_query_vars = array(), bool $force = false )
Parses a URL to produce an array of query variables.
Contents
Most of this functionality was copied from WP::parse_request() method with some changes to avoid conflicts and removing non-required behaviors.
Parameters
- $url
-
(string) (Required) The URLto parse.
- $extra_query_vars
-
(array) (Optional) An associative array of extra query vars to use for the parsing. These vars will be read before the WordPress defined ones overriding them.
Default value: array()
- $force
-
(bool) (Optional) Whether to try and use the cache or force a new canonical URL conversion.
Default value: false
Return
(array) An array of query vars, as parsed from the input URL.
Source
File: src/Tribe/Rewrite.php
public function parse_request( $url, array $extra_query_vars = [], $force = false ) {
if ( null === $this->rewrite ) {
// We re-do this check here as the object might have been initialized before the global rewrite was set.
$this->setup();
}
/**
* Allows short-circuiting the URL parsing.
*
* This filter will run before any logic runs, its result will not be cached and this filter will be called on
* each call to this method.
* Returning a non `null` value here will short-circuit this logic.
*
* @since 4.9.11
*
* @param array $query_vars The parsed query vars array.
* @param array $extra_query_vars An associative array of extra query vars that will be processed before the
* WordPress defined ones.
* @param string $url The URL to parse.
*/
$parsed = apply_filters( 'tribe_rewrite_pre_parse_query_vars', null, $extra_query_vars, $url );
if ( null !== $parsed ) {
return $parsed;
}
if ( ! $force ) {
$this->warmup_cache(
'parse_request',
WEEK_IN_SECONDS,
Listener::TRIGGER_GENERATE_REWRITE_RULES
);
if ( isset( $this->parse_request_cache[ $url ] ) ) {
return $this->parse_request_cache[ $url ];
}
}
$query_vars = [];
$post_type_query_vars = [];
$perma_query_vars = [];
$url_components = parse_url($url);
$url_path = Arr::get( $url_components, 'path', '/' );
$url_query = Arr::get( $url_components, 'query', '' );
parse_str( $url_query, $url_query_vars );
// Look for matches, removing leading `/` char.
$request_match = ltrim( $url_path, '/' );
// Fetch the rewrite rules.
$rewrite_rules = $this->rewrite->wp_rewrite_rules();
$matched_rule = false;
if ( ! empty( $rewrite_rules ) ) {
foreach ( (array) $rewrite_rules as $match => $query ) {
$matches_regex = preg_match( "#^$match#", $request_match, $matches )
|| preg_match( "#^$match#", urldecode( $request_match ), $matches );
if ( ! $matches_regex ) {
continue;
}
if (
$this->rewrite->use_verbose_page_rules
&& preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch )
) {
// This is a verbose page match, let's check to be sure about it.
$page = get_page_by_path( $matches[ $varmatch[1] ] );
if ( ! $page ) {
continue;
}
$post_status_obj = get_post_status_object( $page->post_status );
if (
! $post_status_obj->public
&& ! $post_status_obj->protected
&& ! $post_status_obj->private
&& $post_status_obj->exclude_from_search
) {
continue;
}
}
// Got a match.
$matched_rule = $match;
break;
}
if ( false !== $matched_rule ) {
// Trim the query of everything up to the '?'.
$query = preg_replace( '!^.+\?!', '', $query );
// Substitute the substring matches into the query.
$query = addslashes( WP_MatchesMapRegex::apply( $query, $matches ) );
// Parse the query.
parse_str( $query, $perma_query_vars );
}
}
foreach ( get_post_types( [], 'objects' ) as $post_type => $t ) {
if (
is_post_type_viewable( $t )
&& $t->query_var
) {
$post_type_query_vars[ $t->query_var ] = $post_type;
}
}
global $wp;
/*
* WordPress would apply this filter in the `parse_request` method to allow the registration of additional query
* vars. They might not have been registered at this point so we do this again making sure to avoid duplicates.
*/
$public_query_vars = array_unique( apply_filters( 'query_vars', $wp->public_query_vars ) );
foreach ( $public_query_vars as $wpvar ) {
if ( isset( $extra_query_vars[ $wpvar ] ) ) {
$query_vars[ $wpvar ] = $extra_query_vars[ $wpvar ];
} elseif ( isset( $perma_query_vars[ $wpvar ] ) ) {
$query_vars[ $wpvar ] = $perma_query_vars[ $wpvar ];
}
if ( ! empty( $query_vars[ $wpvar ] ) ) {
if ( ! is_array( $query_vars[ $wpvar ] ) ) {
$query_vars[ $wpvar ] = (string) $query_vars[ $wpvar ];
} else {
foreach ( $query_vars[ $wpvar ] as $vkey => $v ) {
if ( is_scalar( $v ) ) {
$query_vars[ $wpvar ][ $vkey ] = (string) $v;
}
}
}
if ( isset( $post_type_query_vars[ $wpvar ] ) ) {
$query_vars['post_type'] = $post_type_query_vars[ $wpvar ];
$query_vars['name'] = $query_vars[ $wpvar ];
}
}
}
// Convert urldecoded spaces back into `+`.
foreach ( get_taxonomies( [], 'objects' ) as $taxonomy => $t ) {
if ( $t->query_var && isset( $query_vars[ $t->query_var ] ) ) {
$query_vars[ $t->query_var ] = str_replace( ' ', '+', $query_vars[ $t->query_var ] );
}
}
// Don't allow non-publicly queryable taxonomies to be queried from the front end.
if ( ! is_admin() ) {
foreach ( get_taxonomies( [ 'publicly_queryable' => false ], 'objects' ) as $taxonomy => $t ) {
/*
* Disallow when set to the 'taxonomy' query var.
* Non-publicly queryable taxonomies cannot register custom query vars. See register_taxonomy().
*/
if ( isset( $query_vars['taxonomy'] ) && $taxonomy === $query_vars['taxonomy'] ) {
unset( $query_vars['taxonomy'], $query_vars['term'] );
}
}
}
// Limit publicly queried post_types to those that are publicly_queryable
if ( isset( $query_vars['post_type'] ) ) {
$queryable_post_types = get_post_types( [ 'publicly_queryable' => true ] );
if ( ! is_array( $query_vars['post_type'] ) ) {
if ( ! in_array( $query_vars['post_type'], $queryable_post_types ) ) {
unset( $query_vars['post_type'] );
}
} else {
$query_vars['post_type'] = array_intersect( $query_vars['post_type'], $queryable_post_types );
}
}
// Resolve conflicts between posts with numeric slugs and date archive queries.
$query_vars = wp_resolve_numeric_slug_conflicts( $query_vars );
foreach ( (array) $wp->private_query_vars as $var ) {
if ( isset( $extra_query_vars[ $var ] ) ) {
$query_vars[ $var ] = $extra_query_vars[ $var ];
}
}
/*
* If we have both the `name` query var and the post type one, then let's remove the `name` one.
*/
if ( array_intersect( array_keys( $query_vars ), $this->get_post_types() ) ) {
unset( $query_vars['name'] );
}
if ( ! empty( $url_query_vars ) ) {
// If the URL did have query vars keep them if not overridden by our resolution.
$query_vars = array_merge( $url_query_vars, $query_vars );
}
/**
* Filters the array of parsed query variables after the class logic has been applied to it.
*
* Due to the costly nature of this operation the results will be cached. The logic, and this filter, will
* not run a second time for the same URL in the context of the same request.
*
* @since 4.9.11
*
* @param array $query_vars The parsed query vars array.
* @param array $extra_query_vars An associative array of extra query vars that will be processed before the
* WordPress defined ones.
* @param string $url The URL to parse.
*/
$query_vars = apply_filters( 'tribe_rewrite_parse_query_vars', $query_vars, $extra_query_vars, $url );
if ( $matched_rule ) {
// Since we're caching let's not cache unmatchec URLs to allow for their later, valid matching.
$this->parse_request_cache[ $url ] = $query_vars;
}
return $query_vars;
}
Changelog
| Version | Description |
|---|---|
| 4.9.11 | Introduced. |