问题描述

我已经尝试了一些研究,但还没有找到任何坚实的东西。我有一个我正在工作的插件,在最后一个版本和新版本之间,我们对更改某些设置名称 (在后端) 的窗口小工具进行了一些更新,我无法创建升级例程来执行此操作。

到目前为止,我所做的这个 (大部分) 工作是这样的:

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

在我的大部分测试中,这样做的确可以,但是问题就是旧的 widget 不再显示它的输出。只会显示小工具的标题。我可以通过去保存每个单独的小工具来解决这个问题,然后它会正常工作,但是我不想让我的用户做到这一点。

我以为这样的事情可能会起作用:

$settings = $widgets->get_settings();

foreach( $settings as $s ) {

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

    $widgets->save_settings( $s );

}

但是,似乎 save_settings()调用必须是错误的,因为这会完全删除该窗口。

我无法找到任何这样的标准,只是想听到任何想法,想法或链接,你可能要做这样的事情。

提前感谢任何帮助。

编辑:

这实际上并不是关于追踪许可证密钥或升级不在 WP repo 上托管的插件的问题。这更重要的是在用户升级时更新 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
)

最佳解决方案

我已经做了一个快速测试,只是改变选项,它似乎工作。

我所做的是:

  1. 写了一个只有 2 个字段的小工具:”Title” 和”Name” 。将这个小工具的几个实例添加到我的侧边栏。确保它们在前端正确显示。

  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. 我访问了我的网站,使用旧选项保存的小工具显示没有问题使用新的选项。 (当然”last name” 一直是空的) 。

一个好主意可能是替换"is_{$widget_name}_updated"选项,并具有存储实际版本的小工具的选项,这样,下次您需要更新时将会很方便。

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。