Respuestas:
Un módulo que implementa hook_preprocess_page()
o hook_preprocess_node()
puede sugerir nuevos archivos de plantilla alterando la variable $variables['theme_hook_suggestions']
.
El código contenido en template_preprocess_page () que inicializa esa variable es el siguiente.
// Populate the page template suggestions.
if ($suggestions = theme_get_suggestions(arg(), 'page')) {
$variables['theme_hook_suggestions'] = $suggestions;
}
Cada sugerencia de tema debe coincidir con una entrada devuelta por hook_theme () .
En Vistas, debe haber una función de preproceso equivalente para usar de manera similar, o una forma que permita hook_preprocess_page()
que la función entienda si la página está asociada con una vista.
La solución para agregar la clave de 'archivo de plantilla' hook_views_api()
todavía no parece funcionar en Drupal 7. Sin embargo, esto funciona como un encanto:
/**
* 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',
),
);
}
El registro de temas es donde Drupal almacena todo tipo de información sobre qué archivos de plantilla, funciones de tema, etc. utilizar. Jugar con él puede llevar a WTF momentos después, ya que las cosas no funcionarán como predeterminadas.
De todos modos, como todas las cosas de Drupal, hay un gancho: hook_theme_registry_alter
puede usar para alterar el registro de temas y esto mueve sus archivos de plantilla a un módulo. No recomendaría hacer esto, ya que hará que el mantenimiento del sitio sea más complejo. Pero si quieres hacerlo, así es como se hace.
Para las vistas, en teoría existe un mecanismo para las plantillas de vistas (tal vez funcione para todas las plantillas).
Puede establecer la clave "ruta de la plantilla" en su implementación hook_views_api de su módulo personalizado.
Una vez que tenga estas vistas, escaneará el directorio especificado para buscar archivos de plantilla. Lamentablemente, el más simple falla actualmente, por lo que esta característica probablemente aún no se ha portado a drupal7, pero si alguien quiere ingresar, consulte _views_find_module_templates () en views.module.
La forma más fácil es usar hook_theme_registry_alter()
y simplemente agregar la ruta de su módulo a las rutas de tema:
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()
implementación, no parece que theme path
pueda ser una matriz. ¿Estás seguro de que esto funciona? Ver api.drupal.org/api/drupal/includes%21theme.inc/function/theme/7
theme paths
solía funcionar en Drupal 6, pero Drupal 7 cambió ese comportamiento en drupal.org/node/678714 Parece, de los comentarios # 29 y # 31 en el tema mencionado, que las sugerencias de temas de los módulos deben declararse en el hook_theme de ese módulo, pero cómo hacerlo se deja como ejercicio para el lector: /
¿Qué tal un enfoque ligeramente abstracto con Context Reaction Theme?
http://drupal.org/project/context_reaction_theme
Termine su contexto en Características e incluso es exportable. Pero tal vez esta es realmente una pregunta del gurú de Drupal que busca crear algo más profundo y conocer la ruta.
Comencé con la respuesta de googletorp y construí una función genérica:
/**
* 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)));
}
}
Permite no solo sobrescribir la posición y el nombre del nodo y ver los archivos tpl, sino también proporcionar una función de preproceso para las vistas.
Entonces, si llama a su propio módulo mymodule
con un archivo de plantilla, por ejemplo sites/all/modules/mymodule/templates/foo--variant.tpl.php
, ahora puede modificar fácilmente el registro de temas para usar su propio directorio de plantillas:
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');
}
Como dijo @jcsio, la respuesta aceptada en esta página funciona, pero la plantilla no puede ser anulada por un tema.
http://www.metachunk.com/blog/adding-module-path-drupal-7-theme-registry ofrece una solución que le permite agregar la ruta de su módulo (y subcarpetas) para escanear todo tipo de archivos .tpl.php.
Lo cambié ligeramente, ya que contenía una variable de 'rutas de tema' que parece no ser utilizada por 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);
}
Intenté tanto la respuesta aceptada como esta solución, ¡esta última me funciona hasta ahora!