flush_rewrite_rules not working on plugin deactivation, invalid URLs not showing 404

i’m just about to release a community plug-in and have a few last anoying issues.

First, whenever i visit a page that would not be valid for the plugin, www.mydomain.com/forms/tester it will take me to a different page. What should happen, is the plugin code try and use the path ‘tester’, find there is no such file, and then return a page not found error.

Second, i am using AskApache RewriteRules viewer plugin to see my rules, and can see that even though i have deactivated my plug-in, rewrite rules remain ‘index.php?formid=$matches[1]’. I cant understand as i am flushing rewrite rules on plugin deactivation, and i know the function is being called. This gives the same affect as above, with incorrect URLs not going to 404 but instead going to other pages.

Is there anyway to fix this, so that if a wrong page is visited, 404 are thrown?

Code is currently hosted here: . http://www.unifiedmicrosystems.com/products-and-services/software-development/wordpress/jformer-for-wordpress/.

I am just waiting for wordpress.org access to upload the source there for general use. I have tried to copy a cut down version with relevant parts below.

Many thanks in advance,

Chris

class JFormerForWP
{
static $errors = false; /* for debugging */
static $pluginPath;  
static $pluginUrl;  

public static function makeFormFactory($id,$class)
{
    $classPath = self::$pluginPath . "/forms/{$class}.php";
    require_once $classPath; 
}

/* called each request */
public static function init()
{
    self::$pluginPath = dirname(__FILE__);  // Set Plugin Path  
    self::$pluginUrl = WP_PLUGIN_URL . '/jformer-for-wp/'; // Set Plugin URL  

    self::addRewriteRules();
    add_filter( 'query_vars', array(__CLASS__, 'addQueryVars'));
    add_action( 'template_redirect', array(__CLASS__, 'formDisplay'));

    add_action('wp_print_styles', array(__CLASS__, 'styles'));
    add_action('wp_print_scripts', array(__CLASS__, 'scripts') );
    add_shortcode('jformer', array(__CLASS__, 'shortcodeHandler'));

    add_action('wp_ajax_nopriv_jFormerForWp', array(__CLASS__, 'ajaxHandler'));
    add_action('wp_ajax_jFormerForWp', array(__CLASS__, 'ajaxHandler'));
    self::$errors = new WP_Error();
}

public static function ajaxHandler()
{   
    $formID = $_POST['jFormerId'];
    echo self::getForm($formID);
}

public static function shortcodeHandler($atts, $content)
{
    extract( shortcode_atts( array(
    'id' => '0',
    'class' => '',
    'text' => ''
    ), $atts ) );

    // echo 'dumping shortcode values. content: ' . $content . ', id: ' . $id . ', class: ' . $class . '<br >';

    $options = self::getOptions();
    $permastructString = $options['url_string'];
}

public static function getOptions()
{
    $options = get_option('jformer_options',array('url_string' => 'forms'));
    return $options;
}

public static function addRewriteRules()
{
    $options = self::getOptions();
    add_rewrite_rule( $options['url_string'] . '/?([^/]*)','index.php?formid=$matches[1]', 'top' ); 
}

public static function addQueryVars($vars)
{
    $vars[] = 'formid';
    return $vars;
}

public static function formDisplay()
{
}

public static function activate() 
{
    if (version_compare(PHP_VERSION, '5', '<'))
    {
        deactivate_plugins(basename(__FILE__));
    }

    self::addRewriteRules();
    flush_rewrite_rules(true);
}

public static function deactivate()
{

    delete_option('jformer_options');
    //$wp_rewrite->flush_rules(true);  
    flush_rewrite_rules(true);
}

public static function addAdminPage()
{
    add_options_page( 'jFormer', 'jFormer Plugin', 'manage_options', 'jFormerForWP', array( __CLASS__ , 'displayAdminPageHtml' ));
}

public static function adminInit()
{
    register_setting( 'jformer_options', 'jformer_options', array(__CLASS__,'validateOptions') );
    add_settings_section('jformer_main', 'jFormer Settings', array(__CLASS__,'sectionText'), 'jformer_main_options');
    add_settings_field('jformer_url_string', 'Rewrite String', array(__CLASS__,'displayUrlStringSetting'), 'jformer_main_options', 'jformer_main');
    add_action('admin_notices', array(__CLASS__,'displayAdminNotices'));  
}

public static function sectionText()
{
    echo '<p>Main description</p>';
}

public static function displayUrlStringSetting()
{
    $options = self::getOptions();
    echo "<input id='jformer_url_string' name="jformer_options[url_string]" size="40" type="text" value="{$options["url_string']}' />";
}

public static function validateOptions($input)
{
    $input['url_string'] = trim($input['url_string']);

    if(!preg_match('/^[a-z0-9]{1,}$/i', $input['url_string']))
    {
        add_settings_error('jFormerForWP', 'url_string_error', 'Invalid URL string, please fix ensure string consists of alphanumeric characters only and is at least 1 character long', 'error' );
    }
    else
    {
        // add_settings_error('jFormerForWP', 'url_string_updated', 'String updated', 'updated' );
        $validatedOptions['url_string'] = $input['url_string'];
    }

    return $validatedOptions;
}

public static function registerAdminSettings()
{
        register_setting('JFormerForWPSettings', 'JFormerForWPSettings_option1');

}

public static function displayAdminPageHtml()
{   
    ?>
    <div class="wrap">
        <h2>jFormer for WordPress Plugin Options</h2>
        Options relating to the Custom Plugin.
        <form action="options.php" method="post">
            <?php   
            settings_fields('jformer_options'); ?>
            <?php do_settings_sections('jformer_main_options'); ?>
            <input name="Submit" type="submit" value="<?php esc_attr_e('Save Changes'); ?>" />
        </form>
    </div>
    <?php
}

function showMessage($message, $msgclass="updated")
{  
    echo "<div id='message' class="$msgclass">$message</div>";  
}  

public static function insertSettingsLink($links)
{
    $settings_link = '<a href="https://wordpress.stackexchange.com/questions/36152/options-general.php?page=JFormerForWP">'.__('Settings','JFormerForWP').'</a>'; 
     array_unshift( $links, $settings_link ); 
     return $links; 
}

public static function styles()
{       
    wp_enqueue_style('jformer', self::$pluginUrl. 'css/style.css');
}

public static function scripts()
{
    wp_enqueue_script('jformer', self::$pluginUrl . 'jFormer/jFormer.js',array('jquery'));
}
}

register_activation_hook(__FILE__, array('JFormerForWP','activate'));
register_deactivation_hook(__FILE__, array('JFormerForWP','deactivate'));
add_action('init', 'JFormerForWP::init');
add_action('admin_init', 'JFormerForWP::adminInit');
add_action('admin_menu', 'JFormerForWP::addAdminPage');
?>

3 Answers
3

Have you tried delete_option('rewrite_rules'); on deactivate? I came across the following when investigating this problem and it did the trick for me:

Typically you register post types on init. Some time after that, you
get the deactivation action. A responsible plugin would remove its
rewrite rules by flushing. However, it can’t undo the registration, so
the flush doesn’t remove the plugin’s rewrites.

The hacky workaround I’ve used is to just delete the rewrite_rules
option on deactivation. They will be generated again when they are
needed, so the only noticeable effect is that the next site view may
take a bit longer.

Have a look at http://core.trac.wordpress.org/ticket/14761#comment:12 for a discussion on this topic.

Leave a Comment