Як сказати Drupal шукати шаблони в каталозі модулів?


11

Я хотів би забезпечити реалізацію шаблону у своєму модулі та дозволити темам замінити його. В основному я додаю пропозицію цим спрощеним кодом:

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

(Я не хочу використовувати kuka_theme для додавання нової теми, тому що я хочу повторно використовувати функції вузла попередньої обробки. Ім'я теми незручне, але я не хочу писати node_ attach _%, щоб уникнути плутанини з типом вузла.)

Тоді я використовую гачку_theme_registry_alter (), щоб додати шлях модуля:

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

Однак це не працює. Це означає: теми файлів / node - super.tpl.php не використовуються. Він використовується лише в тому випадку, якщо я скопіював його в папку з темами.


Пояснення: я хочу, щоб Drupal шукав у каталозі модулів (а також у темах каталогів) шаблон, визначений кодом (тут: шаблон вузла). Я не хочу визначати новий шаблон.
jcisio

Відповіді:


5

В основному ви можете вберегти себе від головного болю, застосувавши hook_theme()замість зміни реєстру.

Я пропоную переглянути тему_приклад у проекті " Приклади" , відтворений на цій док-сторінці API , можливо, з особливо корисним кодом на цій сторінці .

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

Це все для Drupal 7.


Як я вже говорив у запитанні, я не хочу використовувати klju_theme (), тому що хочу повторно використовувати $ змінні у шаблоні вузла. Ці змінні генеруються в процесі__ (попереднього) процесу багатьох модулів, які не знають існування моєї теми (якщо я визначу її).
jcisio

Тему, яким ви визначаєте тему, є ... за допомогою гачки_theme (). :-) Ви можете визначити тематичні функції в mock_theme (). Назвіть їм все, що завгодно. Зробіть функції shim, якщо хочете. Документи API: "Hook_theme_HOOK () ... слід використовувати лише в тому випадку, якщо модуль повинен переосмислити або додати до попередньої обробки теми для гачка теми, який він не визначав."
paul-m

Я не хочу визначати тему. Якщо ви визначите свою тему "mynode" замість повторного використання "node", у вашому .tpl.php файлі немає змінної.
jcisio

1
Це не здається правдою: тематичні виклики є сукупними, тому реалізація hook_themeповинна дати вам $existingпараметр, який дозволяє вам змінювати річ, не змінюючи її. Якщо це не так, можливо, ви потрапили на помилку.
Countzero

@Countzero, коли ви декларуєте тему node_attach, усі функції_загалуження_встановлення_код не відбудуться з вашою новою темою. Тобто у вас немає нічого у вашому node-attach.tpl.php.
jcisio

5

Можливо, це працює:

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

Тут важливим є ключовий « базовий гачок ».


Ось питання щодо додавання документації для base hook: drupal.org/node/2106635
Andy

+1 upvote - це і похідна відповідь від batigotix, я виявив, що працює. Дякую.
therobyouknow

2

Мені подобається рішення dashohoxha впровадження гачки_теми, але він не зміг змусити його працювати. Після ще декількох googling я знайшов варіацію, яка добре працювала для мене:

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

Примітки: мій спеціальний модуль називається "mymodule", а мій тип власного вмісту - "blog_post". Використовуваний мною tpl.php називається "вузол - blog_post.tpl.php", і він знаходиться в підпапці "шаблони" мого модуля.


+1 спасибі, я виявив, що це працює. Якщо ви також зацікавлені в переопределенні функцій template.php всередині вашого спеціального модуля, подивіться на: snugug.com/musings/override-theme-functions-drupal-7-module - я виявив, що це працює дуже добре
therobyouknow

2

Ось мій фрагмент для оголошення шаблонів подань, збережених у папці «шаблон» мого «custom_module»:

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

Сподіваюся, це комусь допоможе.


врятував мій час. Також працює і потрібен для d8
Микола Миколайович Долинський

-1

Я запитав це один раз на стеці Overflow . По суті, вам потрібно виконати, hook_theme_registry_alter()щоб ваш шлях був доданий до шляху шаблону до гачка теми; потім, hook_enable()ви зателефонуєте drupal_theme_rebuild (), щоб очистити кеш реєстру теми і сканувати ваш шлях на предмет шаблонів.


Можливо, те, що стримує вас, - це просто очищення кеш-пам'ять.
Capi Etheriel

Отже, в основному те саме рішення. Я спробував "drush cc all" не менше 50 разів, протестував це на новому сайті установки тощо без успіху. Я зміню і компактний свій код в мінімальний модуль, щоб кожен міг протестувати.
jcisio

hook_enable()викликається, коли модуль включений; якщо модуль уже ввімкнено, його потрібно відключити та знову ввімкнути.
kiamlaluno

@kiamlaluno: iḿ за допомогою гачки_enable для очищення кеш-пам'яті, якщо він уже встановлений, користувач може просто очистити кеші вручну.
Capi Etheriel

НІ , -1 бали. Це рішення настільки давнє (2009), я навіть не впевнений, що він призначений для D7. Хоча ваше старе рішення призначене для перегляду, воно не ідеально підходить для ситуацій без перегляду, коли розробники можуть спакувати більше ніж 1 шаблон за замовчуванням за тематичний ключ у свої модулі. Уявіть, що ви реалізуєте рішення для 100 пропозицій щодо динамічних тем для однієї клавіші теми. Застосовується поза контекстом Views, я б назвав ваше рішення контрформою.
любительська бариста
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.