Aggiornamento plug-in: impostazioni del widget


9

Ho provato a fare qualche ricerca su questo, ma non ho ancora trovato nulla di solido. Ho un plug-in su cui sto lavorando e tra l'ultima versione e la nuova versione abbiamo apportato alcuni aggiornamenti al widget che modifica alcuni dei nomi delle impostazioni (sul back-end) e non riesco a creare una routine di aggiornamento per farlo.

Quello che ho fatto finora che sembra (principalmente) funzionare è questo:

$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 );
}

Nella maggior parte dei miei test questo funziona bene, ma il problema diventa che il vecchio widget non mostra più il suo output. Verrà mostrato solo il titolo del widget. Posso risolverlo andando e salvando ogni singolo widget e poi funzionerà bene, ma non voglio che i miei utenti lo facciano.

Ho pensato che qualcosa del genere potesse funzionare:

$settings = $widgets->get_settings();

foreach( $settings as $s ) {

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

    $widgets->save_settings( $s );

}

Ma sembra che la save_settings()chiamata debba essere sbagliata perché questo rimuove completamente il widget.

Ho difficoltà a trovare qualsiasi tipo di standard per qualcosa del genere e vorrei solo sentire pensieri, idee o collegamenti che potresti dover fare per fare qualcosa del genere.

Grazie in anticipo per qualsiasi aiuto.

MODIFICARE:

Questa non è in realtà una domanda sul tracciamento delle chiavi di licenza o sull'aggiornamento dei plugin che non sono ospitati nel repository WP. Di cosa si tratta è l'aggiornamento delle impostazioni tra la versione 2 di un plug-in quando un utente esegue l'aggiornamento.

Esempio:

la versione 1.0.0 ha un campo di impostazione name

Bene nella versione 1.1.0 decidiamo che abbiamo bisogno sia del nome che del cognome, quindi cambiamo la vecchia impostazione first_namee poi aggiungiamo una nuova impostazione last_name.

Il trasferimento di queste opzioni se salvato come meta post per un tipo di post personalizzato non è un problema:

$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' );

Quindi quella parte è facile. Ciò di cui sto avendo problemi sembra non essere facile è fare la stessa cosa ma per le impostazioni di WIDGET.

Speriamo che questo chiarisca ogni confusione e aiuti a rendere più semplice la risposta.

MODIFICA 2:

Risultato del echo '<pre>' . print_r( $widget, true ) . '</pre>';primo blocco di codice sopra:

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
)

Ho appena visto questo articolo oggi su Tutsplus, non ho nemmeno letto tutto, ma sembra essere il tuo alleato. Crea un sistema di aggiornamento di temi e plugin controllato da licenza
OnethingSemplice

@OnethingSimple Grazie per la risposta, ma non sembra proprio quello che sto cercando. Aggiornerò la domanda per renderla più chiara.
Nick Young,

Qualunque possibilità potremmo ottenere un dump di come appare la struttura delle impostazioni del widget che stai leggendo (anche se devi modificare alcuni dei valori). Ciò potrebbe aiutare a dare un'idea di cosa non va. ad esempio echo "<pre>". print_r ($ widget, true). "</ pre>";
Privato l'

@Privateer Ora aggiunto alla fine dell'OP.
Nick Young,

Risposte:


3

Ho fatto un rapido test sulla modifica dell'opzione e sembra funzionare.

Quello che ho fatto è:

  1. Ha scritto un widget che ha solo 2 campi: "Titolo" e "Nome". Aggiungi diverse istanze di questo widget alle mie barre laterali. Sono stato sicuro che sono mostrati correttamente in frontend.
  2. Modificata la classe per utilizzare 3 campi: "Titolo" e "Nome" (per sostituire "Nome") e aggiunto "Cognome".
  3. Modificata la funzione su cui è registrato il widget 'widgets_init'per chiamare una funzione che aggiorna le opzioni del 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. Ha scritto una semplice classe per aggiornare le opzioni del 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. Ho modificato la classe del widget per salvare l'opzione "is_{$widget_name}_updated"all'interno del update()metodo, in questo modo la classe di aggiornamento non verrà mai chiamata per i nuovi utenti che non hanno mai installato il vecchio 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. Ho visitato il mio sito e i widget salvati con vecchie opzioni vengono visualizzati senza problemi utilizzando nuove opzioni. (Ovviamente "cognome" è sempre vuoto).

Una buona idea potrebbe essere quella di sostituire l' "is_{$widget_name}_updated"opzione, con un'opzione che memorizza la versione attuale del widget, in questo modo sarà utile la prossima volta che avrai bisogno di un aggiornamento.


Quindi guarda la tua risposta senza provarla ancora. Sembra simile a quello che ho fatto usando solo update_optioncorretto? Mi chiedo ora se il gancio conta forse? Lo sto agganciando al initgancio. C'è invece un'enorme differenza aggiungendola al widgets_initgancio? Ero abbastanza sicuro che sparassero allo stesso tempo. Grazie per l'aiuto.
Nick Young,

@NickYoung Non c'è differenza nel gancio. Ma nel tuo primo frammento di codice (quello simile al mio) il secondo (interno) foreachè sbagliato.
gmazzap

Ho appena avuto la possibilità di implementare il codice che hai scritto. Funziona benissimo, ma sto ancora riscontrando lo stesso problema di prima. Trasferisce correttamente le opzioni, ma dopo aver eseguito la routine di aggiornamento per il plugin il widget smette di mostrare il suo HTML principale e mostra solo il titolo del widget. Se vado alle impostazioni del widget e faccio semplicemente clic sul pulsante Salva, viene nuovamente visualizzato. qualche idea?
Nick Young,

Da aggiungere al mio ultimo commento. È come se le opzioni fossero state aggiornate correttamente, ma l'istanza effettiva non lo è. È anche una possibilità?
Nick Young,

No disabilitato tutta la memorizzazione nella cache. Testato anche su 2 host diversi con lo stesso problema.
Nick Young,

1

Solo per pesare da un'angolazione diversa - piuttosto che aggiornare automaticamente tutte le impostazioni sull'aggiornamento del plugin, è sufficiente verificare al volo una "vecchia" impostazione e mappare le "nuove" impostazioni:

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;
}

0

In cima alla mia testa, a ogni istanza di un widget viene assegnata una sorta di ID univoco. Voglio dire che diventa un prefisso per le chiavi del widget.

Ricordo di averlo cercato qualche tempo fa, ma non ricordo quali fossero gli esatti, scusa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.