Czy można wymusić uruchomienie haka aktualizacji modułu?

18

Jestem autorem modułu Date iCal, a nowa główna wersja, nad którą pracuję (3.x) wymaga dwuczęściowej aktualizacji schematu dla użytkowników, którzy zainstalowali wersję 2.x. Napisałem hak aktualizacji, który wprowadza te zmiany, ale jeśli jeden z moich użytkowników nie uruchomi skryptu aktualizacji bazy danych, otrzyma komunikat o błędzie dotyczący importerów kanałów iCal.

Właściwym rozwiązaniem jest uruchomienie skryptu aktualizacji ... ale jeśli po prostu wejdą i ręcznie zmienią swoich importerów, aby pozbyć się wiadomości, ich importerzy pozostaną trwale uszkodzeni (ponieważ druga część aktualizacji schematu nie zostały stracone).

Czy jest więc jakiś sposób na wyświetlenie komunikatu użytkownikom, którzy nie uruchomili aktualizacji? Czy jakoś wymusić wykonanie haka aktualizacji przy pierwszym załadowaniu strony, gdy 3.x zostanie zainstalowany ponad 2.x?

Coredumperror
źródło
2
Wyobrażam sobie, że możesz zrobić variable_set()w swojej funkcji aktualizacji, która ustawia zmienną, kiedy została pomyślnie uruchomiona, którą możesz zajrzeć do wewnątrz, _preprocess_page()ale będziesz na nią patrzył za każdym razem, więc nie jestem pewien, czy byłaby to przyjazna dla wydajności.
Jimajamma,

Odpowiedzi:

4

rozszerzenie na komentarz Jimajammy:

wykonaj funkcję variable_set()aktualizacji, która ustawia zmienną, gdy została pomyślnie uruchomiona, którą możesz obejrzeć wewnątrz _preprocess_page ()

i zamiast sprawdzania tego na każdym ładowaniu strony, rób to tylko wtedy, gdy przeglądasz obszar administratora i jeśli zainstalowana jest wersja 3.0 (3.1, 3.2, zabij to sprawdzenie, jeśli przestaniesz obsługiwać starą wersję jako ścieżkę uaktualnienia).

Dodatkowo skorzystaj z hook_requirements, aby przekazać opinię na stronie raportu o stanie:

Sprawdź wymagania instalacyjne i wykonaj raportowanie statusu.
(...)
Faza „runtime” nie ogranicza się do czystych wymagań instalacyjnych, ale może być również wykorzystana do bardziej ogólnych informacji o stanie, takich jak zadania konserwacyjne i kwestie bezpieczeństwa.

Andre Baumeier
źródło
15

Istnieje kilka sposobów wymuszenia aktualizacji modułu.

  1. Bezpośrednie wywołanie funkcji aktualizacji.

    $sandbox = [];
    module_load_include('install', 'FOO');
    FOO_update_7001($sandbox);
  2. Resetowanie wersji schematu do interesującego miejsca i uruchamianie aktualizacji jak zwykle.

    drupal_set_installed_schema_version('module_name', '7000');

    Lub zresetuj, aby ponownie uruchomić tylko najnowszy schemat aktualizacji:

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

    Uwagi:

    • Można to umieścić hook_install, aby podczas procesu aktualizacji wykonywane były wszystkie sekwencyjne przechwyty aktualizacji.
    • Aby korzystać z tej funkcji poza plikiem instalacyjnym, musisz install.incnajpierw dołączyć Drupal i plik instalacyjny modułu, np

      require_once DRUPAL_ROOT . '/includes/install.inc';
      module_load_include('install', 'foo');
    • Rozważ dodanie ini_set('max_execution_time', 0);dłuższych aktualizacji instalacji, aby zapobiec przekroczeniu limitu czasu PHP.
  3. Korzystanie drush. Znajdź poniżej kilka przykładów:

    • 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
kenorb
źródło
1
Och, miło, nie wiedziałem o tym drupal_set_installed_schema_version(). To byłoby bardzo przydatne do debugowania haków aktualizacji!
coredumperror
1
Tak więc głównym problemem związanym z wprowadzaniem go hook_install()jest uruchamianie długich partii (piaskownicy). W idealnej sytuacji powinien istnieć sposób na uruchamianie aktualizacji w taki sam sposób, jak update.phpprzy ponownym uruchomieniu wątku PHP, aby zapobiec przekroczeniu limitu czasu. Pomysły na mrówki, jak to zrobić?
Alex Skrypnyk
@ Alex.Designworks Możesz dodać ini_set('max_execution_time', 0);przed uruchomieniem aktualizacji.
kenorb
1

(Przeredagowany na odpowiedź)

Możesz „WYBRAĆ wersję schematu z systemu”, aby wykryć, czy aktualizacja została wykonana. Jeśli nie, odmów uruchomienia (z komunikatem o błędzie).

użytkownik18099
źródło
Przeredaguj swoją odpowiedź i spróbuj podać przykład użycia.
Елин Й.
Zignoruj ​​ten komentarz.
coredumperror
Obawiam się, że to nie zadziała, ponieważ omawiana funkcjonalność jest wtyczką do innego modułu i nie mogę zapobiec temu, aby ten moduł pozwalał użytkownikom zadzierać z importerami.
coredumperror
Nie możesz sprawdzić wersji schematu modułu, który zamierzasz monitorować pod kątem aktualizacji?
user18099
0

Zgadzam się z powyższymi sugestiami - moim jedynym dodatkiem byłoby zbadanie „Wyzwalaczy i akcji” również - wydaje się, że potrzebujesz akcji (powiadom użytkownika lub uruchom aktualizację), aby nastąpiło po uruchomieniu wyzwalacza (użytkownik sprawdza stronę administratora itp.) . Przykłady użycia znajdują się w module Przykłady, istnieje zarówno przykładowy kod akcji, jak i wyzwalacza. :)

mechhfly
źródło
0

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

Alex Skrypnyk
źródło