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 } |
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; |
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 } |
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 |
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"; |
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 |
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 * |