Theme-Hooks gegen Modul-Hooks

10

Manchmal, wenn ich versuche, einen Hook anzuwenden, nur um zu erkennen, dass er sich in einer Moduldatei befinden soll.

Gibt es eine Möglichkeit zu wissen, welche Hooks in der template.php-Datei eines Themas oder in einem Modul implementiert werden können?

hamahama
quelle
4
Wenn ein Hook nicht verfügbar ist, um in einem Thema überschrieben zu werden, hat dies im Allgemeinen gute Gründe. Themen sollten nur für Code sein, der die Anzeige des Inhalts und der Funktionalität der Module betrifft. Code, der Funktionen oder Inhalte hinzufügt / entfernt / ändert, sollte sich normalerweise in einem Modul befinden. Denken Sie auch an die Tatsache, dass Sie beim Ändern von Themen alle in template.php vorgenommenen Anpassungen verlieren. Wenn Sie also Änderungen vornehmen, die Sie wahrscheinlich beibehalten möchten, wenn Sie jemals Themen geändert haben, dann würde dies definitiv in ein Modul aufgenommen werden sollen.
Rooby

Antworten:

11

Im Allgemeinen können nur Änderungs-Hooks durch Themen implementiert werden, dh Hooks wie hook_form_alter()und hook_menu_alter()oder kurz alle Hooks, die drupal_alter()in Drupal 7 und niedriger ( ModuleHandler()::alter()oder ThemeManager::alter()in Drupal 8) aufgerufen werden .

Andere Hooks, die von module_invoke_all()( ModuleHandler::invokeAll()in Drupal 8) aufgerufen werden , werden nicht für Themen aufgerufen, nur weil der Code nicht prüft, ob das aktuell aktivierte Thema einen Haken definiert.

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

In Drupal 8, wo die ModuleHandlerKlasse aus Modulen implementierte Hooks aufruft und die ThemeManagerKlasse durch Themen implementierte Hooks aufruft, implementiert nur die erste Klasse invoke()und invokeAll(). Dies bedeutet, dass in Drupal 8 keine Themen-Hooks vom Drupal-Kern aufgerufen werden.

Dies gilt für Drupal-Core-Hooks und hauptsächlich für alle Hooks, die von Modulen von Drittanbietern verwendet werden. Es liegt dann an einem Modul, zu überprüfen, ob ein Hook auch von einem Thema implementiert wird, und ihn aufzurufen. Dies ist, was das Views-Modul tut.

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

Bei Hooks, die von Modulen von Drittanbietern verwendet werden, müssen Sie den Code überprüfen, mit dem sie aufgerufen werden. Es besteht die Möglichkeit, dass für Themen nur Änderungs-Hooks aufgerufen werden. In einigen Fällen können jedoch auch andere Hooks von Themen implementiert werden.
Beachten Sie, dass bei Themen nicht alle aktivierten Themen auf Hook-Implementierungen überprüft werden, im Gegensatz zu Modulen. Nur das aktuell verwendete Thema und die Basisthemen werden wie im Modul Ansichten überprüft.

kiamlaluno
quelle
hook_entity_view_alter () funktioniert nicht in Themen.
Dxvargas
Zumindest in D7 werden Alter-Hooks in Themes nur aufgerufen, wenn das Theme bereits in derselben Anfrage initialisiert wurde (dh durch Aufruf theme()). Wenn es nicht initialisiert wurde, werden keine Änderungs-Hooks in einem Thema ausgeführt.
zwirbeltier
@zwirbeltier Themen-Hooks werden für das Thema aufgerufen, das zum Rendern der Seite verwendet wird. theme()ändert das für die Seite verwendete Thema nicht, ruft jedoch eine Funktion zum Rendern von Daten auf. Das Thema ändert sich beispielsweise nicht von Garland zu Minelli.
kiamlaluno
@kiamlaluno: Wenn Sie sich den Code drupal_alter()ansehen, sehen Sie, dass er nur dann Alter-Hooks im Thema aufruft, wenn drupal_theme_initialize()er zuvor aufgerufen wurde. Wenn dies nicht der Fall wäre, gibt es (noch) kein aktives Thema und daher werden keine Hooks aufgerufen. Zumindest in D7 gibt es keine Garantie, wenn drupal_theme_initialize()das erste Mal in einer Anfrage aufgerufen wird.
zwirbeltier
@zwirbeltier Das von Drupal festgelegte Design wird bereits beim Rendern einer Seite initialisiert. Wenn ein Modul ein Thema für eine Seite festlegt, ohne die entsprechende Funktion aufzurufen, ist es dafür verantwortlich, es zu initialisieren.
kiamlaluno