Upgrade de Plugin: Configurações de Widget

9

Eu tentei fazer algumas pesquisas sobre isso, mas ainda não encontrei nada sólido. Eu tenho um plugin que estou trabalhando e entre a última versão ea nova versão fizemos algumas atualizações para o widget que altera alguns dos nomes das configurações (no backend) e estou tendo problemas para criar uma rotina de atualização para fazer isso.

O que eu fiz até agora que parece funcionar (principalmente) é este:

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

Na maioria dos meus testes isso funciona ok, mas o problema é que o widget antigo não exibe mais sua saída. Apenas o título do widget será exibido. Eu posso consertar isso indo e salvando cada widget individual e então ele funcionará bem, mas eu não quero que meus usuários façam isso.

Eu pensei que algo assim poderia funcionar:

$settings = $widgets->get_settings();

foreach( $settings as $s ) {

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

    $widgets->save_settings( $s );

}

Mas parece que a chamada save_settings() deve estar errada porque isso remove completamente o widget.

Estou tendo problemas para encontrar qualquer tipo de padrão para algo assim e gostaria apenas de ouvir ideias, ideias ou links que você possa ter para fazer algo assim.

Agradecemos antecipadamente por qualquer ajuda.

EDITAR:

Esta não é uma questão sobre o rastreamento de chaves de licença ou atualização de plugins que não estão hospedados no repositório do WP. O que é mais sobre isso é atualizar as configurações entre a versão 2 de um plugin quando um usuário atualiza.

Exemplo:

A versão 1.0.0 possui um campo de configuração name

Bem, na versão 1.1.0, decidimos que precisamos do primeiro e do último nome, então alteramos a configuração antiga para ser first_name e, em seguida, adicionamos uma nova configuração last_name .

A transferência dessas opções, se salvas como pós meta para um tipo de postagem personalizado, não é 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' );

Então essa parte é fácil. O que eu estou tendo problemas com isso parece não ser fácil é fazer a mesma coisa, mas para as configurações do WIDGET.

Espero que isso elimine qualquer confusão e ajude a tornar isso mais fácil de responder.

EDIT 2:

Resultado de echo '<pre>' . print_r( $widget, true ) . '</pre>'; do primeiro bloco de código acima:

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

3 respostas

3

Eu fiz um teste rápido em apenas mudar a opção e parece funcionar.

O que eu fiz é:

  1. Escreveu um widget que tem apenas dois campos: "Título" e "Nome". Adicione várias instâncias deste widget às minhas barras laterais. Tenha certeza de que eles são exibidos corretamente no frontend.
  2. Editou a turma para usar 3 campos: "Título" e "Nome" (para substituir "Nome") e adicionou "Sobrenome".
  3. Editou a função que registra o widget em 'widgets_init' para chamar uma função que atualiza as opções do 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. Escreveu uma classe simples para atualizar as opções de widgets:

    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. Eu editei a classe widget para salvar a opção "is_{$widget_name}_updated" dentro do método update() , desta forma a classe do atualizador nunca será chamada para novos usuários que nunca instalaram o widget antigo

    class My_Example_Widget {
    
        ...
    
        public function update($new_instance, $old_instance) {
            ...
    
            $widget_name = 'my_example_widget';
            update_option("is_{$widget_name}_updated", 1);
        }
    }
    
  6. Eu visitei meu site e os widgets salvos com opções antigas são exibidos sem problemas usando novas opções. (Claro que "sobrenome" está sempre vazio).

Uma boa ideia pode ser substituir a opção "is_{$widget_name}_updated" , com uma opção que armazena a versão real do widget, desta forma será útil na próxima vez que você precisar de uma atualização.

    
por gmazzap 12.02.2015 / 17:08
1

Apenas para ponderar de um ângulo diferente - em vez de atualizar automaticamente todas as configurações na atualização do plug-in, basta verificar se há uma configuração "antiga" & mapeie para "novas" configurações on-the-fly:

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

Na minha cabeça, cada instância de um widget recebe algum tipo de ID exclusivo. Eu quero dizer que se torna um prexfix para as chaves do widget.

Eu me lembro de cutucá-lo há algum tempo, mas não consigo me lembrar quais eram as exatas, desculpe.

    
por Chief Alchemist 11.02.2015 / 03:55