/** * Parse request to find correct WordPress query. * * Sets up the query variables based on the request. There are also many * filters and actions that can be used to further manipulate the result. * * @since 2.0.0 * * @global WP_Rewrite $wp_rewrite * * @param array|string $extra_query_vars Set the extra query variables. */ public function parse_request($extra_query_vars = '') { global $wp_rewrite; /** * Filter whether to parse the request. * * @since 3.5.0 * * @param bool $bool Whether or not to parse the request. Default true. * @param WP $this Current WordPress environment instance. * @param array|string $extra_query_vars Extra passed query variables. */ if (!apply_filters('do_parse_request', true, $this, $extra_query_vars)) { return; } $this->query_vars = array(); $post_type_query_vars = array(); if (is_array($extra_query_vars)) { $this->extra_query_vars =& $extra_query_vars; } elseif (!empty($extra_query_vars)) { parse_str($extra_query_vars, $this->extra_query_vars); } // Process PATH_INFO, REQUEST_URI, and 404 for permalinks. // Fetch the rewrite rules. $rewrite = $wp_rewrite->wp_rewrite_rules(); if (!empty($rewrite)) { // If we match a rewrite rule, this will be cleared. $error = '404'; $this->did_permalink = true; $pathinfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ''; list($pathinfo) = explode('?', $pathinfo); $pathinfo = str_replace("%", "%25", $pathinfo); list($req_uri) = explode('?', $_SERVER['REQUEST_URI']); $self = $_SERVER['PHP_SELF']; $home_path = trim(parse_url(home_url(), PHP_URL_PATH), '/'); $home_path_regex = sprintf('|^%s|i', preg_quote($home_path, '|')); // Trim path info from the end and the leading home path from the // front. For path info requests, this leaves us with the requesting // filename, if any. For 404 requests, this leaves us with the // requested permalink. $req_uri = str_replace($pathinfo, '', $req_uri); $req_uri = trim($req_uri, '/'); $req_uri = preg_replace($home_path_regex, '', $req_uri); $req_uri = trim($req_uri, '/'); $pathinfo = trim($pathinfo, '/'); $pathinfo = preg_replace($home_path_regex, '', $pathinfo); $pathinfo = trim($pathinfo, '/'); $self = trim($self, '/'); $self = preg_replace($home_path_regex, '', $self); $self = trim($self, '/'); // The requested permalink is in $pathinfo for path info requests and // $req_uri for other requests. if (!empty($pathinfo) && !preg_match('|^.*' . $wp_rewrite->index . '$|', $pathinfo)) { $request = $pathinfo; } else { // If the request uri is the index, blank it out so that we don't try to match it against a rule. if ($req_uri == $wp_rewrite->index) { $req_uri = ''; } $request = $req_uri; } $this->request = $request; // Look for matches. $request_match = $request; if (empty($request_match)) { // An empty request could only match against ^$ regex if (isset($rewrite['$'])) { $this->matched_rule = '$'; $query = $rewrite['$']; $matches = array(''); } } else { foreach ((array) $rewrite as $match => $query) { // If the requesting file is the anchor of the match, prepend it to the path info. if (!empty($req_uri) && strpos($match, $req_uri) === 0 && $req_uri != $request) { $request_match = $req_uri . '/' . $request; } if (preg_match("#^{$match}#", $request_match, $matches) || preg_match("#^{$match}#", urldecode($request_match), $matches)) { if ($wp_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. if (!get_page_by_path($matches[$varmatch[1]])) { continue; } } // Got a match. $this->matched_rule = $match; break; } } } if (isset($this->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)); $this->matched_query = $query; // Parse the query. parse_str($query, $perma_query_vars); // If we're processing a 404 request, clear the error var since we found something. if ('404' == $error) { unset($error, $_GET['error']); } } // If req_uri is empty or if it is a request for ourself, unset error. if (empty($request) || $req_uri == $self || strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false) { unset($error, $_GET['error']); if (isset($perma_query_vars) && strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false) { unset($perma_query_vars); } $this->did_permalink = false; } } /** * Filter the query variables whitelist before processing. * * Allows (publicly allowed) query vars to be added, removed, or changed prior * to executing the query. Needed to allow custom rewrite rules using your own arguments * to work, or any other custom query variables you want to be publicly available. * * @since 1.5.0 * * @param array $public_query_vars The array of whitelisted query variables. */ $this->public_query_vars = apply_filters('query_vars', $this->public_query_vars); foreach (get_post_types(array(), 'objects') as $post_type => $t) { if ($t->query_var) { $post_type_query_vars[$t->query_var] = $post_type; } } foreach ($this->public_query_vars as $wpvar) { if (isset($this->extra_query_vars[$wpvar])) { $this->query_vars[$wpvar] = $this->extra_query_vars[$wpvar]; } elseif (isset($_POST[$wpvar])) { $this->query_vars[$wpvar] = $_POST[$wpvar]; } elseif (isset($_GET[$wpvar])) { $this->query_vars[$wpvar] = $_GET[$wpvar]; } elseif (isset($perma_query_vars[$wpvar])) { $this->query_vars[$wpvar] = $perma_query_vars[$wpvar]; } if (!empty($this->query_vars[$wpvar])) { if (!is_array($this->query_vars[$wpvar])) { $this->query_vars[$wpvar] = (string) $this->query_vars[$wpvar]; } else { foreach ($this->query_vars[$wpvar] as $vkey => $v) { if (!is_object($v)) { $this->query_vars[$wpvar][$vkey] = (string) $v; } } } if (isset($post_type_query_vars[$wpvar])) { $this->query_vars['post_type'] = $post_type_query_vars[$wpvar]; $this->query_vars['name'] = $this->query_vars[$wpvar]; } } } // Convert urldecoded spaces back into + foreach (get_taxonomies(array(), 'objects') as $taxonomy => $t) { if ($t->query_var && isset($this->query_vars[$t->query_var])) { $this->query_vars[$t->query_var] = str_replace(' ', '+', $this->query_vars[$t->query_var]); } } // Limit publicly queried post_types to those that are publicly_queryable if (isset($this->query_vars['post_type'])) { $queryable_post_types = get_post_types(array('publicly_queryable' => true)); if (!is_array($this->query_vars['post_type'])) { if (!in_array($this->query_vars['post_type'], $queryable_post_types)) { unset($this->query_vars['post_type']); } } else { $this->query_vars['post_type'] = array_intersect($this->query_vars['post_type'], $queryable_post_types); } } // Resolve conflicts between posts with numeric slugs and date archive queries. $this->query_vars = wp_resolve_numeric_slug_conflicts($this->query_vars); foreach ((array) $this->private_query_vars as $var) { if (isset($this->extra_query_vars[$var])) { $this->query_vars[$var] = $this->extra_query_vars[$var]; } } if (isset($error)) { $this->query_vars['error'] = $error; } /** * Filter the array of parsed query variables. * * @since 2.1.0 * * @param array $query_vars The array of requested query variables. */ $this->query_vars = apply_filters('request', $this->query_vars); /** * Fires once all query variables for the current request have been parsed. * * @since 2.1.0 * * @param WP &$this Current WordPress environment instance (passed by reference). */ do_action_ref_array('parse_request', array(&$this)); }
/** * Examine a url and try to determine the post ID it represents. * * Checks are supposedly from the hosted site blog. * * @since 1.0.0 * * @global WP_Rewrite $wp_rewrite * @global WP $wp * * @param string $url Permalink to check. * @return int Post ID, or 0 on failure. */ function url_to_postid( $url ) { global $wp_rewrite; /** * Filter the URL to derive the post ID from. * * @since 2.2.0 * * @param string $url The URL to derive the post ID from. */ $url = apply_filters( 'url_to_postid', $url ); // First, check to see if there is a 'p=N' or 'page_id=N' to match against if ( preg_match('#[?&](p|page_id|attachment_id)=(\d+)#', $url, $values) ) { $id = absint($values[2]); if ( $id ) return $id; } // Check to see if we are using rewrite rules $rewrite = $wp_rewrite->wp_rewrite_rules(); // Not using rewrite rules, and 'p=N' and 'page_id=N' methods failed, so we're out of options if ( empty($rewrite) ) return 0; // Get rid of the #anchor $url_split = explode('#', $url); $url = $url_split[0]; // Get rid of URL ?query=string $url_split = explode('?', $url); $url = $url_split[0]; // Add 'www.' if it is absent and should be there if ( false !== strpos(home_url(), '://www.') && false === strpos($url, '://www.') ) $url = str_replace('://', '://www.', $url); // Strip 'www.' if it is present and shouldn't be if ( false === strpos(home_url(), '://www.') ) $url = str_replace('://www.', '://', $url); // Strip 'index.php/' if we're not using path info permalinks if ( !$wp_rewrite->using_index_permalinks() ) $url = str_replace( $wp_rewrite->index . '/', '', $url ); if ( false !== strpos( trailingslashit( $url ), home_url( '/' ) ) ) { // Chop off http://domain.com/[path] $url = str_replace(home_url(), '', $url); } else { // Chop off /path/to/blog $home_path = parse_url( home_url( '/' ) ); $home_path = isset( $home_path['path'] ) ? $home_path['path'] : '' ; $url = preg_replace( sprintf( '#^%s#', preg_quote( $home_path ) ), '', trailingslashit( $url ) ); } // Trim leading and lagging slashes $url = trim($url, '/'); $request = $url; $post_type_query_vars = array(); foreach ( get_post_types( array() , 'objects' ) as $post_type => $t ) { if ( ! empty( $t->query_var ) ) $post_type_query_vars[ $t->query_var ] = $post_type; } // Look for matches. $request_match = $request; foreach ( (array)$rewrite as $match => $query) { // If the requesting file is the anchor of the match, prepend it // to the path info. if ( !empty($url) && ($url != $request) && (strpos($match, $url) === 0) ) $request_match = $url . '/' . $request; if ( preg_match("#^$match#", $request_match, $matches) ) { if ( $wp_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. if ( ! get_page_by_path( $matches[ $varmatch[1] ] ) ) continue; } // Got a match. // 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)); // Filter out non-public query vars global $wp; parse_str( $query, $query_vars ); $query = array(); foreach ( (array) $query_vars as $key => $value ) { if ( in_array( $key, $wp->public_query_vars ) ){ $query[$key] = $value; if ( isset( $post_type_query_vars[$key] ) ) { $query['post_type'] = $post_type_query_vars[$key]; $query['name'] = $value; } } } // Resolve conflicts between posts with numeric slugs and date archive queries. $query = wp_resolve_numeric_slug_conflicts( $query ); // Do the query $query = new WP_Query( $query ); if ( ! empty( $query->posts ) && $query->is_singular ) return $query->post->ID; else return 0; } } return 0; }