Respostas:
Um módulo que implementa hook_preprocess_page()
ou hook_preprocess_node()
pode sugerir novos arquivos de modelo alterando a variável $variables['theme_hook_suggestions']
.
O código contido em template_preprocess_page () que inicializa essa variável é o seguinte.
// Populate the page template suggestions.
if ($suggestions = theme_get_suggestions(arg(), 'page')) {
$variables['theme_hook_suggestions'] = $suggestions;
}
Cada sugestão de tema precisa corresponder a uma entrada retornada por hook_theme () .
No Views, deve haver uma função de pré-processo equivalente para usar da mesma maneira, ou uma maneira que permita hook_preprocess_page()
que a função entenda se a página está associada a uma view.
A solução para adicionar a chave 'arquivo de modelo' hook_views_api()
ainda não parece funcionar no Drupal 7. No entanto, isso funciona como um 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',
),
);
}
O registro de temas é onde o Drupal armazena todos os tipos de informações sobre quais arquivos de modelo, funções de tema, etc, usar. Mexer com isso pode levar ao WTF momentos mais tarde, pois as coisas não funcionarão como padrão.
De qualquer forma, como todas as coisas drupal, existe um gancho: hook_theme_registry_alter
você pode usar para alterar o registro do tema e isso mover seus arquivos de modelo para um módulo. Eu não recomendaria isso, pois isso tornará a manutenção do site mais complexa. Mas se você quiser fazer isso, é assim que é feito.
Para visualizações, existe em teoria um mecanismo para modelos de visualizações (talvez funcione para todos os modelos).
Você pode definir a chave "caminho do modelo" na sua implementação hook_views_api do seu módulo personalizado.
Depois de ter essas visualizações, o diretório especificado irá procurar arquivos de modelo. Infelizmente, o mais simples atualmente falha, portanto esse recurso provavelmente ainda não foi portado para o drupal7, mas se alguém quiser entrar nele, consulte _views_find_module_templates () em views.module.
A maneira mais fácil é usar hook_theme_registry_alter()
e adicionar o caminho do seu módulo aos caminhos do 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()
implementação, não parece que theme path
possa ser uma matriz. Tem certeza de que isso funciona? Veja api.drupal.org/api/drupal/includes%21theme.inc/function/theme/7
theme paths
costumava trabalhar no Drupal 6, mas o Drupal 7 mudou esse comportamento em drupal.org/node/678714 Parece que, nos comentários # 29 e # 31 da edição mencionada, as sugestões de temas dos módulos precisam ser declaradas no hook_theme desse módulo, mas como fazer isso é deixado como um exercício para o leitor: /
Que tal uma abordagem um pouco abstrata com o Tema de reação do contexto?
http://drupal.org/project/context_reaction_theme
Agrupe seu contexto em Recursos e é até exportável. Mas talvez essa seja realmente uma pergunta do guru Drupal que procura criar algo mais profundo e conhecer o caminho.
Comecei com a resposta do googletorp e criei uma função 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)));
}
}
Ele permite não apenas sobrescrever a posição e o nome do nó e visualizar os arquivos tpl, mas também fornecer uma função de pré-processo para as visualizações.
Portanto, se você tiver seu próprio módulo chamado mymodule
com um arquivo de modelo, por exemplo, sites/all/modules/mymodule/templates/foo--variant.tpl.php
agora poderá modificar facilmente o registro do tema para usar seu próprio diretório de modelos:
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 o @jcsio disse, a resposta aceita nesta página funciona, mas o modelo não pode ser substituído por um tema.
http://www.metachunk.com/blog/adding-module-path-drupal-7-theme-registry oferece uma solução que permite adicionar o caminho do seu módulo (e subpastas) a serem verificados para todos os tipos de arquivos .tpl.php.
Eu mudei um pouco, pois continha uma variável 'caminhos de tema' que parece não ser usada pelo 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);
}
Eu tentei a resposta aceita e esta solução, a última funciona para mim até agora!