Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have everything ready for publishing a new version of my plugin but one last issue stands...

The old version had no naming convention for its key option names.

The options grew and I renamed all of them, using prefixes for the sake of good coding practice and my own sanity.

I thought of putting a warning in the Description and the Changelog, but I think it would be gentler if I could make an internal import method.

So, that's the question:

  • how to run a function on plugin update?
  • and how to check if $myOptions['old_key'] exists, pass it value to $myOptions['new_key'] and finally delete the old_key

thanks,

share|improve this question
1  
it sounds like you know what you need to do. see here for the function hook I think you are looking for. I believe when upgrading a plugin it will fire the activation hook after installing the new version. –  Evan Mattson Apr 21 '12 at 2:09
    
@EvanMattson: yes, I got the general idea, only missing the right tools... I guess the register_activation_hook coupled with m0r7if3r answer will get the job done –  brasofilo Apr 21 '12 at 11:09
    
@EvanMattson: nope, register_activation_hook doesn't fire on plugin upgrade.. it wasn't working in my tests and scribu touches the issue here –  brasofilo Apr 21 '12 at 21:01
add comment

3 Answers

up vote 2 down vote accepted

You should store a version number for your plugin in the database (if you don't already, add this pronto), using that you can do this (note that this is pseudocode):

if( $db_version < {your desired version} ) {
    // previous updates and such
    $db_version = $new_version; //put that in the database
}
if( $db_version < $current_version ) {
    create $options array
    foreach( $option as $o ) {
        if( get_option( $o['old_name'] ) ) {
            update_option( $o['new_name'], get_option( $o['old_name'] ) );
            delete_option( $o['old_name'] ); //clean up behind yourself
        }
    }
    and then update your database version again
}

Then, when you release your next update, you change $current_version to the version in which the change happened. The reason behind using this method is that if your updates are ever incrimental (which is to say, you can't go from 1.1 to 1.9, you have to hit 1.3 and 1.5 in between or something like that), you will have a structure in place to manage that. If it gets complex, I'll often keep the code clean and just have the if statement execute something like wpse49717_plugin_release_150() and manage the updates and such with that.

I'd just like to note (well, really, reiterate) that you should only be using this structure for your incrimental updates. You should wholly expect this code to only be run ONCE, so make sure you're updating your database versions and such.

share|improve this answer
    
thanks for the nice input, I'll adapt your code inside a register_activation_hook, as suggested by Evan Mattson, and will set up a github to test it before going live in WP repository... I'll get back as soon as I have the results (hopefully, and most surely, positive), thanks! –  brasofilo Apr 21 '12 at 11:13
    
If this was your solution, please mark it as such to help those with the same issue who find this question. –  m0r7if3r Apr 21 '12 at 16:56
    
hi, m0r7if3r, sorry, i'm still testing, but yes, that's the way to go... I'll mark it right now, thanks again –  brasofilo Apr 21 '12 at 17:00
add comment

Here's the summary of how I solved the issue. The trigger for updating the options is to check if the new option "version" is present or not. And from now on, I can do a version compare if needed.

(I'm not sure if answering my own question is the right thing to do, or if it'd be better to update the question....)

class MyPlugin {
    var $adminOptionsName = "MyPlugin";

    function MyPlugin() {
    }

    function init() {
        $this->getAdminOptions();
    }

    function getAdminOptions() {

        // New options and values
        $theNewOptions = array(
            'option_1' => 0,
            'option_2' => '',
            'version'  => '1.0'
        );

        // Grab the options in the database
        $theOptions = get_option($this->adminOptionsName);

        // Check if options need update
        if( !isset($theOptions['version']) && !empty($theOptions) ) {
            foreach( $theOptions as $key => $value ) {
                if( $key == 'not_needed' ) {
                    unset( $theOptions[$key] );
                }
                if( $key == 'old_option_1') {
                    $theOptions['option_1'] = $value;
                    unset( $theOptions[$key] );
                }
                // etc...
            }
        }

        // Proceed to the normal Options check
        if (!empty($theOptions)) {
            foreach ($theOptions as $key => $option) {
                $theNewOptions[$key] = $option;
            }
        }

        update_option($this->adminOptionsName, $theNewOptions);

    }
}
share|improve this answer
add comment

Here's a nicer, more automated approach (following this answer):

class MyPlugin{

  const 
    OPTION_NAME = 'my_plugin_options',
    VERSION     = '1.0';

  protected
    $options  = null,

    // default options and values go here
    $defaults = array(
                  'version'     => self::VERSION, // this one should not change
                  'test_option' => 'abc',
                  'another_one' => 420, 
                );

  public function getOptions(){

    // already did the checks
    if(isset($this->options))
      return $this->options;    

    // first call, get the options
    $options = get_option(self::OPTION_NAME);

    // options exist
    if($options !== false){

      $new_version = version_compare($options['version'], self::VERSION, '!=');
      $desync = array_diff_key($this->defaults, $options) !== array_diff_key($options, $this->defaults);

      // update options if version changed, or we have missing/extra (out of sync) option entries 
      if($new_version || $desync){

        $new_options = array();

        // check for new options and set defaults if necessary
        foreach($this->defaults as $option => $value)
          $new_options[$option] = isset($options[$option]) ? $options[$option] : $value;        

        // update version info
        $new_options['version'] = self::VERSION;

        update_option(self::OPTION_NAME, $new_options);
        $this->options = $new_options;  

      // no update was required
      }else{
        $this->options = $options;     
      }


    // new install (plugin was just activated)
    }else{
      update_option(self::OPTION_NAME, $this->defaults);
      $this->options = $this->defaults; 
    }

    return $this->options; 

  }    

}

First call to $this->getOptions() will do all the necessary updates to your options. The only things you need to adjust are the constants / $defaults variable.

share|improve this answer
    
thanks for über professional approach –  brasofilo Apr 22 '12 at 16:56
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.