I have overridden some views templates provided by the theme information link in the Views UI interface. Currently these templates are stored in the garland theme folder. I would like these templates to be moved (and if possible, renamed) to mymodule/templates. The reason is that I want my module to be self-contained and theme-independent. I don't want to make users copy these template files to each theme that they use.

I have tried editing the 'theme_paths' attribute of views_view_field in hook_theme_registry alter. I have tried manually implementing the override in hook theme as below:

/**
 * Implementation of hook_theme()
 */
function loa_degree_theme() {
  return array(
    'views_view_field__degrees_edit__tid_1' => array(
      'template' => 'views-view-field--degrees--edit--tid-1',
      'path' => drupal_get_path('module', 'loa_degree') . '/templates',
      'arguments' => array('view' => NULL, 'field' => NULL, 'row' => NULL),
      'original hook' => 'views_view_field',
      'type' => 'module',
      'preprocess functions' => array('template_preprocess', 'template_preprocess_views_view_field'),
    ),
  );
}

Any advice would be appreciated. Thanks!

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

merlinofchaos’s picture

Status: Active » Closed (won't fix)

This is clearly documented in the advanced help. If you have specific questions about that documentation you may ask them.

venkatd’s picture

Got it working!

Sorry about that. I wasn't aware of advanced help. Wish it was part of core and more visible.

hellolindsay’s picture

I have the same problem as stated here. Can you please post the solution?

I would like to move my template files into my module folder. Views doesn't see them when I override them through hook_theme(). I looked through the advanced help (http://mysite.org/admin/advanced_help/views) but didn't find the solution.

juanjo_vlc’s picture

Hello,
I've read the documentation about views theming, and template suggestions, and I understood that the way the templates are searched is module -> base theme -> theme, so, I copied the views templates which are working on my current theme to a module with views embedded, but when i change to another theme the templates are not used.

I've cleared all caches including theme registry several times, rescanned the templates from views ui, but I can't get them to work.

Is there any document explaining how to use templates from a module directory which provides default views?

Thanks.

juanjo_vlc’s picture

Forget about my last comment, it's documented on http://yourdrupalsite.org/help/views/api-default-views

venkatd’s picture

Sorry for a late reply. I've been very distracted.

I wrote the following mini module that lets you put views template overrides in your module's directory (I named my module x, but obviously you can replace x_ with anything you want.) I hope something like this can be part of views because it's such a pain in the __ to do this every time I want to override a template.

/**
 * Implementation of hook_theme()
 **/
function x_theme() {
  $theme = array();
  foreach (module_implements('views_api') as $module) {
    $theme += x_views_get_overrides($module);
  }
  return $theme;
}

function x_views_get_overrides($module) {
  $theme = array();

  $field_template_files = array();
  $template_files = file_scan_directory(drupal_get_path('module', $module), '\.tpl\.php$');
  foreach ($template_files as $file) {
    $path = dirname($file->filename);
    
    // view display override
    if (preg_match('/^(?P<template>views-view--.+)\.tpl.php$/', $file->basename, $match)) {
      $theme_hook = str_replace('-', '_', $match['template']);
      $arguments = array('view' => NULL);
      $theme[$theme_hook] = array(
        'path' => $path,
        'template' => $match['template'],
        'arguments' => array('view' => NULL),
        'original hook' => 'views_view',
      );
    }
    //style override
    elseif (preg_match('/^(?P<template>views-view-list--.+)\.tpl.php$/', $file->basename, $match)) {
      $theme_hook = str_replace('-', '_', $match['template']);
      $theme[$theme_hook] = array(
        'path' => $path,
        'template' => $match['template'],
        'arguments' => array('view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL),
        'original hook' => 'views_view_list',
      );
    }
    // row style override
    elseif (preg_match('/^(?P<template>views-view-fields--.+)\.tpl.php$/', $file->basename, $match)) {
      $theme_hook = str_replace('-', '_', $match['template']);
      $theme[$theme_hook] = array(
        'path' => $path,
        'template' => $match['template'],
        'arguments' => array('view' => NULL, 'options' => NULL, 'row' => NULL),
        'original hook' => 'views_view_fields',
      );
    }
    // field override
    elseif (preg_match('/^(?P<template>views-view-field--.+)\.tpl.php$/', $file->basename, $match)) {
      $theme_hook = str_replace('-', '_', $match['template']);
      $theme[$theme_hook] = array(
        'path' => $path,
        'template' => $match['template'],
        'arguments' => array('view' => NULL, 'field' => NULL, 'row' => NULL),
        'original hook' => 'views_view_field',
      );
    }
  }
  
  return $theme;
  
}
dawehner’s picture

Category: support » feature
Status: Closed (won't fix) » Active

Let's reopen the issue.

I think we shouldn't use regexes here, we should check every existing theme type of views: style-theme/summary-theme etc.
This has to be written generalized.

merlinofchaos’s picture

It would be better written as just a hook or something.

We cannot rely on the naming of templates because something like views_attach could create a template named views-attach--viewname.tpl.php etc. That's perfectly legit.

So what we should do is simply be able to provide a directory where we're doing theme overrides and try to scan it similarly to how core scans a directory and do what is needed.

venkatd’s picture

Would it be possible to add a feature to views so that it scans the /views_templates subdirectory (or something like that) within every module directory?

merlinofchaos’s picture

Could use hook_views_api() to specify the directory easily enough, and then scan that for views-related templates. Actually it'd probably have to be any templates.

dawehner’s picture

tnightingale’s picture

subscribing

dawehner’s picture

Status: Active » Needs review
FileSize
3.35 KB
7.96 KB

Here is a patch, with a test.

One for d6-3 and one for d6-2

merlinofchaos’s picture

Version: 6.x-2.7 » 6.x-3.x-dev
Assigned: Unassigned » dawehner
Category: feature » task
Status: Needs review » Active

Let's do this just for 6.x-3.x

I think the patch looks pretty good. Committed. Two things are needed:

1) Update the documentation so that developers know they can do this.
2) Port to D7.x

dawehner’s picture

Status: Active » Needs review
FileSize
1.4 KB

Here is one.
Adding the info to docs/docs.php and help/api.html.

merlinofchaos’s picture

Version: 6.x-3.x-dev » 7.x-3.x-dev
Status: Needs review » Patch (to be ported)

Committed the documentation to both branches. I suppose that was premature on D7 since the initial patch actually may not have been ported?

dawehner’s picture

Status: Patch (to be ported) » Fixed

It's ported now.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Dippers’s picture

Status: Closed (fixed) » Needs work

The D7 port did not work for me, the new template path was not carried in the $templates structure from _views_find_module_templates. This seemed to be fixed by changing 'path' => dirname($files[$match]->filename) to 'path' => dirname($files[$match]->uri) on line 179. This needs checking as I'm not that familiar with the code.

dawehner’s picture

This sadly didn't fixed the simpletest, but this could be caused by something else.

Feel free to create a real patch file.

mstrelan’s picture

subscribe

mstrelan’s picture

Status: Needs work » Needs review
FileSize
1.3 KB

#19 worked for me. Patch attached.

dawehner’s picture

@mstrelan

Does the simpletest run with your patch?

mstrelan’s picture

Well for a start my patch was meant to only change one line, not two, so here is an updated one. Unfortunately the simpletest fails on viewsModuleTest->testModuleTemplates() but from what I can tell the views_module.test doesn't call module_enable(array('views_test')); like views_query.test does. I'm new to simpletest so I'm not sure if the module gets enabled some other way.

dawehner’s picture

That's fine. The enabling of the module happens because the test class in views_module.test inherits from the one on views_query.test

Can you try to find out whether the test is broken/why it's broken?
This would be really cool.

mstrelan’s picture

I've given it a shot, but still no luck. Here is what I have found.

When I inspect the theme registry on my site with my custom module enabled I see views_view__MYVIEWNAME. When I debug the array keys of the registry from simpletest I don't see views_view__frontpage nor views_view__MYVIEWNAME.

In my custom module implementation of hook_views_api() I set the api version to 3. In views_test.module this is set to 3.0-alpha1. Assuming that this was way too specific, especially since I'm not using alpha1 I tried changing that to 3. No luck.

Finally I thought that when you add template files to your module / theme you have to flush the theme registry, and while I would have thought this was done automatically when views_test.module is enabled I thought I'd whack in a registry_rebuild() and maybe a cache_clear_all(). Still no luck, but I hope that this information will help someone else to find the problem. I probably won't get more time to look in to this for a while, but I am absolutely convinced that it is a broken test case rather than a broken patch.

dawehner’s picture

Status: Needs review » Fixed

3.0-alpha1 is the right version, it's what views_api_version() returns.

You say that your patch works for you, and currently the feature doesn't work at all. So it's fine from my perspective to commit the patch, but fixing the test would be great
Commited to 7.x-3.x

please create a new issue for the test.

mstrelan’s picture

m4olivei’s picture

Maybe the wrong place for this, but in D7 can you still add a views template to your module using the hook_theme() method? The issue I've run into is that I have a feature module (http://drupal.org/features) and as part of it I'd like to include a views template for the view I have in my feature. The issue is that Features module takes care of implementing hook_views_api() in the module_name.features.inc file, so I can't add the template path key to the return array of hook_views_api().

Here is the hook_theme() implementation I have in my module:

/**
 * Implements hook_theme().
 */
function client_news_theme() {
  return array(
    'views_view__fields__news__page' => array(
      'variables' => array('view' => NULL, 'options' => NULL, 'row' => NULL),
      'template' => 'views-view--fields--news--page',
      'base hook' => 'views_view_fields',
      'path' => drupal_get_path('module', 'client_news'),
    ),
  );
}

After adding the file views-view--fields--news--page.tpl.php and clearing the cache, I'm not seeing the override take effect. Any help is appreciated.

Matt

m4olivei’s picture

Sigh...being a programmer is a b*tch. I figured it out. Turns out you can use the hook_theme() method, exactly as I did above except for one suttle difference:

/**
 * Implements hook_theme().
 */
function client_news_theme() {
  return array(
    'views_view_fields__news__page' => array(
      'variables' => array('view' => NULL, 'options' => NULL, 'row' => NULL),
      'template' => 'views-view-fields--news--page',
      'base hook' => 'views_view_fields',
      'path' => drupal_get_path('module', 'client_news'),
    ),
  );
}

I had double '-' and '_' where I should have had single.

Matt

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

eMuse_be’s picture

Does this work in drupal 7 as well ?

I am using this code:

 'views_view_fields__article_images__block' => array(
            'arguments' => array('view' => NULL, 'options' => NULL, 'row' => NULL),
            'template' => 'views-view-fields--article-images--block',
            'original hook' => 'views_view_fields',
            'path' => drupal_get_path('module', 'article_js_and_css') . '/article_slider',
        ),

which works. but in the template file, the $fields variable is empty

netsensei’s picture

which works. but in the template file, the $fields variable is empty

Doesn't work in D6 either.

We've noticed this behaviour when you clear your caches or you're running update.php. It's quite inconsistent when $fields is or isn't empty.
One way of fixing this is to press "rescan templates" in your view which rebuilds the theme registry including the reference to $fields argument in the themeing hook.

Any ideas on this?

PixelClever’s picture

The $fields variable is empty due to the way hook theme was written. I have put a short tutorial here that shows how to get it working on Drupal 6 using views 3. http://pixelclever.com/how-declare-views-template-inside-module

Hope that helps.

AlmogBaku’s picture

EDITED!:

Hey, I've just found out how to template a view from module directory..
So if somone looking for it, you should Implement HOOK_views_api:

/**
 * Implements hook_views_api().
 * 
 * Used for enabling using templates inside my module
 */
function MYMODULE_views_api() {
  return array(
    'api' => 3, 
    'path' => drupal_get_path('module', 'mymodule'), 
    'template path' => drupal_get_path('module', 'mymodule'),
  );
}
johnnydarkko’s picture

Thanks @AlmogBaku!
Slight difference in my implementation, but thanks for getting me in the right path!

/**
 * Implementation of hook_views_api().
 */
function mymodule_views_api() {
  $path = drupal_get_path('module', 'mymodule');
  return array(
    'api' => 2.0,
    'path' => $path,
    'template path' => $path . '/templates',
  );
}
rickmanelius’s picture

FWIW, you can use the 3.0 api as follows (templates only... I'm not including individual views here)

/**
 * Implementation of hook_views_api().
 */
function my_module_views_api() {
  return array(
    'api' => 3,
    'template path' => drupal_get_path('module', 'my_module') . '/templates',
  );
}
ciss’s picture

Issue summary: View changes
Status: Closed (fixed) » Needs work
FileSize
164.17 KB

As of revision 80d968394211ff2e7017c663c945e7721a8d3b67 (Sun Nov 10 21:48:51 2013 +0000) this is not fixed.
_views_find_module_templates() uses dirname() on $file->filename instead of $file->uri. The patch in #24 attempted to fix this, but hasn't been committed.

This screenshot illustrates the problem.