changeset 9 | 177826044cd9 |
parent 7 | cf61fcea0001 |
child 13 | d255fe9cd479 |
8:c7c34916027a | 9:177826044cd9 |
---|---|
10 * Public query variables. |
10 * Public query variables. |
11 * |
11 * |
12 * Long list of public query variables. |
12 * Long list of public query variables. |
13 * |
13 * |
14 * @since 2.0.0 |
14 * @since 2.0.0 |
15 * @var array |
15 * @var string[] |
16 */ |
16 */ |
17 public $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', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type', 'embed' ); |
17 public $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', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type', 'embed' ); |
18 |
18 |
19 /** |
19 /** |
20 * Private query variables. |
20 * Private query variables. |
21 * |
21 * |
22 * Long list of private query variables. |
22 * Long list of private query variables. |
23 * |
23 * |
24 * @since 2.0.0 |
24 * @since 2.0.0 |
25 * @var array |
25 * @var string[] |
26 */ |
26 */ |
27 public $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', 'post_parent__in', 'post_parent__not_in', 'title', 'fields' ); |
27 public $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', 'post_parent__in', 'post_parent__not_in', 'title', 'fields' ); |
28 |
28 |
29 /** |
29 /** |
30 * Extra query variables set by the user. |
30 * Extra query variables set by the user. |
87 * |
87 * |
88 * @since 2.1.0 |
88 * @since 2.1.0 |
89 * |
89 * |
90 * @param string $qv Query variable name. |
90 * @param string $qv Query variable name. |
91 */ |
91 */ |
92 public function add_query_var($qv) { |
92 public function add_query_var( $qv ) { |
93 if ( !in_array($qv, $this->public_query_vars) ) |
93 if ( ! in_array( $qv, $this->public_query_vars ) ) { |
94 $this->public_query_vars[] = $qv; |
94 $this->public_query_vars[] = $qv; |
95 } |
|
95 } |
96 } |
96 |
97 |
97 /** |
98 /** |
98 * Removes a query variable from a list of public query variables. |
99 * Removes a query variable from a list of public query variables. |
99 * |
100 * |
111 * @since 2.3.0 |
112 * @since 2.3.0 |
112 * |
113 * |
113 * @param string $key Query variable name. |
114 * @param string $key Query variable name. |
114 * @param mixed $value Query variable value. |
115 * @param mixed $value Query variable value. |
115 */ |
116 */ |
116 public function set_query_var($key, $value) { |
117 public function set_query_var( $key, $value ) { |
117 $this->query_vars[$key] = $value; |
118 $this->query_vars[ $key ] = $value; |
118 } |
119 } |
119 |
120 |
120 /** |
121 /** |
121 * Parse request to find correct WordPress query. |
122 * Parse request to find correct WordPress query. |
122 * |
123 * |
127 * |
128 * |
128 * @global WP_Rewrite $wp_rewrite |
129 * @global WP_Rewrite $wp_rewrite |
129 * |
130 * |
130 * @param array|string $extra_query_vars Set the extra query variables. |
131 * @param array|string $extra_query_vars Set the extra query variables. |
131 */ |
132 */ |
132 public function parse_request($extra_query_vars = '') { |
133 public function parse_request( $extra_query_vars = '' ) { |
133 global $wp_rewrite; |
134 global $wp_rewrite; |
134 |
135 |
135 /** |
136 /** |
136 * Filters whether to parse the request. |
137 * Filters whether to parse the request. |
137 * |
138 * |
139 * |
140 * |
140 * @param bool $bool Whether or not to parse the request. Default true. |
141 * @param bool $bool Whether or not to parse the request. Default true. |
141 * @param WP $this Current WordPress environment instance. |
142 * @param WP $this Current WordPress environment instance. |
142 * @param array|string $extra_query_vars Extra passed query variables. |
143 * @param array|string $extra_query_vars Extra passed query variables. |
143 */ |
144 */ |
144 if ( ! apply_filters( 'do_parse_request', true, $this, $extra_query_vars ) ) |
145 if ( ! apply_filters( 'do_parse_request', true, $this, $extra_query_vars ) ) { |
145 return; |
146 return; |
146 |
147 } |
147 $this->query_vars = array(); |
148 |
149 $this->query_vars = array(); |
|
148 $post_type_query_vars = array(); |
150 $post_type_query_vars = array(); |
149 |
151 |
150 if ( is_array( $extra_query_vars ) ) { |
152 if ( is_array( $extra_query_vars ) ) { |
151 $this->extra_query_vars = & $extra_query_vars; |
153 $this->extra_query_vars = & $extra_query_vars; |
152 } elseif ( ! empty( $extra_query_vars ) ) { |
154 } elseif ( ! empty( $extra_query_vars ) ) { |
155 // Process PATH_INFO, REQUEST_URI, and 404 for permalinks. |
157 // Process PATH_INFO, REQUEST_URI, and 404 for permalinks. |
156 |
158 |
157 // Fetch the rewrite rules. |
159 // Fetch the rewrite rules. |
158 $rewrite = $wp_rewrite->wp_rewrite_rules(); |
160 $rewrite = $wp_rewrite->wp_rewrite_rules(); |
159 |
161 |
160 if ( ! empty($rewrite) ) { |
162 if ( ! empty( $rewrite ) ) { |
161 // If we match a rewrite rule, this will be cleared. |
163 // If we match a rewrite rule, this will be cleared. |
162 $error = '404'; |
164 $error = '404'; |
163 $this->did_permalink = true; |
165 $this->did_permalink = true; |
164 |
166 |
165 $pathinfo = isset( $_SERVER['PATH_INFO'] ) ? $_SERVER['PATH_INFO'] : ''; |
167 $pathinfo = isset( $_SERVER['PATH_INFO'] ) ? $_SERVER['PATH_INFO'] : ''; |
166 list( $pathinfo ) = explode( '?', $pathinfo ); |
168 list( $pathinfo ) = explode( '?', $pathinfo ); |
167 $pathinfo = str_replace( "%", "%25", $pathinfo ); |
169 $pathinfo = str_replace( '%', '%25', $pathinfo ); |
168 |
170 |
169 list( $req_uri ) = explode( '?', $_SERVER['REQUEST_URI'] ); |
171 list( $req_uri ) = explode( '?', $_SERVER['REQUEST_URI'] ); |
170 $self = $_SERVER['PHP_SELF']; |
172 $self = $_SERVER['PHP_SELF']; |
171 $home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' ); |
173 $home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' ); |
172 $home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) ); |
174 $home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) ); |
173 |
175 |
174 // Trim path info from the end and the leading home path from the |
176 // Trim path info from the end and the leading home path from the |
175 // front. For path info requests, this leaves us with the requesting |
177 // front. For path info requests, this leaves us with the requesting |
176 // filename, if any. For 404 requests, this leaves us with the |
178 // filename, if any. For 404 requests, this leaves us with the |
177 // requested permalink. |
179 // requested permalink. |
178 $req_uri = str_replace($pathinfo, '', $req_uri); |
180 $req_uri = str_replace( $pathinfo, '', $req_uri ); |
179 $req_uri = trim($req_uri, '/'); |
181 $req_uri = trim( $req_uri, '/' ); |
180 $req_uri = preg_replace( $home_path_regex, '', $req_uri ); |
182 $req_uri = preg_replace( $home_path_regex, '', $req_uri ); |
181 $req_uri = trim($req_uri, '/'); |
183 $req_uri = trim( $req_uri, '/' ); |
182 $pathinfo = trim($pathinfo, '/'); |
184 $pathinfo = trim( $pathinfo, '/' ); |
183 $pathinfo = preg_replace( $home_path_regex, '', $pathinfo ); |
185 $pathinfo = preg_replace( $home_path_regex, '', $pathinfo ); |
184 $pathinfo = trim($pathinfo, '/'); |
186 $pathinfo = trim( $pathinfo, '/' ); |
185 $self = trim($self, '/'); |
187 $self = trim( $self, '/' ); |
186 $self = preg_replace( $home_path_regex, '', $self ); |
188 $self = preg_replace( $home_path_regex, '', $self ); |
187 $self = trim($self, '/'); |
189 $self = trim( $self, '/' ); |
188 |
190 |
189 // The requested permalink is in $pathinfo for path info requests and |
191 // The requested permalink is in $pathinfo for path info requests and |
190 // $req_uri for other requests. |
192 // $req_uri for other requests. |
191 if ( ! empty($pathinfo) && !preg_match('|^.*' . $wp_rewrite->index . '$|', $pathinfo) ) { |
193 if ( ! empty( $pathinfo ) && ! preg_match( '|^.*' . $wp_rewrite->index . '$|', $pathinfo ) ) { |
192 $requested_path = $pathinfo; |
194 $requested_path = $pathinfo; |
193 } else { |
195 } else { |
194 // If the request uri is the index, blank it out so that we don't try to match it against a rule. |
196 // If the request uri is the index, blank it out so that we don't try to match it against a rule. |
195 if ( $req_uri == $wp_rewrite->index ) |
197 if ( $req_uri == $wp_rewrite->index ) { |
196 $req_uri = ''; |
198 $req_uri = ''; |
199 } |
|
197 $requested_path = $req_uri; |
200 $requested_path = $req_uri; |
198 } |
201 } |
199 $requested_file = $req_uri; |
202 $requested_file = $req_uri; |
200 |
203 |
201 $this->request = $requested_path; |
204 $this->request = $requested_path; |
204 $request_match = $requested_path; |
207 $request_match = $requested_path; |
205 if ( empty( $request_match ) ) { |
208 if ( empty( $request_match ) ) { |
206 // An empty request could only match against ^$ regex |
209 // An empty request could only match against ^$ regex |
207 if ( isset( $rewrite['$'] ) ) { |
210 if ( isset( $rewrite['$'] ) ) { |
208 $this->matched_rule = '$'; |
211 $this->matched_rule = '$'; |
209 $query = $rewrite['$']; |
212 $query = $rewrite['$']; |
210 $matches = array(''); |
213 $matches = array( '' ); |
211 } |
214 } |
212 } else { |
215 } else { |
213 foreach ( (array) $rewrite as $match => $query ) { |
216 foreach ( (array) $rewrite as $match => $query ) { |
214 // If the requested file is the anchor of the match, prepend it to the path info. |
217 // If the requested file is the anchor of the match, prepend it to the path info. |
215 if ( ! empty($requested_file) && strpos($match, $requested_file) === 0 && $requested_file != $requested_path ) |
218 if ( ! empty( $requested_file ) && strpos( $match, $requested_file ) === 0 && $requested_file != $requested_path ) { |
216 $request_match = $requested_file . '/' . $requested_path; |
219 $request_match = $requested_file . '/' . $requested_path; |
217 |
220 } |
218 if ( preg_match("#^$match#", $request_match, $matches) || |
221 |
219 preg_match("#^$match#", urldecode($request_match), $matches) ) { |
222 if ( preg_match( "#^$match#", $request_match, $matches ) || |
223 preg_match( "#^$match#", urldecode( $request_match ), $matches ) ) { |
|
220 |
224 |
221 if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) { |
225 if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) { |
222 // This is a verbose page match, let's check to be sure about it. |
226 // This is a verbose page match, let's check to be sure about it. |
223 $page = get_page_by_path( $matches[ $varmatch[1] ] ); |
227 $page = get_page_by_path( $matches[ $varmatch[1] ] ); |
224 if ( ! $page ) { |
228 if ( ! $page ) { |
225 continue; |
229 continue; |
226 } |
230 } |
227 |
231 |
228 $post_status_obj = get_post_status_object( $page->post_status ); |
232 $post_status_obj = get_post_status_object( $page->post_status ); |
229 if ( ! $post_status_obj->public && ! $post_status_obj->protected |
233 if ( ! $post_status_obj->public && ! $post_status_obj->protected |
230 && ! $post_status_obj->private && $post_status_obj->exclude_from_search ) { |
234 && ! $post_status_obj->private && $post_status_obj->exclude_from_search ) { |
239 } |
243 } |
240 } |
244 } |
241 |
245 |
242 if ( isset( $this->matched_rule ) ) { |
246 if ( isset( $this->matched_rule ) ) { |
243 // Trim the query of everything up to the '?'. |
247 // Trim the query of everything up to the '?'. |
244 $query = preg_replace("!^.+\?!", '', $query); |
248 $query = preg_replace( '!^.+\?!', '', $query ); |
245 |
249 |
246 // Substitute the substring matches into the query. |
250 // Substitute the substring matches into the query. |
247 $query = addslashes(WP_MatchesMapRegex::apply($query, $matches)); |
251 $query = addslashes( WP_MatchesMapRegex::apply( $query, $matches ) ); |
248 |
252 |
249 $this->matched_query = $query; |
253 $this->matched_query = $query; |
250 |
254 |
251 // Parse the query. |
255 // Parse the query. |
252 parse_str($query, $perma_query_vars); |
256 parse_str( $query, $perma_query_vars ); |
253 |
257 |
254 // If we're processing a 404 request, clear the error var since we found something. |
258 // If we're processing a 404 request, clear the error var since we found something. |
255 if ( '404' == $error ) |
259 if ( '404' == $error ) { |
256 unset( $error, $_GET['error'] ); |
260 unset( $error, $_GET['error'] ); |
261 } |
|
257 } |
262 } |
258 |
263 |
259 // If req_uri is empty or if it is a request for ourself, unset error. |
264 // If req_uri is empty or if it is a request for ourself, unset error. |
260 if ( empty($requested_path) || $requested_file == $self || strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false ) { |
265 if ( empty( $requested_path ) || $requested_file == $self || strpos( $_SERVER['PHP_SELF'], 'wp-admin/' ) !== false ) { |
261 unset( $error, $_GET['error'] ); |
266 unset( $error, $_GET['error'] ); |
262 |
267 |
263 if ( isset($perma_query_vars) && strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false ) |
268 if ( isset( $perma_query_vars ) && strpos( $_SERVER['PHP_SELF'], 'wp-admin/' ) !== false ) { |
264 unset( $perma_query_vars ); |
269 unset( $perma_query_vars ); |
270 } |
|
265 |
271 |
266 $this->did_permalink = false; |
272 $this->did_permalink = false; |
267 } |
273 } |
268 } |
274 } |
269 |
275 |
274 * to executing the query. Needed to allow custom rewrite rules using your own arguments |
280 * to executing the query. Needed to allow custom rewrite rules using your own arguments |
275 * to work, or any other custom query variables you want to be publicly available. |
281 * to work, or any other custom query variables you want to be publicly available. |
276 * |
282 * |
277 * @since 1.5.0 |
283 * @since 1.5.0 |
278 * |
284 * |
279 * @param array $public_query_vars The array of whitelisted query variables. |
285 * @param string[] $public_query_vars The array of whitelisted query variable names. |
280 */ |
286 */ |
281 $this->public_query_vars = apply_filters( 'query_vars', $this->public_query_vars ); |
287 $this->public_query_vars = apply_filters( 'query_vars', $this->public_query_vars ); |
282 |
288 |
283 foreach ( get_post_types( array(), 'objects' ) as $post_type => $t ) { |
289 foreach ( get_post_types( array(), 'objects' ) as $post_type => $t ) { |
284 if ( is_post_type_viewable( $t ) && $t->query_var ) { |
290 if ( is_post_type_viewable( $t ) && $t->query_var ) { |
285 $post_type_query_vars[$t->query_var] = $post_type; |
291 $post_type_query_vars[ $t->query_var ] = $post_type; |
286 } |
292 } |
287 } |
293 } |
288 |
294 |
289 foreach ( $this->public_query_vars as $wpvar ) { |
295 foreach ( $this->public_query_vars as $wpvar ) { |
290 if ( isset( $this->extra_query_vars[$wpvar] ) ) |
296 if ( isset( $this->extra_query_vars[ $wpvar ] ) ) { |
291 $this->query_vars[$wpvar] = $this->extra_query_vars[$wpvar]; |
297 $this->query_vars[ $wpvar ] = $this->extra_query_vars[ $wpvar ]; |
292 elseif ( isset( $_POST[$wpvar] ) ) |
298 } elseif ( isset( $_GET[ $wpvar ] ) && isset( $_POST[ $wpvar ] ) && $_GET[ $wpvar ] !== $_POST[ $wpvar ] ) { |
293 $this->query_vars[$wpvar] = $_POST[$wpvar]; |
299 wp_die( __( 'A variable mismatch has been detected.' ), __( 'Sorry, you are not allowed to view this item.' ), 400 ); |
294 elseif ( isset( $_GET[$wpvar] ) ) |
300 } elseif ( isset( $_POST[ $wpvar ] ) ) { |
295 $this->query_vars[$wpvar] = $_GET[$wpvar]; |
301 $this->query_vars[ $wpvar ] = $_POST[ $wpvar ]; |
296 elseif ( isset( $perma_query_vars[$wpvar] ) ) |
302 } elseif ( isset( $_GET[ $wpvar ] ) ) { |
297 $this->query_vars[$wpvar] = $perma_query_vars[$wpvar]; |
303 $this->query_vars[ $wpvar ] = $_GET[ $wpvar ]; |
298 |
304 } elseif ( isset( $perma_query_vars[ $wpvar ] ) ) { |
299 if ( !empty( $this->query_vars[$wpvar] ) ) { |
305 $this->query_vars[ $wpvar ] = $perma_query_vars[ $wpvar ]; |
300 if ( ! is_array( $this->query_vars[$wpvar] ) ) { |
306 } |
301 $this->query_vars[$wpvar] = (string) $this->query_vars[$wpvar]; |
307 |
308 if ( ! empty( $this->query_vars[ $wpvar ] ) ) { |
|
309 if ( ! is_array( $this->query_vars[ $wpvar ] ) ) { |
|
310 $this->query_vars[ $wpvar ] = (string) $this->query_vars[ $wpvar ]; |
|
302 } else { |
311 } else { |
303 foreach ( $this->query_vars[$wpvar] as $vkey => $v ) { |
312 foreach ( $this->query_vars[ $wpvar ] as $vkey => $v ) { |
304 if ( !is_object( $v ) ) { |
313 if ( is_scalar( $v ) ) { |
305 $this->query_vars[$wpvar][$vkey] = (string) $v; |
314 $this->query_vars[ $wpvar ][ $vkey ] = (string) $v; |
306 } |
315 } |
307 } |
316 } |
308 } |
317 } |
309 |
318 |
310 if ( isset($post_type_query_vars[$wpvar] ) ) { |
319 if ( isset( $post_type_query_vars[ $wpvar ] ) ) { |
311 $this->query_vars['post_type'] = $post_type_query_vars[$wpvar]; |
320 $this->query_vars['post_type'] = $post_type_query_vars[ $wpvar ]; |
312 $this->query_vars['name'] = $this->query_vars[$wpvar]; |
321 $this->query_vars['name'] = $this->query_vars[ $wpvar ]; |
313 } |
322 } |
314 } |
323 } |
315 } |
324 } |
316 |
325 |
317 // Convert urldecoded spaces back into + |
326 // Convert urldecoded spaces back into + |
318 foreach ( get_taxonomies( array() , 'objects' ) as $taxonomy => $t ) |
327 foreach ( get_taxonomies( array(), 'objects' ) as $taxonomy => $t ) { |
319 if ( $t->query_var && isset( $this->query_vars[$t->query_var] ) ) |
328 if ( $t->query_var && isset( $this->query_vars[ $t->query_var ] ) ) { |
320 $this->query_vars[$t->query_var] = str_replace( ' ', '+', $this->query_vars[$t->query_var] ); |
329 $this->query_vars[ $t->query_var ] = str_replace( ' ', '+', $this->query_vars[ $t->query_var ] ); |
330 } |
|
331 } |
|
321 |
332 |
322 // Don't allow non-publicly queryable taxonomies to be queried from the front end. |
333 // Don't allow non-publicly queryable taxonomies to be queried from the front end. |
323 if ( ! is_admin() ) { |
334 if ( ! is_admin() ) { |
324 foreach ( get_taxonomies( array( 'publicly_queryable' => false ), 'objects' ) as $taxonomy => $t ) { |
335 foreach ( get_taxonomies( array( 'publicly_queryable' => false ), 'objects' ) as $taxonomy => $t ) { |
325 /* |
336 /* |
331 } |
342 } |
332 } |
343 } |
333 } |
344 } |
334 |
345 |
335 // Limit publicly queried post_types to those that are publicly_queryable |
346 // Limit publicly queried post_types to those that are publicly_queryable |
336 if ( isset( $this->query_vars['post_type']) ) { |
347 if ( isset( $this->query_vars['post_type'] ) ) { |
337 $queryable_post_types = get_post_types( array('publicly_queryable' => true) ); |
348 $queryable_post_types = get_post_types( array( 'publicly_queryable' => true ) ); |
338 if ( ! is_array( $this->query_vars['post_type'] ) ) { |
349 if ( ! is_array( $this->query_vars['post_type'] ) ) { |
339 if ( ! in_array( $this->query_vars['post_type'], $queryable_post_types ) ) |
350 if ( ! in_array( $this->query_vars['post_type'], $queryable_post_types ) ) { |
340 unset( $this->query_vars['post_type'] ); |
351 unset( $this->query_vars['post_type'] ); |
352 } |
|
341 } else { |
353 } else { |
342 $this->query_vars['post_type'] = array_intersect( $this->query_vars['post_type'], $queryable_post_types ); |
354 $this->query_vars['post_type'] = array_intersect( $this->query_vars['post_type'], $queryable_post_types ); |
343 } |
355 } |
344 } |
356 } |
345 |
357 |
346 // Resolve conflicts between posts with numeric slugs and date archive queries. |
358 // Resolve conflicts between posts with numeric slugs and date archive queries. |
347 $this->query_vars = wp_resolve_numeric_slug_conflicts( $this->query_vars ); |
359 $this->query_vars = wp_resolve_numeric_slug_conflicts( $this->query_vars ); |
348 |
360 |
349 foreach ( (array) $this->private_query_vars as $var) { |
361 foreach ( (array) $this->private_query_vars as $var ) { |
350 if ( isset($this->extra_query_vars[$var]) ) |
362 if ( isset( $this->extra_query_vars[ $var ] ) ) { |
351 $this->query_vars[$var] = $this->extra_query_vars[$var]; |
363 $this->query_vars[ $var ] = $this->extra_query_vars[ $var ]; |
352 } |
364 } |
353 |
365 } |
354 if ( isset($error) ) |
366 |
367 if ( isset( $error ) ) { |
|
355 $this->query_vars['error'] = $error; |
368 $this->query_vars['error'] = $error; |
369 } |
|
356 |
370 |
357 /** |
371 /** |
358 * Filters the array of parsed query variables. |
372 * Filters the array of parsed query variables. |
359 * |
373 * |
360 * @since 2.1.0 |
374 * @since 2.1.0 |
381 * |
395 * |
382 * @since 2.0.0 |
396 * @since 2.0.0 |
383 * @since 4.4.0 `X-Pingback` header is added conditionally after posts have been queried in handle_404(). |
397 * @since 4.4.0 `X-Pingback` header is added conditionally after posts have been queried in handle_404(). |
384 */ |
398 */ |
385 public function send_headers() { |
399 public function send_headers() { |
386 $headers = array(); |
400 $headers = array(); |
387 $status = null; |
401 $status = null; |
388 $exit_required = false; |
402 $exit_required = false; |
389 |
403 |
390 if ( is_user_logged_in() ) |
404 if ( is_user_logged_in() ) { |
391 $headers = array_merge($headers, wp_get_nocache_headers()); |
405 $headers = array_merge( $headers, wp_get_nocache_headers() ); |
406 } |
|
392 if ( ! empty( $this->query_vars['error'] ) ) { |
407 if ( ! empty( $this->query_vars['error'] ) ) { |
393 $status = (int) $this->query_vars['error']; |
408 $status = (int) $this->query_vars['error']; |
394 if ( 404 === $status ) { |
409 if ( 404 === $status ) { |
395 if ( ! is_user_logged_in() ) |
410 if ( ! is_user_logged_in() ) { |
396 $headers = array_merge($headers, wp_get_nocache_headers()); |
411 $headers = array_merge( $headers, wp_get_nocache_headers() ); |
397 $headers['Content-Type'] = get_option('html_type') . '; charset=' . get_option('blog_charset'); |
412 } |
413 $headers['Content-Type'] = get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ); |
|
398 } elseif ( in_array( $status, array( 403, 500, 502, 503 ) ) ) { |
414 } elseif ( in_array( $status, array( 403, 500, 502, 503 ) ) ) { |
399 $exit_required = true; |
415 $exit_required = true; |
400 } |
416 } |
401 } elseif ( empty( $this->query_vars['feed'] ) ) { |
417 } elseif ( empty( $this->query_vars['feed'] ) ) { |
402 $headers['Content-Type'] = get_option('html_type') . '; charset=' . get_option('blog_charset'); |
418 $headers['Content-Type'] = get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ); |
403 } else { |
419 } else { |
404 // Set the correct content type for feeds |
420 // Set the correct content type for feeds |
405 $type = $this->query_vars['feed']; |
421 $type = $this->query_vars['feed']; |
406 if ( 'feed' == $this->query_vars['feed'] ) { |
422 if ( 'feed' == $this->query_vars['feed'] ) { |
407 $type = get_default_feed(); |
423 $type = get_default_feed(); |
408 } |
424 } |
409 $headers['Content-Type'] = feed_content_type( $type ) . '; charset=' . get_option( 'blog_charset' ); |
425 $headers['Content-Type'] = feed_content_type( $type ) . '; charset=' . get_option( 'blog_charset' ); |
410 |
426 |
411 // We're showing a feed, so WP is indeed the only thing that last changed. |
427 // We're showing a feed, so WP is indeed the only thing that last changed. |
412 if ( ! empty( $this->query_vars['withcomments'] ) |
428 if ( ! empty( $this->query_vars['withcomments'] ) |
413 || false !== strpos( $this->query_vars['feed'], 'comments-' ) |
429 || false !== strpos( $this->query_vars['feed'], 'comments-' ) |
414 || ( empty( $this->query_vars['withoutcomments'] ) |
430 || ( empty( $this->query_vars['withoutcomments'] ) |
415 && ( ! empty( $this->query_vars['p'] ) |
431 && ( ! empty( $this->query_vars['p'] ) |
416 || ! empty( $this->query_vars['name'] ) |
432 || ! empty( $this->query_vars['name'] ) |
417 || ! empty( $this->query_vars['page_id'] ) |
433 || ! empty( $this->query_vars['page_id'] ) |
418 || ! empty( $this->query_vars['pagename'] ) |
434 || ! empty( $this->query_vars['pagename'] ) |
419 || ! empty( $this->query_vars['attachment'] ) |
435 || ! empty( $this->query_vars['attachment'] ) |
420 || ! empty( $this->query_vars['attachment_id'] ) |
436 || ! empty( $this->query_vars['attachment_id'] ) |
421 ) |
437 ) |
422 ) |
438 ) |
423 ) { |
439 ) { |
424 $wp_last_modified = mysql2date( 'D, d M Y H:i:s', get_lastcommentmodified( 'GMT' ), false ); |
440 $wp_last_modified = mysql2date( 'D, d M Y H:i:s', get_lastcommentmodified( 'GMT' ), false ); |
425 } else { |
441 } else { |
426 $wp_last_modified = mysql2date( 'D, d M Y H:i:s', get_lastpostmodified( 'GMT' ), false ); |
442 $wp_last_modified = mysql2date( 'D, d M Y H:i:s', get_lastpostmodified( 'GMT' ), false ); |
427 } |
443 } |
430 $wp_last_modified = date( 'D, d M Y H:i:s' ); |
446 $wp_last_modified = date( 'D, d M Y H:i:s' ); |
431 } |
447 } |
432 |
448 |
433 $wp_last_modified .= ' GMT'; |
449 $wp_last_modified .= ' GMT'; |
434 |
450 |
435 $wp_etag = '"' . md5($wp_last_modified) . '"'; |
451 $wp_etag = '"' . md5( $wp_last_modified ) . '"'; |
436 $headers['Last-Modified'] = $wp_last_modified; |
452 $headers['Last-Modified'] = $wp_last_modified; |
437 $headers['ETag'] = $wp_etag; |
453 $headers['ETag'] = $wp_etag; |
438 |
454 |
439 // Support for Conditional GET |
455 // Support for Conditional GET |
440 if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) |
456 if ( isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ) { |
441 $client_etag = wp_unslash( $_SERVER['HTTP_IF_NONE_MATCH'] ); |
457 $client_etag = wp_unslash( $_SERVER['HTTP_IF_NONE_MATCH'] ); |
442 else $client_etag = false; |
458 } else { |
443 |
459 $client_etag = false; |
444 $client_last_modified = empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? '' : trim($_SERVER['HTTP_IF_MODIFIED_SINCE']); |
460 } |
461 |
|
462 $client_last_modified = empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ? '' : trim( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ); |
|
445 // If string is empty, return 0. If not, attempt to parse into a timestamp |
463 // If string is empty, return 0. If not, attempt to parse into a timestamp |
446 $client_modified_timestamp = $client_last_modified ? strtotime($client_last_modified) : 0; |
464 $client_modified_timestamp = $client_last_modified ? strtotime( $client_last_modified ) : 0; |
447 |
465 |
448 // Make a timestamp for our most recent modification... |
466 // Make a timestamp for our most recent modification... |
449 $wp_modified_timestamp = strtotime($wp_last_modified); |
467 $wp_modified_timestamp = strtotime( $wp_last_modified ); |
450 |
468 |
451 if ( ($client_last_modified && $client_etag) ? |
469 if ( ( $client_last_modified && $client_etag ) ? |
452 (($client_modified_timestamp >= $wp_modified_timestamp) && ($client_etag == $wp_etag)) : |
470 ( ( $client_modified_timestamp >= $wp_modified_timestamp ) && ( $client_etag == $wp_etag ) ) : |
453 (($client_modified_timestamp >= $wp_modified_timestamp) || ($client_etag == $wp_etag)) ) { |
471 ( ( $client_modified_timestamp >= $wp_modified_timestamp ) || ( $client_etag == $wp_etag ) ) ) { |
454 $status = 304; |
472 $status = 304; |
455 $exit_required = true; |
473 $exit_required = true; |
456 } |
474 } |
457 } |
475 } |
458 |
476 |
459 /** |
477 /** |
460 * Filters the HTTP headers before they're sent to the browser. |
478 * Filters the HTTP headers before they're sent to the browser. |
461 * |
479 * |
462 * @since 2.8.0 |
480 * @since 2.8.0 |
463 * |
481 * |
464 * @param array $headers The list of headers to be sent. |
482 * @param string[] $headers Associative array of headers to be sent. |
465 * @param WP $this Current WordPress environment instance. |
483 * @param WP $this Current WordPress environment instance. |
466 */ |
484 */ |
467 $headers = apply_filters( 'wp_headers', $headers, $this ); |
485 $headers = apply_filters( 'wp_headers', $headers, $this ); |
468 |
486 |
469 if ( ! empty( $status ) ) |
487 if ( ! empty( $status ) ) { |
470 status_header( $status ); |
488 status_header( $status ); |
489 } |
|
471 |
490 |
472 // If Last-Modified is set to false, it should not be sent (no-cache situation). |
491 // If Last-Modified is set to false, it should not be sent (no-cache situation). |
473 if ( isset( $headers['Last-Modified'] ) && false === $headers['Last-Modified'] ) { |
492 if ( isset( $headers['Last-Modified'] ) && false === $headers['Last-Modified'] ) { |
474 unset( $headers['Last-Modified'] ); |
493 unset( $headers['Last-Modified'] ); |
475 |
494 |
486 } |
505 } |
487 } |
506 } |
488 } |
507 } |
489 } |
508 } |
490 |
509 |
491 foreach ( (array) $headers as $name => $field_value ) |
510 foreach ( (array) $headers as $name => $field_value ) { |
492 @header("{$name}: {$field_value}"); |
511 @header( "{$name}: {$field_value}" ); |
493 |
512 } |
494 if ( $exit_required ) |
513 |
514 if ( $exit_required ) { |
|
495 exit(); |
515 exit(); |
516 } |
|
496 |
517 |
497 /** |
518 /** |
498 * Fires once the requested HTTP headers for caching, content type, etc. have been sent. |
519 * Fires once the requested HTTP headers for caching, content type, etc. have been sent. |
499 * |
520 * |
500 * @since 2.1.0 |
521 * @since 2.1.0 |
512 * |
533 * |
513 * @since 2.0.0 |
534 * @since 2.0.0 |
514 */ |
535 */ |
515 public function build_query_string() { |
536 public function build_query_string() { |
516 $this->query_string = ''; |
537 $this->query_string = ''; |
517 foreach ( (array) array_keys($this->query_vars) as $wpvar) { |
538 foreach ( (array) array_keys( $this->query_vars ) as $wpvar ) { |
518 if ( '' != $this->query_vars[$wpvar] ) { |
539 if ( '' != $this->query_vars[ $wpvar ] ) { |
519 $this->query_string .= (strlen($this->query_string) < 1) ? '' : '&'; |
540 $this->query_string .= ( strlen( $this->query_string ) < 1 ) ? '' : '&'; |
520 if ( !is_scalar($this->query_vars[$wpvar]) ) // Discard non-scalars. |
541 if ( ! is_scalar( $this->query_vars[ $wpvar ] ) ) { // Discard non-scalars. |
521 continue; |
542 continue; |
522 $this->query_string .= $wpvar . '=' . rawurlencode($this->query_vars[$wpvar]); |
543 } |
544 $this->query_string .= $wpvar . '=' . rawurlencode( $this->query_vars[ $wpvar ] ); |
|
523 } |
545 } |
524 } |
546 } |
525 |
547 |
526 if ( has_filter( 'query_string' ) ) { // Don't bother filtering and parsing if no plugins are hooked in. |
548 if ( has_filter( 'query_string' ) ) { // Don't bother filtering and parsing if no plugins are hooked in. |
527 /** |
549 /** |
531 * @deprecated 2.1.0 Use 'query_vars' or 'request' filters instead. |
553 * @deprecated 2.1.0 Use 'query_vars' or 'request' filters instead. |
532 * |
554 * |
533 * @param string $query_string The query string to modify. |
555 * @param string $query_string The query string to modify. |
534 */ |
556 */ |
535 $this->query_string = apply_filters( 'query_string', $this->query_string ); |
557 $this->query_string = apply_filters( 'query_string', $this->query_string ); |
536 parse_str($this->query_string, $this->query_vars); |
558 parse_str( $this->query_string, $this->query_vars ); |
537 } |
559 } |
538 } |
560 } |
539 |
561 |
540 /** |
562 /** |
541 * Set up the WordPress Globals. |
563 * Set up the WordPress Globals. |
562 foreach ( (array) $wp_query->query_vars as $key => $value ) { |
584 foreach ( (array) $wp_query->query_vars as $key => $value ) { |
563 $GLOBALS[ $key ] = $value; |
585 $GLOBALS[ $key ] = $value; |
564 } |
586 } |
565 |
587 |
566 $GLOBALS['query_string'] = $this->query_string; |
588 $GLOBALS['query_string'] = $this->query_string; |
567 $GLOBALS['posts'] = & $wp_query->posts; |
589 $GLOBALS['posts'] = & $wp_query->posts; |
568 $GLOBALS['post'] = isset( $wp_query->post ) ? $wp_query->post : null; |
590 $GLOBALS['post'] = isset( $wp_query->post ) ? $wp_query->post : null; |
569 $GLOBALS['request'] = $wp_query->request; |
591 $GLOBALS['request'] = $wp_query->request; |
570 |
592 |
571 if ( $wp_query->is_single() || $wp_query->is_page() ) { |
593 if ( $wp_query->is_single() || $wp_query->is_page() ) { |
572 $GLOBALS['more'] = 1; |
594 $GLOBALS['more'] = 1; |
573 $GLOBALS['single'] = 1; |
595 $GLOBALS['single'] = 1; |
574 } |
596 } |
575 |
597 |
576 if ( $wp_query->is_author() && isset( $wp_query->post ) ) |
598 if ( $wp_query->is_author() && isset( $wp_query->post ) ) { |
577 $GLOBALS['authordata'] = get_userdata( $wp_query->post->post_author ); |
599 $GLOBALS['authordata'] = get_userdata( $wp_query->post->post_author ); |
600 } |
|
578 } |
601 } |
579 |
602 |
580 /** |
603 /** |
581 * Set up the current user. |
604 * Set up the current user. |
582 * |
605 * |
594 * @global WP_Query $wp_the_query |
617 * @global WP_Query $wp_the_query |
595 */ |
618 */ |
596 public function query_posts() { |
619 public function query_posts() { |
597 global $wp_the_query; |
620 global $wp_the_query; |
598 $this->build_query_string(); |
621 $this->build_query_string(); |
599 $wp_the_query->query($this->query_vars); |
622 $wp_the_query->query( $this->query_vars ); |
600 } |
623 } |
601 |
624 |
602 /** |
625 /** |
603 * Set the Headers for 404, if nothing is found for requested URL. |
626 * Set the Headers for 404, if nothing is found for requested URL. |
604 * |
627 * |
605 * Issue a 404 if a request doesn't match any posts and doesn't match |
628 * Issue a 404 if a request doesn't match any posts and doesn't match |
606 * any object (e.g. an existing-but-empty category, tag, author) and a 404 was not already |
629 * any object (e.g. an existing-but-empty category, tag, author) and a 404 was not already |
607 * issued, and if the request was not a search or the homepage. |
630 * issued, and if the request was not a search or the homepage. |
611 * This sets headers after posts have been queried. handle_404() really means "handle status." |
634 * This sets headers after posts have been queried. handle_404() really means "handle status." |
612 * By inspecting the result of querying posts, seemingly successful requests can be switched to |
635 * By inspecting the result of querying posts, seemingly successful requests can be switched to |
613 * a 404 so that canonical redirection logic can kick in. |
636 * a 404 so that canonical redirection logic can kick in. |
614 * |
637 * |
615 * @since 2.0.0 |
638 * @since 2.0.0 |
616 * |
639 * |
617 * @global WP_Query $wp_query |
640 * @global WP_Query $wp_query |
618 */ |
641 */ |
619 public function handle_404() { |
642 public function handle_404() { |
620 global $wp_query; |
643 global $wp_query; |
621 |
644 |
622 /** |
645 /** |
623 * Filters whether to short-circuit default header status handling. |
646 * Filters whether to short-circuit default header status handling. |
633 if ( false !== apply_filters( 'pre_handle_404', false, $wp_query ) ) { |
656 if ( false !== apply_filters( 'pre_handle_404', false, $wp_query ) ) { |
634 return; |
657 return; |
635 } |
658 } |
636 |
659 |
637 // If we've already issued a 404, bail. |
660 // If we've already issued a 404, bail. |
638 if ( is_404() ) |
661 if ( is_404() ) { |
639 return; |
662 return; |
663 } |
|
640 |
664 |
641 // Never 404 for the admin, robots, or if we found posts. |
665 // Never 404 for the admin, robots, or if we found posts. |
642 if ( is_admin() || is_robots() || $wp_query->posts ) { |
666 if ( is_admin() || is_robots() || $wp_query->posts ) { |
643 |
667 |
644 $success = true; |
668 $success = true; |
655 } |
679 } |
656 |
680 |
657 // check for paged content that exceeds the max number of pages |
681 // check for paged content that exceeds the max number of pages |
658 $next = '<!--nextpage-->'; |
682 $next = '<!--nextpage-->'; |
659 if ( $p && false !== strpos( $p->post_content, $next ) && ! empty( $this->query_vars['page'] ) ) { |
683 if ( $p && false !== strpos( $p->post_content, $next ) && ! empty( $this->query_vars['page'] ) ) { |
660 $page = trim( $this->query_vars['page'], '/' ); |
684 $page = trim( $this->query_vars['page'], '/' ); |
661 $success = (int) $page <= ( substr_count( $p->post_content, $next ) + 1 ); |
685 $success = (int) $page <= ( substr_count( $p->post_content, $next ) + 1 ); |
662 } |
686 } |
663 } |
687 } |
664 |
688 |
665 if ( $success ) { |
689 if ( $success ) { |
706 * |
730 * |
707 * @since 2.0.0 |
731 * @since 2.0.0 |
708 * |
732 * |
709 * @param string|array $query_args Passed to parse_request(). |
733 * @param string|array $query_args Passed to parse_request(). |
710 */ |
734 */ |
711 public function main($query_args = '') { |
735 public function main( $query_args = '' ) { |
712 $this->init(); |
736 $this->init(); |
713 $this->parse_request($query_args); |
737 $this->parse_request( $query_args ); |
714 $this->send_headers(); |
738 $this->send_headers(); |
715 $this->query_posts(); |
739 $this->query_posts(); |
716 $this->handle_404(); |
740 $this->handle_404(); |
717 $this->register_globals(); |
741 $this->register_globals(); |
718 |
742 |