Make WordPress Core

Ticket #2433: wp-rewrite-api.2.diff

File wp-rewrite-api.2.diff, 14.4 KB (added by davidhouse, 18 years ago)
  • wp-includes/rewrite-functions.php

     
     1<?php
     2
     3//Add a straight rewrite rule
     4function add_rewrite_rule($regex, $redirect) {
     5        global $wp_rewrite;
     6        $wp_rewrite->add_extra_rule($regex, $redirect);
     7}
     8
     9//Add a new tag (like %postname%)
     10//warning: you must call this on init or earlier, otherwise the query var addition stuff won't work
     11function add_rewrite_tag($tagname, $regex) {
     12        //validation
     13        if (strlen($tagname) < 3 || $tagname{0} != '%' || $tagname{strlen($tagname)-1} != '%') {
     14                return;
     15        }
     16       
     17        $qv = trim($tagname, '%');
     18       
     19        global $wp_rewrite, $wp;
     20        $wp->add_extra_qv($qv);
     21        $wp_rewrite->add_rewrite_tag($tagname, $regex, $qv . '=');
     22}
     23
     24//Add a new feed type like /atom1/
     25function add_feed($feedname, $filename) {
     26        global $wp_rewrite;
     27        if (!in_array($feedname, $wp_rewrite->feeds)) { //override the file if it is
     28                $wp_rewrite->feeds[] = $feedname;
     29        }
     30        $wp_rewrite->feed_files[$feedname] = $filename;
     31}
     32
     33?>
     34 No newline at end of file
  • wp-includes/classes.php

     
    864864        var $index = 'index.php';
    865865        var $matches = '';
    866866        var $rules;
     867        var $extra_rules; //those not generated by the class, see add_rewrite_rule()
     868        var $non_wp_rules; //rules that don't redirect to WP's index.php
    867869        var $use_verbose_rules = false;
    868870        var $rewritecode =
    869871                array(
     
    913915                                        's='
    914916                                        );
    915917
    916         var $feeds = array ('feed', 'rdf', 'rss', 'rss2', 'atom');
    917 
     918        var $feeds = array ( 'feed', 'rdf', 'rss', 'rss2', 'atom' );
     919       
     920        //the filenames aren't actually used in WP_Rewrite but seems a convenient place as any to store them
     921        var $feed_files = array (
     922                'rdf'  => 'wp-rdf.php',
     923                'rss'  => 'wp-rss.php',
     924                'rss2' => 'wp-rss2.php',
     925                'atom' =>'wp-atom.php'
     926        ); 
     927     
    918928        function using_permalinks() {
    919929                if (empty($this->permalink_structure))
    920930                        return false;
     
    11621172                }
    11631173        }
    11641174
     1175        //the main WP_Rewrite function. generate the rules from permalink structure
    11651176        function generate_rewrite_rules($permalink_structure, $paged = true, $feed = true, $forcomments = false, $walk_dirs = true) {
     1177                //build a regex to match the feed section of URLs, something like (feed|atom|rss|rss2)/?
    11661178                $feedregex2 = '';
    11671179                foreach ($this->feeds as $feed_name) {
    11681180                        $feedregex2 .= $feed_name . '|';
    11691181                }
    11701182                $feedregex2 = '(' . trim($feedregex2, '|') .  ')/?$';
     1183                //$feedregex is identical but with /feed/ added on as well, so URLs like <permalink>/feed/atom
     1184                //and <permalink>/atom are both possible
    11711185                $feedregex = $this->feed_base  . '/' . $feedregex2;
    11721186
     1187                //build a regex to match the trackback and page/xx parts of URLs
    11731188                $trackbackregex = 'trackback/?$';
    11741189                $pageregex = 'page/?([0-9]{1,})/?$';
    11751190
     1191                //get everything up to the first rewrite tag
    11761192                $front = substr($permalink_structure, 0, strpos($permalink_structure, '%'));
     1193                //build an array of the tags (note that said array ends up being in $tokens[0])
    11771194                preg_match_all('/%.+?%/', $permalink_structure, $tokens);
    11781195
    11791196                $num_tokens = count($tokens[0]);
    11801197
    1181                 $index = $this->index;
     1198                $index = $this->index; //probably 'index.php'
    11821199                $feedindex = $index;
    11831200                $trackbackindex = $index;
     1201                //build a list from the rewritecode and queryreplace arrays, that will look something like
     1202                //tagname=$matches[i] where i is the current $i
    11841203                for ($i = 0; $i < $num_tokens; ++$i) {
    11851204                        if (0 < $i) {
    11861205                                $queries[$i] = $queries[$i - 1] . '&';
     
    11901209                        $queries[$i] .= $query_token;
    11911210                }
    11921211
     1212                //get the structure, minus any cruft (stuff that isn't tags) at the front
    11931213                $structure = $permalink_structure;
    11941214                if ($front != '/') {
    11951215                        $structure = str_replace($front, '', $structure);
    11961216                }
     1217                //create a list of dirs to walk over, making rewrite rules for each level
     1218                //so for example, a $structure of /%year%/%month%/%postname% would create
     1219                //rewrite rules for /%year%/, /%year%/%month%/ and /%year%/%month%/%postname%
    11971220                $structure = trim($structure, '/');
    11981221                if ($walk_dirs) {
    11991222                        $dirs = explode('/', $structure);
     
    12021225                }
    12031226                $num_dirs = count($dirs);
    12041227
     1228                //strip slashes from the front of $front
    12051229                $front = preg_replace('|^/+|', '', $front);
    12061230
     1231                //the main workhorse loop
    12071232                $post_rewrite = array();
    12081233                $struct = $front;
    12091234                for ($j = 0; $j < $num_dirs; ++$j) {
    1210                         $struct .= $dirs[$j] . '/';
     1235                        //get the struct for this dir, and trim slashes off the front
     1236                        $struct .= $dirs[$j] . '/'; //accumulate. see comment near explode('/', $structure) above
    12111237                        $struct = ltrim($struct, '/');
     1238                        //replace tags with regexes
    12121239                        $match = str_replace($this->rewritecode, $this->rewritereplace, $struct);
     1240                        //make a list of tags, and store how many there are in $num_toks
    12131241                        $num_toks = preg_match_all('/%.+?%/', $struct, $toks);
     1242                        //get the 'tagname=$matches[i]'
    12141243                        $query = $queries[$num_toks - 1];
    12151244
     1245                        //create query for /page/xx
    12161246                        $pagematch = $match . $pageregex;
    12171247                        $pagequery = $index . '?' . $query . '&paged=' . $this->preg_index($num_toks + 1);
    12181248
     1249                        //create query for /feed/(feed|atom|rss|rss2|rdf)
    12191250                        $feedmatch = $match . $feedregex;
    12201251                        $feedquery = $feedindex . '?' . $query . '&feed=' . $this->preg_index($num_toks + 1);
    12211252
     1253                        //create query for /(feed|atom|rss|rss2|rdf) (see comment near creation of $feedregex)
    12221254                        $feedmatch2 = $match . $feedregex2;
    12231255                        $feedquery2 = $feedindex . '?' . $query . '&feed=' . $this->preg_index($num_toks + 1);
    12241256
     1257                        //if asked to, turn the feed queries into comment feed ones
    12251258                        if ($forcomments) {
    12261259                                $feedquery .= '&withcomments=1';
    12271260                                $feedquery2 .= '&withcomments=1';
    12281261                        }
    12291262
     1263                        //start creating the array of rewrites for this dir
    12301264                        $rewrite = array();
    1231                         if ($feed)
     1265                        if ($feed) //...adding on /feed/ regexes => queries
    12321266                                $rewrite = array($feedmatch => $feedquery, $feedmatch2 => $feedquery2);
    1233                         if ($paged)
     1267                        if ($paged) //...and /page/xx ones
    12341268                                $rewrite = array_merge($rewrite, array($pagematch => $pagequery));
    1235 
     1269                       
     1270                        //if we've got some tags in this dir
    12361271                        if ($num_toks) {
    12371272                                $post = false;
    12381273                                $page = false;
     1274                               
     1275                                //check to see if this dir is permalink-level: i.e. the structure specifies an
     1276                                //individual post. Do this by checking it contains at least one of 1) post name,
     1277                                //2) post ID, 3) page name, 4) timestamp (year, month, day, hour, second and
     1278                                //minute all present)
    12391279                                if (strstr($struct, '%postname%') || strstr($struct, '%post_id%')
    12401280                                                || strstr($struct, '%pagename%')
    12411281                                                || (strstr($struct, '%year%') &&  strstr($struct, '%monthnum%') && strstr($struct, '%day%') && strstr($struct, '%hour%') && strstr($struct, '%minute') && strstr($struct, '%second%'))) {
    12421282                                        $post = true;
    12431283                                        if  ( strstr($struct, '%pagename%') )
    12441284                                                $page = true;
     1285                                        //create query and regex for trackback
    12451286                                        $trackbackmatch = $match . $trackbackregex;
    12461287                                        $trackbackquery = $trackbackindex . '?' . $query . '&tb=1';
     1288                                        //trim slashes from the end of the regex for this dir
    12471289                                        $match = rtrim($match, '/');
     1290                                        //get rid of brackets
    12481291                                        $submatchbase = str_replace(array('(',')'),'',$match);
     1292                                       
     1293                                        //add a rule for at attachements, which take the form of <permalink>/some-text
    12491294                                        $sub1 = $submatchbase . '/([^/]+)/';
    1250                                         $sub1tb = $sub1 . $trackbackregex;
    1251                                         $sub1feed = $sub1 . $feedregex;
    1252                                         $sub1feed2 = $sub1 . $feedregex2;
     1295                                        $sub1tb = $sub1 . $trackbackregex; //add trackback regex
     1296                                        $sub1feed = $sub1 . $feedregex; //and /feed/(atom|...)
     1297                                        $sub1feed2 = $sub1 . $feedregex2; //and (feed|atom...)
     1298                                        //add an ? as we don't have to match that last slash, and finally a $ so we
     1299                                        //match to the end of the URL
    12531300                                        $sub1 .= '?$';
     1301                                       
     1302                                        //add another rule to match attachments in the explicit form:
     1303                                        //<permalink>/attachment/some-text
    12541304                                        $sub2 = $submatchbase . '/attachment/([^/]+)/';
    1255                                         $sub2tb = $sub2 . $trackbackregex;
    1256                                         $sub2feed = $sub2 . $feedregex;
    1257                                         $sub2feed2 = $sub2 . $feedregex2;
    1258                                         $sub2 .= '?$';
     1305                                        $sub2tb = $sub2 . $trackbackregex; //and add trackbacks,
     1306                                        $sub2feed = $sub2 . $feedregex;    //feeds,
     1307                                        $sub2feed2 = $sub2 . $feedregex2;  //and feeds again on to this
     1308                                        $sub2 .= '?$'; //add a ?$ as above
     1309                                       
     1310                                        //create queries for these extra tag-ons we've just dealt with
    12591311                                        $subquery = $index . '?attachment=' . $this->preg_index(1);
    12601312                                        $subtbquery = $subquery . '&tb=1';
    12611313                                        $subfeedquery = $subquery . '&feed=' . $this->preg_index(2);
     1314                                       
     1315                                        //allow URLs like <permalink>/2 for <permalink>/page/2
    12621316                                        $match = $match . '(/[0-9]+)?/?$';
    12631317                                        $query = $index . '?' . $query . '&page=' . $this->preg_index($num_toks + 1);
    12641318                                } else {
     1319                                        //not matching a permalink so this is a lot simpler
    12651320                                        $match .= '?$';
    12661321                                        $query = $index . '?' . $query;
    12671322                                }
    1268                                        
     1323                               
     1324                                //create the final array for this dir by joining the $rewrite array (which currently
     1325                                //only contains rules/queries for trackback, pages etc) to the main regex/query for
     1326                                //this dir
    12691327                                $rewrite = array_merge($rewrite, array($match => $query));
    12701328
     1329                                //if we're matching a permalink, add those extras (attachments etc) on
    12711330                                if ($post) {
     1331                                        //add trackback
    12721332                                        $rewrite = array_merge(array($trackbackmatch => $trackbackquery), $rewrite);
    1273                                         if ( ! $page )
     1333                                       
     1334                                        //add regexes/queries for attachments, attachment trackbacks and so on
     1335                                        if ( ! $page ) //require <permalink>/attachment/stuff form for pages because of confusion with subpages
    12741336                                                $rewrite = array_merge($rewrite, array($sub1 => $subquery, $sub1tb => $subtbquery, $sub1feed => $subfeedquery, $sub1feed2 => $subfeedquery));
    12751337                                        $rewrite = array_merge($rewrite, array($sub2 => $subquery, $sub2tb => $subtbquery, $sub2feed => $subfeedquery, $sub2feed2 => $subfeedquery));
    12761338                                }
    12771339                        }
     1340                        //add the rules for this dir to the accumulating $post_rewrite
    12781341                        $post_rewrite = array_merge($rewrite, $post_rewrite);
    12791342                }
    1280                 return $post_rewrite;
     1343                return $post_rewrite; //the finished rules. phew!
    12811344        }
    12821345
    12831346        function generate_rewrite_rule($permalink_structure, $walk_dirs = false) {
     
    13291392                $page_rewrite = apply_filters('page_rewrite_rules', $page_rewrite);
    13301393
    13311394                // Put them together.
    1332                 $this->rules = array_merge($page_rewrite, $root_rewrite, $comments_rewrite, $search_rewrite, $category_rewrite, $author_rewrite, $date_rewrite, $post_rewrite);
     1395                $this->rules = array_merge($page_rewrite, $root_rewrite, $comments_rewrite, $search_rewrite, $category_rewrite, $author_rewrite, $date_rewrite, $post_rewrite, $this->extra_rules);
    13331396
    13341397                do_action('generate_rewrite_rules', array(&$this));
    13351398                $this->rules = apply_filters('rewrite_rules_array', $this->rules);
     
    13621425                $rules = "<IfModule mod_rewrite.c>\n";
    13631426                $rules .= "RewriteEngine On\n";
    13641427                $rules .= "RewriteBase $home_root\n";
     1428               
     1429                //add in the rules that don't redirect to WP's index.php (and thus shouldn't be handled by WP at all)
     1430                foreach ($this->non_wp_rules as $match => $query) {
     1431                        // Apache 1.3 does not support the reluctant (non-greedy) modifier.
     1432                        $match = str_replace('.+?', '.+', $match);
    13651433
     1434                        // If the match is unanchored and greedy, prepend rewrite conditions
     1435                        // to avoid infinite redirects and eclipsing of real files.
     1436                        if ($match == '(.+)/?$' || $match == '([^/]+)/?$' ) {
     1437                                //nada.
     1438                        }
     1439
     1440                        $rules .= 'RewriteRule ^' . $match . ' ' . $home_root . $query . " [QSA,L]\n";
     1441                }
     1442
    13661443                if ($this->use_verbose_rules) {
    13671444                        $this->matches = '';
    13681445                        $rewrite = $this->rewrite_rules();
     
    14001477
    14011478                return $rules;
    14021479        }
     1480       
     1481        //Add a straight rewrite rule
     1482        function add_extra_rule($regex, $redirect) {
     1483                //get everything up to the first ?
     1484                $index = (strpos($redirect, '?') == false ? strlen($redirect) : strpos($redirect, '?'));
     1485                $front = substr($redirect, 0, $index);
     1486                if ($front != $this->index) { //it doesn't redirect to WP's index.php
     1487                        $this->add_non_wp_rule($regex, $redirect);
     1488                } else {
     1489                        $this->extra_rules[$regex] = $redirect;
     1490                }
     1491        }
     1492       
     1493        //add a rule that doesn't redirect to index.php
     1494        function add_non_wp_rule($regex, $redirect) {
     1495                $this->non_wp_rules[$regex] = $redirect;
     1496        }
    14031497
    14041498        function flush_rules() {
    14051499                generate_page_uri_index();
     
    14101504        }
    14111505
    14121506        function init() {
     1507                $this->extra_rules = $this->non_wp_rules = array();
    14131508                $this->permalink_structure = get_settings('permalink_structure');
    14141509                $this->front = substr($this->permalink_structure, 0, strpos($this->permalink_structure, '%'));
    14151510                $this->root = '';
     
    14561551        var $matched_rule;
    14571552        var $matched_query;
    14581553        var $did_permalink = false;
     1554       
     1555        function add_extra_qv($qv) {
     1556                $this->public_query_vars[] = $qv;
     1557        }
    14591558
    14601559        function parse_request($extra_query_vars = '') {
    14611560                global $wp_rewrite;
     
    15301629                                        preg_match("!^$match!", urldecode($request_match), $matches)) {
    15311630                                        // Got a match.
    15321631                                        $this->matched_rule = $match;
    1533 
     1632                                       
    15341633                                        // Trim the query of everything up to the '?'.
    15351634                                        $query = preg_replace("!^.+\?!", '', $query);
    15361635
  • wp-settings.php

     
    138138require (ABSPATH . WPINC . '/template-functions-post.php');
    139139require (ABSPATH . WPINC . '/template-functions-category.php');
    140140require (ABSPATH . WPINC . '/comment-functions.php');
     141require (ABSPATH . WPINC . '/rewrite-functions.php');
    141142require (ABSPATH . WPINC . '/feed-functions.php');
    142143require (ABSPATH . WPINC . '/links.php');
    143144require (ABSPATH . WPINC . '/kses.php');
  • wp-feed.php

     
    1212    $feed = 'rss2';
    1313}
    1414
     15$file = $wp_rewrite->feed_files[$feed];
     16
    1517if ( is_single() || ($withcomments == 1) ) {
    1618    require(ABSPATH . 'wp-commentsrss2.php');
    17 } else {
    18     switch ($feed) {
    19     case 'atom':
    20         require(ABSPATH . 'wp-atom.php');
    21         break;
    22     case 'rdf':
    23         require(ABSPATH . 'wp-rdf.php');
    24         break;
    25     case 'rss':
    26         require(ABSPATH . 'wp-rss.php');
    27         break;
    28     case 'rss2':
    29         require(ABSPATH . 'wp-rss2.php');
    30         break;
    31     case 'comments-rss2':
    32         require(ABSPATH . 'wp-commentsrss2.php');
    33         break;
    34     }
     19} elseif (in_array($feed, $wp_rewrite->feeds) && !empty($file) && file_exists(ABSPATH . $file)) {
     20                require ABSPATH . $file;
     21        }
    3522}
    3623
    3724?>