Adding Mod Rewrite Rules Programmatically in WordPress Plugin

admin

Administrator
Staff member
The following sample plugin adds the custom mod rewrite rules to
Code:
.htaccess
when the user changes the permalink settings.

Code:
/* Plugin Name: Sample Mod Rewrite  */

add_action('generate_rewrite_rules', array(new custom_mod_rewrite, "generate_rewrite_rules"));

class custom_mod_rewrite {
    function __construct() {
        $this->wp_rewrite = & $GLOBALS["wp_rewrite"];
    }
    function generate_rewrite_rules() {

        $non_wp_rules = array(
            'simple-redirect/?$plugin_name' => 'http://google.com',
            'one-more-redirect/?$plugin_name' => 'http://yahoo.com'
        );

        $this->wp_rewrite->non_wp_rules = $non_wp_rules + $this->wp_rewrite->non_wp_rules;
        add_filter('mod_rewrite_rules', array(&$this, "mod_rewrite_rules"));
    }
    function mod_rewrite_rules($rules) {
        return preg_replace('#^(RewriteRule \^.*/)\?\$plugin_name .*(http://.*) \[QSA,L\]#mi', '$1 $2 [R=301,L]', $rules);
    }
}

There are two problems I found with this.

<ol>
<li>If it is set to the default permalink, it won't add the rules.</li>
<li><s>More importantly, unless the user changes the permalink settings, the rules won't be added.</s> (can be solved with
Code:
$wp_rewrite-&gt;flush_rules()
performed at the plugin activation)</li>
</ol>

For #2, I'm wondering if there is a good way to add the rules programmatically.

<blockquote>
IIS (common on Windows servers) does not support mod_rewrite.
</blockquote>

source: <a href="http://codex.wordpress.org/Using_Permalinks#Permalinks_without_mod_rewrite">http://codex.wordpress.org/Using_Permalinks#Permalinks_without_mod_rewrite</a>

It sounds like not all systems use
Code:
.htaccess
. So directly editing the
Code:
.htaccess
file may not be the best choice for a distributed plugin. I don't know. Probably I have to check if the server uses Apache and if so I need to check whether .htacess is writable and existing rules do not have the adding rules, then at last I can append the rules to it. Also when the user deactivate the plugin, the rules have to be erased. So it's kind of troublesome.

If WordPress can handle it with a built-in API or something, I'd like to leave it to WordPress. But the above example was what I could have found so far. So I appreciate your information.

<strong>Update</strong>

As <em>pfefferle</em> suggested, I could use
Code:
$wp_rewrite-&gt;flush_rules()
. However, the problem #1 still persists; it won't take any effect when the default permalink settings is used. Any ideas?

Code:
/* Plugin Name: Sample Mod Rewrite  */

$custom_mod_rewrite = new custom_mod_rewrite;
register_activation_hook( __FILE__, array($custom_mod_rewrite, 'flush_rewrite_rules'));
register_deactivation_hook( __FILE__, array($custom_mod_rewrite, 'flush_rewrite_rules'));
add_action('generate_rewrite_rules', array($custom_mod_rewrite, "generate_rewrite_rules"));

class custom_mod_rewrite {
    function __construct() {
        $this-&gt;wp_rewrite = &amp; $GLOBALS["wp_rewrite"];
    }
    function flush_rewrite_rules() {
        $this-&gt;wp_rewrite-&gt;flush_rules();
    }
    function generate_rewrite_rules() {

        $non_wp_rules = array(
            'simple-redirect/?$plugin_name' =&gt; 'http://google.com',
            'one-more-redirect/?$plugin_name' =&gt; 'http://yahoo.com'
        );

        $this-&gt;wp_rewrite-&gt;non_wp_rules = $non_wp_rules + $this-&gt;wp_rewrite-&gt;non_wp_rules;
        add_filter('mod_rewrite_rules', array(&amp;$this, "mod_rewrite_rules"));
    }
    function mod_rewrite_rules($rules) {
        return preg_replace('#^(RewriteRule \^.*/)\?\$plugin_name .*(http://.*) \[QSA,L\]#mi', '$1 $2 [R=301,L]', $rules);
    }
}

Also, when deactivating the plugin, it doesn't change back to the previous rules. I just followed the codex example and just set it to flush the rules when deactivating the plugin. So there should be some code to delete the added rules.

As a side note, according to <a href="http://codex.wordpress.org/Function_Reference/flush_rewrite_rules">the codex</a>,

<blockquote>
Flushing the rewrite rules is an expensive operation, ... ... you should flush rewrite rules on the activation hook of a plugin, or when you know that the rewrite rules need to be changed
</blockquote>

<strong>Remaining Issues:</strong>

<ol>
<li>If it is set to the default permalink, it won't add the rules.</li>
<li>When deactivating the plugin, it doesn't change back to the previous rules.</li>
</ol>