web-dev-qa-db-fra.com

Lancement de la nouvelle version du plugin, comment renommer les anciennes clés d’options?

Tout est prêt pour la publication d'une nouvelle version de mon plugin, mais un dernier numéro est en suspens ...

L'ancienne version n'avait pas de convention de dénomination pour ses noms d'options clés.

Les options se sont multipliées et je les ai toutes renommées, en utilisant des préfixes dans l’intérêt des bonnes pratiques de codage et de ma propre santé mentale.

J'ai pensé mettre un avertissement dans la description et le Changelog, mais je pense que ce serait plus doux si je pouvais créer une méthode d'importation interne.

Donc, c'est la question:

  • comment exécuter une fonction sur la mise à jour du plugin?
  • et comment vérifier si $ myOptions ['old_key'] existe, passez-la à $ myOptions ['new_key'] et supprimez finalement old_key

merci,

6
brasofilo

Vous devriez stocker un numéro de version pour votre plugin dans la base de données (si vous ne le faites pas déjà, ajoutez ceci pronto), en utilisant ce que vous pouvez faire (notez qu'il s'agit d'un 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
}

Ensuite, lorsque vous publiez votre prochaine mise à jour, vous remplacez $current_version par la version dans laquelle le changement a eu lieu. L’utilisation de cette méthode tient au fait que si vos mises à jour sont incrémentielles (c’est-à-dire que vous ne pouvez pas passer de 1.1 à 1.9, vous devez taper 1.3 et 1.5 entre eux ou quelque chose comme ça), vous aurez une structure. en place pour gérer cela. Si cela devient complexe, je garderai souvent le code propre et laisserai simplement l'instruction if exécuter quelque chose comme wpse49717_plugin_release_150() et gérer les mises à jour, etc.

Je voudrais juste noter (et bien, vraiment, réitérer) que vous ne devriez utiliser cette structure que pour vos mises à jour incroyables. Vous devez absolument vous attendre à ce que ce code ne soit exécuté qu'une seule fois. Assurez-vous donc que vous mettez à jour vos versions de base de données, etc.

3
mor7ifer

Voici une approche plus agréable et plus automatisée (après cette réponse ):

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; 

  }    

}

Le premier appel à $this->getOptions() fera toutes les mises à jour nécessaires selon vos options. Les seules choses que vous devez ajuster sont la variable constantes/$ default.

3
onetrickpony

Voici le résumé de la façon dont j'ai résolu le problème. Le déclencheur de la mise à jour des options est de vérifier si la nouvelle option "version" est présente ou non. Et à partir de maintenant, je peux faire une version de comparaison si nécessaire.

(Je ne sais pas si répondre à ma propre question est la bonne chose à faire, ou s'il serait préférable de mettre à jour la 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);

    }
}
1
brasofilo