Bagaimana cara memberitahu Drupal untuk mencari templat di direktori modul?


11

Saya ingin memberikan implementasi template dalam modul saya dan memungkinkan tema untuk menimpanya. Pada dasarnya, saya menambahkan saran dengan kode sederhana ini:

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

(Saya tidak ingin menggunakan hook_theme untuk menambahkan tema baru karena saya ingin menggunakan kembali fungsi node preproses. Nama tema canggung tetapi saya tidak ingin menulis node_ melampirkan _% untuk menghindari kebingungan dengan jenis simpul.)

Lalu saya menggunakan hook_theme_registry_alter () untuk menambahkan path modul:

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

Namun itu tidak berhasil. Itu berarti: tema file / simpul - super.tpl.php tidak digunakan. Ini digunakan hanya jika saya menyalinnya ke folder tema.


Klarifikasi: Saya ingin Drupal mencari di direktori modul (dan juga di direktori tema) untuk template yang ditentukan oleh kode (di sini: node template). Saya tidak ingin mendefinisikan template baru.
jcisio

Jawaban:


5

Pada dasarnya Anda dapat menghemat sedikit sakit kepala dengan menerapkan hook_theme()alih-alih mengubah registri.

Saya sarankan melihat theming_example dalam proyek Contoh , dengan mudah direproduksi di halaman doc API ini , mungkin dengan kode yang sangat membantu di halaman ini .

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

Ini semua untuk Drupal 7.


Seperti yang saya katakan dalam pertanyaan, saya tidak ingin menggunakan hook_theme () karena saya ingin menggunakan kembali $ variabel dalam template node. Variabel-variabel itu dihasilkan dalam proses hook_ (pre) banyak modul yang tidak tahu keberadaan tema saya (jika saya mendefinisikan satu).
jcisio

Cara Anda mendefinisikan tema adalah ... dengan hook_theme (). :-) Anda dapat mendefinisikan fungsi tema di hook_theme (). Beri nama mereka apa pun yang Anda inginkan. Buat fungsi shim jika Anda mau. Dokumentasi API: "hook_theme_HOOK () ... hanya boleh digunakan jika modul perlu mengganti atau menambahkan ke preprocessing tema untuk kait tema yang tidak ditentukan."
paul-m

Saya tidak ingin mendefinisikan tema. Jika Anda mendefinisikan tema 'mynode' alih-alih menggunakan kembali 'node', Anda tidak memiliki variabel apa pun di file .tpl.php Anda.
jcisio

1
Ini sepertinya tidak benar: panggilan tema bersifat kumulatif sehingga penerapan hook_themeharus memberi Anda $existingparameter yang memungkinkan Anda memodifikasi hal itu, bukan menimpanya. Jika bukan itu masalahnya, mungkin Anda sedang memukul bug.
Countzero

@Countzero ketika Anda mendeklarasikan theme node_attach, maka semua fungsi hook_preprocess_node tidak akan terjadi dengan tema baru Anda. Yaitu Anda tidak memiliki apa pun di node-attach.tpl.php Anda.
jcisio

5

Mungkin yang ini berhasil:

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

Yang penting di sini adalah kunci ' kait dasar '.


Inilah masalah untuk menambahkan dokumentasi untuk base hook: drupal.org/node/2106635
Andy

+1 upvote - ini dan jawaban turunannya dari batigotix yang saya temukan berfungsi. Terima kasih.
therobyouknow

2

Saya suka solusi dashohoxha dari implementasi hook_theme tetapi tidak bisa membuatnya bekerja. Setelah googling lagi saya menemukan variasi yang bekerja baik untuk saya:

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

Catatan: modul khusus saya disebut 'mymodule' dan tipe konten khusus saya disebut 'blog_post'. Tpl.php yang saya gunakan disebut 'node - blog_post.tpl.php' dan terletak di sub folder 'templates' pada modul saya.


+1 terima kasih saya menemukan ini berfungsi. Jika Anda juga tertarik untuk mengesampingkan fungsi template.php di dalam modul khusus Anda, lihat: snugug.com/musings/override-theme-functions-drupal-7-module - Saya menemukan ini berfungsi dengan sangat baik
therobyouknow

2

Ini cuplikan saya untuk mendeklarasikan templat tampilan yang disimpan di folder "templat" dari "custom_module" saya:

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

Semoga ini bisa membantu seseorang.


menghemat waktu saya. Juga berfungsi dan diperlukan untuk d8
Mykola Mykolayovich Dolynskyi

-1

Saya pernah menanyakan ini di Stack Overflow . Pada dasarnya, Anda harus menerapkan hook_theme_registry_alter()untuk mendapatkan jalur Anda ditambahkan ke jalur templat tema kait; kemudian, aktif hook_enable(), Anda memanggil drupal_theme_rebuild () untuk menghapus cache registri tema dan mendapatkan jalur Anda dipindai untuk templat.


Mungkin yang menahan Anda hanyalah membersihkan cache.
Capi Etheriel

Jadi, pada dasarnya solusi yang sama. Saya mencoba "drush cc all" tidak kurang dari 50 kali, mengujinya di situs instal baru dll tanpa hasil. Saya akan memodifikasi dan memadatkan kode saya menjadi modul minimal sehingga semua orang dapat menguji.
jcisio

hook_enable()dipanggil ketika modul diaktifkan; jika modul sudah diaktifkan, itu harus dinonaktifkan, dan kemudian diaktifkan kembali.
kiamlaluno

@kiamlaluno: iḿ menggunakan hook_enable untuk menghapus cache, jika sudah diinstal maka pengguna mungkin hanya menghapus cache secara manual.
Capi Etheriel

TIDAK , -1 poin. Solusi itu sudah sangat tua (2009), saya bahkan tidak yakin itu dimaksudkan untuk D7. Meskipun solusi lama Anda dirancang untuk Tampilan, itu tidak ideal untuk situasi non-Tampilan di mana pengembang mungkin ingin mengemas lebih dari 1 templat default per kunci tema dalam modul mereka. Bayangkan menerapkan solusi Anda untuk 100 saran tema dinamis untuk satu kunci tema. Diterapkan di luar konteks Tampilan Saya akan menyebut solusi Anda sebagai pola tandingan.
amatir barista
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.