Réponses:
Un module qui implémente hook_preprocess_page()
ou hook_preprocess_node()
peut suggérer de nouveaux fichiers modèles en modifiant la variable $variables['theme_hook_suggestions']
.
Le code contenu dans template_preprocess_page () qui initialise cette variable est le suivant.
// Populate the page template suggestions.
if ($suggestions = theme_get_suggestions(arg(), 'page')) {
$variables['theme_hook_suggestions'] = $suggestions;
}
Chaque suggestion de thème doit correspondre à une entrée renvoyée par hook_theme () .
Dans les vues, il devrait y avoir une fonction de prétraitement équivalente à utiliser de la même manière, ou une manière hook_preprocess_page()
qui permet à la fonction de comprendre si la page est associée à une vue.
La solution à laquelle ajouter la clé «modèle de fichier» hook_views_api()
ne semble pas encore fonctionner dans Drupal 7. Cependant, cela fonctionne comme un charme:
/**
* Implements hook_theme().
*/
function bigtexas_theme() {
return array(
'views_view_fields__slideshow' => array(
'variables' => array('view' => NULL, 'options' => NULL, 'row' => NULL),
'template' => 'views-view-fields--slideshow',
'base hook' => 'views_view_fields',
'path' => drupal_get_path('module', 'bigtexas') . '/theme',
),
);
}
Le registre des thèmes est l'endroit où Drupal stocke toutes sortes d'informations sur les fichiers de modèle, les fonctions de thème, etc. à utiliser. Jouer avec cela peut conduire à des moments WTF plus tard, car les choses ne fonctionneront pas comme par défaut.
Quoi qu'il en soit, comme tout ce qui est drupal, il y a un crochet: hook_theme_registry_alter
vous pouvez utiliser pour modifier le registre des thèmes et déplacer vos fichiers de modèle dans un module. Je ne conseillerais pas de faire cela, car cela rendra la maintenance du site plus complexe. Mais si vous voulez le faire, c'est comme ça que c'est fait.
Pour les vues, il existe en théorie un mécanisme pour les modèles de vues (peut-être que cela fonctionne pour tous les modèles).
Vous pouvez définir la clé "chemin du modèle" dans votre implémentation hook_views_api de votre module personnalisé.
Une fois que vous disposez de ces vues, le fichier spécifié sera analysé pour les fichiers de modèle. Malheureusement, le test le plus simple échoue actuellement, donc cette fonctionnalité n'est probablement pas encore portée sur drupal7, mais si quelqu'un veut y entrer, consultez _views_find_module_templates () dans views.module.
La façon la plus simple est d'utiliser hook_theme_registry_alter()
et d'ajouter simplement le chemin de votre module aux chemins du thème:
function mymodule_theme_registry_alter(&$theme_registry) {
$theme_registry['[theme hook name, ie. page or views-view]']['theme paths'][] = drupal_get_path('module', 'mymodule');
}
theme()
implémentation, il ne semble pas que ce theme path
soit un tableau. Êtes-vous sûr que cela fonctionne? Voir api.drupal.org/api/drupal/includes%21theme.inc/function/theme/7
theme paths
auparavant dans Drupal 6, mais Drupal 7 a changé ce comportement dans drupal.org/node/678714 Il semble, à partir des commentaires # 29 et # 31 dans le numéro mentionné, que les suggestions de thèmes des modules doivent être déclarées dans le hook_theme de ce module, mais comment le faire est laissé comme un exercice au lecteur: /
Que diriez-vous d'une approche légèrement abstraite avec le thème de réaction contextuelle?
http://drupal.org/project/context_reaction_theme
Enveloppez votre contexte dans les fonctionnalités et il est même exportable. Mais c'est peut-être en fait une question de gourou Drupal qui cherche à créer quelque chose de plus profond et à connaître l'itinéraire.
J'ai commencé avec la réponse de googletorp et j'ai construit une fonction générique:
/**
* Overrides a third-party template file with a local copy.
*
* To be called from hook_theme_registry_alter():
* @code
* function mymodule_theme_registry_alter(&$theme_registry) {
* // Override variant of foo template using local copy.
* custom_override_template($theme_registry, 'foo--variant', drupal_get_path('module', 'mymodule') . '/templates');
* }
* @endcode
*
* @param array $theme_registry
* Theme registry array as passed to hook_theme_registry_alter().
* @param string $template
* Name of template file without '.tpl.php' extension. Example: 'foo--variant'.
* @param string $path
* Directory to load $template from.
* @param string $preprocess_function
* Optional preprocess function.
*/
function custom_override_template(&$theme_registry, $template, $path, $preprocess_function = NULL) {
if (strpos($template, '--') !== FALSE) {
$hook_name = array_shift(explode('--', $template));
}
else {
$hook_name = $template;
}
$hook_name = str_replace('-', '_', $hook_name);
if (isset($theme_registry[$hook_name])) {
// Copy hook info.
$hook_info = $theme_registry[$hook_name];
$hook_info['path'] = $path;
$hook_info['template'] = $template;
// Add to theme registry.
$new_hook = str_replace('-', '_', $template);
$theme_registry[$new_hook] = $hook_info;
// Add preprocess function.
if(!is_null($preprocess_function)){
$theme_registry[$new_hook]['preprocess functions'][] = $preprocess_function;
}
return $new_hook;
}
else {
throw new Exception(t('Unknown theme hook %hook.', array('%hook' => $hook_name)));
}
}
Il permet non seulement d'écraser la position et le nom du nœud et d'afficher les fichiers tpl, mais également de fournir une fonction de prétraitement pour les vues.
Donc, si vous avez appelé votre propre module mymodule
avec un fichier de modèle, sites/all/modules/mymodule/templates/foo--variant.tpl.php
vous pouvez maintenant facilement modifier le registre des thèmes pour utiliser votre propre répertoire de modèles:
function mymodule_theme_registry_alter(&$theme_registry) {
// Override variant of foo template using local copy.
custom_override_template($theme_registry, 'foo--variant', drupal_get_path('module', 'mymodule') . '/templates');
}
Comme l'a dit @jcsio, la réponse acceptée sur cette page fonctionne, mais le modèle ne peut pas être remplacé par un thème.
http://www.metachunk.com/blog/adding-module-path-drupal-7-theme-registry propose une solution qui vous permet d'ajouter le chemin de votre module (et sous-dossiers) à scanner pour toutes sortes des fichiers .tpl.php.
Je l'ai légèrement changé, car il contenait une variable `` chemins de thème '' qui ne semble pas utilisée par Drupal 7.
/**
* Implements hook_theme_registry_alter()
**/
function mymodule_theme_registry_alter(&$theme_registry) {
$mod_path = drupal_get_path('module', 'mymodule');
$theme_registry_copy = $theme_registry; // munge on a copy
_theme_process_registry($theme_registry_copy, 'phptemplate', 'theme_engine', 'pow', $mod_path);
$theme_registry += array_diff_key($theme_registry_copy, $theme_registry);
}
J'ai essayé à la fois la réponse acceptée et cette solution, cette dernière fonctionne pour moi jusqu'à présent!