wp/wp-includes/class-wp-rewrite.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
   440 
   440 
   441 		$page_uris            = array();
   441 		$page_uris            = array();
   442 		$page_attachment_uris = array();
   442 		$page_attachment_uris = array();
   443 
   443 
   444 		foreach ( $posts as $id => $post ) {
   444 		foreach ( $posts as $id => $post ) {
   445 			// URL => page name
   445 			// URL => page name.
   446 			$uri         = get_page_uri( $id );
   446 			$uri         = get_page_uri( $id );
   447 			$attachments = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_name, post_parent FROM $wpdb->posts WHERE post_type = 'attachment' AND post_parent = %d", $id ) );
   447 			$attachments = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_name, post_parent FROM $wpdb->posts WHERE post_type = 'attachment' AND post_parent = %d", $id ) );
   448 			if ( ! empty( $attachments ) ) {
   448 			if ( ! empty( $attachments ) ) {
   449 				foreach ( $attachments as $attachment ) {
   449 				foreach ( $attachments as $attachment ) {
   450 					$attach_uri                          = get_page_uri( $attachment->ID );
   450 					$attach_uri                          = get_page_uri( $attachment->ID );
   461 	/**
   461 	/**
   462 	 * Retrieves all of the rewrite rules for pages.
   462 	 * Retrieves all of the rewrite rules for pages.
   463 	 *
   463 	 *
   464 	 * @since 1.5.0
   464 	 * @since 1.5.0
   465 	 *
   465 	 *
   466 	 * @return array Page rewrite rules.
   466 	 * @return string[] Page rewrite rules.
   467 	 */
   467 	 */
   468 	public function page_rewrite_rules() {
   468 	public function page_rewrite_rules() {
   469 		// The extra .? at the beginning prevents clashes with other regular expressions in the rules array.
   469 		// The extra .? at the beginning prevents clashes with other regular expressions in the rules array.
   470 		$this->add_rewrite_tag( '%pagename%', '(.?.+?)', 'pagename=' );
   470 		$this->add_rewrite_tag( '%pagename%', '(.?.+?)', 'pagename=' );
   471 
   471 
   487 	 * 'date/' before the actual permalink to form the complete date permalink
   487 	 * 'date/' before the actual permalink to form the complete date permalink
   488 	 * structure.
   488 	 * structure.
   489 	 *
   489 	 *
   490 	 * @since 1.5.0
   490 	 * @since 1.5.0
   491 	 *
   491 	 *
   492 	 * @return string|false False on no permalink structure. Date permalink structure.
   492 	 * @return string|false Date permalink structure on success, false on failure.
   493 	 */
   493 	 */
   494 	public function get_date_permastruct() {
   494 	public function get_date_permastruct() {
   495 		if ( isset( $this->date_structure ) ) {
   495 		if ( isset( $this->date_structure ) ) {
   496 			return $this->date_structure;
   496 			return $this->date_structure;
   497 		}
   497 		}
   524 		 */
   524 		 */
   525 		$front = $this->front;
   525 		$front = $this->front;
   526 		preg_match_all( '/%.+?%/', $this->permalink_structure, $tokens );
   526 		preg_match_all( '/%.+?%/', $this->permalink_structure, $tokens );
   527 		$tok_index = 1;
   527 		$tok_index = 1;
   528 		foreach ( (array) $tokens[0] as $token ) {
   528 		foreach ( (array) $tokens[0] as $token ) {
   529 			if ( '%post_id%' == $token && ( $tok_index <= 3 ) ) {
   529 			if ( '%post_id%' === $token && ( $tok_index <= 3 ) ) {
   530 				$front = $front . 'date/';
   530 				$front = $front . 'date/';
   531 				break;
   531 				break;
   532 			}
   532 			}
   533 			$tok_index++;
   533 			$tok_index++;
   534 		}
   534 		}
   544 	 * Gets the date permalink structure and strips out the month and day
   544 	 * Gets the date permalink structure and strips out the month and day
   545 	 * permalink structures.
   545 	 * permalink structures.
   546 	 *
   546 	 *
   547 	 * @since 1.5.0
   547 	 * @since 1.5.0
   548 	 *
   548 	 *
   549 	 * @return false|string False on failure. Year structure on success.
   549 	 * @return string|false Year permalink structure on success, false on failure.
   550 	 */
   550 	 */
   551 	public function get_year_permastruct() {
   551 	public function get_year_permastruct() {
   552 		$structure = $this->get_date_permastruct();
   552 		$structure = $this->get_date_permastruct();
   553 
   553 
   554 		if ( empty( $structure ) ) {
   554 		if ( empty( $structure ) ) {
   568 	 * Gets the date permalink structure and strips out the day permalink
   568 	 * Gets the date permalink structure and strips out the day permalink
   569 	 * structures. Keeps the year permalink structure.
   569 	 * structures. Keeps the year permalink structure.
   570 	 *
   570 	 *
   571 	 * @since 1.5.0
   571 	 * @since 1.5.0
   572 	 *
   572 	 *
   573 	 * @return false|string False on failure. Year/Month structure on success.
   573 	 * @return string|false Year/Month permalink structure on success, false on failure.
   574 	 */
   574 	 */
   575 	public function get_month_permastruct() {
   575 	public function get_month_permastruct() {
   576 		$structure = $this->get_date_permastruct();
   576 		$structure = $this->get_date_permastruct();
   577 
   577 
   578 		if ( empty( $structure ) ) {
   578 		if ( empty( $structure ) ) {
   590 	 *
   590 	 *
   591 	 * Keeps date permalink structure with all year, month, and day.
   591 	 * Keeps date permalink structure with all year, month, and day.
   592 	 *
   592 	 *
   593 	 * @since 1.5.0
   593 	 * @since 1.5.0
   594 	 *
   594 	 *
   595 	 * @return string|false False on failure. Year/Month/Day structure on success.
   595 	 * @return string|false Year/Month/Day permalink structure on success, false on failure.
   596 	 */
   596 	 */
   597 	public function get_day_permastruct() {
   597 	public function get_day_permastruct() {
   598 		return $this->get_date_permastruct();
   598 		return $this->get_date_permastruct();
   599 	}
   599 	}
   600 
   600 
   606 	 * '%category%'. If it does, then the root property will be used, along with
   606 	 * '%category%'. If it does, then the root property will be used, along with
   607 	 * the category_base property value.
   607 	 * the category_base property value.
   608 	 *
   608 	 *
   609 	 * @since 1.5.0
   609 	 * @since 1.5.0
   610 	 *
   610 	 *
   611 	 * @return string|false False on failure. Category permalink structure.
   611 	 * @return string|false Category permalink structure on success, false on failure.
   612 	 */
   612 	 */
   613 	public function get_category_permastruct() {
   613 	public function get_category_permastruct() {
   614 		return $this->get_extra_permastruct( 'category' );
   614 		return $this->get_extra_permastruct( 'category' );
   615 	}
   615 	}
   616 
   616 
   622 	 * does, then the root property will be used, along with the tag_base
   622 	 * does, then the root property will be used, along with the tag_base
   623 	 * property value.
   623 	 * property value.
   624 	 *
   624 	 *
   625 	 * @since 2.3.0
   625 	 * @since 2.3.0
   626 	 *
   626 	 *
   627 	 * @return string|false False on failure. Tag permalink structure.
   627 	 * @return string|false Tag permalink structure on success, false on failure.
   628 	 */
   628 	 */
   629 	public function get_tag_permastruct() {
   629 	public function get_tag_permastruct() {
   630 		return $this->get_extra_permastruct( 'post_tag' );
   630 		return $this->get_extra_permastruct( 'post_tag' );
   631 	}
   631 	}
   632 
   632 
   634 	 * Retrieves an extra permalink structure by name.
   634 	 * Retrieves an extra permalink structure by name.
   635 	 *
   635 	 *
   636 	 * @since 2.5.0
   636 	 * @since 2.5.0
   637 	 *
   637 	 *
   638 	 * @param string $name Permalink structure name.
   638 	 * @param string $name Permalink structure name.
   639 	 * @return string|false False if not found. Permalink structure string.
   639 	 * @return string|false Permalink structure string on success, false on failure.
   640 	 */
   640 	 */
   641 	public function get_extra_permastruct( $name ) {
   641 	public function get_extra_permastruct( $name ) {
   642 		if ( empty( $this->permalink_structure ) ) {
   642 		if ( empty( $this->permalink_structure ) ) {
   643 			return false;
   643 			return false;
   644 		}
   644 		}
   657 	 * '/%author%'. Will set the author_structure property and then return it
   657 	 * '/%author%'. Will set the author_structure property and then return it
   658 	 * without attempting to set the value again.
   658 	 * without attempting to set the value again.
   659 	 *
   659 	 *
   660 	 * @since 1.5.0
   660 	 * @since 1.5.0
   661 	 *
   661 	 *
   662 	 * @return string|false False if not found. Permalink structure string.
   662 	 * @return string|false Author permalink structure on success, false on failure.
   663 	 */
   663 	 */
   664 	public function get_author_permastruct() {
   664 	public function get_author_permastruct() {
   665 		if ( isset( $this->author_structure ) ) {
   665 		if ( isset( $this->author_structure ) ) {
   666 			return $this->author_structure;
   666 			return $this->author_structure;
   667 		}
   667 		}
   683 	 * '/%search%'. Will set the search_structure property and then return it
   683 	 * '/%search%'. Will set the search_structure property and then return it
   684 	 * without attempting to set the value again.
   684 	 * without attempting to set the value again.
   685 	 *
   685 	 *
   686 	 * @since 1.5.0
   686 	 * @since 1.5.0
   687 	 *
   687 	 *
   688 	 * @return string|false False if not found. Permalink structure string.
   688 	 * @return string|false Search permalink structure on success, false on failure.
   689 	 */
   689 	 */
   690 	public function get_search_permastruct() {
   690 	public function get_search_permastruct() {
   691 		if ( isset( $this->search_structure ) ) {
   691 		if ( isset( $this->search_structure ) ) {
   692 			return $this->search_structure;
   692 			return $this->search_structure;
   693 		}
   693 		}
   709 	 * page_structure property and then return it without attempting to set the
   709 	 * page_structure property and then return it without attempting to set the
   710 	 * value again.
   710 	 * value again.
   711 	 *
   711 	 *
   712 	 * @since 1.5.0
   712 	 * @since 1.5.0
   713 	 *
   713 	 *
   714 	 * @return string|false False if not found. Permalink structure string.
   714 	 * @return string|false Page permalink structure on success, false on failure.
   715 	 */
   715 	 */
   716 	public function get_page_permastruct() {
   716 	public function get_page_permastruct() {
   717 		if ( isset( $this->page_structure ) ) {
   717 		if ( isset( $this->page_structure ) ) {
   718 			return $this->page_structure;
   718 			return $this->page_structure;
   719 		}
   719 		}
   735 	 * '/%feed%'. Will set the feed_structure property and then return it
   735 	 * '/%feed%'. Will set the feed_structure property and then return it
   736 	 * without attempting to set the value again.
   736 	 * without attempting to set the value again.
   737 	 *
   737 	 *
   738 	 * @since 1.5.0
   738 	 * @since 1.5.0
   739 	 *
   739 	 *
   740 	 * @return string|false False if not found. Permalink structure string.
   740 	 * @return string|false Feed permalink structure on success, false on failure.
   741 	 */
   741 	 */
   742 	public function get_feed_permastruct() {
   742 	public function get_feed_permastruct() {
   743 		if ( isset( $this->feed_structure ) ) {
   743 		if ( isset( $this->feed_structure ) ) {
   744 			return $this->feed_structure;
   744 			return $this->feed_structure;
   745 		}
   745 		}
   761 	 * base and finally '/%feed%'. Will set the comment_feed_structure property
   761 	 * base and finally '/%feed%'. Will set the comment_feed_structure property
   762 	 * and then return it without attempting to set the value again.
   762 	 * and then return it without attempting to set the value again.
   763 	 *
   763 	 *
   764 	 * @since 1.5.0
   764 	 * @since 1.5.0
   765 	 *
   765 	 *
   766 	 * @return string|false False if not found. Permalink structure string.
   766 	 * @return string|false Comment feed permalink structure on success, false on failure.
   767 	 */
   767 	 */
   768 	public function get_comment_feed_permastruct() {
   768 	public function get_comment_feed_permastruct() {
   769 		if ( isset( $this->comment_feed_structure ) ) {
   769 		if ( isset( $this->comment_feed_structure ) ) {
   770 			return $this->comment_feed_structure;
   770 			return $this->comment_feed_structure;
   771 		}
   771 		}
   795 	 * @param string $tag   Name of the rewrite tag to add or update.
   795 	 * @param string $tag   Name of the rewrite tag to add or update.
   796 	 * @param string $regex Regular expression to substitute the tag for in rewrite rules.
   796 	 * @param string $regex Regular expression to substitute the tag for in rewrite rules.
   797 	 * @param string $query String to append to the rewritten query. Must end in '='.
   797 	 * @param string $query String to append to the rewritten query. Must end in '='.
   798 	 */
   798 	 */
   799 	public function add_rewrite_tag( $tag, $regex, $query ) {
   799 	public function add_rewrite_tag( $tag, $regex, $query ) {
   800 		$position = array_search( $tag, $this->rewritecode );
   800 		$position = array_search( $tag, $this->rewritecode, true );
   801 		if ( false !== $position && null !== $position ) {
   801 		if ( false !== $position && null !== $position ) {
   802 			$this->rewritereplace[ $position ] = $regex;
   802 			$this->rewritereplace[ $position ] = $regex;
   803 			$this->queryreplace[ $position ]   = $query;
   803 			$this->queryreplace[ $position ]   = $query;
   804 		} else {
   804 		} else {
   805 			$this->rewritecode[]    = $tag;
   805 			$this->rewritecode[]    = $tag;
   819 	 * @see WP_Rewrite::$queryreplace
   819 	 * @see WP_Rewrite::$queryreplace
   820 	 *
   820 	 *
   821 	 * @param string $tag Name of the rewrite tag to remove.
   821 	 * @param string $tag Name of the rewrite tag to remove.
   822 	 */
   822 	 */
   823 	public function remove_rewrite_tag( $tag ) {
   823 	public function remove_rewrite_tag( $tag ) {
   824 		$position = array_search( $tag, $this->rewritecode );
   824 		$position = array_search( $tag, $this->rewritecode, true );
   825 		if ( false !== $position && null !== $position ) {
   825 		if ( false !== $position && null !== $position ) {
   826 			unset( $this->rewritecode[ $position ] );
   826 			unset( $this->rewritecode[ $position ] );
   827 			unset( $this->rewritereplace[ $position ] );
   827 			unset( $this->rewritereplace[ $position ] );
   828 			unset( $this->queryreplace[ $position ] );
   828 			unset( $this->queryreplace[ $position ] );
   829 		}
   829 		}
   852 	 *                                    Default false.
   852 	 *                                    Default false.
   853 	 * @param bool   $walk_dirs           Optional. Whether the 'directories' making up the structure should be walked
   853 	 * @param bool   $walk_dirs           Optional. Whether the 'directories' making up the structure should be walked
   854 	 *                                    over and rewrite rules built for each in-turn. Default true.
   854 	 *                                    over and rewrite rules built for each in-turn. Default true.
   855 	 * @param bool   $endpoints           Optional. Whether endpoints should be applied to the generated rewrite rules.
   855 	 * @param bool   $endpoints           Optional. Whether endpoints should be applied to the generated rewrite rules.
   856 	 *                                    Default true.
   856 	 *                                    Default true.
   857 	 * @return array Rewrite rule list.
   857 	 * @return string[] Array of rewrite rules keyed by their regex pattern.
   858 	 */
   858 	 */
   859 	public function generate_rewrite_rules( $permalink_structure, $ep_mask = EP_NONE, $paged = true, $feed = true, $forcomments = false, $walk_dirs = true, $endpoints = true ) {
   859 	public function generate_rewrite_rules( $permalink_structure, $ep_mask = EP_NONE, $paged = true, $feed = true, $forcomments = false, $walk_dirs = true, $endpoints = true ) {
   860 		// Build a regex to match the feed section of URLs, something like (feed|atom|rss|rss2)/?
   860 		// Build a regex to match the feed section of URLs, something like (feed|atom|rss|rss2)/?
   861 		$feedregex2 = '';
   861 		$feedregex2 = '';
   862 		foreach ( (array) $this->feeds as $feed_name ) {
   862 		foreach ( (array) $this->feeds as $feed_name ) {
   895 		// Build an array of the tags (note that said array ends up being in $tokens[0]).
   895 		// Build an array of the tags (note that said array ends up being in $tokens[0]).
   896 		preg_match_all( '/%.+?%/', $permalink_structure, $tokens );
   896 		preg_match_all( '/%.+?%/', $permalink_structure, $tokens );
   897 
   897 
   898 		$num_tokens = count( $tokens[0] );
   898 		$num_tokens = count( $tokens[0] );
   899 
   899 
   900 		$index          = $this->index; //probably 'index.php'
   900 		$index          = $this->index; // Probably 'index.php'.
   901 		$feedindex      = $index;
   901 		$feedindex      = $index;
   902 		$trackbackindex = $index;
   902 		$trackbackindex = $index;
   903 		$embedindex     = $index;
   903 		$embedindex     = $index;
   904 
   904 
   905 		/*
   905 		/*
   918 			$queries[ $i ] .= $query_token;
   918 			$queries[ $i ] .= $query_token;
   919 		}
   919 		}
   920 
   920 
   921 		// Get the structure, minus any cruft (stuff that isn't tags) at the front.
   921 		// Get the structure, minus any cruft (stuff that isn't tags) at the front.
   922 		$structure = $permalink_structure;
   922 		$structure = $permalink_structure;
   923 		if ( $front != '/' ) {
   923 		if ( '/' !== $front ) {
   924 			$structure = str_replace( $front, '', $structure );
   924 			$structure = str_replace( $front, '', $structure );
   925 		}
   925 		}
   926 
   926 
   927 		/*
   927 		/*
   928 		 * Create a list of dirs to walk over, making rewrite rules for each level
   928 		 * Create a list of dirs to walk over, making rewrite rules for each level
  1001 			}
  1001 			}
  1002 
  1002 
  1003 			// Start creating the array of rewrites for this dir.
  1003 			// Start creating the array of rewrites for this dir.
  1004 			$rewrite = array();
  1004 			$rewrite = array();
  1005 
  1005 
  1006 			// ...adding on /feed/ regexes => queries
  1006 			// ...adding on /feed/ regexes => queries.
  1007 			if ( $feed ) {
  1007 			if ( $feed ) {
  1008 				$rewrite = array(
  1008 				$rewrite = array(
  1009 					$feedmatch  => $feedquery,
  1009 					$feedmatch  => $feedquery,
  1010 					$feedmatch2 => $feedquery2,
  1010 					$feedmatch2 => $feedquery2,
  1011 					$embedmatch => $embedquery,
  1011 					$embedmatch => $embedquery,
  1012 				);
  1012 				);
  1013 			}
  1013 			}
  1014 
  1014 
  1015 			//...and /page/xx ones
  1015 			// ...and /page/xx ones.
  1016 			if ( $paged ) {
  1016 			if ( $paged ) {
  1017 				$rewrite = array_merge( $rewrite, array( $pagematch => $pagequery ) );
  1017 				$rewrite = array_merge( $rewrite, array( $pagematch => $pagequery ) );
  1018 			}
  1018 			}
  1019 
  1019 
  1020 			// Only on pages with comments add ../comment-page-xx/.
  1020 			// Only on pages with comments add ../comment-page-xx/.
  1226 	 * @since 1.5.0
  1226 	 * @since 1.5.0
  1227 	 *
  1227 	 *
  1228 	 * @see WP_Rewrite::generate_rewrite_rules() See for long description and rest of parameters.
  1228 	 * @see WP_Rewrite::generate_rewrite_rules() See for long description and rest of parameters.
  1229 	 *
  1229 	 *
  1230 	 * @param string $permalink_structure The permalink structure to generate rules.
  1230 	 * @param string $permalink_structure The permalink structure to generate rules.
  1231 	 * @param bool   $walk_dirs           Optional, default is false. Whether to create list of directories to walk over.
  1231 	 * @param bool   $walk_dirs           Optional. Whether to create list of directories to walk over.
       
  1232 	 *                                    Default false.
  1232 	 * @return array
  1233 	 * @return array
  1233 	 */
  1234 	 */
  1234 	public function generate_rewrite_rule( $permalink_structure, $walk_dirs = false ) {
  1235 	public function generate_rewrite_rule( $permalink_structure, $walk_dirs = false ) {
  1235 		return $this->generate_rewrite_rules( $permalink_structure, EP_NONE, false, false, false, $walk_dirs );
  1236 		return $this->generate_rewrite_rules( $permalink_structure, EP_NONE, false, false, false, $walk_dirs );
  1236 	}
  1237 	}
  1248 	 * object or just manipulating the rewrite rule array before it is passed
  1249 	 * object or just manipulating the rewrite rule array before it is passed
  1249 	 * from the function.
  1250 	 * from the function.
  1250 	 *
  1251 	 *
  1251 	 * @since 1.5.0
  1252 	 * @since 1.5.0
  1252 	 *
  1253 	 *
  1253 	 * @return array An associate array of matches and queries.
  1254 	 * @return string[] An associative array of matches and queries.
  1254 	 */
  1255 	 */
  1255 	public function rewrite_rules() {
  1256 	public function rewrite_rules() {
  1256 		$rewrite = array();
  1257 		$rewrite = array();
  1257 
  1258 
  1258 		if ( empty( $this->permalink_structure ) ) {
  1259 		if ( empty( $this->permalink_structure ) ) {
  1259 			return $rewrite;
  1260 			return $rewrite;
  1260 		}
  1261 		}
  1261 
  1262 
  1262 		// robots.txt -only if installed at the root
  1263 		// robots.txt -- only if installed at the root.
  1263 		$home_path      = parse_url( home_url() );
  1264 		$home_path      = parse_url( home_url() );
  1264 		$robots_rewrite = ( empty( $home_path['path'] ) || '/' == $home_path['path'] ) ? array( 'robots\.txt$' => $this->index . '?robots=1' ) : array();
  1265 		$robots_rewrite = ( empty( $home_path['path'] ) || '/' === $home_path['path'] ) ? array( 'robots\.txt$' => $this->index . '?robots=1' ) : array();
       
  1266 
       
  1267 		// favicon.ico -- only if installed at the root.
       
  1268 		$favicon_rewrite = ( empty( $home_path['path'] ) || '/' === $home_path['path'] ) ? array( 'favicon\.ico$' => $this->index . '?favicon=1' ) : array();
  1265 
  1269 
  1266 		// Old feed and service files.
  1270 		// Old feed and service files.
  1267 		$deprecated_files = array(
  1271 		$deprecated_files = array(
  1268 			'.*wp-(atom|rdf|rss|rss2|feed|commentsrss2)\.php$' => $this->index . '?feed=old',
  1272 			'.*wp-(atom|rdf|rss|rss2|feed|commentsrss2)\.php$' => $this->index . '?feed=old',
  1269 			'.*wp-app\.php(/.*)?$' => $this->index . '?error=403',
  1273 			'.*wp-app\.php(/.*)?$' => $this->index . '?error=403',
  1285 		/**
  1289 		/**
  1286 		 * Filters rewrite rules used for "post" archives.
  1290 		 * Filters rewrite rules used for "post" archives.
  1287 		 *
  1291 		 *
  1288 		 * @since 1.5.0
  1292 		 * @since 1.5.0
  1289 		 *
  1293 		 *
  1290 		 * @param array $post_rewrite The rewrite rules for posts.
  1294 		 * @param string[] $post_rewrite Array of rewrite rules for posts, keyed by their regex pattern.
  1291 		 */
  1295 		 */
  1292 		$post_rewrite = apply_filters( 'post_rewrite_rules', $post_rewrite );
  1296 		$post_rewrite = apply_filters( 'post_rewrite_rules', $post_rewrite );
  1293 
  1297 
  1294 		// Date rewrite rules.
  1298 		// Date rewrite rules.
  1295 		$date_rewrite = $this->generate_rewrite_rules( $this->get_date_permastruct(), EP_DATE );
  1299 		$date_rewrite = $this->generate_rewrite_rules( $this->get_date_permastruct(), EP_DATE );
  1299 		 *
  1303 		 *
  1300 		 * Likely date archives would include /yyyy/, /yyyy/mm/, and /yyyy/mm/dd/.
  1304 		 * Likely date archives would include /yyyy/, /yyyy/mm/, and /yyyy/mm/dd/.
  1301 		 *
  1305 		 *
  1302 		 * @since 1.5.0
  1306 		 * @since 1.5.0
  1303 		 *
  1307 		 *
  1304 		 * @param array $date_rewrite The rewrite rules for date archives.
  1308 		 * @param string[] $date_rewrite Array of rewrite rules for date archives, keyed by their regex pattern.
  1305 		 */
  1309 		 */
  1306 		$date_rewrite = apply_filters( 'date_rewrite_rules', $date_rewrite );
  1310 		$date_rewrite = apply_filters( 'date_rewrite_rules', $date_rewrite );
  1307 
  1311 
  1308 		// Root-level rewrite rules.
  1312 		// Root-level rewrite rules.
  1309 		$root_rewrite = $this->generate_rewrite_rules( $this->root . '/', EP_ROOT );
  1313 		$root_rewrite = $this->generate_rewrite_rules( $this->root . '/', EP_ROOT );
  1314 		 * Likely root-level archives would include pagination rules for the homepage
  1318 		 * Likely root-level archives would include pagination rules for the homepage
  1315 		 * as well as site-wide post feeds (e.g. /feed/, and /feed/atom/).
  1319 		 * as well as site-wide post feeds (e.g. /feed/, and /feed/atom/).
  1316 		 *
  1320 		 *
  1317 		 * @since 1.5.0
  1321 		 * @since 1.5.0
  1318 		 *
  1322 		 *
  1319 		 * @param array $root_rewrite The root-level rewrite rules.
  1323 		 * @param string[] $root_rewrite Array of root-level rewrite rules, keyed by their regex pattern.
  1320 		 */
  1324 		 */
  1321 		$root_rewrite = apply_filters( 'root_rewrite_rules', $root_rewrite );
  1325 		$root_rewrite = apply_filters( 'root_rewrite_rules', $root_rewrite );
  1322 
  1326 
  1323 		// Comments rewrite rules.
  1327 		// Comments rewrite rules.
  1324 		$comments_rewrite = $this->generate_rewrite_rules( $this->root . $this->comments_base, EP_COMMENTS, false, true, true, false );
  1328 		$comments_rewrite = $this->generate_rewrite_rules( $this->root . $this->comments_base, EP_COMMENTS, false, true, true, false );
  1328 		 *
  1332 		 *
  1329 		 * Likely comments feed archives include /comments/feed/, and /comments/feed/atom/.
  1333 		 * Likely comments feed archives include /comments/feed/, and /comments/feed/atom/.
  1330 		 *
  1334 		 *
  1331 		 * @since 1.5.0
  1335 		 * @since 1.5.0
  1332 		 *
  1336 		 *
  1333 		 * @param array $comments_rewrite The rewrite rules for the site-wide comments feeds.
  1337 		 * @param string[] $comments_rewrite Array of rewrite rules for the site-wide comments feeds, keyed by their regex pattern.
  1334 		 */
  1338 		 */
  1335 		$comments_rewrite = apply_filters( 'comments_rewrite_rules', $comments_rewrite );
  1339 		$comments_rewrite = apply_filters( 'comments_rewrite_rules', $comments_rewrite );
  1336 
  1340 
  1337 		// Search rewrite rules.
  1341 		// Search rewrite rules.
  1338 		$search_structure = $this->get_search_permastruct();
  1342 		$search_structure = $this->get_search_permastruct();
  1344 		 * Likely search-related archives include /search/search+query/ as well as
  1348 		 * Likely search-related archives include /search/search+query/ as well as
  1345 		 * pagination and feed paths for a search.
  1349 		 * pagination and feed paths for a search.
  1346 		 *
  1350 		 *
  1347 		 * @since 1.5.0
  1351 		 * @since 1.5.0
  1348 		 *
  1352 		 *
  1349 		 * @param array $search_rewrite The rewrite rules for search queries.
  1353 		 * @param string[] $search_rewrite Array of rewrite rules for search queries, keyed by their regex pattern.
  1350 		 */
  1354 		 */
  1351 		$search_rewrite = apply_filters( 'search_rewrite_rules', $search_rewrite );
  1355 		$search_rewrite = apply_filters( 'search_rewrite_rules', $search_rewrite );
  1352 
  1356 
  1353 		// Author rewrite rules.
  1357 		// Author rewrite rules.
  1354 		$author_rewrite = $this->generate_rewrite_rules( $this->get_author_permastruct(), EP_AUTHORS );
  1358 		$author_rewrite = $this->generate_rewrite_rules( $this->get_author_permastruct(), EP_AUTHORS );
  1359 		 * Likely author archives would include /author/author-name/, as well as
  1363 		 * Likely author archives would include /author/author-name/, as well as
  1360 		 * pagination and feed paths for author archives.
  1364 		 * pagination and feed paths for author archives.
  1361 		 *
  1365 		 *
  1362 		 * @since 1.5.0
  1366 		 * @since 1.5.0
  1363 		 *
  1367 		 *
  1364 		 * @param array $author_rewrite The rewrite rules for author archives.
  1368 		 * @param string[] $author_rewrite Array of rewrite rules for author archives, keyed by their regex pattern.
  1365 		 */
  1369 		 */
  1366 		$author_rewrite = apply_filters( 'author_rewrite_rules', $author_rewrite );
  1370 		$author_rewrite = apply_filters( 'author_rewrite_rules', $author_rewrite );
  1367 
  1371 
  1368 		// Pages rewrite rules.
  1372 		// Pages rewrite rules.
  1369 		$page_rewrite = $this->page_rewrite_rules();
  1373 		$page_rewrite = $this->page_rewrite_rules();
  1371 		/**
  1375 		/**
  1372 		 * Filters rewrite rules used for "page" post type archives.
  1376 		 * Filters rewrite rules used for "page" post type archives.
  1373 		 *
  1377 		 *
  1374 		 * @since 1.5.0
  1378 		 * @since 1.5.0
  1375 		 *
  1379 		 *
  1376 		 * @param array $page_rewrite The rewrite rules for the "page" post type.
  1380 		 * @param string[] $page_rewrite Array of rewrite rules for the "page" post type, keyed by their regex pattern.
  1377 		 */
  1381 		 */
  1378 		$page_rewrite = apply_filters( 'page_rewrite_rules', $page_rewrite );
  1382 		$page_rewrite = apply_filters( 'page_rewrite_rules', $page_rewrite );
  1379 
  1383 
  1380 		// Extra permastructs.
  1384 		// Extra permastructs.
  1381 		foreach ( $this->extra_permastructs as $permastructname => $struct ) {
  1385 		foreach ( $this->extra_permastructs as $permastructname => $struct ) {
  1396 			 * to the name of the registered permastruct, e.g. 'post_tag' (tags),
  1400 			 * to the name of the registered permastruct, e.g. 'post_tag' (tags),
  1397 			 * 'category' (categories), etc.
  1401 			 * 'category' (categories), etc.
  1398 			 *
  1402 			 *
  1399 			 * @since 3.1.0
  1403 			 * @since 3.1.0
  1400 			 *
  1404 			 *
  1401 			 * @param array $rules The rewrite rules generated for the current permastruct.
  1405 			 * @param string[] $rules Array of rewrite rules generated for the current permastruct, keyed by their regex pattern.
  1402 			 */
  1406 			 */
  1403 			$rules = apply_filters( "{$permastructname}_rewrite_rules", $rules );
  1407 			$rules = apply_filters( "{$permastructname}_rewrite_rules", $rules );
  1404 			if ( 'post_tag' == $permastructname ) {
  1408 
       
  1409 			if ( 'post_tag' === $permastructname ) {
  1405 
  1410 
  1406 				/**
  1411 				/**
  1407 				 * Filters rewrite rules used specifically for Tags.
  1412 				 * Filters rewrite rules used specifically for Tags.
  1408 				 *
  1413 				 *
  1409 				 * @since 2.3.0
  1414 				 * @since 2.3.0
  1410 				 * @deprecated 3.1.0 Use 'post_tag_rewrite_rules' instead
  1415 				 * @deprecated 3.1.0 Use {@see 'post_tag_rewrite_rules'} instead.
  1411 				 *
  1416 				 *
  1412 				 * @param array $rules The rewrite rules generated for tags.
  1417 				 * @param string[] $rules Array of rewrite rules generated for tags, keyed by their regex pattern.
  1413 				 */
  1418 				 */
  1414 				$rules = apply_filters( 'tag_rewrite_rules', $rules );
  1419 				$rules = apply_filters_deprecated( 'tag_rewrite_rules', array( $rules ), '3.1.0', 'post_tag_rewrite_rules' );
  1415 			}
  1420 			}
  1416 
  1421 
  1417 			$this->extra_rules_top = array_merge( $this->extra_rules_top, $rules );
  1422 			$this->extra_rules_top = array_merge( $this->extra_rules_top, $rules );
  1418 		}
  1423 		}
  1419 
  1424 
  1420 		// Put them together.
  1425 		// Put them together.
  1421 		if ( $this->use_verbose_page_rules ) {
  1426 		if ( $this->use_verbose_page_rules ) {
  1422 			$this->rules = array_merge( $this->extra_rules_top, $robots_rewrite, $deprecated_files, $registration_pages, $root_rewrite, $comments_rewrite, $search_rewrite, $author_rewrite, $date_rewrite, $page_rewrite, $post_rewrite, $this->extra_rules );
  1427 			$this->rules = array_merge( $this->extra_rules_top, $robots_rewrite, $favicon_rewrite, $deprecated_files, $registration_pages, $root_rewrite, $comments_rewrite, $search_rewrite, $author_rewrite, $date_rewrite, $page_rewrite, $post_rewrite, $this->extra_rules );
  1423 		} else {
  1428 		} else {
  1424 			$this->rules = array_merge( $this->extra_rules_top, $robots_rewrite, $deprecated_files, $registration_pages, $root_rewrite, $comments_rewrite, $search_rewrite, $author_rewrite, $date_rewrite, $post_rewrite, $page_rewrite, $this->extra_rules );
  1429 			$this->rules = array_merge( $this->extra_rules_top, $robots_rewrite, $favicon_rewrite, $deprecated_files, $registration_pages, $root_rewrite, $comments_rewrite, $search_rewrite, $author_rewrite, $date_rewrite, $post_rewrite, $page_rewrite, $this->extra_rules );
  1425 		}
  1430 		}
  1426 
  1431 
  1427 		/**
  1432 		/**
  1428 		 * Fires after the rewrite rules are generated.
  1433 		 * Fires after the rewrite rules are generated.
  1429 		 *
  1434 		 *
  1436 		/**
  1441 		/**
  1437 		 * Filters the full set of generated rewrite rules.
  1442 		 * Filters the full set of generated rewrite rules.
  1438 		 *
  1443 		 *
  1439 		 * @since 1.5.0
  1444 		 * @since 1.5.0
  1440 		 *
  1445 		 *
  1441 		 * @param array $this->rules The compiled array of rewrite rules.
  1446 		 * @param string[] $rules The compiled array of rewrite rules, keyed by their regex pattern.
  1442 		 */
  1447 		 */
  1443 		$this->rules = apply_filters( 'rewrite_rules_array', $this->rules );
  1448 		$this->rules = apply_filters( 'rewrite_rules_array', $this->rules );
  1444 
  1449 
  1445 		return $this->rules;
  1450 		return $this->rules;
  1446 	}
  1451 	}
  1453 	 * it. This prevents having to process all of the permalinks to get the rewrite rules
  1458 	 * it. This prevents having to process all of the permalinks to get the rewrite rules
  1454 	 * in the form of caching.
  1459 	 * in the form of caching.
  1455 	 *
  1460 	 *
  1456 	 * @since 1.5.0
  1461 	 * @since 1.5.0
  1457 	 *
  1462 	 *
  1458 	 * @return array Rewrite rules.
  1463 	 * @return string[] Array of rewrite rules keyed by their regex pattern.
  1459 	 */
  1464 	 */
  1460 	public function wp_rewrite_rules() {
  1465 	public function wp_rewrite_rules() {
  1461 		$this->rules = get_option( 'rewrite_rules' );
  1466 		$this->rules = get_option( 'rewrite_rules' );
  1462 		if ( empty( $this->rules ) ) {
  1467 		if ( empty( $this->rules ) ) {
  1463 			$this->matches = 'matches';
  1468 			$this->matches = 'matches';
  1554 
  1559 
  1555 		/**
  1560 		/**
  1556 		 * Filters the list of rewrite rules formatted for output to an .htaccess file.
  1561 		 * Filters the list of rewrite rules formatted for output to an .htaccess file.
  1557 		 *
  1562 		 *
  1558 		 * @since 1.5.0
  1563 		 * @since 1.5.0
  1559 		 * @deprecated 1.5.0 Use the mod_rewrite_rules filter instead.
  1564 		 * @deprecated 1.5.0 Use the {@see 'mod_rewrite_rules'} filter instead.
  1560 		 *
  1565 		 *
  1561 		 * @param string $rules mod_rewrite Rewrite rules formatted for .htaccess.
  1566 		 * @param string $rules mod_rewrite Rewrite rules formatted for .htaccess.
  1562 		 */
  1567 		 */
  1563 		return apply_filters( 'rewrite_rules', $rules );
  1568 		return apply_filters_deprecated( 'rewrite_rules', array( $rules ), '1.5.0', 'mod_rewrite_rules' );
  1564 	}
  1569 	}
  1565 
  1570 
  1566 	/**
  1571 	/**
  1567 	 * Retrieves IIS7 URL Rewrite formatted rewrite rules to write to web.config file.
  1572 	 * Retrieves IIS7 URL Rewrite formatted rewrite rules to write to web.config file.
  1568 	 *
  1573 	 *
  1642 
  1647 
  1643 		// "external" = it doesn't correspond to index.php.
  1648 		// "external" = it doesn't correspond to index.php.
  1644 		if ( $external ) {
  1649 		if ( $external ) {
  1645 			$this->add_external_rule( $regex, $query );
  1650 			$this->add_external_rule( $regex, $query );
  1646 		} else {
  1651 		} else {
  1647 			if ( 'bottom' == $after ) {
  1652 			if ( 'bottom' === $after ) {
  1648 				$this->extra_rules = array_merge( $this->extra_rules, array( $regex => $query ) );
  1653 				$this->extra_rules = array_merge( $this->extra_rules, array( $regex => $query ) );
  1649 			} else {
  1654 			} else {
  1650 				$this->extra_rules_top = array_merge( $this->extra_rules_top, array( $regex => $query ) );
  1655 				$this->extra_rules_top = array_merge( $this->extra_rules_top, array( $regex => $query ) );
  1651 			}
  1656 			}
  1652 		}
  1657 		}
  1670 	 * @since 2.1.0
  1675 	 * @since 2.1.0
  1671 	 * @since 3.9.0 $query_var parameter added.
  1676 	 * @since 3.9.0 $query_var parameter added.
  1672 	 * @since 4.3.0 Added support for skipping query var registration by passing `false` to `$query_var`.
  1677 	 * @since 4.3.0 Added support for skipping query var registration by passing `false` to `$query_var`.
  1673 	 *
  1678 	 *
  1674 	 * @see add_rewrite_endpoint() for full documentation.
  1679 	 * @see add_rewrite_endpoint() for full documentation.
  1675 	 * @global WP $wp
  1680 	 * @global WP $wp Current WordPress environment instance.
  1676 	 *
  1681 	 *
  1677 	 * @param string      $name      Name of the endpoint.
  1682 	 * @param string      $name      Name of the endpoint.
  1678 	 * @param int         $places    Endpoint mask describing the places the endpoint should be added.
  1683 	 * @param int         $places    Endpoint mask describing the places the endpoint should be added.
  1679 	 * @param string|bool $query_var Optional. Name of the corresponding query variable. Pass `false` to
  1684 	 * @param string|bool $query_var Optional. Name of the corresponding query variable. Pass `false` to
  1680 	 *                               skip registering a query_var for this endpoint. Defaults to the
  1685 	 *                               skip registering a query_var for this endpoint. Defaults to the
  1682 	 */
  1687 	 */
  1683 	public function add_endpoint( $name, $places, $query_var = true ) {
  1688 	public function add_endpoint( $name, $places, $query_var = true ) {
  1684 		global $wp;
  1689 		global $wp;
  1685 
  1690 
  1686 		// For backward compatibility, if null has explicitly been passed as `$query_var`, assume `true`.
  1691 		// For backward compatibility, if null has explicitly been passed as `$query_var`, assume `true`.
  1687 		if ( true === $query_var || null === func_get_arg( 2 ) ) {
  1692 		if ( true === $query_var || null === $query_var ) {
  1688 			$query_var = $name;
  1693 			$query_var = $name;
  1689 		}
  1694 		}
  1690 		$this->endpoints[] = array( $places, $name, $query_var );
  1695 		$this->endpoints[] = array( $places, $name, $query_var );
  1691 
  1696 
  1692 		if ( $query_var ) {
  1697 		if ( $query_var ) {
  1780 	 * Calls WP_Rewrite::wp_rewrite_rules() after removing the 'rewrite_rules' option.
  1785 	 * Calls WP_Rewrite::wp_rewrite_rules() after removing the 'rewrite_rules' option.
  1781 	 * If the function named 'save_mod_rewrite_rules' exists, it will be called.
  1786 	 * If the function named 'save_mod_rewrite_rules' exists, it will be called.
  1782 	 *
  1787 	 *
  1783 	 * @since 2.0.1
  1788 	 * @since 2.0.1
  1784 	 *
  1789 	 *
  1785 	 * @staticvar bool $do_hard_later
       
  1786 	 *
       
  1787 	 * @param bool $hard Whether to update .htaccess (hard flush) or just update rewrite_rules option (soft flush). Default is true (hard).
  1790 	 * @param bool $hard Whether to update .htaccess (hard flush) or just update rewrite_rules option (soft flush). Default is true (hard).
  1788 	 */
  1791 	 */
  1789 	public function flush_rules( $hard = true ) {
  1792 	public function flush_rules( $hard = true ) {
  1790 		static $do_hard_later = null;
  1793 		static $do_hard_later = null;
  1791 
  1794 
  1832 	 * '%tag%', or '%author%'.
  1835 	 * '%tag%', or '%author%'.
  1833 	 *
  1836 	 *
  1834 	 * @since 1.5.0
  1837 	 * @since 1.5.0
  1835 	 */
  1838 	 */
  1836 	public function init() {
  1839 	public function init() {
  1837 		$this->extra_rules         = $this->non_wp_rules = $this->endpoints = array();
  1840 		$this->extra_rules         = array();
       
  1841 		$this->non_wp_rules        = array();
       
  1842 		$this->endpoints           = array();
  1838 		$this->permalink_structure = get_option( 'permalink_structure' );
  1843 		$this->permalink_structure = get_option( 'permalink_structure' );
  1839 		$this->front               = substr( $this->permalink_structure, 0, strpos( $this->permalink_structure, '%' ) );
  1844 		$this->front               = substr( $this->permalink_structure, 0, strpos( $this->permalink_structure, '%' ) );
  1840 		$this->root                = '';
  1845 		$this->root                = '';
  1841 
  1846 
  1842 		if ( $this->using_index_permalinks() ) {
  1847 		if ( $this->using_index_permalinks() ) {
  1847 		unset( $this->date_structure );
  1852 		unset( $this->date_structure );
  1848 		unset( $this->page_structure );
  1853 		unset( $this->page_structure );
  1849 		unset( $this->search_structure );
  1854 		unset( $this->search_structure );
  1850 		unset( $this->feed_structure );
  1855 		unset( $this->feed_structure );
  1851 		unset( $this->comment_feed_structure );
  1856 		unset( $this->comment_feed_structure );
  1852 		$this->use_trailing_slashes = ( '/' == substr( $this->permalink_structure, -1, 1 ) );
  1857 
       
  1858 		$this->use_trailing_slashes = ( '/' === substr( $this->permalink_structure, -1, 1 ) );
  1853 
  1859 
  1854 		// Enable generic rules for pages if permalink structure doesn't begin with a wildcard.
  1860 		// Enable generic rules for pages if permalink structure doesn't begin with a wildcard.
  1855 		if ( preg_match( '/^[^%]*%(?:postname|category|tag|author)%/', $this->permalink_structure ) ) {
  1861 		if ( preg_match( '/^[^%]*%(?:postname|category|tag|author)%/', $this->permalink_structure ) ) {
  1856 			$this->use_verbose_page_rules = true;
  1862 			$this->use_verbose_page_rules = true;
  1857 		} else {
  1863 		} else {
  1902 	 * @since 1.5.0
  1908 	 * @since 1.5.0
  1903 	 *
  1909 	 *
  1904 	 * @param string $category_base Category permalink structure base.
  1910 	 * @param string $category_base Category permalink structure base.
  1905 	 */
  1911 	 */
  1906 	public function set_category_base( $category_base ) {
  1912 	public function set_category_base( $category_base ) {
  1907 		if ( $category_base != get_option( 'category_base' ) ) {
  1913 		if ( get_option( 'category_base' ) !== $category_base ) {
  1908 			update_option( 'category_base', $category_base );
  1914 			update_option( 'category_base', $category_base );
  1909 			$this->init();
  1915 			$this->init();
  1910 		}
  1916 		}
  1911 	}
  1917 	}
  1912 
  1918 
  1920 	 * @since 2.3.0
  1926 	 * @since 2.3.0
  1921 	 *
  1927 	 *
  1922 	 * @param string $tag_base Tag permalink structure base.
  1928 	 * @param string $tag_base Tag permalink structure base.
  1923 	 */
  1929 	 */
  1924 	public function set_tag_base( $tag_base ) {
  1930 	public function set_tag_base( $tag_base ) {
  1925 		if ( $tag_base != get_option( 'tag_base' ) ) {
  1931 		if ( get_option( 'tag_base' ) !== $tag_base ) {
  1926 			update_option( 'tag_base', $tag_base );
  1932 			update_option( 'tag_base', $tag_base );
  1927 			$this->init();
  1933 			$this->init();
  1928 		}
  1934 		}
  1929 	}
  1935 	}
  1930 
  1936