8

I created a feature module containing only a view and a content type.

Right now my page-node-x.tpl.php and my views-view-y.tpl.php files lie in my themes directory.

Is it possible to move them into my feature module?

8 Answers 8

5

A module that implements hook_preprocess_page() or hook_preprocess_node() can suggest new template files by altering the variable $variables['theme_hook_suggestions'].

The code contained in template_preprocess_page() that initialize that variable is the following.

// Populate the page template suggestions.
if ($suggestions = theme_get_suggestions(arg(), 'page')) {
  $variables['theme_hook_suggestions'] = $suggestions;
}

Each theme suggestion needs to match with an entry returned by hook_theme().

In Views, there should be an equivalent preprocess function to use in the similar way, or a way that allows to hook_preprocess_page() that allows to the function to understand if the page is associated with a view.

3

The solution to add the 'template file' key to hook_views_api() does not appear to work in Drupal 7 yet. However, this works like a charm:

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

The theme registry is where Drupal stores all sorts of info about what template files, theme functions etc to use. Messing with it can lead to WTF moments later on, as things will not work like default.

Anyways like all things drupal, there is a hook: hook_theme_registry_alter you can use to alter the theme registry and this move your template files into a module. I wouldn't advise doing this, as it will make maintaining the site more complex. But if you want to do is, this is how it's done.

2
  • +1 - I tried this but without success.. Could you plz provide an example?
    – jantimon
    Commented Apr 26, 2011 at 12:06
  • @Ghommey: The link provided comes with example code, not sure how to explain it better.
    – googletorp
    Commented Apr 26, 2011 at 13:00
2
+25

For views there is in theory a mechanism for views templates(perhaps it works for all templates).

You can set the key "template path" in your hook_views_api implementation of your custom module.

Once you have this views will scan your specified directory for template files. Sadly the simpletest currently fails, so this feature is probably not ported yet to drupal7, but if someone wants to get into it, see _views_find_module_templates() in views.module.

2

The easiest way is to use hook_theme_registry_alter() and just add the path of your module to the theme paths:

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
  • Looking at theme() implementation, it doesn't seem like theme path can be an array. Are you sure this works? See api.drupal.org/api/drupal/includes%21theme.inc/function/theme/7 Commented Oct 17, 2012 at 15:38
  • Regarding my comment above: theme paths used to work in Drupal 6, but Drupal 7 changed that behaviour in drupal.org/node/678714 It seems, from comments #29 and #31 in the mentioned issue, that theme suggestions from modules have to be declared in that module's hook_theme, but how to do that is left as an exercise to the reader :/ Commented Oct 17, 2012 at 16:10
1

How about a slightly abstracted approach with Context Reaction Theme?

http://drupal.org/project/context_reaction_theme

Wrap up your context in Features and it's even exportable. But maybe this is actually a Drupal guru question looking to create something deeper and know the route.

2
  • There is no D7 module and the last commit was a half year ago.
    – jantimon
    Commented May 4, 2011 at 12:56
  • Still works real well on my Drupal 6 sites :)
    – doublejosh
    Commented May 9, 2011 at 19:00
1

I started with the answer of googletorp and built a generic function:

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

It allows not only to overwrite the position and name of node and view tpl files but also to provide a preprocess function for views.

So if you got your own module called mymodule with a template file e.g sites/all/modules/mymodule/templates/foo--variant.tpl.php you can now easily modify the theme registry to use your own template directory:

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
  • This forces Drupal to use the template in your module folder. A theme won't be able to override it (which it should be).
    – jcisio
    Commented Mar 18, 2012 at 18:25
1

As @jcsio said, the accepted answer on this page works, but the template cannot be overridden by a theme.

http://www.metachunk.com/blog/adding-module-path-drupal-7-theme-registry offers a solution that allows you to add the path of your module (and sub-folders) to be scanned for all kinds of .tpl.php files.

I slightly changed it, since it contained a 'theme paths' variable that seems not used by 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);
}

I tried both the accepted answer and this solution, the latter works for me so far!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.