wp/wp-includes/class-wp.php
changeset 0 d970ebf37754
child 5 5e2f62d02dcd
equal deleted inserted replaced
-1:000000000000 0:d970ebf37754
       
     1 <?php
       
     2 /**
       
     3  * WordPress environment setup class.
       
     4  *
       
     5  * @package WordPress
       
     6  * @since 2.0.0
       
     7  */
       
     8 class WP {
       
     9 	/**
       
    10 	 * Public query variables.
       
    11 	 *
       
    12 	 * Long list of public query variables.
       
    13 	 *
       
    14 	 * @since 2.0.0
       
    15 	 * @access public
       
    16 	 * @var array
       
    17 	 */
       
    18 	var $public_query_vars = array('m', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'static', 'pagename', 'page_id', 'error', 'comments_popup', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type');
       
    19 
       
    20 	/**
       
    21 	 * Private query variables.
       
    22 	 *
       
    23 	 * Long list of private query variables.
       
    24 	 *
       
    25 	 * @since 2.0.0
       
    26 	 * @var array
       
    27 	 */
       
    28 	var $private_query_vars = array( 'offset', 'posts_per_page', 'posts_per_archive_page', 'showposts', 'nopaging', 'post_type', 'post_status', 'category__in', 'category__not_in', 'category__and', 'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and', 'tag_id', 'post_mime_type', 'perm', 'comments_per_page', 'post__in', 'post__not_in', 'post_parent__in', 'post_parent__not_in' );
       
    29 
       
    30 	/**
       
    31 	 * Extra query variables set by the user.
       
    32 	 *
       
    33 	 * @since 2.1.0
       
    34 	 * @var array
       
    35 	 */
       
    36 	var $extra_query_vars = array();
       
    37 
       
    38 	/**
       
    39 	 * Query variables for setting up the WordPress Query Loop.
       
    40 	 *
       
    41 	 * @since 2.0.0
       
    42 	 * @var array
       
    43 	 */
       
    44 	var $query_vars;
       
    45 
       
    46 	/**
       
    47 	 * String parsed to set the query variables.
       
    48 	 *
       
    49 	 * @since 2.0.0
       
    50 	 * @var string
       
    51 	 */
       
    52 	var $query_string;
       
    53 
       
    54 	/**
       
    55 	 * Permalink or requested URI.
       
    56 	 *
       
    57 	 * @since 2.0.0
       
    58 	 * @var string
       
    59 	 */
       
    60 	var $request;
       
    61 
       
    62 	/**
       
    63 	 * Rewrite rule the request matched.
       
    64 	 *
       
    65 	 * @since 2.0.0
       
    66 	 * @var string
       
    67 	 */
       
    68 	var $matched_rule;
       
    69 
       
    70 	/**
       
    71 	 * Rewrite query the request matched.
       
    72 	 *
       
    73 	 * @since 2.0.0
       
    74 	 * @var string
       
    75 	 */
       
    76 	var $matched_query;
       
    77 
       
    78 	/**
       
    79 	 * Whether already did the permalink.
       
    80 	 *
       
    81 	 * @since 2.0.0
       
    82 	 * @var bool
       
    83 	 */
       
    84 	var $did_permalink = false;
       
    85 
       
    86 	/**
       
    87 	 * Add name to list of public query variables.
       
    88 	 *
       
    89 	 * @since 2.1.0
       
    90 	 *
       
    91 	 * @param string $qv Query variable name.
       
    92 	 */
       
    93 	function add_query_var($qv) {
       
    94 		if ( !in_array($qv, $this->public_query_vars) )
       
    95 			$this->public_query_vars[] = $qv;
       
    96 	}
       
    97 
       
    98 	/**
       
    99 	 * Set the value of a query variable.
       
   100 	 *
       
   101 	 * @since 2.3.0
       
   102 	 *
       
   103 	 * @param string $key Query variable name.
       
   104 	 * @param mixed $value Query variable value.
       
   105 	 */
       
   106 	function set_query_var($key, $value) {
       
   107 		$this->query_vars[$key] = $value;
       
   108 	}
       
   109 
       
   110 	/**
       
   111 	 * Parse request to find correct WordPress query.
       
   112 	 *
       
   113 	 * Sets up the query variables based on the request. There are also many
       
   114 	 * filters and actions that can be used to further manipulate the result.
       
   115 	 *
       
   116 	 * @since 2.0.0
       
   117 	 *
       
   118 	 * @param array|string $extra_query_vars Set the extra query variables.
       
   119 	 */
       
   120 	function parse_request($extra_query_vars = '') {
       
   121 		global $wp_rewrite;
       
   122 
       
   123 		if ( ! apply_filters( 'do_parse_request', true, $this, $extra_query_vars ) )
       
   124 			return;
       
   125 
       
   126 		$this->query_vars = array();
       
   127 		$post_type_query_vars = array();
       
   128 
       
   129 		if ( is_array($extra_query_vars) )
       
   130 			$this->extra_query_vars = & $extra_query_vars;
       
   131 		else if (! empty($extra_query_vars))
       
   132 			parse_str($extra_query_vars, $this->extra_query_vars);
       
   133 
       
   134 		// Process PATH_INFO, REQUEST_URI, and 404 for permalinks.
       
   135 
       
   136 		// Fetch the rewrite rules.
       
   137 		$rewrite = $wp_rewrite->wp_rewrite_rules();
       
   138 
       
   139 		if ( ! empty($rewrite) ) {
       
   140 			// If we match a rewrite rule, this will be cleared.
       
   141 			$error = '404';
       
   142 			$this->did_permalink = true;
       
   143 
       
   144 			$pathinfo = isset( $_SERVER['PATH_INFO'] ) ? $_SERVER['PATH_INFO'] : '';
       
   145 			list( $pathinfo ) = explode( '?', $pathinfo );
       
   146 			$pathinfo = str_replace( "%", "%25", $pathinfo );
       
   147 
       
   148 			list( $req_uri ) = explode( '?', $_SERVER['REQUEST_URI'] );
       
   149 			$self = $_SERVER['PHP_SELF'];
       
   150 			$home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' );
       
   151 
       
   152 			// Trim path info from the end and the leading home path from the
       
   153 			// front. For path info requests, this leaves us with the requesting
       
   154 			// filename, if any. For 404 requests, this leaves us with the
       
   155 			// requested permalink.
       
   156 			$req_uri = str_replace($pathinfo, '', $req_uri);
       
   157 			$req_uri = trim($req_uri, '/');
       
   158 			$req_uri = preg_replace("|^$home_path|i", '', $req_uri);
       
   159 			$req_uri = trim($req_uri, '/');
       
   160 			$pathinfo = trim($pathinfo, '/');
       
   161 			$pathinfo = preg_replace("|^$home_path|i", '', $pathinfo);
       
   162 			$pathinfo = trim($pathinfo, '/');
       
   163 			$self = trim($self, '/');
       
   164 			$self = preg_replace("|^$home_path|i", '', $self);
       
   165 			$self = trim($self, '/');
       
   166 
       
   167 			// The requested permalink is in $pathinfo for path info requests and
       
   168 			//  $req_uri for other requests.
       
   169 			if ( ! empty($pathinfo) && !preg_match('|^.*' . $wp_rewrite->index . '$|', $pathinfo) ) {
       
   170 				$request = $pathinfo;
       
   171 			} else {
       
   172 				// If the request uri is the index, blank it out so that we don't try to match it against a rule.
       
   173 				if ( $req_uri == $wp_rewrite->index )
       
   174 					$req_uri = '';
       
   175 				$request = $req_uri;
       
   176 			}
       
   177 
       
   178 			$this->request = $request;
       
   179 
       
   180 			// Look for matches.
       
   181 			$request_match = $request;
       
   182 			if ( empty( $request_match ) ) {
       
   183 				// An empty request could only match against ^$ regex
       
   184 				if ( isset( $rewrite['$'] ) ) {
       
   185 					$this->matched_rule = '$';
       
   186 					$query = $rewrite['$'];
       
   187 					$matches = array('');
       
   188 				}
       
   189 			} else {
       
   190 				foreach ( (array) $rewrite as $match => $query ) {
       
   191 					// If the requesting file is the anchor of the match, prepend it to the path info.
       
   192 					if ( ! empty($req_uri) && strpos($match, $req_uri) === 0 && $req_uri != $request )
       
   193 						$request_match = $req_uri . '/' . $request;
       
   194 
       
   195 					if ( preg_match("#^$match#", $request_match, $matches) ||
       
   196 						preg_match("#^$match#", urldecode($request_match), $matches) ) {
       
   197 
       
   198 						if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) {
       
   199 							// this is a verbose page match, lets check to be sure about it
       
   200 							if ( ! get_page_by_path( $matches[ $varmatch[1] ] ) )
       
   201 						 		continue;
       
   202 						}
       
   203 
       
   204 						// Got a match.
       
   205 						$this->matched_rule = $match;
       
   206 						break;
       
   207 					}
       
   208 				}
       
   209 			}
       
   210 
       
   211 			if ( isset( $this->matched_rule ) ) {
       
   212 				// Trim the query of everything up to the '?'.
       
   213 				$query = preg_replace("!^.+\?!", '', $query);
       
   214 
       
   215 				// Substitute the substring matches into the query.
       
   216 				$query = addslashes(WP_MatchesMapRegex::apply($query, $matches));
       
   217 
       
   218 				$this->matched_query = $query;
       
   219 
       
   220 				// Parse the query.
       
   221 				parse_str($query, $perma_query_vars);
       
   222 
       
   223 				// If we're processing a 404 request, clear the error var since we found something.
       
   224 				if ( '404' == $error )
       
   225 					unset( $error, $_GET['error'] );
       
   226 			}
       
   227 
       
   228 			// If req_uri is empty or if it is a request for ourself, unset error.
       
   229 			if ( empty($request) || $req_uri == $self || strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false ) {
       
   230 				unset( $error, $_GET['error'] );
       
   231 
       
   232 				if ( isset($perma_query_vars) && strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false )
       
   233 					unset( $perma_query_vars );
       
   234 
       
   235 				$this->did_permalink = false;
       
   236 			}
       
   237 		}
       
   238 
       
   239 		$this->public_query_vars = apply_filters('query_vars', $this->public_query_vars);
       
   240 
       
   241 		foreach ( get_post_types( array(), 'objects' ) as $post_type => $t )
       
   242 			if ( $t->query_var )
       
   243 				$post_type_query_vars[$t->query_var] = $post_type;
       
   244 
       
   245 		foreach ( $this->public_query_vars as $wpvar ) {
       
   246 			if ( isset( $this->extra_query_vars[$wpvar] ) )
       
   247 				$this->query_vars[$wpvar] = $this->extra_query_vars[$wpvar];
       
   248 			elseif ( isset( $_POST[$wpvar] ) )
       
   249 				$this->query_vars[$wpvar] = $_POST[$wpvar];
       
   250 			elseif ( isset( $_GET[$wpvar] ) )
       
   251 				$this->query_vars[$wpvar] = $_GET[$wpvar];
       
   252 			elseif ( isset( $perma_query_vars[$wpvar] ) )
       
   253 				$this->query_vars[$wpvar] = $perma_query_vars[$wpvar];
       
   254 
       
   255 			if ( !empty( $this->query_vars[$wpvar] ) ) {
       
   256 				if ( ! is_array( $this->query_vars[$wpvar] ) ) {
       
   257 					$this->query_vars[$wpvar] = (string) $this->query_vars[$wpvar];
       
   258 				} else {
       
   259 					foreach ( $this->query_vars[$wpvar] as $vkey => $v ) {
       
   260 						if ( !is_object( $v ) ) {
       
   261 							$this->query_vars[$wpvar][$vkey] = (string) $v;
       
   262 						}
       
   263 					}
       
   264 				}
       
   265 
       
   266 				if ( isset($post_type_query_vars[$wpvar] ) ) {
       
   267 					$this->query_vars['post_type'] = $post_type_query_vars[$wpvar];
       
   268 					$this->query_vars['name'] = $this->query_vars[$wpvar];
       
   269 				}
       
   270 			}
       
   271 		}
       
   272 
       
   273 		// Convert urldecoded spaces back into +
       
   274 		foreach ( get_taxonomies( array() , 'objects' ) as $taxonomy => $t )
       
   275 			if ( $t->query_var && isset( $this->query_vars[$t->query_var] ) )
       
   276 				$this->query_vars[$t->query_var] = str_replace( ' ', '+', $this->query_vars[$t->query_var] );
       
   277 
       
   278 		// Limit publicly queried post_types to those that are publicly_queryable
       
   279 		if ( isset( $this->query_vars['post_type']) ) {
       
   280 			$queryable_post_types = get_post_types( array('publicly_queryable' => true) );
       
   281 			if ( ! is_array( $this->query_vars['post_type'] ) ) {
       
   282 				if ( ! in_array( $this->query_vars['post_type'], $queryable_post_types ) )
       
   283 					unset( $this->query_vars['post_type'] );
       
   284 			} else {
       
   285 				$this->query_vars['post_type'] = array_intersect( $this->query_vars['post_type'], $queryable_post_types );
       
   286 			}
       
   287 		}
       
   288 
       
   289 		foreach ( (array) $this->private_query_vars as $var) {
       
   290 			if ( isset($this->extra_query_vars[$var]) )
       
   291 				$this->query_vars[$var] = $this->extra_query_vars[$var];
       
   292 		}
       
   293 
       
   294 		if ( isset($error) )
       
   295 			$this->query_vars['error'] = $error;
       
   296 
       
   297 		$this->query_vars = apply_filters('request', $this->query_vars);
       
   298 
       
   299 		do_action_ref_array('parse_request', array(&$this));
       
   300 	}
       
   301 
       
   302 	/**
       
   303 	 * Send additional HTTP headers for caching, content type, etc.
       
   304 	 *
       
   305 	 * Sets the X-Pingback header, 404 status (if 404), Content-type. If showing
       
   306 	 * a feed, it will also send last-modified, etag, and 304 status if needed.
       
   307 	 *
       
   308 	 * @since 2.0.0
       
   309 	 */
       
   310 	function send_headers() {
       
   311 		$headers = array('X-Pingback' => get_bloginfo('pingback_url'));
       
   312 		$status = null;
       
   313 		$exit_required = false;
       
   314 
       
   315 		if ( is_user_logged_in() )
       
   316 			$headers = array_merge($headers, wp_get_nocache_headers());
       
   317 		if ( ! empty( $this->query_vars['error'] ) ) {
       
   318 			$status = (int) $this->query_vars['error'];
       
   319 			if ( 404 === $status ) {
       
   320 				if ( ! is_user_logged_in() )
       
   321 					$headers = array_merge($headers, wp_get_nocache_headers());
       
   322 				$headers['Content-Type'] = get_option('html_type') . '; charset=' . get_option('blog_charset');
       
   323 			} elseif ( in_array( $status, array( 403, 500, 502, 503 ) ) ) {
       
   324 				$exit_required = true;
       
   325 			}
       
   326 		} else if ( empty($this->query_vars['feed']) ) {
       
   327 			$headers['Content-Type'] = get_option('html_type') . '; charset=' . get_option('blog_charset');
       
   328 		} else {
       
   329 			// We're showing a feed, so WP is indeed the only thing that last changed
       
   330 			if ( !empty($this->query_vars['withcomments'])
       
   331 				|| false !== strpos( $this->query_vars['feed'], 'comments-' )
       
   332 				|| ( empty($this->query_vars['withoutcomments'])
       
   333 					&& ( !empty($this->query_vars['p'])
       
   334 						|| !empty($this->query_vars['name'])
       
   335 						|| !empty($this->query_vars['page_id'])
       
   336 						|| !empty($this->query_vars['pagename'])
       
   337 						|| !empty($this->query_vars['attachment'])
       
   338 						|| !empty($this->query_vars['attachment_id'])
       
   339 					)
       
   340 				)
       
   341 			)
       
   342 				$wp_last_modified = mysql2date('D, d M Y H:i:s', get_lastcommentmodified('GMT'), 0).' GMT';
       
   343 			else
       
   344 				$wp_last_modified = mysql2date('D, d M Y H:i:s', get_lastpostmodified('GMT'), 0).' GMT';
       
   345 			$wp_etag = '"' . md5($wp_last_modified) . '"';
       
   346 			$headers['Last-Modified'] = $wp_last_modified;
       
   347 			$headers['ETag'] = $wp_etag;
       
   348 
       
   349 			// Support for Conditional GET
       
   350 			if (isset($_SERVER['HTTP_IF_NONE_MATCH']))
       
   351 				$client_etag = wp_unslash( $_SERVER['HTTP_IF_NONE_MATCH'] );
       
   352 			else $client_etag = false;
       
   353 
       
   354 			$client_last_modified = empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? '' : trim($_SERVER['HTTP_IF_MODIFIED_SINCE']);
       
   355 			// If string is empty, return 0. If not, attempt to parse into a timestamp
       
   356 			$client_modified_timestamp = $client_last_modified ? strtotime($client_last_modified) : 0;
       
   357 
       
   358 			// Make a timestamp for our most recent modification...
       
   359 			$wp_modified_timestamp = strtotime($wp_last_modified);
       
   360 
       
   361 			if ( ($client_last_modified && $client_etag) ?
       
   362 					 (($client_modified_timestamp >= $wp_modified_timestamp) && ($client_etag == $wp_etag)) :
       
   363 					 (($client_modified_timestamp >= $wp_modified_timestamp) || ($client_etag == $wp_etag)) ) {
       
   364 				$status = 304;
       
   365 				$exit_required = true;
       
   366 			}
       
   367 		}
       
   368 
       
   369 		$headers = apply_filters('wp_headers', $headers, $this);
       
   370 
       
   371 		if ( ! empty( $status ) )
       
   372 			status_header( $status );
       
   373 
       
   374 		// If Last-Modified is set to false, it should not be sent (no-cache situation).
       
   375 		if ( isset( $headers['Last-Modified'] ) && false === $headers['Last-Modified'] ) {
       
   376 			unset( $headers['Last-Modified'] );
       
   377 
       
   378 			// In PHP 5.3+, make sure we are not sending a Last-Modified header.
       
   379 			if ( function_exists( 'header_remove' ) ) {
       
   380 				@header_remove( 'Last-Modified' );
       
   381 			} else {
       
   382 				// In PHP 5.2, send an empty Last-Modified header, but only as a
       
   383 				// last resort to override a header already sent. #WP23021
       
   384 				foreach ( headers_list() as $header ) {
       
   385 					if ( 0 === stripos( $header, 'Last-Modified' ) ) {
       
   386 						$headers['Last-Modified'] = '';
       
   387 						break;
       
   388 					}
       
   389 				}
       
   390 			}
       
   391 		}
       
   392 
       
   393 		foreach( (array) $headers as $name => $field_value )
       
   394 			@header("{$name}: {$field_value}");
       
   395 
       
   396 		if ( $exit_required )
       
   397 			exit();
       
   398 
       
   399 		do_action_ref_array('send_headers', array(&$this));
       
   400 	}
       
   401 
       
   402 	/**
       
   403 	 * Sets the query string property based off of the query variable property.
       
   404 	 *
       
   405 	 * The 'query_string' filter is deprecated, but still works. Plugins should
       
   406 	 * use the 'request' filter instead.
       
   407 	 *
       
   408 	 * @since 2.0.0
       
   409 	 */
       
   410 	function build_query_string() {
       
   411 		$this->query_string = '';
       
   412 		foreach ( (array) array_keys($this->query_vars) as $wpvar) {
       
   413 			if ( '' != $this->query_vars[$wpvar] ) {
       
   414 				$this->query_string .= (strlen($this->query_string) < 1) ? '' : '&';
       
   415 				if ( !is_scalar($this->query_vars[$wpvar]) ) // Discard non-scalars.
       
   416 					continue;
       
   417 				$this->query_string .= $wpvar . '=' . rawurlencode($this->query_vars[$wpvar]);
       
   418 			}
       
   419 		}
       
   420 
       
   421 		// query_string filter deprecated. Use request filter instead.
       
   422 		if ( has_filter('query_string') ) {  // Don't bother filtering and parsing if no plugins are hooked in.
       
   423 			$this->query_string = apply_filters('query_string', $this->query_string);
       
   424 			parse_str($this->query_string, $this->query_vars);
       
   425 		}
       
   426 	}
       
   427 
       
   428 	/**
       
   429 	 * Set up the WordPress Globals.
       
   430 	 *
       
   431 	 * The query_vars property will be extracted to the GLOBALS. So care should
       
   432 	 * be taken when naming global variables that might interfere with the
       
   433 	 * WordPress environment.
       
   434 	 *
       
   435 	 * @global string $query_string Query string for the loop.
       
   436 	 * @global array $posts The found posts.
       
   437 	 * @global WP_Post|null $post The current post, if available.
       
   438 	 * @global string $request The SQL statement for the request.
       
   439 	 * @global int $more Only set, if single page or post.
       
   440 	 * @global int $single If single page or post. Only set, if single page or post.
       
   441 	 * @global WP_User $authordata Only set, if author archive.
       
   442 	 *
       
   443 	 * @since 2.0.0
       
   444 	 */
       
   445 	function register_globals() {
       
   446 		global $wp_query;
       
   447 
       
   448 		// Extract updated query vars back into global namespace.
       
   449 		foreach ( (array) $wp_query->query_vars as $key => $value ) {
       
   450 			$GLOBALS[ $key ] = $value;
       
   451 		}
       
   452 
       
   453 		$GLOBALS['query_string'] = $this->query_string;
       
   454 		$GLOBALS['posts'] = & $wp_query->posts;
       
   455 		$GLOBALS['post'] = isset( $wp_query->post ) ? $wp_query->post : null;
       
   456 		$GLOBALS['request'] = $wp_query->request;
       
   457 
       
   458 		if ( $wp_query->is_single() || $wp_query->is_page() ) {
       
   459 			$GLOBALS['more']   = 1;
       
   460 			$GLOBALS['single'] = 1;
       
   461 		}
       
   462 
       
   463 		if ( $wp_query->is_author() && isset( $wp_query->post ) )
       
   464 			$GLOBALS['authordata'] = get_userdata( $wp_query->post->post_author );
       
   465 	}
       
   466 
       
   467 	/**
       
   468 	 * Set up the current user.
       
   469 	 *
       
   470 	 * @since 2.0.0
       
   471 	 */
       
   472 	function init() {
       
   473 		wp_get_current_user();
       
   474 	}
       
   475 
       
   476 	/**
       
   477 	 * Set up the Loop based on the query variables.
       
   478 	 *
       
   479 	 * @uses WP::$query_vars
       
   480 	 * @since 2.0.0
       
   481 	 */
       
   482 	function query_posts() {
       
   483 		global $wp_the_query;
       
   484 		$this->build_query_string();
       
   485 		$wp_the_query->query($this->query_vars);
       
   486  	}
       
   487 
       
   488  	/**
       
   489  	 * Set the Headers for 404, if nothing is found for requested URL.
       
   490 	 *
       
   491 	 * Issue a 404 if a request doesn't match any posts and doesn't match
       
   492 	 * any object (e.g. an existing-but-empty category, tag, author) and a 404 was not already
       
   493 	 * issued, and if the request was not a search or the homepage.
       
   494 	 *
       
   495 	 * Otherwise, issue a 200.
       
   496 	 *
       
   497 	 * @since 2.0.0
       
   498  	 */
       
   499 	function handle_404() {
       
   500 		global $wp_query;
       
   501 
       
   502 		// If we've already issued a 404, bail.
       
   503 		if ( is_404() )
       
   504 			return;
       
   505 
       
   506 		// Never 404 for the admin, robots, or if we found posts.
       
   507 		if ( is_admin() || is_robots() || $wp_query->posts ) {
       
   508 			status_header( 200 );
       
   509 			return;
       
   510 		}
       
   511 
       
   512 		// We will 404 for paged queries, as no posts were found.
       
   513 		if ( ! is_paged() ) {
       
   514 
       
   515 			// Don't 404 for these queries if they matched an object.
       
   516 			if ( ( is_tag() || is_category() || is_tax() || is_author() || is_post_type_archive() ) && $wp_query->get_queried_object() ) {
       
   517 				status_header( 200 );
       
   518 				return;
       
   519 			}
       
   520 
       
   521 			// Don't 404 for these queries either.
       
   522 			if ( is_home() || is_search() ) {
       
   523 				status_header( 200 );
       
   524 				return;
       
   525 			}
       
   526 		}
       
   527 
       
   528 		// Guess it's time to 404.
       
   529 		$wp_query->set_404();
       
   530 		status_header( 404 );
       
   531 		nocache_headers();
       
   532 	}
       
   533 
       
   534 	/**
       
   535 	 * Sets up all of the variables required by the WordPress environment.
       
   536 	 *
       
   537 	 * The action 'wp' has one parameter that references the WP object. It
       
   538 	 * allows for accessing the properties and methods to further manipulate the
       
   539 	 * object.
       
   540 	 *
       
   541 	 * @since 2.0.0
       
   542 	 *
       
   543 	 * @param string|array $query_args Passed to {@link parse_request()}
       
   544 	 */
       
   545 	function main($query_args = '') {
       
   546 		$this->init();
       
   547 		$this->parse_request($query_args);
       
   548 		$this->send_headers();
       
   549 		$this->query_posts();
       
   550 		$this->handle_404();
       
   551 		$this->register_globals();
       
   552 		do_action_ref_array('wp', array(&$this));
       
   553 	}
       
   554 
       
   555 }
       
   556 
       
   557 /**
       
   558  * Helper class to remove the need to use eval to replace $matches[] in query strings.
       
   559  *
       
   560  * @since 2.9.0
       
   561  */
       
   562 class WP_MatchesMapRegex {
       
   563 	/**
       
   564 	 * store for matches
       
   565 	 *
       
   566 	 * @access private
       
   567 	 * @var array
       
   568 	 */
       
   569 	var $_matches;
       
   570 
       
   571 	/**
       
   572 	 * store for mapping result
       
   573 	 *
       
   574 	 * @access public
       
   575 	 * @var string
       
   576 	 */
       
   577 	var $output;
       
   578 
       
   579 	/**
       
   580 	 * subject to perform mapping on (query string containing $matches[] references
       
   581 	 *
       
   582 	 * @access private
       
   583 	 * @var string
       
   584 	 */
       
   585 	var $_subject;
       
   586 
       
   587 	/**
       
   588 	 * regexp pattern to match $matches[] references
       
   589 	 *
       
   590 	 * @var string
       
   591 	 */
       
   592 	var $_pattern = '(\$matches\[[1-9]+[0-9]*\])'; // magic number
       
   593 
       
   594 	/**
       
   595 	 * constructor
       
   596 	 *
       
   597 	 * @param string $subject subject if regex
       
   598 	 * @param array  $matches data to use in map
       
   599 	 * @return self
       
   600 	 */
       
   601 	function WP_MatchesMapRegex($subject, $matches) {
       
   602 		$this->_subject = $subject;
       
   603 		$this->_matches = $matches;
       
   604 		$this->output = $this->_map();
       
   605 	}
       
   606 
       
   607 	/**
       
   608 	 * Substitute substring matches in subject.
       
   609 	 *
       
   610 	 * static helper function to ease use
       
   611 	 *
       
   612 	 * @access public
       
   613 	 * @param string $subject subject
       
   614 	 * @param array  $matches data used for substitution
       
   615 	 * @return string
       
   616 	 */
       
   617 	public static function apply($subject, $matches) {
       
   618 		$oSelf = new WP_MatchesMapRegex($subject, $matches);
       
   619 		return $oSelf->output;
       
   620 	}
       
   621 
       
   622 	/**
       
   623 	 * do the actual mapping
       
   624 	 *
       
   625 	 * @access private
       
   626 	 * @return string
       
   627 	 */
       
   628 	function _map() {
       
   629 		$callback = array($this, 'callback');
       
   630 		return preg_replace_callback($this->_pattern, $callback, $this->_subject);
       
   631 	}
       
   632 
       
   633 	/**
       
   634 	 * preg_replace_callback hook
       
   635 	 *
       
   636 	 * @access public
       
   637 	 * @param  array $matches preg_replace regexp matches
       
   638 	 * @return string
       
   639 	 */
       
   640 	function callback($matches) {
       
   641 		$index = intval(substr($matches[0], 9, -1));
       
   642 		return ( isset( $this->_matches[$index] ) ? urlencode($this->_matches[$index]) : '' );
       
   643 	}
       
   644 
       
   645 }