Mise à niveau du plugin: paramètres du widget

9

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

Ce que j'ai fait jusqu'à présent et qui semble (surtout) fonctionner 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 devient que l'ancien widget n'affiche plus sa sortie. Seul le titre du widget s'affichera. Je peux résoudre ce problème en enregistrant chaque widget individuel, puis cela fonctionnera correctement, mais je ne veux pas que mes utilisateurs le fassent.

Je pensais que quelque chose comme ça pourrait fonctionner:

$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' save_settings()appel doit être incorrect car cela supprime complètement le widget.

J'ai du mal à trouver une sorte de norme pour quelque chose comme ça et je voudrais juste entendre les pensées, les idées ou les liens que vous pourriez avoir pour faire quelque chose comme ça.

Merci d'avance pour votre aide.

ÉDITER:

Il ne s'agit en fait pas d'une question sur le suivi des clés de licence ou la mise à niveau des plugins qui ne sont pas hébergés sur le dépôt WP. Il s'agit plus de mettre à jour les paramètres entre 2 versions d'un plugin lors de la mise à niveau d'un utilisateur.

Exemple:

la version 1.0.0 a un champ de réglage name

Eh bien, dans la version 1.1.0, nous décidons que nous avons besoin du prénom et du nom, nous changeons donc l'ancien paramètre first_nameet ajoutons un nouveau paramètre last_name.

Le transfert de ces options si elles sont enregistrées en tant que méta-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 que j'ai du mal avec cela ne semble pas être facile, c'est de faire la même chose, mais pour les paramètres WIDGET.

J'espère que cela dissipera toute confusion et contribuera à faciliter la réponse.

EDIT 2:

Résultat 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
)
Nick Young
la source
Je viens de voir cet article aujourd'hui sur Tutsplus, je n'ai même pas tout lu, mais il semble être votre allié. Créer un thème contrôlé par licence et un système de mise à jour de plugin
OnethingSimple
@OnethingSimple Merci pour la réponse mais cela ne ressemble pas vraiment à ce que je cherche. Je mettrai à jour la question pour la rendre plus claire.
Nick Young
Toute chance que nous puissions obtenir un vidage de ce à quoi ressemble la structure des paramètres du widget que vous lisez (même si vous devez changer certaines des valeurs). Cela pourrait aider à donner une idée de ce qui ne va pas. par exemple echo "<pre>". print_r ($ widget, true). "</pre>";
Privateer
@Privateer Ajoutée au bas de l'OP maintenant.
Nick Young

Réponses:

3

J'ai fait un test rapide sur juste changer l'option et cela semble fonctionner.

Ce que j'ai fait c'est:

  1. A écrit un widget qui n'a que 2 champs: "Titre" et "Nom". Ajoutez plusieurs instances de ce widget à mes barres latérales. Je suis sûr qu'ils sont affichés correctement en frontend.
  2. Modification de la classe pour utiliser 3 champs: "Titre" et "Prénom" (pour remplacer "Nom") et ajout de "Nom".
  3. Modifié la fonction qui enregistre le widget '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 édité la classe de widget pour enregistrer l'option "is_{$widget_name}_updated"dans la update()méthode, de cette façon la classe de mise à jour ne sera jamais appelée pour les nouveaux utilisateurs qui n'ont 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 en utilisant de nouvelles options. (Bien sûr, "nom" est toujours vide).

Une bonne idée peut être de remplacer l' "is_{$widget_name}_updated"option, par une option qui stocke la version réelle du widget, de cette façon, ce sera pratique la prochaine fois que vous aurez besoin d'une mise à jour.

gmazzap
la source
Donc, en regardant votre réponse sans la tester pour l'instant. Cela semble similaire à ce que j'ai fait en utilisant juste update_optioncorrect? Je me demande maintenant si le crochet compte peut-être? Je l'accroche au initcrochet. Y a-t-il une énorme différence en l'ajoutant au widgets_initcrochet à la place? J'étais à peu près sûr qu'ils tiraient en même temps. Merci de votre aide.
Nick Young le
@NickYoung Il n'y a aucune différence dans le crochet. Mais dans votre premier extrait de code (qui est similaire au mien), le second (intérieur) foreachest faux.
gmazzap
Je viens de mettre en œuvre le code que vous avez rédigé. Cela fonctionne très bien, mais je reçois toujours le même problème qu'auparavant. Il transfère les options avec succès, mais après avoir exécuté la routine de mise à niveau du plugin, le widget cesse de produire son code HTML principal et affiche uniquement le titre du widget. Si je vais dans les paramètres du widget et que je clique simplement sur le bouton Enregistrer, il réapparaîtra. Des pensées?
Nick Young
Pour ajouter à mon dernier commentaire. C'est comme si les options étaient correctement mises à jour, mais l'instance réelle ne l'est pas. Est-ce même une possibilité?
Nick Young
Non désactivé toute mise en cache. Également testé sur 2 hôtes différents avec le même problème.
Nick Young
1

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 plugin, vérifiez simplement un «ancien» paramètre et mappez-le à la «nouvelle» configuration à 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;
}
TheDeadMedic
la source
0

Tout en haut de ma tête, chaque instance d'un widget reçoit une sorte d'ID unique. Je veux dire que cela devient un prexfix pour les clés du widget.

Je me souviens d'avoir piqué ceci il y a quelque temps, mais je ne me souviens pas de la nature exacte, désolé.

Alchimiste en chef
la source