Nâng cấp plugin: Cài đặt widget


9

Tôi đã thử thực hiện một số nghiên cứu về điều này nhưng vẫn chưa tìm thấy gì vững chắc. Tôi có một plugin tôi đang làm việc và giữa phiên bản mới nhất và phiên bản mới, chúng tôi đã thực hiện một số cập nhật cho tiện ích thay đổi một số tên cài đặt (trên phụ trợ) và tôi gặp khó khăn khi tạo thói quen nâng cấp để thực hiện việc này.

Những gì tôi đã làm cho đến nay dường như (hầu hết) làm việc là thế này:

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

Trong hầu hết các thử nghiệm của tôi, điều này hoạt động tốt, nhưng vấn đề là tiện ích cũ không còn hiển thị đầu ra nữa. Chỉ tiêu đề của widget sẽ hiển thị. Tôi có thể khắc phục điều này bằng cách đi và lưu từng tiện ích riêng lẻ và sau đó nó sẽ hoạt động tốt, nhưng tôi không muốn làm cho người dùng của mình làm điều đó.

Tôi nghĩ một cái gì đó như thế này có thể làm việc:

$settings = $widgets->get_settings();

foreach( $settings as $s ) {

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

    $widgets->save_settings( $s );

}

Nhưng có vẻ như save_settings()cuộc gọi phải sai vì điều này loại bỏ hoàn toàn widget.

Tôi gặp khó khăn khi tìm bất kỳ loại tiêu chuẩn nào cho một cái gì đó như thế này và chỉ muốn nghe bất kỳ ý tưởng, ý tưởng hoặc liên kết nào bạn có thể phải làm một cái gì đó như thế này.

Cảm ơn trước sự giúp đỡ nào.

BIÊN TẬP:

Đây thực sự không phải là một câu hỏi về việc theo dõi các khóa cấp phép hoặc nâng cấp các plugin không được lưu trữ trên repo WP. Điều này có nghĩa là cập nhật cài đặt giữa 2 phiên bản plugin khi người dùng nâng cấp.

Thí dụ:

phiên bản 1.0.0 có trường cài đặt name

Vâng, trong phiên bản 1.1.0, chúng tôi quyết định chúng tôi cần cả tên và họ để thay đổi cài đặt cũ thành first_namevà sau đó thêm cài đặt mới last_name.

Việc chuyển các tùy chọn này nếu được lưu dưới dạng meta bài đăng cho loại bài đăng tùy chỉnh là không có vấn đề:

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

Vì vậy, phần đó là dễ dàng. Điều tôi gặp khó khăn với điều đó dường như không dễ dàng là làm điều tương tự nhưng đối với các cài đặt WIDGET.

Hy vọng rằng điều này sẽ làm sáng tỏ bất kỳ sự nhầm lẫn và giúp làm cho điều này dễ trả lời hơn.

EDIT 2:

Kết quả echo '<pre>' . print_r( $widget, true ) . '</pre>';từ đoạn mã đầu tiên ở trên:

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
)

Tôi mới xem bài viết này hôm nay trên Tutsplus, tôi thậm chí chưa đọc hết, nhưng dường như nó là đồng minh của bạn. Tạo một hệ thống cập nhật plugin và chủ đề được kiểm soát giấy phép
Onet BreathSimple 11/2/2015

@Onet BreathSimple Cảm ơn bạn đã trả lời nhưng nó không hoàn toàn giống với những gì tôi sẽ làm. Tôi sẽ cập nhật câu hỏi để làm cho nó rõ ràng hơn.
Nick Young

Bất kỳ cơ hội nào chúng ta cũng có thể nhận được kết cấu của cấu trúc cài đặt widget trông giống như bạn đang đọc (ngay cả khi bạn phải thay đổi một số giá trị). Điều đó có thể giúp đưa ra một ý tưởng về những gì đang xảy ra. ví dụ tiếng vang "<pre>". print_r ($ widget, đúng). "</ pre>";
Privateer

@Privateer Được thêm vào dưới cùng của OP bây giờ.
Nick Young

Câu trả lời:


3

Tôi đã làm một bài kiểm tra nhanh về việc chỉ thay đổi tùy chọn và nó dường như hoạt động.

Những gì tôi đã làm là:

  1. Đã viết một widget chỉ có 2 trường: "Tiêu đề" và "Tên". Thêm một số phiên bản của tiện ích này vào thanh bên của tôi. Đã chắc chắn rằng chúng được hiển thị chính xác trong frontend.
  2. Đã chỉnh sửa lớp để sử dụng 3 trường: "Tiêu đề" và "Tên" (để thay thế "Tên") và thêm "Họ".
  3. Đã chỉnh sửa chức năng đăng ký widget 'widgets_init'để gọi một chức năng cập nhật các tùy chọn 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. Đã viết một lớp đơn giản để cập nhật các tùy chọn 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. Tôi đã chỉnh sửa lớp widget để lưu tùy chọn "is_{$widget_name}_updated"bên trong update()phương thức, theo cách này, lớp updater sẽ không bao giờ được gọi cho người dùng mới không bao giờ cài đặt widget cũ

    class My_Example_Widget {
    
        ...
    
        public function update($new_instance, $old_instance) {
            ...
    
            $widget_name = 'my_example_widget';
            update_option("is_{$widget_name}_updated", 1);
        }
    }
  6. Tôi đã truy cập trang web của mình và các tiện ích được lưu với các tùy chọn cũ được hiển thị mà không gặp sự cố khi sử dụng tùy chọn mới. (Tất nhiên "họ" luôn trống).

Một ý tưởng tốt có thể được thay thế "is_{$widget_name}_updated"tùy chọn, với tùy chọn lưu trữ phiên bản thực tế của tiện ích, theo cách này, nó sẽ hữu ích vào lần tới khi bạn cần cập nhật.


SO nhìn qua câu trả lời của bạn mà không cần kiểm tra nó. Nó có vẻ giống với những gì tôi đã làm chỉ với việc sử dụng update_optionđúng? Tôi đang tự hỏi bây giờ nếu vấn đề móc có thể? Tôi đang móc nó vào initcái móc. Có một sự khác biệt rất lớn bằng cách thêm nó vào widgets_inithook thay thế? Tôi khá chắc chắn rằng họ bắn ra cùng một lúc. Cảm ơn bạn đã giúp đỡ.
Nick Young

@NickYoung Không có sự khác biệt trong hook. Nhưng trong đoạn mã đầu tiên của bạn (đó là đoạn mã tương tự với mã của tôi) thì đoạn mã thứ hai (bên trong) foreachlà sai.
gmazzap

Tôi vừa có cơ hội để thực hiện mã bạn đã viết lên. Nó hoạt động rất tốt, nhưng tôi vẫn gặp vấn đề giống như tôi đã gặp trước đây. Nó chuyển các tùy chọn thành công, nhưng sau khi chạy thói quen nâng cấp cho plugin, tiện ích dừng xuất ra HTML chính và chỉ hiển thị tiêu đề của tiện ích. Nếu tôi đi đến cài đặt widget và chỉ cần nhấp vào nút lưu thì nó sẽ bật lên một lần nữa. Có suy nghĩ gì không?
Nick Young

Để thêm vào bình luận cuối cùng của tôi. Giống như các tùy chọn đang được cập nhật chính xác nhưng thực tế không phải vậy. Đó thậm chí là một khả năng?
Nick Young

Không có tất cả bộ nhớ đệm. Cũng đã thử nghiệm trên 2 máy chủ khác nhau với cùng một vấn đề.
Nick Young

1

Chỉ cần cân nhắc từ một góc độ khác - thay vì tự động nâng cấp tất cả các cài đặt khi cập nhật plugin, chỉ cần kiểm tra cài đặt & bản đồ "cũ" thành cài đặt "mới" khi đang di chuyển:

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

Ngoài đỉnh đầu của tôi, mỗi phiên bản của một tiện ích được cung cấp một số loại ID duy nhất. Tôi muốn nói rằng trở thành tiền tố cho các khóa cho widget.

Tôi nhớ chọc vào điều này một thời gian trước đây nhưng không thể nhớ những gì ngoại lệ, xin lỗi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.