web-dev-qa-db-ja.com

プラグインのアップグレード:ウィジェット設定

私はこれについていくつかの研究をしてみましたが、まだ確かなことは何も見つけていません。私は作業中のプラグインを持っていて、前回のバージョンと新しいバージョンの間で(バックエンドで)いくつかの設定名を変更するウィジェットにいくつかの更新を行いました。

私がこれまでにやったことは、(ほとんど)うまくいくように思えます。

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

私のテストのほとんどでこれはうまくいきますが、問題は古いウィジェットがもはやその出力を表示しないことになります。ウィジェットのタイトルだけが表示されます。個々のウィジェットを保存して保存すれば問題は解決しますが、問題なく動作しますが、ユーザーにそうさせたくありません。

私はこのような何かがうまくいくかもしれないと思った:

$settings = $widgets->get_settings();

foreach( $settings as $s ) {

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

    $widgets->save_settings( $s );

}

しかし、これはウィジェットを完全に削除するので、save_settings()呼び出しは間違っていなければならないようです。

私はこのような何かのための標準の種類を見つけるのに苦労していて、ちょうどあなたがこのような何かをするために持っているかもしれないどんな考え、アイデア、またはリンクも聞きたいです。

ご協力ありがとうございます。

編集:

これは、実際にはライセンスキーの追跡やWPリポジトリでホストされていないプラグインのアップグレードに関する問題ではありません。これがより詳細なのは、ユーザーがアップグレードしたときに2つのバージョンのプラグインの間で設定を更新することです。

例:

バージョン1.0.0には設定フィールドnameがあります

バージョン1.1.0では、姓と名の両方が必要なので、古い設定をfirst_nameに変更してから、新しい設定last_nameを追加します。

カスタム投稿タイプの投稿メタとして保存されている場合、これらのオプションを転送しても問題ありません。

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

だからその部分は簡単です。私がそれで問題を抱えているのは容易ではないように思われますがWIDGET設定のためにこれと同じことをすることです。

うまくいけば、これで混乱が解消され、答えやすくなります。

編集2:

上記の最初のコードチャンクからのecho '<pre>' . print_r( $widget, true ) . '</pre>';の結果:

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

オプションを変更するだけの簡単なテストをしましたが、うまくいくようです。

私がしたことは、

  1. 「タイトル」と「名前」の2つのフィールドしかないウィジェットを作成しました。このウィジェットのいくつかのインスタンスをサイドバーに追加します。フロントエンドで正しく表示されていることを確認しました。
  2. 3つのフィールドを使用するようにクラスを編集しました: "Title"と "First Name"( "Name"を置き換えるため)と "Last Name"を追加しました。
  3. ウィジェットのオプションを更新する関数を呼び出すために、ウィジェットを'widgets_init'に登録する関数を編集しました。

    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. ウィジェットオプションを更新するための簡単なクラスを書きました:

    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. 私はウィジェットクラスを編集してオプション"is_{$widget_name}_updated"update()メソッド内に保存しています。このようにして、古いウィジェットをインストールしたことがない新しいユーザーに対してupdaterクラスが呼び出されることは決してありません

    class My_Example_Widget {
    
        ...
    
        public function update($new_instance, $old_instance) {
            ...
    
            $widget_name = 'my_example_widget';
            update_option("is_{$widget_name}_updated", 1);
        }
    }
    
  6. 私は自分のサイトにアクセスし、古いオプションで保存されたウィジェットは新しいオプションを使っても問題なく表示されています。 (もちろん、「姓」は常に空です)。

"is_{$widget_name}_updated"オプションを実際のバージョンのウィジェットを格納するオプションに置き換えることをお勧めします。こうすれば、次回の更新が必要になったときに便利です。

3
gmazzap

プラグインの更新時にすべての設定を自動アップグレードするのではなく、異なる角度から検討するために、単に「古い」設定をチェックして「新しい」設定にマップします。

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

私の頭の上では、ウィジェットの各インスタンスにある種の固有のIDが与えられています。私はそれがウィジェットのキーの接頭辞になると言いたい。

私はしばらく前にこのことを突っついたのを覚えていますが、その厳しさが何であったのか覚えていません、申し訳ありません。

0
Chief Alchemist