Crochets thématiques vs crochets de modules

10

Parfois, lorsque j'essaie d'appliquer un hook, juste pour réaliser qu'il est censé être dans un fichier de module.

Existe-t-il un moyen de savoir quels crochets peuvent être implémentés dans le fichier template.php d'un thème ou dans un module?

hamahama
la source
4
Généralement, lorsqu'un crochet n'est pas disponible pour être remplacé dans un thème, c'est pour une bonne raison. Les thèmes ne doivent concerner que le code relatif à l'affichage du contenu et des fonctionnalités fournis par les modules. Le code qui ajoute / supprime / modifie des fonctionnalités ou du contenu devrait généralement se trouver dans un module. Pensez également au fait que si vous changez de thème, vous perdez toutes les personnalisations effectuées dans template.php, donc si vous apportez des modifications que vous voudrez probablement conserver si vous changez de thème, vous voudrez certainement aller dans un module.
rooby

Réponses:

11

De manière générale, seuls les hooks alter peuvent être implémentés par des thèmes, ce qui signifie des hooks comme hook_form_alter()et hook_menu_alter(), ou en bref tous les hooks qui sont invoqués drupal_alter()dans Drupal 7 et inférieurs ( ModuleHandler()::alter()ou ThemeManager::alter()dans Drupal 8).

D'autres hooks, qui sont invoqués par module_invoke_all()( ModuleHandler::invokeAll()dans Drupal 8), ne sont pas invoqués pour les thèmes simplement parce que le code ne vérifie pas si le thème actuellement activé définit un hook.

  foreach (module_implements($hook) as $module) {
    $function = $module . '_' . $hook;
    if (function_exists($function)) {
      $result = call_user_func_array($function, $args);
      if (isset($result) && is_array($result)) {
        $return = array_merge_recursive($return, $result);
      }
      elseif (isset($result)) {
        $return[] = $result;
      }
    }
  }

Dans Drupal 8, où la ModuleHandlerclasse invoque des hooks implémentés à partir de modules et la ThemeManagerclasse invoque des hooks implémentés par des thèmes, seule la première classe implémente invoke()et invokeAll(). Cela signifie que dans Drupal 8, les hooks de thème ne sont pas invoqués par Drupal core.

Ceci est valable pour les hooks de base Drupal, et surtout tous les hooks utilisés par les modules tiers. Il appartient ensuite à un module de vérifier qu'un hook est également implémenté par un thème et de l'invoquer. C'est ce que fait le module Vues.

  // Let modules modify the view just prior to rendering it.
  foreach (module_implements('views_pre_render') as $module) {
    $function = $module . '_views_pre_render';
    $function($this);
  }

  // Let the themes play too, because pre render is a very themey thing.
  foreach ($GLOBALS['base_theme_info'] as $base) {
    $function = $base->name . '_views_pre_render';
    if (function_exists($function)) {
      $function($this);
    }
  }
  $function = $GLOBALS['theme'] . '_views_pre_render';
  if (function_exists($function)) {
    $function($this);
  }

Pour les hooks utilisés par des modules tiers, vous devez vérifier le code utilisé pour les appeler. Il est probable que seuls les hooks alter soient invoqués pour les thèmes, mais dans certains cas, d'autres hooks peuvent également être implémentés par les thèmes.
Gardez à l'esprit que dans le cas des thèmes, tous les thèmes activés ne sont pas vérifiés pour les implémentations de hook, contrairement à ce qui se passe avec les modules. Seuls le thème actuellement utilisé et les thèmes de base sont vérifiés, comme cela est fait à partir du module Vues.

kiamlaluno
la source
hook_entity_view_alter () ne fonctionne pas dans les thèmes.
dxvargas
Au moins en D7, les crochets dans les thèmes ne sont invoqués que si le thème a déjà été initialisé dans la même demande (c'est-à-dire en appelant theme()). S'il n'a pas été initialisé, aucun crochet supplémentaire dans aucun thème ne sera exécuté.
zwirbeltier
@zwirbeltier Les crochets de thème sont invoqués pour le thème utilisé pour le rendu de la page. theme()ne change pas le thème utilisé pour la page, mais il appelle une fonction pour rendre les données. Cela ne change pas le thème, par exemple, de Garland à Minelli.
kiamlaluno
@kiamlaluno: Si vous regardez le code, drupal_alter()vous voyez qu'il n'invoque que des crochets alternatifs dans le thème s'il a drupal_theme_initialize()été appelé auparavant. Si ce n'est pas le cas, il n'y a pas (encore) de thème actif et donc pas de hooks appelés. Au moins dans D7, il n'y a aucune garantie quand drupal_theme_initialize()est appelé la première fois dans une demande.
zwirbeltier
@zwirbeltier L'ensemble de thèmes de Drupal est déjà initialisé lors du rendu d'une page. Si un module définit un thème pour une page sans appeler la fonction appropriée, c'est sa responsabilité de l'initialiser.
kiamlaluno