web-dev-qa-db-fra.com

Mise à niveau du plugin: Paramètres du widget

J'ai essayé de faire des recherches à ce sujet mais je n'ai encore rien trouvé de solide. Je travaille sur un plugin et entre la dernière version et la nouvelle version, nous avons mis à jour le widget qui modifie certains noms de paramètres (sur le backend) et je ne parviens pas à créer une routine de mise à niveau pour le faire.

Ce que j’ai fait jusqu’à présent et qui semble fonctionner (principalement) est le suivant:

$widget = get_option( 'widget_name' );

if( is_array( $widget ) && ! empty( $widget ) ) {
    foreach( $widget as $a => $b ) {
        if( ! is_array( $b ) ) {
            continue;
        } 

        foreach( $b as $k => $v ) {
            $widget[$a]['setting1'] = $widget[$a]['oldsetting1'];
            $widget[$a]['setting2'] = $widget[$a]['oldsetting2'];
        }
    }

    update_option( 'widget_name', $widget );
}

Dans la plupart de mes tests, cela fonctionne bien, mais le problème est que l'ancien widget n'affiche plus sa sortie. Seul le titre du widget sera affiché. Je peux résoudre ce problème en enregistrant chaque widget individuellement, puis tout fonctionnera correctement, mais je ne veux pas que mes utilisateurs le fassent.

Je pensais que quelque chose comme ça pourrait marcher:

$settings = $widgets->get_settings();

foreach( $settings as $s ) {

    $s['setting1'] = $s['oldsetting1'];
    $s['setting2'] = $s['oldsetting2'];

    $widgets->save_settings( $s );

}

Mais il semble que l'appel save_settings() doit être incorrect car cela supprime entièrement le widget.

J'ai de la difficulté à trouver une norme quelconque pour quelque chose de ce genre et j'aimerais simplement connaître vos idées, idées ou liens pour faire quelque chose de ce genre.

Merci d'avance pour votre aide.

MODIFIER:

Ce n’est pas vraiment une question sur le suivi des clés de licence ou la mise à niveau de plug-ins qui ne sont pas hébergés sur le référentiel WP. Il s’agit plutôt de mettre à jour les paramètres entre 2 versions d’un plugin lorsqu’un utilisateur effectue une mise à niveau.

Exemple:

la version 1.0.0 a un champ de réglage name

Dans la version 1.1.0, nous décidons d’avoir besoin du prénom et du nom de famille. Nous avons donc modifié l’ancien paramètre en first_name, puis ajouté un nouveau paramètre last_name.

Transférer ces options si elles sont enregistrées en tant que méta de publication pour un type de publication personnalisé ne pose aucun problème:

$old_name = get_post_meta( $post->ID, 'name', true );
$first_name = update_post_meta ( $post->ID, 'first_name', true );
delete_post_meta( $post->ID, 'name' );

Donc, cette partie est facile. Ce qui me pose problème, cela ne semble pas être facile, c’est de faire la même chose, mais pour les paramètres WIDGET.

Espérons que cela dissipera toute confusion et qu’il sera plus facile de répondre.

EDIT 2:

Résultat de echo '<pre>' . print_r( $widget, true ) . '</pre>'; du premier bloc de code ci-dessus:

Array
(
[2] => Array
    (
        [title] => Class Schedule
        [id] => 23
        [display_type] => grid
        [order] => asc
        [display_title_text] => Events on
        [paging] => 1
        [list_max_num] => 7
        [list_max_length] => days
        [list_start_offset_num] => 0
        [list_start_offset_direction] => back
        [gce_per_page_num] => 7
        [gce_events_per_page] => days
    )

[3] => Array
    (
        [title] => Examples
        [id] => 24
        [display_type] => grid
        [order] => asc
        [display_title_text] => Events on
        [paging] => 1
        [list_max_num] => 7
        [list_max_length] => days
        [list_start_offset_num] => 0
        [list_start_offset_direction] => back
        [gce_per_page_num] => 7
        [gce_events_per_page] => days
    )

[_multiwidget] => 1
)
9
Nick Young

J'ai fait un test rapide en changeant simplement l'option et cela semble fonctionner.

Ce que j'ai fait c'est:

  1. Écrit un widget qui ne contient que 2 champs: "Titre" et "Nom". Ajoutez plusieurs instances de ce widget à mes barres latérales. Etes sûr qu'ils sont montrés correctement dans le frontend.
  2. Modifié la classe pour utiliser 3 champs: "Titre" et "Prénom" (pour remplacer "Nom") et ajouté "Nom".
  3. Édité la fonction qui enregistre le widget sur 'widgets_init' pour appeler une fonction qui met à jour les options du widget:

    add_action( 'widgets_init', 'my_example_widget_register' );
    
    function my_example_widget_register() {
    
      $widget_name = 'my_example_widget';  // <-- You will probably replace this
    
      $options = get_option("widget_{$widget_name}");
    
      // if the widget is not updated, run a function that updates it
      if ($options && ! get_option("is_{$widget_name}_updated")) {
          // use class below to update options
          $updater = new MyExampleWidgetUpdater($widget_name, $options);
          $updater->update();
      }
    
      register_widget('My_Example_Widget'); // <-- You will probably replace this
    }
    
  4. A écrit une classe simple pour mettre à jour les options du widget:

    class MyExampleWidgetUpdater
    {
    
      private $name;
      private $options;
    
      public function __construct($name, $options) {
         $this->name = $name;
         $this->options = $options;
      }
    
      public function update() {
        // loop all the options
        array_walk($this->options, function(&$option, $key) {
            if (is_array($option) && is_numeric($key)) {
              $option = $this->getOption($option);
            }
        });
        // update all options in DB
        update_option("widget_{$this->name}", $this->options);
        // set the widget as updated
        update_option("is_{$this->name}_updated", 1);
      }
    
      private function getOption($options) {
        if (!isset($options['name'])) {
           return $options;
        }
        $options['first_name'] = $options['name'];
        $options['last_name'] = '';
        unset($options['name']);
        return $options;
      }
    }
    
  5. J'ai modifié la classe de widgets pour enregistrer l'option "is_{$widget_name}_updated" dans la méthode update(). De cette manière, la classe de programme de mise à jour ne sera jamais appelée pour les nouveaux utilisateurs n'ayant jamais installé l'ancien widget.

    class My_Example_Widget {
    
        ...
    
        public function update($new_instance, $old_instance) {
            ...
    
            $widget_name = 'my_example_widget';
            update_option("is_{$widget_name}_updated", 1);
        }
    }
    
  6. J'ai visité mon site et les widgets enregistrés avec les anciennes options sont affichés sans problème avec les nouvelles options. (Bien sûr, "nom" est toujours vide).

Une bonne idée peut être de remplacer l'option "is_{$widget_name}_updated" par une option permettant de stocker la version réelle du widget. Ainsi, il sera pratique la prochaine fois que vous aurez besoin d'une mise à jour.

3
gmazzap

Juste pour peser sous un angle différent - plutôt que de mettre à jour automatiquement tous les paramètres lors de la mise à jour du plug-in, il suffit de rechercher un "ancien" paramètre et une carte avec les "nouveaux" paramètres à la volée:

function widget( $args, $instance ) {
    if ( isset( $instance['old_setting'] ) )
         $instance = self::_version_compat( $instance );
}

static function _version_compat( $instance ) {
    $instance['new_setting'] = $instance['old_setting'];
    // etc.

    return $instance;
}
1
TheDeadMedic

De mémoire, chaque instance d'un widget reçoit une sorte d'identifiant unique. Je veux dire que cela devient un prexfix des clés pour le widget.

Je me souviens de l'avoir piquée il y a quelque temps, mais je ne me souviens plus des chiffres exacts, désolée.

0
Chief Alchemist