เป็นไปได้ไหมที่จะบังคับให้ hook การอัพเดทของโมดูลทำงานได้?


18

ฉันเป็นผู้เขียนโมดูล Date iCal และเวอร์ชันหลักใหม่ที่ฉันใช้งาน (3.x) ต้องมีการอัพเดตสกีมาสองส่วนสำหรับผู้ใช้ที่ติดตั้ง 2.x ฉันเขียนเบ็ดการอัพเดทที่ทำให้เกิดการเปลี่ยนแปลงเหล่านี้ แต่หากผู้ใช้ของฉันไม่สามารถเรียกใช้สคริปต์การอัพเดทฐานข้อมูลพวกเขาจะได้รับข้อความแสดงข้อผิดพลาดที่เกี่ยวข้องกับผู้นำเข้าฟีด iCal ของพวกเขา

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

ดังนั้นจะมีวิธีใดที่จะแสดงข้อความถึงผู้ใช้ที่ไม่ได้เรียกใช้การอัปเดต หรือบังคับให้ดำเนินการอัพเดตเบ็ดเสร็จครั้งแรกที่มีการโหลดหน้าเว็บเกิดขึ้นเมื่อ 3.x ได้รับการติดตั้งมากเกินไป 2.x?


2
ฉันคิดว่าคุณสามารถทำvariable_set()ในฟังก์ชั่นอัพเดทของคุณที่ตั้งค่าตัวแปรเมื่อมันทำงานได้สำเร็จซึ่งคุณสามารถมองเข้าไปข้างในได้_preprocess_page()แต่คุณจะมองมันทุกครั้งดังนั้นไม่แน่ใจว่าประสิทธิภาพการทำงานที่เป็นมิตรนี้จะเป็นอย่างไร
Jimajamma

คำตอบ:


4

ขยายความคิดเห็นจาก Jimajamma:

ทำvariable_set()ในฟังก์ชั่นอัปเดตของคุณที่ตั้งค่าตัวแปรเมื่อเรียกใช้สำเร็จซึ่งคุณสามารถดูภายใน _preprocess_page ()

และแทนที่จะตรวจสอบสิ่งนี้ในทุก ๆ หน้าโหลดทำได้เฉพาะเมื่อเรียกดูพื้นที่ผู้ดูแลระบบและหากเวอร์ชันที่ติดตั้งคือ 3.0 (3.1, 3.2 ให้ปิดการตรวจสอบนั้นหากคุณหยุดสนับสนุนเวอร์ชันเก่าเป็นเส้นทางอัพเกรด)

นอกจากนี้ยังใช้ประโยชน์จากhook_requirementsเพื่อให้ข้อเสนอแนะในหน้ารายงานสถานะ:

ตรวจสอบข้อกำหนดการติดตั้งและทำรายงานสถานะ
(... )
เฟส 'รันไทม์' ไม่ จำกัด เพียงข้อกำหนดการติดตั้งจริง แต่ยังสามารถใช้สำหรับข้อมูลสถานะทั่วไปเพิ่มเติมเช่นงานบำรุงรักษาและปัญหาด้านความปลอดภัย


15

มีหลายวิธีในการบังคับให้อัปเดตโมดูล

  1. เรียกใช้ฟังก์ชันการอัพเดทโดยตรง

    $sandbox = [];
    module_load_include('install', 'FOO');
    FOO_update_7001($sandbox);
  2. รีเซ็ตเวอร์ชันของสกีมาเป็นจุดสนใจและเรียกใช้การอัปเดตอีกครั้งตามปกติ

    drupal_set_installed_schema_version('module_name', '7000');

    หรือรีเซ็ตเพื่อให้รันเฉพาะสกีมาอัพเดตล่าสุดเท่านั้น:

    drupal_set_installed_schema_version('foo', drupal_get_installed_schema_version('foo') - 1);

    หมายเหตุ:

    • สิ่งนี้สามารถอยู่ในhook_installดังนั้นในระหว่างกระบวนการปรับปรุง hooks การปรับปรุงตามลำดับทั้งหมดจะถูกดำเนินการ
    • ในการใช้งานฟังก์ชั่นนี้นอกไฟล์ติดตั้งคุณจะต้องรวม Drupal install.incก่อนและไฟล์การติดตั้งของโมดูลเช่น

      require_once DRUPAL_ROOT . '/includes/install.inc';
      module_load_include('install', 'foo');
    • พิจารณาเพิ่มini_set('max_execution_time', 0);สำหรับการปรับปรุงการติดตั้งอีกต่อไปเพื่อป้องกัน PHP หมดเวลา
  3. drushการใช้ ค้นหาตัวอย่างด้านล่าง:

    • drush eval 'module_load_include('install', 'foo'); $s = []; foo_update_7001($s);'
    • drush sqlq "UPDATE system SET schema_version = 7000 WHERE name = 'foo'" && drush -y updb

1
โอ้ดีฉันไม่รู้จักdrupal_set_installed_schema_version()เลย นั่นเป็นประโยชน์อย่างยิ่งสำหรับการแก้ไขข้อผิดพลาดของ hooks การอัพเดท!
coredumperror

1
ดังนั้นปัญหาหลักในการใส่ลงในนั้นก็hook_install()คือการอัพเดทแบบต่อเนื่องเป็นชุด ในสถานการณ์ที่เหมาะควรมีวิธีที่จะทริกเกอร์การอัพเดตในลักษณะเดียวupdate.phpกับการรีสตาร์ทเธรด PHP เพื่อป้องกันการหมดเวลา ความคิดมดทำอย่างไร
Alex Skrypnyk

@ Alex.Designworks คุณสามารถเพิ่มini_set('max_execution_time', 0);ก่อนเรียกการอัพเดท
kenorb

1

(ได้รับคำตอบเป็นคำตอบ)

คุณสามารถ "เลือก schema_version จากระบบ" เพื่อตรวจสอบว่ามีการอัปเดตหรือไม่ ถ้าไม่เช่นนั้นปฏิเสธที่จะทำงาน


โปรดใส่คำตอบของคุณอีกครั้งและลองยกตัวอย่างการใช้งาน
ЕлинЙ

ละเว้นความคิดเห็นนี้
coredumperror

ฉันกลัวว่ามันจะไม่ทำงานเพราะฟังก์ชั่นดังกล่าวเป็นปลั๊กอินสำหรับโมดูลอื่นและฉันไม่สามารถป้องกันโมดูลนั้นไม่ให้ผู้ใช้สับสนกับผู้นำเข้า
coredumperror

คุณไม่สามารถตรวจสอบเวอร์ชั่นสกีมาของโมดูลที่คุณต้องการตรวจสอบการปรับปรุงได้หรือไม่
user18099

0

ฉันเห็นด้วยกับคำแนะนำข้างต้น - การเพิ่มเพียงอย่างเดียวของฉันคือการตรวจสอบ "ทริกเกอร์และการดำเนินการ" ด้วย - ดูเหมือนว่าคุณต้องการการกระทำ (แจ้งเตือนผู้ใช้หรือเรียกใช้การอัปเดต) เพื่อให้เกิดขึ้นเมื่อดึงทริกเกอร์ . สำหรับตัวอย่างการใช้งานให้ดูที่โมดูลตัวอย่างมีทั้งการทำงานและโค้ดตัวอย่าง :)


0

function MYMODULE_install() { $functions = get_defined_functions(); foreach ($functions['user'] as $function) { if (strpos($function, 'MYMODULE_update_') === 0) { call_user_func($function); } } }

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