อัปเกรดปลั๊กอิน: การตั้งค่าวิดเจ็ต


9

ฉันได้ลองทำวิจัยเรื่องนี้แล้ว แต่ยังไม่พบว่ามีอะไรที่แข็ง ฉันมีปลั๊กอินที่ฉันใช้งานและระหว่างเวอร์ชันล่าสุดและเวอร์ชันใหม่ที่เราได้ทำการปรับปรุงบางอย่างสำหรับวิดเจ็ตที่เปลี่ยนชื่อการตั้งค่าบางส่วน (ในแบ็กเอนด์) และฉันมีปัญหาในการสร้างรูทีนการอัพเกรดเพื่อทำสิ่งนี้

สิ่งที่ฉันได้ทำจนถึงตอนนี้ที่ดูเหมือนว่าจะทำงาน (ส่วนใหญ่) คือ:

$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()โทรจะต้องผิดเพราะจะลบเครื่องมือทั้งหมด

ฉันมีปัญหาในการค้นหามาตรฐานใด ๆ สำหรับสิ่งนี้และต้องการฟังความคิดความคิดหรือลิงก์ที่คุณอาจต้องทำอะไรแบบนี้

ขอบคุณล่วงหน้าสำหรับความช่วยเหลือใด ๆ

แก้ไข:

นี่ไม่ใช่คำถามเกี่ยวกับการติดตามคีย์ใบอนุญาตหรือการอัปเกรดปลั๊กอินที่ไม่ได้โฮสต์บน repo WP สิ่งนี้คือเพิ่มเติมเกี่ยวกับการอัปเดตการตั้งค่าระหว่างปลั๊กอิน 2 เวอร์ชันเมื่อผู้ใช้อัปเกรด

ตัวอย่าง:

รุ่น 1.0.0 มีช่องการตั้งค่า name

ดีในรุ่น 1.1.0 เราตัดสินใจที่เราจำเป็นต้องใช้ทั้งชื่อและนามสกุลดังนั้นเราจึงเปลี่ยนการตั้งค่าเก่าที่จะแล้วเพิ่มการตั้งค่าใหม่first_namelast_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' );

เพื่อให้ส่วนนั้นเป็นเรื่องง่าย สิ่งที่ฉันมีปัญหากับที่ดูเหมือนจะไม่ง่ายคือการทำสิ่งเดียวกัน แต่สำหรับการตั้งค่าเครื่องมือ

หวังว่านี่จะช่วยขจัดความสับสนและช่วยให้ตอบคำถามได้ง่ายขึ้น

แก้ไข 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
)

ฉันเพิ่งเห็นบทความนี้ใน Tutsplus วันนี้ฉันยังไม่ได้อ่านเลย แต่ดูเหมือนว่าจะเป็นพันธมิตรของคุณ สร้างชุดรูปแบบควบคุมลิขสิทธิ์และระบบอัปเดตปลั๊กอิน
OnethingSimple

@OnSimpleSimple ขอบคุณสำหรับการตอบกลับ แต่ไม่ได้ดูเหมือนว่าฉันจะทำอะไร ฉันจะอัปเดตคำถามเพื่อให้ชัดเจนยิ่งขึ้น
นิคยัง

โอกาสใดก็ตามที่เราสามารถรับดัมพ์ของโครงสร้างการตั้งค่าวิดเจ็ตที่ดูเหมือนว่าคุณกำลังอ่านอยู่ (แม้ว่าคุณจะต้องเปลี่ยนค่าบางอย่าง) นั่นอาจช่วยให้ทราบว่าเกิดอะไรผิดพลาดขึ้น เช่น echo "<pre>" print_r ($ widget, จริง) "</ pre>";
ส่วนตัว

@ ส่วนบุคคลต่อท้ายที่ด้านล่างของ OP ตอนนี้
นิคยัง

คำตอบ:


3

ฉันทำแบบทดสอบสั้น ๆ เกี่ยวกับการเปลี่ยนตัวเลือกและดูเหมือนว่าจะใช้งานได้

สิ่งที่ฉันทำคือ:

  1. เขียนวิดเจ็ตที่มีเพียง 2 ฟิลด์: "ชื่อ" และ "ชื่อ" เพิ่มอินสแตนซ์ต่าง ๆ ของวิดเจ็ตนี้ลงในแถบด้านข้างของฉัน ต้องแน่ใจว่าพวกเขาจะแสดงอย่างถูกต้องในส่วนหน้า
  2. แก้ไขคลาสเพื่อใช้ 3 ฟิลด์: "ชื่อ" และ "ชื่อ" (เพื่อแทนที่ "ชื่อ") และเพิ่ม "นามสกุล"
  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()เมธอดด้วยวิธีนี้คลาสตัวอัปเดตจะไม่ถูกเรียกใช้สำหรับผู้ใช้ใหม่ที่ไม่เคยติดตั้งวิดเจ็ตเก่า

    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"ตัวเลือกด้วยตัวเลือกที่เก็บรุ่นจริงของวิดเจ็ตด้วยวิธีนี้จะมีประโยชน์ในครั้งต่อไปที่คุณต้องการอัปเดต


ลองดูคำตอบของคุณโดยไม่ทดสอบเลย ดูเหมือนว่าฉันจะใช้update_optionถูกต้องหรือไม่ ฉันสงสัยว่าตอนนี้ถ้าเบ็ดสำคัญอาจ? ฉันขอไปที่initตะขอ มีความแตกต่างมากโดยการเพิ่มลงในwidgets_initตะขอแทนหรือไม่? ฉันค่อนข้างแน่ใจว่าพวกเขายิงออกในเวลาเดียวกัน ขอบคุณสำหรับความช่วยเหลือของคุณ.
Nick Young

@NickYoung ไม่มีความแตกต่างในเบ็ด แต่ในข้อมูลโค้ดแรกของคุณ (นั่นคือโค้ดที่คล้ายกับของฉัน) ส่วนที่สอง (ภายใน) foreachผิด
gmazzap

ฉันเพิ่งมีโอกาสใช้รหัสที่คุณเขียนขึ้น มันใช้งานได้ดี แต่ฉันยังคงมีปัญหาเช่นเดิมเมื่อก่อน มันถ่ายโอนตัวเลือกได้สำเร็จ แต่หลังจากรันรูทีนการอัปเกรดสำหรับปลั๊กอินวิดเจ็ตจะหยุดแสดงผลเป็น HTML หลักและแสดงเฉพาะชื่อของวิดเจ็ต ถ้าฉันไปที่การตั้งค่าวิดเจ็ตและเพียงแค่คลิกที่ปุ่มบันทึกจากนั้นก็จะปรากฏขึ้นอีกครั้ง ความคิดใด ๆ
นิคยัง

เพื่อเพิ่มความคิดเห็นล่าสุดของฉัน มันเหมือนมีการอัพเดทตัวเลือกอย่างถูกต้อง แต่อินสแตนซ์จริงไม่ใช่ นั่นเป็นความเป็นไปได้หรือไม่?
นิคยัง

Nope ปิดใช้งานการแคชทั้งหมด ทดสอบกับโฮสต์ที่แตกต่างกัน 2 แห่งด้วยปัญหาเดียวกัน
Nick Young

1

เพียงชั่งน้ำหนักจากมุมที่แตกต่าง - แทนที่จะอัปเดตการตั้งค่าทั้งหมดในการอัปเดตปลั๊กอินโดยอัตโนมัติเพียงตรวจสอบการตั้งค่า "แผนที่เก่า" และแผนที่เป็น "ใหม่" การตั้งค่าแบบทันที:

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

ด้านบนของหัวของฉันแต่ละอินสแตนซ์ของวิดเจ็ตจะได้รับ ID บางประเภทที่ไม่ซ้ำกัน ฉันอยากจะบอกว่ามันจะกลายเป็นคำนำหน้าของปุ่มสำหรับวิดเจ็ต

ฉันจำได้ว่าล้อเล่นเมื่อไม่นานมานี้ แต่จำไม่ได้ว่าอะไรคือคำขอโทษ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.