web-dev-qa-db-fra.com

Ajout d'une suggestion de thème par programme

J'ai créé un module de fonctionnalités contenant uniquement une vue et un type de contenu.

En ce moment mon page-node-x.tpl.php et mon views-view-y.tpl.php les fichiers se trouvent dans mon répertoire de thèmes.

Est-il possible de les déplacer dans mon module de fonctionnalités?

8
jantimon

J'ai commencé avec le réponse de googletorp et 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 votre propre module appelé mymodule avec un fichier modèle, par exemple 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');
}
1
jantimon

Un module qui implémente hook_preprocess_page() ou hook_preprocess_node() peut suggérer de nouveaux fichiers de modèle 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 qui permet à hook_preprocess_page() qui permet à la fonction de comprendre si la page est associée à une vue.

5
kiamlaluno

La solution pour ajouter la clé de "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',
  ),
 );
}
3
Joe Hyde

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 avez ces vues, votre 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.

2
Daniel Wehner

Le registre de thème est où Drupal stocke toutes sortes d'informations sur les fichiers de modèle, les fonctions de thème, etc. à utiliser. Jouer avec lui peut conduire à des moments WTF plus tard, car les choses ne fonctionneront pas comme par défaut.

Quoi qu'il en soit, comme toutes les choses 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.

2
googletorp

La façon la plus simple est d'utiliser hook_theme_registry_alter() et d'ajouter simplement le chemin de votre module aux chemins de 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');
}
2
Damien Tournoud

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 ) à analyser pour toutes sortes de 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!

1
lmeurs

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 peut-être que c'est en fait une Drupal question gourou cherchant à créer quelque chose de plus profond et à connaître l'itinéraire.

1
doublejosh