Est-il possible de forcer l'exécution du hook de mise à jour de votre module?

18

Je suis l'auteur du module Date iCal, et la nouvelle version majeure sur laquelle je travaille (3.x) nécessite une mise à jour du schéma en deux parties pour les utilisateurs qui ont installé 2.x. J'ai écrit le crochet de mise à jour qui apporte ces modifications, mais si l'un de mes utilisateurs ne parvient pas à exécuter le script de mise à jour de la base de données, il recevra un message d'erreur concernant ses importateurs de flux iCal.

La bonne solution est pour eux d'exécuter le script de mise à jour ... mais s'ils se contentent d'entrer et de changer manuellement leurs importateurs pour se débarrasser du message, leurs importateurs resteront définitivement interrompus (car la deuxième partie de la mise à jour du schéma ne le fera pas). ont été exécutés).

Existe-t-il un moyen d'afficher un message aux utilisateurs qui n'ont pas exécuté la mise à jour? Ou exécuter en quelque sorte de force le crochet de mise à jour la première fois qu'un chargement de page se produit lorsque 3.x est installé au-dessus de 2.x?

coredumperror
la source
2
J'imagine que vous pourriez faire variable_set()dans votre fonction de mise à jour qui définit une variable lorsqu'elle a été exécutée avec succès que vous pourriez regarder à l'intérieur d'un _preprocess_page()mais vous le regarderiez à chaque fois, donc vous ne savez pas à quel point cela serait convivial.
Jimajamma

Réponses:

4

prolongeant le commentaire de Jimajamma:

faire une variable_set()dans votre fonction de mise à jour qui définit une variable lors de son exécution réussie que vous pouvez regarder à l'intérieur d'une _preprocess_page ()

et au lieu de vérifier cela à chaque chargement de page, ne le faites que si vous parcourez la zone d'administration et si la version installée est 3.0 (3.1, 3.2, supprimez cette vérification si vous arrêtez de prendre en charge l'ancienne version comme chemin de mise à niveau).

Utilisez en outre hook_requirements pour fournir des commentaires sur la page de rapport d'état:

Vérifiez les exigences d'installation et effectuez des rapports d'état.
(...)
La phase «runtime» ne se limite pas aux exigences d'installation pure mais peut également être utilisée pour des informations d'état plus générales comme les tâches de maintenance et les problèmes de sécurité.

Andre Baumeier
la source
15

Il existe plusieurs façons de forcer la mise à jour du module.

  1. Appel direct de la fonction de mise à jour.

    $sandbox = [];
    module_load_include('install', 'FOO');
    FOO_update_7001($sandbox);
  2. Réinitialisation de la version du schéma au point d'intérêt et réexécutez les mises à jour comme d'habitude.

    drupal_set_installed_schema_version('module_name', '7000');

    Ou réinitialisez pour réexécuter uniquement le dernier schéma de mise à jour:

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

    Remarques:

    • Cela peut être placé hook_install, donc pendant le processus de mise à jour, tous les hooks de mise à jour séquentiels seront exécutés.
    • Pour utiliser cette fonction en dehors du fichier d'installation, vous devez inclure Drupal install.inc et le fichier d'installation du module, par exemple

      require_once DRUPAL_ROOT . '/includes/install.inc';
      module_load_include('install', 'foo');
    • Pensez à ajouter ini_set('max_execution_time', 0); des mises à jour d'installation plus longues pour éviter les délais d'attente PHP.
  3. Utilisation drush. Trouvez ci-dessous quelques exemples:

    • 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
la source
1
Oh bien, je ne savais pas drupal_set_installed_schema_version(). Ce serait super pratique pour déboguer les crochets de mise à jour!
coredumperror
1
Ainsi, le principal problème hook_install()lié à son intégration consiste à exécuter de longues mises à jour par lots (en bac à sable). Dans une situation idéale, il devrait y avoir un moyen de déclencher des mises à jour de la même manière update.phpqu'avec le redémarrage du thread PHP pour éviter les délais d'attente. Des idées de fourmis comment faire ça?
Alex Skrypnyk
@ Alex.Designworks Vous pouvez ajouter ini_set('max_execution_time', 0);avant de déclencher les mises à jour.
kenorb
1

(Reformulé en réponse)

Vous pouvez "SELECT schema_version FROM system" pour détecter si une mise à jour a été effectuée. Sinon, refusez d'exécuter (avec un message d'erreur).

user18099
la source
Veuillez reformuler votre réponse et essayer de donner un exemple d'utilisation.
Елин Й.
Ignorez ce commentaire.
coredumperror
Je crains que cela ne fonctionne pas, car la fonctionnalité en question est un plugin pour un autre module, et je ne peux pas empêcher ce module de laisser les utilisateurs jouer avec leurs importateurs.
coredumperror
Vous ne pouvez pas vérifier la version de schéma du module que vous avez l'intention de surveiller pour les mises à jour?
user18099
0

Je suis d'accord avec les suggestions ci-dessus - mon seul ajout serait d'enquêter sur les "déclencheurs et actions" également - il semble que vous ayez besoin d'une action (notifier l'utilisateur ou exécuter la mise à jour) pour se produire lorsqu'un déclencheur (l'utilisateur vérifie la page d'administration, etc.) est tiré . Pour des exemples d'utilisation, voir le module Exemples, il existe à la fois des exemples d'action et de déclenchement de code. :)

mechhfly
la source
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
la source