Actualización de complementos: configuración de widgets

9

He intentado investigar un poco sobre esto pero todavía no he encontrado nada sólido. Tengo un complemento en el que estoy trabajando y, entre la última versión y la nueva versión, hicimos algunas actualizaciones al widget que cambia algunos de los nombres de configuración (en el backend) y tengo problemas para crear una rutina de actualización para hacer esto.

Lo que he hecho hasta ahora que parece (en su mayoría) trabajo es lo siguiente:

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

En la mayoría de mis pruebas esto funciona bien, pero el problema es que el widget antiguo ya no muestra su salida. Solo se mostrará el título del widget. Puedo arreglar esto yendo y guardando cada widget individual y luego funcionará bien, pero no quiero que mis usuarios hagan eso.

Pensé que algo como esto podría funcionar:

$settings = $widgets->get_settings();

foreach( $settings as $s ) {

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

    $widgets->save_settings( $s );

}

Pero parece que la llamada save_settings() debe estar equivocada porque esto elimina el widget por completo.

Estoy teniendo problemas para encontrar algún tipo de estándar para algo como esto y me gustaría escuchar cualquier idea, idea o enlace que tengas que hacer algo como esto.

Gracias de antemano por cualquier ayuda.

EDITAR:

Esto no es realmente una pregunta sobre el seguimiento de las claves de licencia o la actualización de complementos que no están alojados en el repositorio de WP. De lo que se trata es de actualizar la configuración entre 2 versiones de un complemento cuando un usuario actualiza.

Ejemplo:

la versión 1.0.0 tiene un campo de configuración name

Bueno, en la versión 1.1.0 decidimos que necesitamos tanto el nombre como el apellido, por lo que cambiamos la configuración anterior a first_name y luego agregamos una nueva configuración last_name .

La transferencia de estas opciones si se guarda como meta de publicación para un tipo de publicación personalizada no es 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' );

Así que esa parte es fácil. Lo que estoy teniendo problemas con eso no parece ser fácil es hacer lo mismo pero para la configuración de WIDGET.

Esperamos que esto aclare cualquier confusión y ayude a que esto sea más fácil de responder.

EDIT 2:

Resultado de echo '<pre>' . print_r( $widget, true ) . '</pre>'; del primer fragmento de código anterior:

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
)
    
pregunta Nick Young 08.02.2015 - 20:55

3 respuestas

3

He hecho una prueba rápida con solo cambiar la opción y parece funcionar.

Lo que hice es:

  1. Escribió un widget que tiene solo 2 campos: "Título" y "Nombre". Añadir varias instancias de este widget a mis barras laterales. Asegúrese de que se muestran correctamente en la interfaz.
  2. Edite la clase para usar 3 campos: "Título" y "Nombre" (para reemplazar "Nombre") y agregó "Apellido".
  3. Edité la función que registra el widget en 'widgets_init' para llamar a una función que actualiza las opciones 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. Escribió una clase simple para actualizar las opciones 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. Edité la clase de widget para guardar la opción "is_{$widget_name}_updated" dentro del método update() , de esta manera nunca se llamará a la clase del actualizador para nuevos usuarios que nunca hayan instalado un widget antiguo

    class My_Example_Widget {
    
        ...
    
        public function update($new_instance, $old_instance) {
            ...
    
            $widget_name = 'my_example_widget';
            update_option("is_{$widget_name}_updated", 1);
        }
    }
    
  6. Visité mi sitio y los widgets guardados con las opciones anteriores se muestran sin problemas usando nuevas opciones. (Por supuesto, "apellido" siempre está vacío).

Una buena idea puede ser reemplazar la opción "is_{$widget_name}_updated" , con una opción que almacene la versión real del widget, de esta manera será útil la próxima vez que necesite una actualización.

    
respondido por el gmazzap 12.02.2015 - 17:08
1

Solo para realizar un pesaje desde un ángulo diferente, en lugar de actualizar automáticamente todas las configuraciones en la actualización del complemento, simplemente busque una configuración "antigua" & mapear a "nuevos" ajustes sobre la marcha:

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;
}
    
respondido por el TheDeadMedic 16.02.2015 - 14:23
0

Fuera de la parte superior de mi cabeza, a cada instancia de un widget se le asigna algún tipo de ID única. Quiero decir que se convierte en un prefijo para las claves del widget.

Recuerdo haberlo intentado hace un tiempo, pero no puedo recordar cuáles fueron los resultados, lo siento.

    
respondido por el Chief Alchemist 11.02.2015 - 03:55

Lea otras preguntas en las etiquetas