/** * Examine a url and try to determine the post ID it represents. * * Checks are supposedly from the hosted site blog. * * @since 0.0.1 * * @global HQ_Rewrite $hq_rewrite * @global HQ $hq * * @param string $url Permalink to check. * @return int Post ID, or 0 on failure. */ function url_to_postid($url) { global $hq_rewrite; /** * Filter the URL to derive the post ID from. * * @since 0.0.1 * * @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 = $hq_rewrite->hq_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 (!$hq_rewrite->using_index_permalinks()) { $url = str_replace($hq_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 ($hq_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(HQ_MatchesMapRegex::apply($query, $matches)); // Filter out non-public query vars global $hq; parse_str($query, $query_vars); $query = array(); foreach ((array) $query_vars as $key => $value) { if (in_array($key, $hq->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 = hq_resolve_numeric_slug_conflicts($query); // Do the query $query = new HQ_Query($query); if (!empty($query->posts) && $query->is_singular) { return $query->post->ID; } else { return 0; } } } return 0; }
/** * 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 0.0.1 * * @global HQ_Rewrite $hq_rewrite * * @param array|string $extra_query_vars Set the extra query variables. */ public function parse_request($extra_query_vars = '') { global $hq_rewrite; /** * Filter whether to parse the request. * * @since 0.0.1 * * @param bool $bool Whether or not to parse the request. Default true. * @param HQ $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 = $hq_rewrite->hq_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('|^.*' . $hq_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 == $hq_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 ($hq_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(HQ_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'], 'hq-admin/') !== false) { unset($error, $_GET['error']); if (isset($perma_query_vars) && strpos($_SERVER['PHP_SELF'], 'hq-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 0.0.1 * * @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 $hqvar) { if (isset($this->extra_query_vars[$hqvar])) { $this->query_vars[$hqvar] = $this->extra_query_vars[$hqvar]; } elseif (isset($_POST[$hqvar])) { $this->query_vars[$hqvar] = $_POST[$hqvar]; } elseif (isset($_GET[$hqvar])) { $this->query_vars[$hqvar] = $_GET[$hqvar]; } elseif (isset($perma_query_vars[$hqvar])) { $this->query_vars[$hqvar] = $perma_query_vars[$hqvar]; } if (!empty($this->query_vars[$hqvar])) { if (!is_array($this->query_vars[$hqvar])) { $this->query_vars[$hqvar] = (string) $this->query_vars[$hqvar]; } else { foreach ($this->query_vars[$hqvar] as $vkey => $v) { if (!is_object($v)) { $this->query_vars[$hqvar][$vkey] = (string) $v; } } } if (isset($post_type_query_vars[$hqvar])) { $this->query_vars['post_type'] = $post_type_query_vars[$hqvar]; $this->query_vars['name'] = $this->query_vars[$hqvar]; } } } // Convert urldecoded spaces back into + //TODO: Goyo no taxonomies //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 = hq_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 0.0.1 * * @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 0.0.1 * * @param HQ &$this Current WordPress environment instance (passed by reference). */ do_action_ref_array('parse_request', array(&$this)); }