Wie kann man Drupal anweisen, im Modulverzeichnis nach Vorlagen zu suchen?

11

Ich möchte eine Vorlagenimplementierung in meinem Modul bereitstellen und zulassen, dass Themen diese überschreiben. Grundsätzlich füge ich einen Vorschlag durch diesen vereinfachten Code hinzu:

function attach_preprocess_node(&$vars) {
  $vars['theme_hook_suggestions'][] = 'node__test';
}

(Ich will nicht hook_theme verwenden , um ein neues Thema hinzuzufügen , weil ich Vorprozess Knoten Funktionen wiederverwenden möge. Das Thema Namen sind umständlich , aber ich will nicht node_ schreiben befestigen _% zu vermeiden , um Verwechslungen mit Knotentyp.)

Dann benutze ich hook_theme_registry_alter (), um den Modulpfad hinzuzufügen:

function attach_theme_registry_alter(&$theme_registry) {
  $path = drupal_get_path('module', 'attach') . '/themes';
  $theme_registry_copy = $theme_registry;
  _theme_process_registry($theme_registry_copy, 'phptemplate', 'theme_engine', 'node', drupal_get_path('module', 'node'));
  $theme_registry += array_diff_key($theme_registry_copy, $theme_registry);
  if (!isset($theme_registry['node']['theme paths'])) {
    $theme_registry['node']['theme paths'] = array();
  }
  if (!isset($theme_registry['node']['theme paths'])) {
    $first_element = array_shift($theme_registry['node']['theme paths']);
    if ($first_element) {
      array_unshift($theme_registry['node']['theme paths'], $first_element, $path);
    }
    else {
      array_unshift($theme_registry['node']['theme paths'], $path);
    }
  }
}

Es funktioniert jedoch nicht. Das heißt: Die Datei Themes / Node - super.tpl.php wird nicht verwendet. Es wird nur verwendet, wenn ich es in den Themenordner kopiert habe.

jcisio
quelle
Erläuterung: Ich möchte, dass Drupal im Modulverzeichnis (und auch in Themenverzeichnissen) nach einer durch Code definierten Vorlage sucht (hier: Knotenvorlage). Ich möchte keine neue Vorlage definieren.
Jcisio

Antworten:

5

Grundsätzlich können Sie sich ein bisschen Kopfschmerzen ersparen, hook_theme()indem Sie die Registrierung implementieren, anstatt sie zu ändern.

Ich schlage einen Blick auf theming_example im Beispielprojekt vor , das auf dieser API-Dokumentseite handlich reproduziert werden kann , möglicherweise mit besonders hilfreichem Code auf dieser Seite .

function theming_example_list_page() {
  $items = array(
    t('First item'),
    t('Second item'),
    t('Third item'),
    t('Fourth item'),
  );

  // First we'll create a render array that simply uses theme_item_list.
  $title = t("A list returned to be rendered using theme('item_list')");
  $build['render_version'] = array(
    // We use #theme here instead of #theme_wrappers because theme_item_list()
    // is the classic type of theme function that does not just assume a
    // render array, but instead has its own properties (#type, #title, #items).
    '#theme' => 'item_list',
    // '#type' => 'ul',  // The default type is 'ul'
    // We can easily make sure that a css or js file is present using #attached. 
    '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')), 
    '#title' => $title, 
    '#items' => $items, 
    '#attributes' => array('class' => array('render-version-list')),
  );

  // Now we'll create a render array which uses our own list formatter,
  // theme('theming_example_list').
  $title = t("The same list rendered by theme('theming_example_list')");
  $build['our_theme_function'] = array(
    '#theme' => 'theming_example_list', 
    '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')), 
    '#title' => $title, 
    '#items' => $items,
  );
  return $build;
}

Dies ist alles für Drupal 7.

paul-m
quelle
Wie ich in der Frage sagte, möchte ich hook_theme () nicht verwenden, da ich $ Variablen in der Knotenvorlage wiederverwenden möchte. Diese Variablen werden im Hook_- (Vor-) Prozess vieler Module generiert, die die Existenz meines Themas nicht kennen (falls ich eines definiere).
Jcisio
Sie definieren ein Thema wie folgt: mit hook_theme (). :-) Sie können Theming-Funktionen in hook_theme () definieren. Nennen Sie ihnen alles, was Sie wollen. Machen Sie Shim-Funktionen, wenn Sie wollen. API-Dokumente: "hook_theme_HOOK () ... sollte nur verwendet werden, wenn ein Modul die Themenvorverarbeitung für einen nicht definierten Themen-Hook überschreiben oder ergänzen muss."
Paul-m
Ich möchte kein Thema definieren. Wenn Sie Ihr Thema 'mynode' definieren, anstatt 'node' wiederzuverwenden, haben Sie keine Variable in Ihrer .tpl.php-Datei.
Jcisio
1
Dies scheint nicht wahr zu sein: Themenaufrufe sind kumulativ, daher hook_themesollte die Implementierung Ihnen den $existingParameter geben, mit dem Sie das Objekt ändern und nicht überschreiben können. Wenn dies nicht der Fall ist, stoßen Sie möglicherweise auf einen Fehler.
Countzero
@Countzero Wenn Sie ein Thema node_attach deklarieren, werden alle Funktionen von hook_preprocess_node mit Ihrem neuen Thema nicht ausgeführt. Dh du hast nichts in deiner node-attach.tpl.php.
Jcisio
5

Vielleicht funktioniert dieser:

/**
 * Implements hook_theme().
 */
function MODULE_theme($existing, $type, $theme, $path) {
  return array (
    'node__CONTENTTYPE' => array (
      'variables' => array( . . . ),
      'template' => 'node--CONTENTTYPE' ,
      'base hook' => 'node',
      'path' => drupal_get_path('module', 'MODULE'),
    ),
  );
}

Wichtig ist hier der Schlüssel ' Basishaken '.

dashohoxha
quelle
Hier ist das Problem für das Hinzufügen von Dokumentation für base hook: drupal.org/node/2106635
Andy
+1 Upvote - dies und die abgeleitete Antwort von Batigotix, die ich gefunden habe, funktionieren. Vielen Dank.
Therobyouknow
2

Ich mag dashohoxhas Lösung der hook_theme-Implementierung, konnte sie aber nicht zum Laufen bringen. Nach einigem googeln fand ich eine Variante, die für mich gut funktionierte :

/**
 * Implements hook_theme().
 */
function mymodule_theme($existing, $type, $theme, $path) {
  $theme = array();
  $theme['node__blog_post'] = array(
    'render element' => 'content',
    'base hook' => 'node',
    'template' => 'node--blog_post',
    'path' => drupal_get_path('module', 'mymodule') . '/templates',
   );
  return $theme;
}

Hinweise: Mein benutzerdefiniertes Modul heißt "mymodule" und mein benutzerdefinierter Inhaltstyp heißt "blog_post". Die von mir verwendete tpl.php heißt 'node - blog_post.tpl.php' und befindet sich im Unterordner 'templates' meines Moduls.

Batigolix
quelle
+1 danke Ich fand das funktioniert. Wenn Sie auch daran interessiert sind, die Funktionen von template.php in Ihrem benutzerdefinierten Modul zu überschreiben, schauen Sie sich Folgendes an: snugug.com/musings/override-theme-functions-drupal-7-module - Ich fand, dass dies sehr gut
funktioniert
1

Hier ist mein Snippet zum Deklarieren von Ansichtsvorlagen, die im Ordner "template" meines "custom_module" gespeichert sind:

/**
 * Implements hook_theme_registry_alter().
 */
function custom_module_theme_registry_alter(&$theme_registry) {
  $extension   = '.tpl.php';
  $module_path = drupal_get_path('module', 'custom_module');
  $files       = file_scan_directory($module_path . '/templates', '/' . preg_quote($extension) . '$/');

  foreach ($files as $file) {
    $template = drupal_basename($file->filename, $extension);
    $theme    = str_replace('-', '_', $template);
    list($base_theme, $specific) = explode('__', $theme, 2);

    // Don't override base theme.
    if (!empty($specific) && isset($theme_registry[$base_theme])) {
      $theme_info = array(
        'template'   => $template,
        'path'       => drupal_dirname($file->uri),
        'variables'  => $theme_registry[$base_theme]['variables'],
        'base hook'  => $base_theme,
        // Other available value: theme_engine.
        'type'       => 'module',
        'theme path' => $module_path,
      );

      $theme_registry[$theme] = $theme_info;
    }
  }
}

Hoffe es hilft jemandem.

Sebastien M.
quelle
-1

Ich habe dies einmal bei Stack Overflow gefragt . Grundsätzlich müssen Sie implementieren hook_theme_registry_alter(), damit Ihr Pfad zum Pfad der Themen-Hook-Vorlage hinzugefügt wird. Anschließend hook_enable()rufen Sie drupal_theme_rebuild () auf, um den Theme-Registrierungscache zu löschen und Ihren Pfad nach Vorlagen zu durchsuchen.

Capi Etheriel
quelle
Vielleicht ist das, was Sie zurückhält, nur das Löschen der Caches.
Capi Etheriel
Also im Grunde die gleiche Lösung. Ich habe "drush cc all" nicht weniger als 50 Mal ausprobiert, es auf einer neuen Installationsseite usw. ohne Erfolg getestet. Ich werde meinen Code in ein minimales Modul ändern und komprimieren, damit jeder testen kann.
Jcisio
hook_enable()wird aufgerufen, wenn ein Modul aktiviert ist; Wenn das Modul bereits aktiviert ist, muss es deaktiviert und dann erneut aktiviert werden.
Kiamlaluno
@kiamlaluno: iḿ Verwenden von hook_enable zum Löschen der Caches. Wenn es bereits installiert ist, löscht der Benutzer die Caches möglicherweise nur manuell.
Capi Etheriel
NEIN , -1 Punkte. Diese Lösung ist so alt (2009), dass ich nicht einmal sicher bin, ob sie für D7 gedacht war. Während Ihre alte Lösung auf Ansichten zugeschnitten ist, ist sie nicht ideal für Situationen ohne Ansichten, in denen Entwickler möglicherweise mehr als eine Standardvorlage pro Themenschlüssel in ihre Module packen möchten. Stellen Sie sich vor, Sie implementieren Ihre Lösung für 100 dynamische Themenvorschläge für einen einzelnen Themenschlüssel. Außerhalb eines Views-Kontexts angewendet, würde ich Ihre Lösung als Gegenmuster bezeichnen.
Amateur Barista