Ganchos de tema vs ganchos de módulo

10

Às vezes, quando tento aplicar um gancho, apenas para perceber que ele deveria estar em um arquivo de módulo.

Existe uma maneira de saber quais ganchos podem ser implementados no arquivo template.php de um tema ou em um módulo?

hamahama
fonte
4
Geralmente, quando um gancho não está disponível para ser substituído em um tema, é por uma boa razão. Os temas devem ser apenas para códigos relacionados à exibição do conteúdo e da funcionalidade que os módulos fornecem. O código que adiciona / remove / altera a funcionalidade ou o conteúdo geralmente deve estar em um módulo. Pense também no fato de que, se você alterar os temas, perderá as personalizações feitas no template.php; portanto, se você estiver fazendo alterações que provavelmente gostaria de manter se alguma vez mudasse de tema, isso definitivamente iria para um módulo.
Rooby

Respostas:

11

De um modo geral, apenas os ganchos alternativos podem ser implementados por temas, o que significa ganchos como hook_form_alter()e hook_menu_alter(), ou, em resumo, todos os ganchos invocados drupal_alter()no Drupal 7 e inferiores ( ModuleHandler()::alter()ou ThemeManager::alter()no Drupal 8).

Outros ganchos, chamados por module_invoke_all()( ModuleHandler::invokeAll()no Drupal 8), não são chamados para temas simplesmente porque o código não verifica se o tema atualmente ativado define algum gancho.

  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;
      }
    }
  }

No Drupal 8, onde a ModuleHandlerclasse chama ganchos implementados a partir de módulos e a ThemeManagerclasse chama ganchos implementados por temas, apenas a primeira classe implementa invoke()e invokeAll(). Isso significa que, no Drupal 8, os ganchos temáticos não são chamados, pelo núcleo do Drupal.

Isso é válido para os ganchos do núcleo Drupal e, principalmente, para todos os ganchos usados ​​por módulos de terceiros. Cabe então a um módulo verificar se um gancho também é implementado por um tema e invocá-lo. É isso que o módulo Views faz.

  // 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);
  }

Para ganchos usados ​​por módulos de terceiros, é necessário verificar o código usado para invocá-los. As chances são de que apenas ganchos alternativos sejam chamados para temas, mas em alguns casos também outros ganchos podem ser implementados por temas.
Lembre-se de que, no caso de temas, nem todos os temas ativados são verificados para implementações de gancho, ao contrário do que acontece com os módulos. Somente o tema atualmente usado e os temas base são verificados, conforme feito no módulo Views.

kiamlaluno
fonte
hook_entity_view_alter () não funciona em temas.
Dxvargas 29/04/19
Pelo menos no D7, os ganchos nos temas são invocados apenas se o tema já tiver sido inicializado na mesma solicitação (ou seja, chamando theme()). Se não tiver sido inicializado, nenhum gancho alternativo em nenhum tema será executado.
zwirbeltier 8/04
Os ganchos de tema @zwirbeltier são chamados para o tema usado para renderizar a página. theme()não altera o tema usado para a página, mas invoca uma função para renderizar dados. Isso não muda o tema, por exemplo, de Garland para Minelli.
kiamlaluno
@kiamlaluno: Se você olhar para o código, drupal_alter()verá que ele apenas chama alter-hooks no tema se drupal_theme_initialize()foi chamado antes. Caso contrário, não há um tema ativo (ainda) e, portanto, nenhum gancho é chamado. Pelo menos em D7, não há garantia quando drupal_theme_initialize()é chamado pela primeira vez em uma solicitação.
zwirbeltier 8/04
@zwirbeltier O tema definido no Drupal já está inicializado quando uma página é renderizada. Se um módulo define um tema para uma página sem chamar a função apropriada, é sua responsabilidade inicializá-la.
kiamlaluno