wp/wp-includes/class-wp-rewrite.php
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
   286 		'%second%',
   286 		'%second%',
   287 		'%postname%',
   287 		'%postname%',
   288 		'%post_id%',
   288 		'%post_id%',
   289 		'%author%',
   289 		'%author%',
   290 		'%pagename%',
   290 		'%pagename%',
   291 		'%search%'
   291 		'%search%',
   292 	);
   292 	);
   293 
   293 
   294 	/**
   294 	/**
   295 	 * Regular expressions to be substituted into rewrite rules in place
   295 	 * Regular expressions to be substituted into rewrite rules in place
   296 	 * of rewrite tags, see WP_Rewrite::$rewritecode.
   296 	 * of rewrite tags, see WP_Rewrite::$rewritecode.
   307 		'([0-9]{1,2})',
   307 		'([0-9]{1,2})',
   308 		'([^/]+)',
   308 		'([^/]+)',
   309 		'([0-9]+)',
   309 		'([0-9]+)',
   310 		'([^/]+)',
   310 		'([^/]+)',
   311 		'([^/]+?)',
   311 		'([^/]+?)',
   312 		'(.+)'
   312 		'(.+)',
   313 	);
   313 	);
   314 
   314 
   315 	/**
   315 	/**
   316 	 * Query variables that rewrite tags map to, see WP_Rewrite::$rewritecode.
   316 	 * Query variables that rewrite tags map to, see WP_Rewrite::$rewritecode.
   317 	 *
   317 	 *
   327 		'second=',
   327 		'second=',
   328 		'name=',
   328 		'name=',
   329 		'p=',
   329 		'p=',
   330 		'author_name=',
   330 		'author_name=',
   331 		'pagename=',
   331 		'pagename=',
   332 		's='
   332 		's=',
   333 	);
   333 	);
   334 
   334 
   335 	/**
   335 	/**
   336 	 * Supported default feeds.
   336 	 * Supported default feeds.
   337 	 *
   337 	 *
   348 	 * @since 1.5.0
   348 	 * @since 1.5.0
   349 	 *
   349 	 *
   350 	 * @return bool True, if permalinks are enabled.
   350 	 * @return bool True, if permalinks are enabled.
   351 	 */
   351 	 */
   352 	public function using_permalinks() {
   352 	public function using_permalinks() {
   353 		return ! empty($this->permalink_structure);
   353 		return ! empty( $this->permalink_structure );
   354 	}
   354 	}
   355 
   355 
   356 	/**
   356 	/**
   357 	 * Determines whether permalinks are being used and rewrite module is not enabled.
   357 	 * Determines whether permalinks are being used and rewrite module is not enabled.
   358 	 *
   358 	 *
   397 	 * @since 1.5.0
   397 	 * @since 1.5.0
   398 	 *
   398 	 *
   399 	 * @param int $number Index number.
   399 	 * @param int $number Index number.
   400 	 * @return string
   400 	 * @return string
   401 	 */
   401 	 */
   402 	public function preg_index($number) {
   402 	public function preg_index( $number ) {
   403 		$match_prefix = '$';
   403 		$match_prefix = '$';
   404 		$match_suffix = '';
   404 		$match_suffix = '';
   405 
   405 
   406 		if ( ! empty($this->matches) ) {
   406 		if ( ! empty( $this->matches ) ) {
   407 			$match_prefix = '$' . $this->matches . '[';
   407 			$match_prefix = '$' . $this->matches . '[';
   408 			$match_suffix = ']';
   408 			$match_suffix = ']';
   409 		}
   409 		}
   410 
   410 
   411 		return "$match_prefix$number$match_suffix";
   411 		return "$match_prefix$number$match_suffix";
   425 	 */
   425 	 */
   426 	public function page_uri_index() {
   426 	public function page_uri_index() {
   427 		global $wpdb;
   427 		global $wpdb;
   428 
   428 
   429 		// Get pages in order of hierarchy, i.e. children after parents.
   429 		// Get pages in order of hierarchy, i.e. children after parents.
   430 		$pages = $wpdb->get_results("SELECT ID, post_name, post_parent FROM $wpdb->posts WHERE post_type = 'page' AND post_status != 'auto-draft'");
   430 		$pages = $wpdb->get_results( "SELECT ID, post_name, post_parent FROM $wpdb->posts WHERE post_type = 'page' AND post_status != 'auto-draft'" );
   431 		$posts = get_page_hierarchy( $pages );
   431 		$posts = get_page_hierarchy( $pages );
   432 
   432 
   433 		// If we have no pages get out quick.
   433 		// If we have no pages get out quick.
   434 		if ( !$posts )
   434 		if ( ! $posts ) {
   435 			return array( array(), array() );
   435 			return array( array(), array() );
       
   436 		}
   436 
   437 
   437 		// Now reverse it, because we need parents after children for rewrite rules to work properly.
   438 		// Now reverse it, because we need parents after children for rewrite rules to work properly.
   438 		$posts = array_reverse($posts, true);
   439 		$posts = array_reverse( $posts, true );
   439 
   440 
   440 		$page_uris = array();
   441 		$page_uris            = array();
   441 		$page_attachment_uris = array();
   442 		$page_attachment_uris = array();
   442 
   443 
   443 		foreach ( $posts as $id => $post ) {
   444 		foreach ( $posts as $id => $post ) {
   444 			// URL => page name
   445 			// URL => page name
   445 			$uri = get_page_uri($id);
   446 			$uri         = get_page_uri( $id );
   446 			$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 ) );
   447 			if ( !empty($attachments) ) {
   448 			if ( ! empty( $attachments ) ) {
   448 				foreach ( $attachments as $attachment ) {
   449 				foreach ( $attachments as $attachment ) {
   449 					$attach_uri = get_page_uri($attachment->ID);
   450 					$attach_uri                          = get_page_uri( $attachment->ID );
   450 					$page_attachment_uris[$attach_uri] = $attachment->ID;
   451 					$page_attachment_uris[ $attach_uri ] = $attachment->ID;
   451 				}
   452 				}
   452 			}
   453 			}
   453 
   454 
   454 			$page_uris[$uri] = $id;
   455 			$page_uris[ $uri ] = $id;
   455 		}
   456 		}
   456 
   457 
   457 		return array( $page_uris, $page_attachment_uris );
   458 		return array( $page_uris, $page_attachment_uris );
   458 	}
   459 	}
   459 
   460 
   489 	 * @since 1.5.0
   490 	 * @since 1.5.0
   490 	 *
   491 	 *
   491 	 * @return string|false False on no permalink structure. Date permalink structure.
   492 	 * @return string|false False on no permalink structure. Date permalink structure.
   492 	 */
   493 	 */
   493 	public function get_date_permastruct() {
   494 	public function get_date_permastruct() {
   494 		if ( isset($this->date_structure) )
   495 		if ( isset( $this->date_structure ) ) {
   495 			return $this->date_structure;
   496 			return $this->date_structure;
   496 
   497 		}
   497 		if ( empty($this->permalink_structure) ) {
   498 
       
   499 		if ( empty( $this->permalink_structure ) ) {
   498 			$this->date_structure = '';
   500 			$this->date_structure = '';
   499 			return false;
   501 			return false;
   500 		}
   502 		}
   501 
   503 
   502 		// The date permalink must have year, month, and day separated by slashes.
   504 		// The date permalink must have year, month, and day separated by slashes.
   503 		$endians = array('%year%/%monthnum%/%day%', '%day%/%monthnum%/%year%', '%monthnum%/%day%/%year%');
   505 		$endians = array( '%year%/%monthnum%/%day%', '%day%/%monthnum%/%year%', '%monthnum%/%day%/%year%' );
   504 
   506 
   505 		$this->date_structure = '';
   507 		$this->date_structure = '';
   506 		$date_endian = '';
   508 		$date_endian          = '';
   507 
   509 
   508 		foreach ( $endians as $endian ) {
   510 		foreach ( $endians as $endian ) {
   509 			if ( false !== strpos($this->permalink_structure, $endian) ) {
   511 			if ( false !== strpos( $this->permalink_structure, $endian ) ) {
   510 				$date_endian= $endian;
   512 				$date_endian = $endian;
   511 				break;
   513 				break;
   512 			}
   514 			}
   513 		}
   515 		}
   514 
   516 
   515 		if ( empty($date_endian) )
   517 		if ( empty( $date_endian ) ) {
   516 			$date_endian = '%year%/%monthnum%/%day%';
   518 			$date_endian = '%year%/%monthnum%/%day%';
       
   519 		}
   517 
   520 
   518 		/*
   521 		/*
   519 		 * Do not allow the date tags and %post_id% to overlap in the permalink
   522 		 * Do not allow the date tags and %post_id% to overlap in the permalink
   520 		 * structure. If they do, move the date tags to $front/date/.
   523 		 * structure. If they do, move the date tags to $front/date/.
   521 		 */
   524 		 */
   522 		$front = $this->front;
   525 		$front = $this->front;
   523 		preg_match_all('/%.+?%/', $this->permalink_structure, $tokens);
   526 		preg_match_all( '/%.+?%/', $this->permalink_structure, $tokens );
   524 		$tok_index = 1;
   527 		$tok_index = 1;
   525 		foreach ( (array) $tokens[0] as $token) {
   528 		foreach ( (array) $tokens[0] as $token ) {
   526 			if ( '%post_id%' == $token && ($tok_index <= 3) ) {
   529 			if ( '%post_id%' == $token && ( $tok_index <= 3 ) ) {
   527 				$front = $front . 'date/';
   530 				$front = $front . 'date/';
   528 				break;
   531 				break;
   529 			}
   532 			}
   530 			$tok_index++;
   533 			$tok_index++;
   531 		}
   534 		}
   546 	 * @return false|string False on failure. Year structure on success.
   549 	 * @return false|string False on failure. Year structure on success.
   547 	 */
   550 	 */
   548 	public function get_year_permastruct() {
   551 	public function get_year_permastruct() {
   549 		$structure = $this->get_date_permastruct();
   552 		$structure = $this->get_date_permastruct();
   550 
   553 
   551 		if ( empty($structure) )
   554 		if ( empty( $structure ) ) {
   552 			return false;
   555 			return false;
   553 
   556 		}
   554 		$structure = str_replace('%monthnum%', '', $structure);
   557 
   555 		$structure = str_replace('%day%', '', $structure);
   558 		$structure = str_replace( '%monthnum%', '', $structure );
   556 		$structure = preg_replace('#/+#', '/', $structure);
   559 		$structure = str_replace( '%day%', '', $structure );
       
   560 		$structure = preg_replace( '#/+#', '/', $structure );
   557 
   561 
   558 		return $structure;
   562 		return $structure;
   559 	}
   563 	}
   560 
   564 
   561 	/**
   565 	/**
   569 	 * @return false|string False on failure. Year/Month structure on success.
   573 	 * @return false|string False on failure. Year/Month structure on success.
   570 	 */
   574 	 */
   571 	public function get_month_permastruct() {
   575 	public function get_month_permastruct() {
   572 		$structure = $this->get_date_permastruct();
   576 		$structure = $this->get_date_permastruct();
   573 
   577 
   574 		if ( empty($structure) )
   578 		if ( empty( $structure ) ) {
   575 			return false;
   579 			return false;
   576 
   580 		}
   577 		$structure = str_replace('%day%', '', $structure);
   581 
   578 		$structure = preg_replace('#/+#', '/', $structure);
   582 		$structure = str_replace( '%day%', '', $structure );
       
   583 		$structure = preg_replace( '#/+#', '/', $structure );
   579 
   584 
   580 		return $structure;
   585 		return $structure;
   581 	}
   586 	}
   582 
   587 
   583 	/**
   588 	/**
   604 	 * @since 1.5.0
   609 	 * @since 1.5.0
   605 	 *
   610 	 *
   606 	 * @return string|false False on failure. Category permalink structure.
   611 	 * @return string|false False on failure. Category permalink structure.
   607 	 */
   612 	 */
   608 	public function get_category_permastruct() {
   613 	public function get_category_permastruct() {
   609 		return $this->get_extra_permastruct('category');
   614 		return $this->get_extra_permastruct( 'category' );
   610 	}
   615 	}
   611 
   616 
   612 	/**
   617 	/**
   613 	 * Retrieve the permalink structure for tags.
   618 	 * Retrieve the permalink structure for tags.
   614 	 *
   619 	 *
   620 	 * @since 2.3.0
   625 	 * @since 2.3.0
   621 	 *
   626 	 *
   622 	 * @return string|false False on failure. Tag permalink structure.
   627 	 * @return string|false False on failure. Tag permalink structure.
   623 	 */
   628 	 */
   624 	public function get_tag_permastruct() {
   629 	public function get_tag_permastruct() {
   625 		return $this->get_extra_permastruct('post_tag');
   630 		return $this->get_extra_permastruct( 'post_tag' );
   626 	}
   631 	}
   627 
   632 
   628 	/**
   633 	/**
   629 	 * Retrieves an extra permalink structure by name.
   634 	 * Retrieves an extra permalink structure by name.
   630 	 *
   635 	 *
   631 	 * @since 2.5.0
   636 	 * @since 2.5.0
   632 	 *
   637 	 *
   633 	 * @param string $name Permalink structure name.
   638 	 * @param string $name Permalink structure name.
   634 	 * @return string|false False if not found. Permalink structure string.
   639 	 * @return string|false False if not found. Permalink structure string.
   635 	 */
   640 	 */
   636 	public function get_extra_permastruct($name) {
   641 	public function get_extra_permastruct( $name ) {
   637 		if ( empty($this->permalink_structure) )
   642 		if ( empty( $this->permalink_structure ) ) {
   638 			return false;
   643 			return false;
   639 
   644 		}
   640 		if ( isset($this->extra_permastructs[$name]) )
   645 
   641 			return $this->extra_permastructs[$name]['struct'];
   646 		if ( isset( $this->extra_permastructs[ $name ] ) ) {
       
   647 			return $this->extra_permastructs[ $name ]['struct'];
       
   648 		}
   642 
   649 
   643 		return false;
   650 		return false;
   644 	}
   651 	}
   645 
   652 
   646 	/**
   653 	/**
   653 	 * @since 1.5.0
   660 	 * @since 1.5.0
   654 	 *
   661 	 *
   655 	 * @return string|false False if not found. Permalink structure string.
   662 	 * @return string|false False if not found. Permalink structure string.
   656 	 */
   663 	 */
   657 	public function get_author_permastruct() {
   664 	public function get_author_permastruct() {
   658 		if ( isset($this->author_structure) )
   665 		if ( isset( $this->author_structure ) ) {
   659 			return $this->author_structure;
   666 			return $this->author_structure;
   660 
   667 		}
   661 		if ( empty($this->permalink_structure) ) {
   668 
       
   669 		if ( empty( $this->permalink_structure ) ) {
   662 			$this->author_structure = '';
   670 			$this->author_structure = '';
   663 			return false;
   671 			return false;
   664 		}
   672 		}
   665 
   673 
   666 		$this->author_structure = $this->front . $this->author_base . '/%author%';
   674 		$this->author_structure = $this->front . $this->author_base . '/%author%';
   678 	 * @since 1.5.0
   686 	 * @since 1.5.0
   679 	 *
   687 	 *
   680 	 * @return string|false False if not found. Permalink structure string.
   688 	 * @return string|false False if not found. Permalink structure string.
   681 	 */
   689 	 */
   682 	public function get_search_permastruct() {
   690 	public function get_search_permastruct() {
   683 		if ( isset($this->search_structure) )
   691 		if ( isset( $this->search_structure ) ) {
   684 			return $this->search_structure;
   692 			return $this->search_structure;
   685 
   693 		}
   686 		if ( empty($this->permalink_structure) ) {
   694 
       
   695 		if ( empty( $this->permalink_structure ) ) {
   687 			$this->search_structure = '';
   696 			$this->search_structure = '';
   688 			return false;
   697 			return false;
   689 		}
   698 		}
   690 
   699 
   691 		$this->search_structure = $this->root . $this->search_base . '/%search%';
   700 		$this->search_structure = $this->root . $this->search_base . '/%search%';
   703 	 * @since 1.5.0
   712 	 * @since 1.5.0
   704 	 *
   713 	 *
   705 	 * @return string|false False if not found. Permalink structure string.
   714 	 * @return string|false False if not found. Permalink structure string.
   706 	 */
   715 	 */
   707 	public function get_page_permastruct() {
   716 	public function get_page_permastruct() {
   708 		if ( isset($this->page_structure) )
   717 		if ( isset( $this->page_structure ) ) {
   709 			return $this->page_structure;
   718 			return $this->page_structure;
   710 
   719 		}
   711 		if (empty($this->permalink_structure)) {
   720 
       
   721 		if ( empty( $this->permalink_structure ) ) {
   712 			$this->page_structure = '';
   722 			$this->page_structure = '';
   713 			return false;
   723 			return false;
   714 		}
   724 		}
   715 
   725 
   716 		$this->page_structure = $this->root . '%pagename%';
   726 		$this->page_structure = $this->root . '%pagename%';
   728 	 * @since 1.5.0
   738 	 * @since 1.5.0
   729 	 *
   739 	 *
   730 	 * @return string|false False if not found. Permalink structure string.
   740 	 * @return string|false False if not found. Permalink structure string.
   731 	 */
   741 	 */
   732 	public function get_feed_permastruct() {
   742 	public function get_feed_permastruct() {
   733 		if ( isset($this->feed_structure) )
   743 		if ( isset( $this->feed_structure ) ) {
   734 			return $this->feed_structure;
   744 			return $this->feed_structure;
   735 
   745 		}
   736 		if ( empty($this->permalink_structure) ) {
   746 
       
   747 		if ( empty( $this->permalink_structure ) ) {
   737 			$this->feed_structure = '';
   748 			$this->feed_structure = '';
   738 			return false;
   749 			return false;
   739 		}
   750 		}
   740 
   751 
   741 		$this->feed_structure = $this->root . $this->feed_base . '/%feed%';
   752 		$this->feed_structure = $this->root . $this->feed_base . '/%feed%';
   753 	 * @since 1.5.0
   764 	 * @since 1.5.0
   754 	 *
   765 	 *
   755 	 * @return string|false False if not found. Permalink structure string.
   766 	 * @return string|false False if not found. Permalink structure string.
   756 	 */
   767 	 */
   757 	public function get_comment_feed_permastruct() {
   768 	public function get_comment_feed_permastruct() {
   758 		if ( isset($this->comment_feed_structure) )
   769 		if ( isset( $this->comment_feed_structure ) ) {
   759 			return $this->comment_feed_structure;
   770 			return $this->comment_feed_structure;
   760 
   771 		}
   761 		if (empty($this->permalink_structure)) {
   772 
       
   773 		if ( empty( $this->permalink_structure ) ) {
   762 			$this->comment_feed_structure = '';
   774 			$this->comment_feed_structure = '';
   763 			return false;
   775 			return false;
   764 		}
   776 		}
   765 
   777 
   766 		$this->comment_feed_structure = $this->root . $this->comments_base . '/' . $this->feed_base . '/%feed%';
   778 		$this->comment_feed_structure = $this->root . $this->comments_base . '/' . $this->feed_base . '/%feed%';
   786 	 */
   798 	 */
   787 	public function add_rewrite_tag( $tag, $regex, $query ) {
   799 	public function add_rewrite_tag( $tag, $regex, $query ) {
   788 		$position = array_search( $tag, $this->rewritecode );
   800 		$position = array_search( $tag, $this->rewritecode );
   789 		if ( false !== $position && null !== $position ) {
   801 		if ( false !== $position && null !== $position ) {
   790 			$this->rewritereplace[ $position ] = $regex;
   802 			$this->rewritereplace[ $position ] = $regex;
   791 			$this->queryreplace[ $position ] = $query;
   803 			$this->queryreplace[ $position ]   = $query;
   792 		} else {
   804 		} else {
   793 			$this->rewritecode[] = $tag;
   805 			$this->rewritecode[]    = $tag;
   794 			$this->rewritereplace[] = $regex;
   806 			$this->rewritereplace[] = $regex;
   795 			$this->queryreplace[] = $query;
   807 			$this->queryreplace[]   = $query;
   796 		}
   808 		}
   797 	}
   809 	}
   798 
   810 
   799 
   811 
   800 	/**
   812 	/**
   842 	 *                                    over and rewrite rules built for each in-turn. Default true.
   854 	 *                                    over and rewrite rules built for each in-turn. Default true.
   843 	 * @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.
   844 	 *                                    Default true.
   856 	 *                                    Default true.
   845 	 * @return array Rewrite rule list.
   857 	 * @return array Rewrite rule list.
   846 	 */
   858 	 */
   847 	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 ) {
   848 		// 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)/?
   849 		$feedregex2 = '';
   861 		$feedregex2 = '';
   850 		foreach ( (array) $this->feeds as $feed_name)
   862 		foreach ( (array) $this->feeds as $feed_name ) {
   851 			$feedregex2 .= $feed_name . '|';
   863 			$feedregex2 .= $feed_name . '|';
   852 		$feedregex2 = '(' . trim($feedregex2, '|') . ')/?$';
   864 		}
       
   865 		$feedregex2 = '(' . trim( $feedregex2, '|' ) . ')/?$';
   853 
   866 
   854 		/*
   867 		/*
   855 		 * $feedregex is identical but with /feed/ added on as well, so URLs like <permalink>/feed/atom
   868 		 * $feedregex is identical but with /feed/ added on as well, so URLs like <permalink>/feed/atom
   856 		 * and <permalink>/atom are both possible
   869 		 * and <permalink>/atom are both possible
   857 		 */
   870 		 */
   858 		$feedregex = $this->feed_base . '/' . $feedregex2;
   871 		$feedregex = $this->feed_base . '/' . $feedregex2;
   859 
   872 
   860 		// Build a regex to match the trackback and page/xx parts of URLs.
   873 		// Build a regex to match the trackback and page/xx parts of URLs.
   861 		$trackbackregex = 'trackback/?$';
   874 		$trackbackregex = 'trackback/?$';
   862 		$pageregex = $this->pagination_base . '/?([0-9]{1,})/?$';
   875 		$pageregex      = $this->pagination_base . '/?([0-9]{1,})/?$';
   863 		$commentregex = $this->comments_pagination_base . '-([0-9]{1,})/?$';
   876 		$commentregex   = $this->comments_pagination_base . '-([0-9]{1,})/?$';
   864 		$embedregex = 'embed/?$';
   877 		$embedregex     = 'embed/?$';
   865 
   878 
   866 		// Build up an array of endpoint regexes to append => queries to append.
   879 		// Build up an array of endpoint regexes to append => queries to append.
   867 		if ( $endpoints ) {
   880 		if ( $endpoints ) {
   868 			$ep_query_append = array ();
   881 			$ep_query_append = array();
   869 			foreach ( (array) $this->endpoints as $endpoint) {
   882 			foreach ( (array) $this->endpoints as $endpoint ) {
   870 				// Match everything after the endpoint name, but allow for nothing to appear there.
   883 				// Match everything after the endpoint name, but allow for nothing to appear there.
   871 				$epmatch = $endpoint[1] . '(/(.*))?/?$';
   884 				$epmatch = $endpoint[1] . '(/(.*))?/?$';
   872 
   885 
   873 				// This will be appended on to the rest of the query for each dir.
   886 				// This will be appended on to the rest of the query for each dir.
   874 				$epquery = '&' . $endpoint[2] . '=';
   887 				$epquery                     = '&' . $endpoint[2] . '=';
   875 				$ep_query_append[$epmatch] = array ( $endpoint[0], $epquery );
   888 				$ep_query_append[ $epmatch ] = array( $endpoint[0], $epquery );
   876 			}
   889 			}
   877 		}
   890 		}
   878 
   891 
   879 		// Get everything up to the first rewrite tag.
   892 		// Get everything up to the first rewrite tag.
   880 		$front = substr($permalink_structure, 0, strpos($permalink_structure, '%'));
   893 		$front = substr( $permalink_structure, 0, strpos( $permalink_structure, '%' ) );
   881 
   894 
   882 		// 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]).
   883 		preg_match_all('/%.+?%/', $permalink_structure, $tokens);
   896 		preg_match_all( '/%.+?%/', $permalink_structure, $tokens );
   884 
   897 
   885 		$num_tokens = count($tokens[0]);
   898 		$num_tokens = count( $tokens[0] );
   886 
   899 
   887 		$index = $this->index; //probably 'index.php'
   900 		$index          = $this->index; //probably 'index.php'
   888 		$feedindex = $index;
   901 		$feedindex      = $index;
   889 		$trackbackindex = $index;
   902 		$trackbackindex = $index;
   890 		$embedindex = $index;
   903 		$embedindex     = $index;
   891 
   904 
   892 		/*
   905 		/*
   893 		 * Build a list from the rewritecode and queryreplace arrays, that will look something
   906 		 * Build a list from the rewritecode and queryreplace arrays, that will look something
   894 		 * like tagname=$matches[i] where i is the current $i.
   907 		 * like tagname=$matches[i] where i is the current $i.
   895 		 */
   908 		 */
   896 		$queries = array();
   909 		$queries = array();
   897 		for ( $i = 0; $i < $num_tokens; ++$i ) {
   910 		for ( $i = 0; $i < $num_tokens; ++$i ) {
   898 			if ( 0 < $i )
   911 			if ( 0 < $i ) {
   899 				$queries[$i] = $queries[$i - 1] . '&';
   912 				$queries[ $i ] = $queries[ $i - 1 ] . '&';
   900 			else
   913 			} else {
   901 				$queries[$i] = '';
   914 				$queries[ $i ] = '';
   902 
   915 			}
   903 			$query_token = str_replace($this->rewritecode, $this->queryreplace, $tokens[0][$i]) . $this->preg_index($i+1);
   916 
   904 			$queries[$i] .= $query_token;
   917 			$query_token    = str_replace( $this->rewritecode, $this->queryreplace, $tokens[0][ $i ] ) . $this->preg_index( $i + 1 );
       
   918 			$queries[ $i ] .= $query_token;
   905 		}
   919 		}
   906 
   920 
   907 		// 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.
   908 		$structure = $permalink_structure;
   922 		$structure = $permalink_structure;
   909 		if ( $front != '/' )
   923 		if ( $front != '/' ) {
   910 			$structure = str_replace($front, '', $structure);
   924 			$structure = str_replace( $front, '', $structure );
       
   925 		}
   911 
   926 
   912 		/*
   927 		/*
   913 		 * 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
   914 		 * so for example, a $structure of /%year%/%monthnum%/%postname% would create
   929 		 * so for example, a $structure of /%year%/%monthnum%/%postname% would create
   915 		 * rewrite rules for /%year%/, /%year%/%monthnum%/ and /%year%/%monthnum%/%postname%
   930 		 * rewrite rules for /%year%/, /%year%/%monthnum%/ and /%year%/%monthnum%/%postname%
   916 		 */
   931 		 */
   917 		$structure = trim($structure, '/');
   932 		$structure = trim( $structure, '/' );
   918 		$dirs = $walk_dirs ? explode('/', $structure) : array( $structure );
   933 		$dirs      = $walk_dirs ? explode( '/', $structure ) : array( $structure );
   919 		$num_dirs = count($dirs);
   934 		$num_dirs  = count( $dirs );
   920 
   935 
   921 		// Strip slashes from the front of $front.
   936 		// Strip slashes from the front of $front.
   922 		$front = preg_replace('|^/+|', '', $front);
   937 		$front = preg_replace( '|^/+|', '', $front );
   923 
   938 
   924 		// The main workhorse loop.
   939 		// The main workhorse loop.
   925 		$post_rewrite = array();
   940 		$post_rewrite = array();
   926 		$struct = $front;
   941 		$struct       = $front;
   927 		for ( $j = 0; $j < $num_dirs; ++$j ) {
   942 		for ( $j = 0; $j < $num_dirs; ++$j ) {
   928 			// Get the struct for this dir, and trim slashes off the front.
   943 			// Get the struct for this dir, and trim slashes off the front.
   929 			$struct .= $dirs[$j] . '/'; // Accumulate. see comment near explode('/', $structure) above.
   944 			$struct .= $dirs[ $j ] . '/'; // Accumulate. see comment near explode('/', $structure) above.
   930 			$struct = ltrim($struct, '/');
   945 			$struct  = ltrim( $struct, '/' );
   931 
   946 
   932 			// Replace tags with regexes.
   947 			// Replace tags with regexes.
   933 			$match = str_replace($this->rewritecode, $this->rewritereplace, $struct);
   948 			$match = str_replace( $this->rewritecode, $this->rewritereplace, $struct );
   934 
   949 
   935 			// Make a list of tags, and store how many there are in $num_toks.
   950 			// Make a list of tags, and store how many there are in $num_toks.
   936 			$num_toks = preg_match_all('/%.+?%/', $struct, $toks);
   951 			$num_toks = preg_match_all( '/%.+?%/', $struct, $toks );
   937 
   952 
   938 			// Get the 'tagname=$matches[i]'.
   953 			// Get the 'tagname=$matches[i]'.
   939 			$query = ( ! empty( $num_toks ) && isset( $queries[$num_toks - 1] ) ) ? $queries[$num_toks - 1] : '';
   954 			$query = ( ! empty( $num_toks ) && isset( $queries[ $num_toks - 1 ] ) ) ? $queries[ $num_toks - 1 ] : '';
   940 
   955 
   941 			// Set up $ep_mask_specific which is used to match more specific URL types.
   956 			// Set up $ep_mask_specific which is used to match more specific URL types.
   942 			switch ( $dirs[$j] ) {
   957 			switch ( $dirs[ $j ] ) {
   943 				case '%year%':
   958 				case '%year%':
   944 					$ep_mask_specific = EP_YEAR;
   959 					$ep_mask_specific = EP_YEAR;
   945 					break;
   960 					break;
   946 				case '%monthnum%':
   961 				case '%monthnum%':
   947 					$ep_mask_specific = EP_MONTH;
   962 					$ep_mask_specific = EP_MONTH;
   953 					$ep_mask_specific = EP_NONE;
   968 					$ep_mask_specific = EP_NONE;
   954 			}
   969 			}
   955 
   970 
   956 			// Create query for /page/xx.
   971 			// Create query for /page/xx.
   957 			$pagematch = $match . $pageregex;
   972 			$pagematch = $match . $pageregex;
   958 			$pagequery = $index . '?' . $query . '&paged=' . $this->preg_index($num_toks + 1);
   973 			$pagequery = $index . '?' . $query . '&paged=' . $this->preg_index( $num_toks + 1 );
   959 
   974 
   960 			// Create query for /comment-page-xx.
   975 			// Create query for /comment-page-xx.
   961 			$commentmatch = $match . $commentregex;
   976 			$commentmatch = $match . $commentregex;
   962 			$commentquery = $index . '?' . $query . '&cpage=' . $this->preg_index($num_toks + 1);
   977 			$commentquery = $index . '?' . $query . '&cpage=' . $this->preg_index( $num_toks + 1 );
   963 
   978 
   964 			if ( get_option('page_on_front') ) {
   979 			if ( get_option( 'page_on_front' ) ) {
   965 				// Create query for Root /comment-page-xx.
   980 				// Create query for Root /comment-page-xx.
   966 				$rootcommentmatch = $match . $commentregex;
   981 				$rootcommentmatch = $match . $commentregex;
   967 				$rootcommentquery = $index . '?' . $query . '&page_id=' . get_option('page_on_front') . '&cpage=' . $this->preg_index($num_toks + 1);
   982 				$rootcommentquery = $index . '?' . $query . '&page_id=' . get_option( 'page_on_front' ) . '&cpage=' . $this->preg_index( $num_toks + 1 );
   968 			}
   983 			}
   969 
   984 
   970 			// Create query for /feed/(feed|atom|rss|rss2|rdf).
   985 			// Create query for /feed/(feed|atom|rss|rss2|rdf).
   971 			$feedmatch = $match . $feedregex;
   986 			$feedmatch = $match . $feedregex;
   972 			$feedquery = $feedindex . '?' . $query . '&feed=' . $this->preg_index($num_toks + 1);
   987 			$feedquery = $feedindex . '?' . $query . '&feed=' . $this->preg_index( $num_toks + 1 );
   973 
   988 
   974 			// Create query for /(feed|atom|rss|rss2|rdf) (see comment near creation of $feedregex).
   989 			// Create query for /(feed|atom|rss|rss2|rdf) (see comment near creation of $feedregex).
   975 			$feedmatch2 = $match . $feedregex2;
   990 			$feedmatch2 = $match . $feedregex2;
   976 			$feedquery2 = $feedindex . '?' . $query . '&feed=' . $this->preg_index($num_toks + 1);
   991 			$feedquery2 = $feedindex . '?' . $query . '&feed=' . $this->preg_index( $num_toks + 1 );
   977 
   992 
   978 			// Create query and regex for embeds.
   993 			// Create query and regex for embeds.
   979 			$embedmatch = $match . $embedregex;
   994 			$embedmatch = $match . $embedregex;
   980 			$embedquery = $embedindex . '?' . $query . '&embed=true';
   995 			$embedquery = $embedindex . '?' . $query . '&embed=true';
   981 
   996 
   982 			// If asked to, turn the feed queries into comment feed ones.
   997 			// If asked to, turn the feed queries into comment feed ones.
   983 			if ( $forcomments ) {
   998 			if ( $forcomments ) {
   984 				$feedquery .= '&withcomments=1';
   999 				$feedquery  .= '&withcomments=1';
   985 				$feedquery2 .= '&withcomments=1';
  1000 				$feedquery2 .= '&withcomments=1';
   986 			}
  1001 			}
   987 
  1002 
   988 			// Start creating the array of rewrites for this dir.
  1003 			// Start creating the array of rewrites for this dir.
   989 			$rewrite = array();
  1004 			$rewrite = array();
   990 
  1005 
   991 			// ...adding on /feed/ regexes => queries
  1006 			// ...adding on /feed/ regexes => queries
   992 			if ( $feed ) {
  1007 			if ( $feed ) {
   993 				$rewrite = array( $feedmatch => $feedquery, $feedmatch2 => $feedquery2, $embedmatch => $embedquery );
  1008 				$rewrite = array(
       
  1009 					$feedmatch  => $feedquery,
       
  1010 					$feedmatch2 => $feedquery2,
       
  1011 					$embedmatch => $embedquery,
       
  1012 				);
   994 			}
  1013 			}
   995 
  1014 
   996 			//...and /page/xx ones
  1015 			//...and /page/xx ones
   997 			if ( $paged ) {
  1016 			if ( $paged ) {
   998 				$rewrite = array_merge( $rewrite, array( $pagematch => $pagequery ) );
  1017 				$rewrite = array_merge( $rewrite, array( $pagematch => $pagequery ) );
   999 			}
  1018 			}
  1000 
  1019 
  1001 			// Only on pages with comments add ../comment-page-xx/.
  1020 			// Only on pages with comments add ../comment-page-xx/.
  1002 			if ( EP_PAGES & $ep_mask || EP_PERMALINK & $ep_mask ) {
  1021 			if ( EP_PAGES & $ep_mask || EP_PERMALINK & $ep_mask ) {
  1003 				$rewrite = array_merge($rewrite, array($commentmatch => $commentquery));
  1022 				$rewrite = array_merge( $rewrite, array( $commentmatch => $commentquery ) );
  1004 			} elseif ( EP_ROOT & $ep_mask && get_option('page_on_front') ) {
  1023 			} elseif ( EP_ROOT & $ep_mask && get_option( 'page_on_front' ) ) {
  1005 				$rewrite = array_merge($rewrite, array($rootcommentmatch => $rootcommentquery));
  1024 				$rewrite = array_merge( $rewrite, array( $rootcommentmatch => $rootcommentquery ) );
  1006 			}
  1025 			}
  1007 
  1026 
  1008 			// Do endpoints.
  1027 			// Do endpoints.
  1009 			if ( $endpoints ) {
  1028 			if ( $endpoints ) {
  1010 				foreach ( (array) $ep_query_append as $regex => $ep) {
  1029 				foreach ( (array) $ep_query_append as $regex => $ep ) {
  1011 					// Add the endpoints on if the mask fits.
  1030 					// Add the endpoints on if the mask fits.
  1012 					if ( $ep[0] & $ep_mask || $ep[0] & $ep_mask_specific )
  1031 					if ( $ep[0] & $ep_mask || $ep[0] & $ep_mask_specific ) {
  1013 						$rewrite[$match . $regex] = $index . '?' . $query . $ep[1] . $this->preg_index($num_toks + 2);
  1032 						$rewrite[ $match . $regex ] = $index . '?' . $query . $ep[1] . $this->preg_index( $num_toks + 2 );
       
  1033 					}
  1014 				}
  1034 				}
  1015 			}
  1035 			}
  1016 
  1036 
  1017 			// If we've got some tags in this dir.
  1037 			// If we've got some tags in this dir.
  1018 			if ( $num_toks ) {
  1038 			if ( $num_toks ) {
  1023 				 * Check to see if this dir is permalink-level: i.e. the structure specifies an
  1043 				 * Check to see if this dir is permalink-level: i.e. the structure specifies an
  1024 				 * individual post. Do this by checking it contains at least one of 1) post name,
  1044 				 * individual post. Do this by checking it contains at least one of 1) post name,
  1025 				 * 2) post ID, 3) page name, 4) timestamp (year, month, day, hour, second and
  1045 				 * 2) post ID, 3) page name, 4) timestamp (year, month, day, hour, second and
  1026 				 * minute all present). Set these flags now as we need them for the endpoints.
  1046 				 * minute all present). Set these flags now as we need them for the endpoints.
  1027 				 */
  1047 				 */
  1028 				if ( strpos($struct, '%postname%') !== false
  1048 				if ( strpos( $struct, '%postname%' ) !== false
  1029 						|| strpos($struct, '%post_id%') !== false
  1049 						|| strpos( $struct, '%post_id%' ) !== false
  1030 						|| strpos($struct, '%pagename%') !== false
  1050 						|| strpos( $struct, '%pagename%' ) !== false
  1031 						|| (strpos($struct, '%year%') !== false && strpos($struct, '%monthnum%') !== false && strpos($struct, '%day%') !== false && strpos($struct, '%hour%') !== false && strpos($struct, '%minute%') !== false && strpos($struct, '%second%') !== false)
  1051 						|| ( strpos( $struct, '%year%' ) !== false && strpos( $struct, '%monthnum%' ) !== false && strpos( $struct, '%day%' ) !== false && strpos( $struct, '%hour%' ) !== false && strpos( $struct, '%minute%' ) !== false && strpos( $struct, '%second%' ) !== false )
  1032 						) {
  1052 						) {
  1033 					$post = true;
  1053 					$post = true;
  1034 					if ( strpos($struct, '%pagename%') !== false )
  1054 					if ( strpos( $struct, '%pagename%' ) !== false ) {
  1035 						$page = true;
  1055 						$page = true;
       
  1056 					}
  1036 				}
  1057 				}
  1037 
  1058 
  1038 				if ( ! $post ) {
  1059 				if ( ! $post ) {
  1039 					// For custom post types, we need to add on endpoints as well.
  1060 					// For custom post types, we need to add on endpoints as well.
  1040 					foreach ( get_post_types( array('_builtin' => false ) ) as $ptype ) {
  1061 					foreach ( get_post_types( array( '_builtin' => false ) ) as $ptype ) {
  1041 						if ( strpos($struct, "%$ptype%") !== false ) {
  1062 						if ( strpos( $struct, "%$ptype%" ) !== false ) {
  1042 							$post = true;
  1063 							$post = true;
  1043 
  1064 
  1044 							// This is for page style attachment URLs.
  1065 							// This is for page style attachment URLs.
  1045 							$page = is_post_type_hierarchical( $ptype );
  1066 							$page = is_post_type_hierarchical( $ptype );
  1046 							break;
  1067 							break;
  1057 					// Create query and regex for embeds.
  1078 					// Create query and regex for embeds.
  1058 					$embedmatch = $match . $embedregex;
  1079 					$embedmatch = $match . $embedregex;
  1059 					$embedquery = $embedindex . '?' . $query . '&embed=true';
  1080 					$embedquery = $embedindex . '?' . $query . '&embed=true';
  1060 
  1081 
  1061 					// Trim slashes from the end of the regex for this dir.
  1082 					// Trim slashes from the end of the regex for this dir.
  1062 					$match = rtrim($match, '/');
  1083 					$match = rtrim( $match, '/' );
  1063 
  1084 
  1064 					// Get rid of brackets.
  1085 					// Get rid of brackets.
  1065 					$submatchbase = str_replace( array('(', ')'), '', $match);
  1086 					$submatchbase = str_replace( array( '(', ')' ), '', $match );
  1066 
  1087 
  1067 					// Add a rule for at attachments, which take the form of <permalink>/some-text.
  1088 					// Add a rule for at attachments, which take the form of <permalink>/some-text.
  1068 					$sub1 = $submatchbase . '/([^/]+)/';
  1089 					$sub1 = $submatchbase . '/([^/]+)/';
  1069 
  1090 
  1070 					// Add trackback regex <permalink>/trackback/...
  1091 					// Add trackback regex <permalink>/trackback/...
  1102 
  1123 
  1103 					// And <permalink>/embed/...
  1124 					// And <permalink>/embed/...
  1104 					$sub2embed = $sub2 . $embedregex;
  1125 					$sub2embed = $sub2 . $embedregex;
  1105 
  1126 
  1106 					// Create queries for these extra tag-ons we've just dealt with.
  1127 					// Create queries for these extra tag-ons we've just dealt with.
  1107 					$subquery = $index . '?attachment=' . $this->preg_index(1);
  1128 					$subquery        = $index . '?attachment=' . $this->preg_index( 1 );
  1108 					$subtbquery = $subquery . '&tb=1';
  1129 					$subtbquery      = $subquery . '&tb=1';
  1109 					$subfeedquery = $subquery . '&feed=' . $this->preg_index(2);
  1130 					$subfeedquery    = $subquery . '&feed=' . $this->preg_index( 2 );
  1110 					$subcommentquery = $subquery . '&cpage=' . $this->preg_index(2);
  1131 					$subcommentquery = $subquery . '&cpage=' . $this->preg_index( 2 );
  1111 					$subembedquery = $subquery . '&embed=true';
  1132 					$subembedquery   = $subquery . '&embed=true';
  1112 
  1133 
  1113 					// Do endpoints for attachments.
  1134 					// Do endpoints for attachments.
  1114 					if ( !empty($endpoints) ) {
  1135 					if ( ! empty( $endpoints ) ) {
  1115 						foreach ( (array) $ep_query_append as $regex => $ep ) {
  1136 						foreach ( (array) $ep_query_append as $regex => $ep ) {
  1116 							if ( $ep[0] & EP_ATTACHMENT ) {
  1137 							if ( $ep[0] & EP_ATTACHMENT ) {
  1117 								$rewrite[$sub1 . $regex] = $subquery . $ep[1] . $this->preg_index(3);
  1138 								$rewrite[ $sub1 . $regex ] = $subquery . $ep[1] . $this->preg_index( 3 );
  1118 								$rewrite[$sub2 . $regex] = $subquery . $ep[1] . $this->preg_index(3);
  1139 								$rewrite[ $sub2 . $regex ] = $subquery . $ep[1] . $this->preg_index( 3 );
  1119 							}
  1140 							}
  1120 						}
  1141 						}
  1121 					}
  1142 					}
  1122 
  1143 
  1123 					/*
  1144 					/*
  1132 					 * Post pagination, e.g. <permalink>/2/
  1153 					 * Post pagination, e.g. <permalink>/2/
  1133 					 * Previously: '(/[0-9]+)?/?$', which produced '/2' for page.
  1154 					 * Previously: '(/[0-9]+)?/?$', which produced '/2' for page.
  1134 					 * When cast to int, returned 0.
  1155 					 * When cast to int, returned 0.
  1135 					 */
  1156 					 */
  1136 					$match = $match . '(?:/([0-9]+))?/?$';
  1157 					$match = $match . '(?:/([0-9]+))?/?$';
  1137 					$query = $index . '?' . $query . '&page=' . $this->preg_index($num_toks + 1);
  1158 					$query = $index . '?' . $query . '&page=' . $this->preg_index( $num_toks + 1 );
  1138 
  1159 
  1139 				// Not matching a permalink so this is a lot simpler.
  1160 					// Not matching a permalink so this is a lot simpler.
  1140 				} else {
  1161 				} else {
  1141 					// Close the match and finalise the query.
  1162 					// Close the match and finalise the query.
  1142 					$match .= '?$';
  1163 					$match .= '?$';
  1143 					$query = $index . '?' . $query;
  1164 					$query  = $index . '?' . $query;
  1144 				}
  1165 				}
  1145 
  1166 
  1146 				/*
  1167 				/*
  1147 				 * Create the final array for this dir by joining the $rewrite array (which currently
  1168 				 * Create the final array for this dir by joining the $rewrite array (which currently
  1148 				 * only contains rules/queries for trackback, pages etc) to the main regex/query for
  1169 				 * only contains rules/queries for trackback, pages etc) to the main regex/query for
  1149 				 * this dir
  1170 				 * this dir
  1150 				 */
  1171 				 */
  1151 				$rewrite = array_merge($rewrite, array($match => $query));
  1172 				$rewrite = array_merge( $rewrite, array( $match => $query ) );
  1152 
  1173 
  1153 				// If we're matching a permalink, add those extras (attachments etc) on.
  1174 				// If we're matching a permalink, add those extras (attachments etc) on.
  1154 				if ( $post ) {
  1175 				if ( $post ) {
  1155 					// Add trackback.
  1176 					// Add trackback.
  1156 					$rewrite = array_merge(array($trackbackmatch => $trackbackquery), $rewrite);
  1177 					$rewrite = array_merge( array( $trackbackmatch => $trackbackquery ), $rewrite );
  1157 
  1178 
  1158 					// Add embed.
  1179 					// Add embed.
  1159 					$rewrite = array_merge( array( $embedmatch => $embedquery ), $rewrite );
  1180 					$rewrite = array_merge( array( $embedmatch => $embedquery ), $rewrite );
  1160 
  1181 
  1161 					// Add regexes/queries for attachments, attachment trackbacks and so on.
  1182 					// Add regexes/queries for attachments, attachment trackbacks and so on.
  1162 					if ( ! $page ) {
  1183 					if ( ! $page ) {
  1163 						// Require <permalink>/attachment/stuff form for pages because of confusion with subpages.
  1184 						// Require <permalink>/attachment/stuff form for pages because of confusion with subpages.
  1164 						$rewrite = array_merge( $rewrite, array(
  1185 						$rewrite = array_merge(
  1165 							$sub1        => $subquery,
  1186 							$rewrite,
  1166 							$sub1tb      => $subtbquery,
  1187 							array(
  1167 							$sub1feed    => $subfeedquery,
  1188 								$sub1        => $subquery,
  1168 							$sub1feed2   => $subfeedquery,
  1189 								$sub1tb      => $subtbquery,
  1169 							$sub1comment => $subcommentquery,
  1190 								$sub1feed    => $subfeedquery,
  1170 							$sub1embed   => $subembedquery
  1191 								$sub1feed2   => $subfeedquery,
  1171 						) );
  1192 								$sub1comment => $subcommentquery,
       
  1193 								$sub1embed   => $subembedquery,
       
  1194 							)
       
  1195 						);
  1172 					}
  1196 					}
  1173 
  1197 
  1174 					$rewrite = array_merge( array( $sub2 => $subquery, $sub2tb => $subtbquery, $sub2feed => $subfeedquery, $sub2feed2 => $subfeedquery, $sub2comment => $subcommentquery, $sub2embed => $subembedquery ), $rewrite );
  1198 					$rewrite = array_merge(
       
  1199 						array(
       
  1200 							$sub2        => $subquery,
       
  1201 							$sub2tb      => $subtbquery,
       
  1202 							$sub2feed    => $subfeedquery,
       
  1203 							$sub2feed2   => $subfeedquery,
       
  1204 							$sub2comment => $subcommentquery,
       
  1205 							$sub2embed   => $subembedquery,
       
  1206 						),
       
  1207 						$rewrite
       
  1208 					);
  1175 				}
  1209 				}
  1176 			}
  1210 			}
  1177 			// Add the rules for this dir to the accumulating $post_rewrite.
  1211 			// Add the rules for this dir to the accumulating $post_rewrite.
  1178 			$post_rewrite = array_merge($rewrite, $post_rewrite);
  1212 			$post_rewrite = array_merge( $rewrite, $post_rewrite );
  1179 		}
  1213 		}
  1180 
  1214 
  1181 		// The finished rules. phew!
  1215 		// The finished rules. phew!
  1182 		return $post_rewrite;
  1216 		return $post_rewrite;
  1183 	}
  1217 	}
  1195 	 *
  1229 	 *
  1196 	 * @param string $permalink_structure The permalink structure to generate rules.
  1230 	 * @param string $permalink_structure The permalink structure to generate rules.
  1197 	 * @param bool   $walk_dirs           Optional, default is false. Whether to create list of directories to walk over.
  1231 	 * @param bool   $walk_dirs           Optional, default is false. Whether to create list of directories to walk over.
  1198 	 * @return array
  1232 	 * @return array
  1199 	 */
  1233 	 */
  1200 	public function generate_rewrite_rule($permalink_structure, $walk_dirs = false) {
  1234 	public function generate_rewrite_rule( $permalink_structure, $walk_dirs = false ) {
  1201 		return $this->generate_rewrite_rules($permalink_structure, EP_NONE, false, false, false, $walk_dirs);
  1235 		return $this->generate_rewrite_rules( $permalink_structure, EP_NONE, false, false, false, $walk_dirs );
  1202 	}
  1236 	}
  1203 
  1237 
  1204 	/**
  1238 	/**
  1205 	 * Constructs rewrite matches and queries from permalink structure.
  1239 	 * Constructs rewrite matches and queries from permalink structure.
  1206 	 *
  1240 	 *
  1219 	 * @return array An associate array of matches and queries.
  1253 	 * @return array An associate array of matches and queries.
  1220 	 */
  1254 	 */
  1221 	public function rewrite_rules() {
  1255 	public function rewrite_rules() {
  1222 		$rewrite = array();
  1256 		$rewrite = array();
  1223 
  1257 
  1224 		if ( empty($this->permalink_structure) )
  1258 		if ( empty( $this->permalink_structure ) ) {
  1225 			return $rewrite;
  1259 			return $rewrite;
       
  1260 		}
  1226 
  1261 
  1227 		// robots.txt -only if installed at the root
  1262 		// robots.txt -only if installed at the root
  1228 		$home_path = parse_url( home_url() );
  1263 		$home_path      = parse_url( home_url() );
  1229 		$robots_rewrite = ( empty( $home_path['path'] ) || '/' == $home_path['path'] ) ? array( 'robots\.txt$' => $this->index . '?robots=1' ) : array();
  1264 		$robots_rewrite = ( empty( $home_path['path'] ) || '/' == $home_path['path'] ) ? array( 'robots\.txt$' => $this->index . '?robots=1' ) : array();
  1230 
  1265 
  1231 		// Old feed and service files.
  1266 		// Old feed and service files.
  1232 		$deprecated_files = array(
  1267 		$deprecated_files = array(
  1233 			'.*wp-(atom|rdf|rss|rss2|feed|commentsrss2)\.php$' => $this->index . '?feed=old',
  1268 			'.*wp-(atom|rdf|rss|rss2|feed|commentsrss2)\.php$' => $this->index . '?feed=old',
  1235 		);
  1270 		);
  1236 
  1271 
  1237 		// Registration rules.
  1272 		// Registration rules.
  1238 		$registration_pages = array();
  1273 		$registration_pages = array();
  1239 		if ( is_multisite() && is_main_site() ) {
  1274 		if ( is_multisite() && is_main_site() ) {
  1240 			$registration_pages['.*wp-signup.php$'] = $this->index . '?signup=true';
  1275 			$registration_pages['.*wp-signup.php$']   = $this->index . '?signup=true';
  1241 			$registration_pages['.*wp-activate.php$'] = $this->index . '?activate=true';
  1276 			$registration_pages['.*wp-activate.php$'] = $this->index . '?activate=true';
  1242 		}
  1277 		}
  1243 
  1278 
  1244 		// Deprecated.
  1279 		// Deprecated.
  1245 		$registration_pages['.*wp-register.php$'] = $this->index . '?register=true';
  1280 		$registration_pages['.*wp-register.php$'] = $this->index . '?register=true';
  1255 		 * @param array $post_rewrite The rewrite rules for posts.
  1290 		 * @param array $post_rewrite The rewrite rules for posts.
  1256 		 */
  1291 		 */
  1257 		$post_rewrite = apply_filters( 'post_rewrite_rules', $post_rewrite );
  1292 		$post_rewrite = apply_filters( 'post_rewrite_rules', $post_rewrite );
  1258 
  1293 
  1259 		// Date rewrite rules.
  1294 		// Date rewrite rules.
  1260 		$date_rewrite = $this->generate_rewrite_rules($this->get_date_permastruct(), EP_DATE);
  1295 		$date_rewrite = $this->generate_rewrite_rules( $this->get_date_permastruct(), EP_DATE );
  1261 
  1296 
  1262 		/**
  1297 		/**
  1263 		 * Filters rewrite rules used for date archives.
  1298 		 * Filters rewrite rules used for date archives.
  1264 		 *
  1299 		 *
  1265 		 * Likely date archives would include /yyyy/, /yyyy/mm/, and /yyyy/mm/dd/.
  1300 		 * Likely date archives would include /yyyy/, /yyyy/mm/, and /yyyy/mm/dd/.
  1269 		 * @param array $date_rewrite The rewrite rules for date archives.
  1304 		 * @param array $date_rewrite The rewrite rules for date archives.
  1270 		 */
  1305 		 */
  1271 		$date_rewrite = apply_filters( 'date_rewrite_rules', $date_rewrite );
  1306 		$date_rewrite = apply_filters( 'date_rewrite_rules', $date_rewrite );
  1272 
  1307 
  1273 		// Root-level rewrite rules.
  1308 		// Root-level rewrite rules.
  1274 		$root_rewrite = $this->generate_rewrite_rules($this->root . '/', EP_ROOT);
  1309 		$root_rewrite = $this->generate_rewrite_rules( $this->root . '/', EP_ROOT );
  1275 
  1310 
  1276 		/**
  1311 		/**
  1277 		 * Filters rewrite rules used for root-level archives.
  1312 		 * Filters rewrite rules used for root-level archives.
  1278 		 *
  1313 		 *
  1279 		 * Likely root-level archives would include pagination rules for the homepage
  1314 		 * Likely root-level archives would include pagination rules for the homepage
  1284 		 * @param array $root_rewrite The root-level rewrite rules.
  1319 		 * @param array $root_rewrite The root-level rewrite rules.
  1285 		 */
  1320 		 */
  1286 		$root_rewrite = apply_filters( 'root_rewrite_rules', $root_rewrite );
  1321 		$root_rewrite = apply_filters( 'root_rewrite_rules', $root_rewrite );
  1287 
  1322 
  1288 		// Comments rewrite rules.
  1323 		// Comments rewrite rules.
  1289 		$comments_rewrite = $this->generate_rewrite_rules($this->root . $this->comments_base, EP_COMMENTS, false, true, true, false);
  1324 		$comments_rewrite = $this->generate_rewrite_rules( $this->root . $this->comments_base, EP_COMMENTS, false, true, true, false );
  1290 
  1325 
  1291 		/**
  1326 		/**
  1292 		 * Filters rewrite rules used for comment feed archives.
  1327 		 * Filters rewrite rules used for comment feed archives.
  1293 		 *
  1328 		 *
  1294 		 * Likely comments feed archives include /comments/feed/, and /comments/feed/atom/.
  1329 		 * Likely comments feed archives include /comments/feed/, and /comments/feed/atom/.
  1299 		 */
  1334 		 */
  1300 		$comments_rewrite = apply_filters( 'comments_rewrite_rules', $comments_rewrite );
  1335 		$comments_rewrite = apply_filters( 'comments_rewrite_rules', $comments_rewrite );
  1301 
  1336 
  1302 		// Search rewrite rules.
  1337 		// Search rewrite rules.
  1303 		$search_structure = $this->get_search_permastruct();
  1338 		$search_structure = $this->get_search_permastruct();
  1304 		$search_rewrite = $this->generate_rewrite_rules($search_structure, EP_SEARCH);
  1339 		$search_rewrite   = $this->generate_rewrite_rules( $search_structure, EP_SEARCH );
  1305 
  1340 
  1306 		/**
  1341 		/**
  1307 		 * Filters rewrite rules used for search archives.
  1342 		 * Filters rewrite rules used for search archives.
  1308 		 *
  1343 		 *
  1309 		 * Likely search-related archives include /search/search+query/ as well as
  1344 		 * Likely search-related archives include /search/search+query/ as well as
  1314 		 * @param array $search_rewrite The rewrite rules for search queries.
  1349 		 * @param array $search_rewrite The rewrite rules for search queries.
  1315 		 */
  1350 		 */
  1316 		$search_rewrite = apply_filters( 'search_rewrite_rules', $search_rewrite );
  1351 		$search_rewrite = apply_filters( 'search_rewrite_rules', $search_rewrite );
  1317 
  1352 
  1318 		// Author rewrite rules.
  1353 		// Author rewrite rules.
  1319 		$author_rewrite = $this->generate_rewrite_rules($this->get_author_permastruct(), EP_AUTHORS);
  1354 		$author_rewrite = $this->generate_rewrite_rules( $this->get_author_permastruct(), EP_AUTHORS );
  1320 
  1355 
  1321 		/**
  1356 		/**
  1322 		 * Filters rewrite rules used for author archives.
  1357 		 * Filters rewrite rules used for author archives.
  1323 		 *
  1358 		 *
  1324 		 * Likely author archives would include /author/author-name/, as well as
  1359 		 * Likely author archives would include /author/author-name/, as well as
  1343 		$page_rewrite = apply_filters( 'page_rewrite_rules', $page_rewrite );
  1378 		$page_rewrite = apply_filters( 'page_rewrite_rules', $page_rewrite );
  1344 
  1379 
  1345 		// Extra permastructs.
  1380 		// Extra permastructs.
  1346 		foreach ( $this->extra_permastructs as $permastructname => $struct ) {
  1381 		foreach ( $this->extra_permastructs as $permastructname => $struct ) {
  1347 			if ( is_array( $struct ) ) {
  1382 			if ( is_array( $struct ) ) {
  1348 				if ( count( $struct ) == 2 )
  1383 				if ( count( $struct ) == 2 ) {
  1349 					$rules = $this->generate_rewrite_rules( $struct[0], $struct[1] );
  1384 					$rules = $this->generate_rewrite_rules( $struct[0], $struct[1] );
  1350 				else
  1385 				} else {
  1351 					$rules = $this->generate_rewrite_rules( $struct['struct'], $struct['ep_mask'], $struct['paged'], $struct['feed'], $struct['forcomments'], $struct['walk_dirs'], $struct['endpoints'] );
  1386 					$rules = $this->generate_rewrite_rules( $struct['struct'], $struct['ep_mask'], $struct['paged'], $struct['feed'], $struct['forcomments'], $struct['walk_dirs'], $struct['endpoints'] );
       
  1387 				}
  1352 			} else {
  1388 			} else {
  1353 				$rules = $this->generate_rewrite_rules( $struct );
  1389 				$rules = $this->generate_rewrite_rules( $struct );
  1354 			}
  1390 			}
  1355 
  1391 
  1356 			/**
  1392 			/**
  1376 				 * @param array $rules The rewrite rules generated for tags.
  1412 				 * @param array $rules The rewrite rules generated for tags.
  1377 				 */
  1413 				 */
  1378 				$rules = apply_filters( 'tag_rewrite_rules', $rules );
  1414 				$rules = apply_filters( 'tag_rewrite_rules', $rules );
  1379 			}
  1415 			}
  1380 
  1416 
  1381 			$this->extra_rules_top = array_merge($this->extra_rules_top, $rules);
  1417 			$this->extra_rules_top = array_merge( $this->extra_rules_top, $rules );
  1382 		}
  1418 		}
  1383 
  1419 
  1384 		// Put them together.
  1420 		// Put them together.
  1385 		if ( $this->use_verbose_page_rules )
  1421 		if ( $this->use_verbose_page_rules ) {
  1386 			$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);
  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 );
  1387 		else
  1423 		} else {
  1388 			$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);
  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 );
       
  1425 		}
  1389 
  1426 
  1390 		/**
  1427 		/**
  1391 		 * Fires after the rewrite rules are generated.
  1428 		 * Fires after the rewrite rules are generated.
  1392 		 *
  1429 		 *
  1393 		 * @since 1.5.0
  1430 		 * @since 1.5.0
  1419 	 * @since 1.5.0
  1456 	 * @since 1.5.0
  1420 	 *
  1457 	 *
  1421 	 * @return array Rewrite rules.
  1458 	 * @return array Rewrite rules.
  1422 	 */
  1459 	 */
  1423 	public function wp_rewrite_rules() {
  1460 	public function wp_rewrite_rules() {
  1424 		$this->rules = get_option('rewrite_rules');
  1461 		$this->rules = get_option( 'rewrite_rules' );
  1425 		if ( empty($this->rules) ) {
  1462 		if ( empty( $this->rules ) ) {
  1426 			$this->matches = 'matches';
  1463 			$this->matches = 'matches';
  1427 			$this->rewrite_rules();
  1464 			$this->rewrite_rules();
  1428 			if ( ! did_action( 'wp_loaded' ) ) {
  1465 			if ( ! did_action( 'wp_loaded' ) ) {
  1429 				add_action( 'wp_loaded', array( $this, 'flush_rules' ) );
  1466 				add_action( 'wp_loaded', array( $this, 'flush_rules' ) );
  1430 				return $this->rules;
  1467 				return $this->rules;
  1431 			}
  1468 			}
  1432 			update_option('rewrite_rules', $this->rules);
  1469 			update_option( 'rewrite_rules', $this->rules );
  1433 		}
  1470 		}
  1434 
  1471 
  1435 		return $this->rules;
  1472 		return $this->rules;
  1436 	}
  1473 	}
  1437 
  1474 
  1447 	 * @since 1.5.0
  1484 	 * @since 1.5.0
  1448 	 *
  1485 	 *
  1449 	 * @return string
  1486 	 * @return string
  1450 	 */
  1487 	 */
  1451 	public function mod_rewrite_rules() {
  1488 	public function mod_rewrite_rules() {
  1452 		if ( ! $this->using_permalinks() )
  1489 		if ( ! $this->using_permalinks() ) {
  1453 			return '';
  1490 			return '';
       
  1491 		}
  1454 
  1492 
  1455 		$site_root = parse_url( site_url() );
  1493 		$site_root = parse_url( site_url() );
  1456 		if ( isset( $site_root['path'] ) )
  1494 		if ( isset( $site_root['path'] ) ) {
  1457 			$site_root = trailingslashit($site_root['path']);
  1495 			$site_root = trailingslashit( $site_root['path'] );
  1458 
  1496 		}
  1459 		$home_root = parse_url(home_url());
  1497 
  1460 		if ( isset( $home_root['path'] ) )
  1498 		$home_root = parse_url( home_url() );
  1461 			$home_root = trailingslashit($home_root['path']);
  1499 		if ( isset( $home_root['path'] ) ) {
  1462 		else
  1500 			$home_root = trailingslashit( $home_root['path'] );
       
  1501 		} else {
  1463 			$home_root = '/';
  1502 			$home_root = '/';
  1464 
  1503 		}
  1465 		$rules = "<IfModule mod_rewrite.c>\n";
  1504 
       
  1505 		$rules  = "<IfModule mod_rewrite.c>\n";
  1466 		$rules .= "RewriteEngine On\n";
  1506 		$rules .= "RewriteEngine On\n";
  1467 		$rules .= "RewriteBase $home_root\n";
  1507 		$rules .= "RewriteBase $home_root\n";
  1468 
  1508 
  1469 		// Prevent -f checks on index.php.
  1509 		// Prevent -f checks on index.php.
  1470 		$rules .= "RewriteRule ^index\.php$ - [L]\n";
  1510 		$rules .= "RewriteRule ^index\.php$ - [L]\n";
  1471 
  1511 
  1472 		// Add in the rules that don't redirect to WP's index.php (and thus shouldn't be handled by WP at all).
  1512 		// Add in the rules that don't redirect to WP's index.php (and thus shouldn't be handled by WP at all).
  1473 		foreach ( (array) $this->non_wp_rules as $match => $query) {
  1513 		foreach ( (array) $this->non_wp_rules as $match => $query ) {
  1474 			// Apache 1.3 does not support the reluctant (non-greedy) modifier.
  1514 			// Apache 1.3 does not support the reluctant (non-greedy) modifier.
  1475 			$match = str_replace('.+?', '.+', $match);
  1515 			$match = str_replace( '.+?', '.+', $match );
  1476 
  1516 
  1477 			$rules .= 'RewriteRule ^' . $match . ' ' . $home_root . $query . " [QSA,L]\n";
  1517 			$rules .= 'RewriteRule ^' . $match . ' ' . $home_root . $query . " [QSA,L]\n";
  1478 		}
  1518 		}
  1479 
  1519 
  1480 		if ( $this->use_verbose_rules ) {
  1520 		if ( $this->use_verbose_rules ) {
  1481 			$this->matches = '';
  1521 			$this->matches = '';
  1482 			$rewrite = $this->rewrite_rules();
  1522 			$rewrite       = $this->rewrite_rules();
  1483 			$num_rules = count($rewrite);
  1523 			$num_rules     = count( $rewrite );
  1484 			$rules .= "RewriteCond %{REQUEST_FILENAME} -f [OR]\n" .
  1524 			$rules        .= "RewriteCond %{REQUEST_FILENAME} -f [OR]\n" .
  1485 				"RewriteCond %{REQUEST_FILENAME} -d\n" .
  1525 				"RewriteCond %{REQUEST_FILENAME} -d\n" .
  1486 				"RewriteRule ^.*$ - [S=$num_rules]\n";
  1526 				"RewriteRule ^.*$ - [S=$num_rules]\n";
  1487 
  1527 
  1488 			foreach ( (array) $rewrite as $match => $query) {
  1528 			foreach ( (array) $rewrite as $match => $query ) {
  1489 				// Apache 1.3 does not support the reluctant (non-greedy) modifier.
  1529 				// Apache 1.3 does not support the reluctant (non-greedy) modifier.
  1490 				$match = str_replace('.+?', '.+', $match);
  1530 				$match = str_replace( '.+?', '.+', $match );
  1491 
  1531 
  1492 				if ( strpos($query, $this->index) !== false )
  1532 				if ( strpos( $query, $this->index ) !== false ) {
  1493 					$rules .= 'RewriteRule ^' . $match . ' ' . $home_root . $query . " [QSA,L]\n";
  1533 					$rules .= 'RewriteRule ^' . $match . ' ' . $home_root . $query . " [QSA,L]\n";
  1494 				else
  1534 				} else {
  1495 					$rules .= 'RewriteRule ^' . $match . ' ' . $site_root . $query . " [QSA,L]\n";
  1535 					$rules .= 'RewriteRule ^' . $match . ' ' . $site_root . $query . " [QSA,L]\n";
       
  1536 				}
  1496 			}
  1537 			}
  1497 		} else {
  1538 		} else {
  1498 			$rules .= "RewriteCond %{REQUEST_FILENAME} !-f\n" .
  1539 			$rules .= "RewriteCond %{REQUEST_FILENAME} !-f\n" .
  1499 				"RewriteCond %{REQUEST_FILENAME} !-d\n" .
  1540 				"RewriteCond %{REQUEST_FILENAME} !-d\n" .
  1500 				"RewriteRule . {$home_root}{$this->index} [L]\n";
  1541 				"RewriteRule . {$home_root}{$this->index} [L]\n";
  1533 	 * @param bool $add_parent_tags Optional. Whether to add parent tags to the rewrite rule sets.
  1574 	 * @param bool $add_parent_tags Optional. Whether to add parent tags to the rewrite rule sets.
  1534 	 *                              Default false.
  1575 	 *                              Default false.
  1535 	 * @return string IIS7 URL rewrite rule sets.
  1576 	 * @return string IIS7 URL rewrite rule sets.
  1536 	 */
  1577 	 */
  1537 	public function iis7_url_rewrite_rules( $add_parent_tags = false ) {
  1578 	public function iis7_url_rewrite_rules( $add_parent_tags = false ) {
  1538 		if ( ! $this->using_permalinks() )
  1579 		if ( ! $this->using_permalinks() ) {
  1539 			return '';
  1580 			return '';
       
  1581 		}
  1540 		$rules = '';
  1582 		$rules = '';
  1541 		if ( $add_parent_tags ) {
  1583 		if ( $add_parent_tags ) {
  1542 			$rules .= '<configuration>
  1584 			$rules .= '<configuration>
  1543 	<system.webServer>
  1585 	<system.webServer>
  1544 		<rewrite>
  1586 		<rewrite>
  1588 	 *                            or 'bottom'. Default 'bottom'.
  1630 	 *                            or 'bottom'. Default 'bottom'.
  1589 	 */
  1631 	 */
  1590 	public function add_rule( $regex, $query, $after = 'bottom' ) {
  1632 	public function add_rule( $regex, $query, $after = 'bottom' ) {
  1591 		if ( is_array( $query ) ) {
  1633 		if ( is_array( $query ) ) {
  1592 			$external = false;
  1634 			$external = false;
  1593 			$query = add_query_arg( $query, 'index.php' );
  1635 			$query    = add_query_arg( $query, 'index.php' );
  1594 		} else {
  1636 		} else {
  1595 			$index = false === strpos( $query, '?' ) ? strlen( $query ) : strpos( $query, '?' );
  1637 			$index = false === strpos( $query, '?' ) ? strlen( $query ) : strpos( $query, '?' );
  1596 			$front = substr( $query, 0, $index );
  1638 			$front = substr( $query, 0, $index );
  1597 
  1639 
  1598 			$external = $front != $this->index;
  1640 			$external = $front != $this->index;
  1690 	 *     @type bool $endpoints   Whether endpoints should be applied to the generated rules. Default true.
  1732 	 *     @type bool $endpoints   Whether endpoints should be applied to the generated rules. Default true.
  1691 	 * }
  1733 	 * }
  1692 	 */
  1734 	 */
  1693 	public function add_permastruct( $name, $struct, $args = array() ) {
  1735 	public function add_permastruct( $name, $struct, $args = array() ) {
  1694 		// Back-compat for the old parameters: $with_front and $ep_mask.
  1736 		// Back-compat for the old parameters: $with_front and $ep_mask.
  1695 		if ( ! is_array( $args ) )
  1737 		if ( ! is_array( $args ) ) {
  1696 			$args = array( 'with_front' => $args );
  1738 			$args = array( 'with_front' => $args );
  1697 		if ( func_num_args() == 4 )
  1739 		}
       
  1740 		if ( func_num_args() == 4 ) {
  1698 			$args['ep_mask'] = func_get_arg( 3 );
  1741 			$args['ep_mask'] = func_get_arg( 3 );
       
  1742 		}
  1699 
  1743 
  1700 		$defaults = array(
  1744 		$defaults = array(
  1701 			'with_front' => true,
  1745 			'with_front'  => true,
  1702 			'ep_mask' => EP_NONE,
  1746 			'ep_mask'     => EP_NONE,
  1703 			'paged' => true,
  1747 			'paged'       => true,
  1704 			'feed' => true,
  1748 			'feed'        => true,
  1705 			'forcomments' => false,
  1749 			'forcomments' => false,
  1706 			'walk_dirs' => true,
  1750 			'walk_dirs'   => true,
  1707 			'endpoints' => true,
  1751 			'endpoints'   => true,
  1708 		);
  1752 		);
  1709 		$args = array_intersect_key( $args, $defaults );
  1753 		$args     = array_intersect_key( $args, $defaults );
  1710 		$args = wp_parse_args( $args, $defaults );
  1754 		$args     = wp_parse_args( $args, $defaults );
  1711 
  1755 
  1712 		if ( $args['with_front'] )
  1756 		if ( $args['with_front'] ) {
  1713 			$struct = $this->front . $struct;
  1757 			$struct = $this->front . $struct;
  1714 		else
  1758 		} else {
  1715 			$struct = $this->root . $struct;
  1759 			$struct = $this->root . $struct;
       
  1760 		}
  1716 		$args['struct'] = $struct;
  1761 		$args['struct'] = $struct;
  1717 
  1762 
  1718 		$this->extra_permastructs[ $name ] = $args;
  1763 		$this->extra_permastructs[ $name ] = $args;
  1719 	}
  1764 	}
  1720 
  1765 
  1769 		 * @param bool $hard Whether to flush rewrite rules "hard". Default true.
  1814 		 * @param bool $hard Whether to flush rewrite rules "hard". Default true.
  1770 		 */
  1815 		 */
  1771 		if ( ! $hard || ! apply_filters( 'flush_rewrite_rules_hard', true ) ) {
  1816 		if ( ! $hard || ! apply_filters( 'flush_rewrite_rules_hard', true ) ) {
  1772 			return;
  1817 			return;
  1773 		}
  1818 		}
  1774 		if ( function_exists( 'save_mod_rewrite_rules' ) )
  1819 		if ( function_exists( 'save_mod_rewrite_rules' ) ) {
  1775 			save_mod_rewrite_rules();
  1820 			save_mod_rewrite_rules();
  1776 		if ( function_exists( 'iis7_save_url_rewrite_rules' ) )
  1821 		}
       
  1822 		if ( function_exists( 'iis7_save_url_rewrite_rules' ) ) {
  1777 			iis7_save_url_rewrite_rules();
  1823 			iis7_save_url_rewrite_rules();
       
  1824 		}
  1778 	}
  1825 	}
  1779 
  1826 
  1780 	/**
  1827 	/**
  1781 	 * Sets up the object's properties.
  1828 	 * Sets up the object's properties.
  1782 	 *
  1829 	 *
  1785 	 * '%tag%', or '%author%'.
  1832 	 * '%tag%', or '%author%'.
  1786 	 *
  1833 	 *
  1787 	 * @since 1.5.0
  1834 	 * @since 1.5.0
  1788 	 */
  1835 	 */
  1789 	public function init() {
  1836 	public function init() {
  1790 		$this->extra_rules = $this->non_wp_rules = $this->endpoints = array();
  1837 		$this->extra_rules         = $this->non_wp_rules = $this->endpoints = array();
  1791 		$this->permalink_structure = get_option('permalink_structure');
  1838 		$this->permalink_structure = get_option( 'permalink_structure' );
  1792 		$this->front = substr($this->permalink_structure, 0, strpos($this->permalink_structure, '%'));
  1839 		$this->front               = substr( $this->permalink_structure, 0, strpos( $this->permalink_structure, '%' ) );
  1793 		$this->root = '';
  1840 		$this->root                = '';
  1794 
  1841 
  1795 		if ( $this->using_index_permalinks() )
  1842 		if ( $this->using_index_permalinks() ) {
  1796 			$this->root = $this->index . '/';
  1843 			$this->root = $this->index . '/';
  1797 
  1844 		}
  1798 		unset($this->author_structure);
  1845 
  1799 		unset($this->date_structure);
  1846 		unset( $this->author_structure );
  1800 		unset($this->page_structure);
  1847 		unset( $this->date_structure );
  1801 		unset($this->search_structure);
  1848 		unset( $this->page_structure );
  1802 		unset($this->feed_structure);
  1849 		unset( $this->search_structure );
  1803 		unset($this->comment_feed_structure);
  1850 		unset( $this->feed_structure );
  1804 		$this->use_trailing_slashes = ( '/' == substr($this->permalink_structure, -1, 1) );
  1851 		unset( $this->comment_feed_structure );
       
  1852 		$this->use_trailing_slashes = ( '/' == substr( $this->permalink_structure, -1, 1 ) );
  1805 
  1853 
  1806 		// Enable generic rules for pages if permalink structure doesn't begin with a wildcard.
  1854 		// Enable generic rules for pages if permalink structure doesn't begin with a wildcard.
  1807 		if ( preg_match("/^[^%]*%(?:postname|category|tag|author)%/", $this->permalink_structure) )
  1855 		if ( preg_match( '/^[^%]*%(?:postname|category|tag|author)%/', $this->permalink_structure ) ) {
  1808 			 $this->use_verbose_page_rules = true;
  1856 			$this->use_verbose_page_rules = true;
  1809 		else
  1857 		} else {
  1810 			$this->use_verbose_page_rules = false;
  1858 			$this->use_verbose_page_rules = false;
       
  1859 		}
  1811 	}
  1860 	}
  1812 
  1861 
  1813 	/**
  1862 	/**
  1814 	 * Sets the main permalink structure for the site.
  1863 	 * Sets the main permalink structure for the site.
  1815 	 *
  1864 	 *
  1822 	 *
  1871 	 *
  1823 	 * @since 1.5.0
  1872 	 * @since 1.5.0
  1824 	 *
  1873 	 *
  1825 	 * @param string $permalink_structure Permalink structure.
  1874 	 * @param string $permalink_structure Permalink structure.
  1826 	 */
  1875 	 */
  1827 	public function set_permalink_structure($permalink_structure) {
  1876 	public function set_permalink_structure( $permalink_structure ) {
  1828 		if ( $permalink_structure != $this->permalink_structure ) {
  1877 		if ( $permalink_structure != $this->permalink_structure ) {
  1829 			$old_permalink_structure = $this->permalink_structure;
  1878 			$old_permalink_structure = $this->permalink_structure;
  1830 			update_option('permalink_structure', $permalink_structure);
  1879 			update_option( 'permalink_structure', $permalink_structure );
  1831 
  1880 
  1832 			$this->init();
  1881 			$this->init();
  1833 
  1882 
  1834 			/**
  1883 			/**
  1835 			 * Fires after the permalink structure is updated.
  1884 			 * Fires after the permalink structure is updated.
  1852 	 *
  1901 	 *
  1853 	 * @since 1.5.0
  1902 	 * @since 1.5.0
  1854 	 *
  1903 	 *
  1855 	 * @param string $category_base Category permalink structure base.
  1904 	 * @param string $category_base Category permalink structure base.
  1856 	 */
  1905 	 */
  1857 	public function set_category_base($category_base) {
  1906 	public function set_category_base( $category_base ) {
  1858 		if ( $category_base != get_option('category_base') ) {
  1907 		if ( $category_base != get_option( 'category_base' ) ) {
  1859 			update_option('category_base', $category_base);
  1908 			update_option( 'category_base', $category_base );
  1860 			$this->init();
  1909 			$this->init();
  1861 		}
  1910 		}
  1862 	}
  1911 	}
  1863 
  1912 
  1864 	/**
  1913 	/**
  1871 	 * @since 2.3.0
  1920 	 * @since 2.3.0
  1872 	 *
  1921 	 *
  1873 	 * @param string $tag_base Tag permalink structure base.
  1922 	 * @param string $tag_base Tag permalink structure base.
  1874 	 */
  1923 	 */
  1875 	public function set_tag_base( $tag_base ) {
  1924 	public function set_tag_base( $tag_base ) {
  1876 		if ( $tag_base != get_option( 'tag_base') ) {
  1925 		if ( $tag_base != get_option( 'tag_base' ) ) {
  1877 			update_option( 'tag_base', $tag_base );
  1926 			update_option( 'tag_base', $tag_base );
  1878 			$this->init();
  1927 			$this->init();
  1879 		}
  1928 		}
  1880 	}
  1929 	}
  1881 
  1930 
  1882 	/**
  1931 	/**
  1883 	 * Constructor - Calls init(), which runs setup.
  1932 	 * Constructor - Calls init(), which runs setup.
  1884 	 *
  1933 	 *
  1885 	 * @since 1.5.0
  1934 	 * @since 1.5.0
  1886 	 *
       
  1887 	 */
  1935 	 */
  1888 	public function __construct() {
  1936 	public function __construct() {
  1889 		$this->init();
  1937 		$this->init();
  1890 	}
  1938 	}
  1891 }
  1939 }