wp/wp-includes/rewrite.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
   125  * being placed at the top of the rewrite rules.
   125  * being placed at the top of the rewrite rules.
   126  *
   126  *
   127  * @since 2.1.0
   127  * @since 2.1.0
   128  * @since 4.4.0 Array support was added to the `$query` parameter.
   128  * @since 4.4.0 Array support was added to the `$query` parameter.
   129  *
   129  *
   130  * @global WP_Rewrite $wp_rewrite WordPress Rewrite Component.
   130  * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
   131  *
   131  *
   132  * @param string       $regex Regular expression to match request against.
   132  * @param string       $regex Regular expression to match request against.
   133  * @param string|array $query The corresponding query vars for this rewrite rule.
   133  * @param string|array $query The corresponding query vars for this rewrite rule.
   134  * @param string       $after Optional. Priority of the new rule. Accepts 'top'
   134  * @param string       $after Optional. Priority of the new rule. Accepts 'top'
   135  *                            or 'bottom'. Default 'bottom'.
   135  *                            or 'bottom'. Default 'bottom'.
   147  * you call this on, or before, the {@see 'init'} hook. This is because $query defaults
   147  * you call this on, or before, the {@see 'init'} hook. This is because $query defaults
   148  * to "$tag=", and for this to work a new query var has to be added.
   148  * to "$tag=", and for this to work a new query var has to be added.
   149  *
   149  *
   150  * @since 2.1.0
   150  * @since 2.1.0
   151  *
   151  *
   152  * @global WP_Rewrite $wp_rewrite
   152  * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
   153  * @global WP         $wp
   153  * @global WP         $wp         Current WordPress environment instance.
   154  *
   154  *
   155  * @param string $tag   Name of the new rewrite tag.
   155  * @param string $tag   Name of the new rewrite tag.
   156  * @param string $regex Regular expression to substitute the tag for in rewrite rules.
   156  * @param string $regex Regular expression to substitute the tag for in rewrite rules.
   157  * @param string $query Optional. String to append to the rewritten query. Must end in '='. Default empty.
   157  * @param string $query Optional. String to append to the rewritten query. Must end in '='. Default empty.
   158  */
   158  */
   159 function add_rewrite_tag( $tag, $regex, $query = '' ) {
   159 function add_rewrite_tag( $tag, $regex, $query = '' ) {
   160 	// validate the tag's name
   160 	// Validate the tag's name.
   161 	if ( strlen( $tag ) < 3 || $tag[0] != '%' || $tag[ strlen( $tag ) - 1 ] != '%' ) {
   161 	if ( strlen( $tag ) < 3 || '%' !== $tag[0] || '%' !== $tag[ strlen( $tag ) - 1 ] ) {
   162 		return;
   162 		return;
   163 	}
   163 	}
   164 
   164 
   165 	global $wp_rewrite, $wp;
   165 	global $wp_rewrite, $wp;
   166 
   166 
   236 /**
   236 /**
   237  * Add a new feed type like /atom1/.
   237  * Add a new feed type like /atom1/.
   238  *
   238  *
   239  * @since 2.1.0
   239  * @since 2.1.0
   240  *
   240  *
   241  * @global WP_Rewrite $wp_rewrite
   241  * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
   242  *
   242  *
   243  * @param string   $feedname Feed name.
   243  * @param string   $feedname Feed name.
   244  * @param callable $function Callback to run on feed display.
   244  * @param callable $function Callback to run on feed display.
   245  * @return string Feed action name.
   245  * @return string Feed action name.
   246  */
   246  */
   247 function add_feed( $feedname, $function ) {
   247 function add_feed( $feedname, $function ) {
   248 	global $wp_rewrite;
   248 	global $wp_rewrite;
   249 
   249 
   250 	if ( ! in_array( $feedname, $wp_rewrite->feeds ) ) {
   250 	if ( ! in_array( $feedname, $wp_rewrite->feeds, true ) ) {
   251 		$wp_rewrite->feeds[] = $feedname;
   251 		$wp_rewrite->feeds[] = $feedname;
   252 	}
   252 	}
   253 
   253 
   254 	$hook = 'do_feed_' . $feedname;
   254 	$hook = 'do_feed_' . $feedname;
   255 
   255 
   256 	// Remove default function hook
   256 	// Remove default function hook.
   257 	remove_action( $hook, $hook );
   257 	remove_action( $hook, $hook );
   258 
   258 
   259 	add_action( $hook, $function, 10, 2 );
   259 	add_action( $hook, $function, 10, 2 );
   260 
   260 
   261 	return $hook;
   261 	return $hook;
   264 /**
   264 /**
   265  * Remove rewrite rules and then recreate rewrite rules.
   265  * Remove rewrite rules and then recreate rewrite rules.
   266  *
   266  *
   267  * @since 3.0.0
   267  * @since 3.0.0
   268  *
   268  *
   269  * @global WP_Rewrite $wp_rewrite
   269  * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
   270  *
   270  *
   271  * @param bool $hard Whether to update .htaccess (hard flush) or just update
   271  * @param bool $hard Whether to update .htaccess (hard flush) or just update
   272  *                   rewrite_rules transient (soft flush). Default is true (hard).
   272  *                   rewrite_rules option (soft flush). Default is true (hard).
   273  */
   273  */
   274 function flush_rewrite_rules( $hard = true ) {
   274 function flush_rewrite_rules( $hard = true ) {
   275 	global $wp_rewrite;
   275 	global $wp_rewrite;
   276 	$wp_rewrite->flush_rules( $hard );
   276 
       
   277 	if ( is_callable( array( $wp_rewrite, 'flush_rules' ) ) ) {
       
   278 		$wp_rewrite->flush_rules( $hard );
       
   279 	}
   277 }
   280 }
   278 
   281 
   279 /**
   282 /**
   280  * Add an endpoint, like /trackback/.
   283  * Add an endpoint, like /trackback/.
   281  *
   284  *
   299  * activated and deactivated.
   302  * activated and deactivated.
   300  *
   303  *
   301  * @since 2.1.0
   304  * @since 2.1.0
   302  * @since 4.3.0 Added support for skipping query var registration by passing `false` to `$query_var`.
   305  * @since 4.3.0 Added support for skipping query var registration by passing `false` to `$query_var`.
   303  *
   306  *
   304  * @global WP_Rewrite $wp_rewrite
   307  * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
   305  *
   308  *
   306  * @param string      $name      Name of the endpoint.
   309  * @param string      $name      Name of the endpoint.
   307  * @param int         $places    Endpoint mask describing the places the endpoint should be added.
   310  * @param int         $places    Endpoint mask describing the places the endpoint should be added.
   308  * @param string|bool $query_var Name of the corresponding query variable. Pass `false` to skip registering a query_var
   311  * @param string|bool $query_var Name of the corresponding query variable. Pass `false` to skip registering a query_var
   309  *                               for this endpoint. Defaults to the value of `$name`.
   312  *                               for this endpoint. Defaults to the value of `$name`.
   359 		return $query_vars;
   362 		return $query_vars;
   360 	}
   363 	}
   361 
   364 
   362 	// Identify the 'postname' position in the permastruct array.
   365 	// Identify the 'postname' position in the permastruct array.
   363 	$permastructs   = array_values( array_filter( explode( '/', get_option( 'permalink_structure' ) ) ) );
   366 	$permastructs   = array_values( array_filter( explode( '/', get_option( 'permalink_structure' ) ) ) );
   364 	$postname_index = array_search( '%postname%', $permastructs );
   367 	$postname_index = array_search( '%postname%', $permastructs, true );
   365 
   368 
   366 	if ( false === $postname_index ) {
   369 	if ( false === $postname_index ) {
   367 		return $query_vars;
   370 		return $query_vars;
   368 	}
   371 	}
   369 
   372 
   415 	if ( 'year' === $compare && isset( $query_vars['monthnum'] ) ) {
   418 	if ( 'year' === $compare && isset( $query_vars['monthnum'] ) ) {
   416 		$maybe_page = $query_vars['monthnum'];
   419 		$maybe_page = $query_vars['monthnum'];
   417 	} elseif ( 'monthnum' === $compare && isset( $query_vars['day'] ) ) {
   420 	} elseif ( 'monthnum' === $compare && isset( $query_vars['day'] ) ) {
   418 		$maybe_page = $query_vars['day'];
   421 		$maybe_page = $query_vars['day'];
   419 	}
   422 	}
   420 	// Bug found in #11694 - 'page' was returning '/4'
   423 	// Bug found in #11694 - 'page' was returning '/4'.
   421 	$maybe_page = (int) trim( $maybe_page, '/' );
   424 	$maybe_page = (int) trim( $maybe_page, '/' );
   422 
   425 
   423 	$post_page_count = substr_count( $post->post_content, '<!--nextpage-->' ) + 1;
   426 	$post_page_count = substr_count( $post->post_content, '<!--nextpage-->' ) + 1;
   424 
   427 
   425 	// If the post doesn't have multiple pages, but a 'page' candidate is found, resolve to the date archive.
   428 	// If the post doesn't have multiple pages, but a 'page' candidate is found, resolve to the date archive.
   454  *
   457  *
   455  * Checks are supposedly from the hosted site blog.
   458  * Checks are supposedly from the hosted site blog.
   456  *
   459  *
   457  * @since 1.0.0
   460  * @since 1.0.0
   458  *
   461  *
   459  * @global WP_Rewrite $wp_rewrite
   462  * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
   460  * @global WP         $wp
   463  * @global WP         $wp         Current WordPress environment instance.
   461  *
   464  *
   462  * @param string $url Permalink to check.
   465  * @param string $url Permalink to check.
   463  * @return int Post ID, or 0 on failure.
   466  * @return int Post ID, or 0 on failure.
   464  */
   467  */
   465 function url_to_postid( $url ) {
   468 function url_to_postid( $url ) {
   480 	// Bail early if the URL does not belong to this site.
   483 	// Bail early if the URL does not belong to this site.
   481 	if ( $url_host && $url_host !== $home_url_host ) {
   484 	if ( $url_host && $url_host !== $home_url_host ) {
   482 		return 0;
   485 		return 0;
   483 	}
   486 	}
   484 
   487 
   485 	// First, check to see if there is a 'p=N' or 'page_id=N' to match against
   488 	// First, check to see if there is a 'p=N' or 'page_id=N' to match against.
   486 	if ( preg_match( '#[?&](p|page_id|attachment_id)=(\d+)#', $url, $values ) ) {
   489 	if ( preg_match( '#[?&](p|page_id|attachment_id)=(\d+)#', $url, $values ) ) {
   487 		$id = absint( $values[2] );
   490 		$id = absint( $values[2] );
   488 		if ( $id ) {
   491 		if ( $id ) {
   489 			return $id;
   492 			return $id;
   490 		}
   493 		}
   491 	}
   494 	}
   492 
   495 
   493 	// Get rid of the #anchor
   496 	// Get rid of the #anchor.
   494 	$url_split = explode( '#', $url );
   497 	$url_split = explode( '#', $url );
   495 	$url       = $url_split[0];
   498 	$url       = $url_split[0];
   496 
   499 
   497 	// Get rid of URL ?query=string
   500 	// Get rid of URL ?query=string.
   498 	$url_split = explode( '?', $url );
   501 	$url_split = explode( '?', $url );
   499 	$url       = $url_split[0];
   502 	$url       = $url_split[0];
   500 
   503 
   501 	// Set the correct URL scheme.
   504 	// Set the correct URL scheme.
   502 	$scheme = parse_url( home_url(), PHP_URL_SCHEME );
   505 	$scheme = parse_url( home_url(), PHP_URL_SCHEME );
   503 	$url    = set_url_scheme( $url, $scheme );
   506 	$url    = set_url_scheme( $url, $scheme );
   504 
   507 
   505 	// Add 'www.' if it is absent and should be there
   508 	// Add 'www.' if it is absent and should be there.
   506 	if ( false !== strpos( home_url(), '://www.' ) && false === strpos( $url, '://www.' ) ) {
   509 	if ( false !== strpos( home_url(), '://www.' ) && false === strpos( $url, '://www.' ) ) {
   507 		$url = str_replace( '://', '://www.', $url );
   510 		$url = str_replace( '://', '://www.', $url );
   508 	}
   511 	}
   509 
   512 
   510 	// Strip 'www.' if it is present and shouldn't be
   513 	// Strip 'www.' if it is present and shouldn't be.
   511 	if ( false === strpos( home_url(), '://www.' ) ) {
   514 	if ( false === strpos( home_url(), '://www.' ) ) {
   512 		$url = str_replace( '://www.', '://', $url );
   515 		$url = str_replace( '://www.', '://', $url );
   513 	}
   516 	}
   514 
   517 
   515 	if ( trim( $url, '/' ) === home_url() && 'page' == get_option( 'show_on_front' ) ) {
   518 	if ( trim( $url, '/' ) === home_url() && 'page' === get_option( 'show_on_front' ) ) {
   516 		$page_on_front = get_option( 'page_on_front' );
   519 		$page_on_front = get_option( 'page_on_front' );
   517 
   520 
   518 		if ( $page_on_front && get_post( $page_on_front ) instanceof WP_Post ) {
   521 		if ( $page_on_front && get_post( $page_on_front ) instanceof WP_Post ) {
   519 			return (int) $page_on_front;
   522 			return (int) $page_on_front;
   520 		}
   523 		}
   521 	}
   524 	}
   522 
   525 
   523 	// Check to see if we are using rewrite rules
   526 	// Check to see if we are using rewrite rules.
   524 	$rewrite = $wp_rewrite->wp_rewrite_rules();
   527 	$rewrite = $wp_rewrite->wp_rewrite_rules();
   525 
   528 
   526 	// Not using rewrite rules, and 'p=N' and 'page_id=N' methods failed, so we're out of options
   529 	// Not using rewrite rules, and 'p=N' and 'page_id=N' methods failed, so we're out of options.
   527 	if ( empty( $rewrite ) ) {
   530 	if ( empty( $rewrite ) ) {
   528 		return 0;
   531 		return 0;
   529 	}
   532 	}
   530 
   533 
   531 	// Strip 'index.php/' if we're not using path info permalinks
   534 	// Strip 'index.php/' if we're not using path info permalinks.
   532 	if ( ! $wp_rewrite->using_index_permalinks() ) {
   535 	if ( ! $wp_rewrite->using_index_permalinks() ) {
   533 		$url = str_replace( $wp_rewrite->index . '/', '', $url );
   536 		$url = str_replace( $wp_rewrite->index . '/', '', $url );
   534 	}
   537 	}
   535 
   538 
   536 	if ( false !== strpos( trailingslashit( $url ), home_url( '/' ) ) ) {
   539 	if ( false !== strpos( trailingslashit( $url ), home_url( '/' ) ) ) {
   537 		// Chop off http://domain.com/[path]
   540 		// Chop off http://domain.com/[path].
   538 		$url = str_replace( home_url(), '', $url );
   541 		$url = str_replace( home_url(), '', $url );
   539 	} else {
   542 	} else {
   540 		// Chop off /path/to/blog
   543 		// Chop off /path/to/blog.
   541 		$home_path = parse_url( home_url( '/' ) );
   544 		$home_path = parse_url( home_url( '/' ) );
   542 		$home_path = isset( $home_path['path'] ) ? $home_path['path'] : '';
   545 		$home_path = isset( $home_path['path'] ) ? $home_path['path'] : '';
   543 		$url       = preg_replace( sprintf( '#^%s#', preg_quote( $home_path ) ), '', trailingslashit( $url ) );
   546 		$url       = preg_replace( sprintf( '#^%s#', preg_quote( $home_path ) ), '', trailingslashit( $url ) );
   544 	}
   547 	}
   545 
   548 
   546 	// Trim leading and lagging slashes
   549 	// Trim leading and lagging slashes.
   547 	$url = trim( $url, '/' );
   550 	$url = trim( $url, '/' );
   548 
   551 
   549 	$request              = $url;
   552 	$request              = $url;
   550 	$post_type_query_vars = array();
   553 	$post_type_query_vars = array();
   551 
   554 
   557 
   560 
   558 	// Look for matches.
   561 	// Look for matches.
   559 	$request_match = $request;
   562 	$request_match = $request;
   560 	foreach ( (array) $rewrite as $match => $query ) {
   563 	foreach ( (array) $rewrite as $match => $query ) {
   561 
   564 
   562 		// If the requesting file is the anchor of the match, prepend it
   565 		// If the requesting file is the anchor of the match,
   563 		// to the path info.
   566 		// prepend it to the path info.
   564 		if ( ! empty( $url ) && ( $url != $request ) && ( strpos( $match, $url ) === 0 ) ) {
   567 		if ( ! empty( $url ) && ( $url != $request ) && ( strpos( $match, $url ) === 0 ) ) {
   565 			$request_match = $url . '/' . $request;
   568 			$request_match = $url . '/' . $request;
   566 		}
   569 		}
   567 
   570 
   568 		if ( preg_match( "#^$match#", $request_match, $matches ) ) {
   571 		if ( preg_match( "#^$match#", $request_match, $matches ) ) {
   586 			$query = preg_replace( '!^.+\?!', '', $query );
   589 			$query = preg_replace( '!^.+\?!', '', $query );
   587 
   590 
   588 			// Substitute the substring matches into the query.
   591 			// Substitute the substring matches into the query.
   589 			$query = addslashes( WP_MatchesMapRegex::apply( $query, $matches ) );
   592 			$query = addslashes( WP_MatchesMapRegex::apply( $query, $matches ) );
   590 
   593 
   591 			// Filter out non-public query vars
   594 			// Filter out non-public query vars.
   592 			global $wp;
   595 			global $wp;
   593 			parse_str( $query, $query_vars );
   596 			parse_str( $query, $query_vars );
   594 			$query = array();
   597 			$query = array();
   595 			foreach ( (array) $query_vars as $key => $value ) {
   598 			foreach ( (array) $query_vars as $key => $value ) {
   596 				if ( in_array( $key, $wp->public_query_vars ) ) {
   599 				if ( in_array( (string) $key, $wp->public_query_vars, true ) ) {
   597 					$query[ $key ] = $value;
   600 					$query[ $key ] = $value;
   598 					if ( isset( $post_type_query_vars[ $key ] ) ) {
   601 					if ( isset( $post_type_query_vars[ $key ] ) ) {
   599 						$query['post_type'] = $post_type_query_vars[ $key ];
   602 						$query['post_type'] = $post_type_query_vars[ $key ];
   600 						$query['name']      = $value;
   603 						$query['name']      = $value;
   601 					}
   604 					}
   603 			}
   606 			}
   604 
   607 
   605 			// Resolve conflicts between posts with numeric slugs and date archive queries.
   608 			// Resolve conflicts between posts with numeric slugs and date archive queries.
   606 			$query = wp_resolve_numeric_slug_conflicts( $query );
   609 			$query = wp_resolve_numeric_slug_conflicts( $query );
   607 
   610 
   608 			// Do the query
   611 			// Do the query.
   609 			$query = new WP_Query( $query );
   612 			$query = new WP_Query( $query );
   610 			if ( ! empty( $query->posts ) && $query->is_singular ) {
   613 			if ( ! empty( $query->posts ) && $query->is_singular ) {
   611 				return $query->post->ID;
   614 				return $query->post->ID;
   612 			} else {
   615 			} else {
   613 				return 0;
   616 				return 0;