Hi,

I'm using TFD7(Twig for D7), it's a theme engine for Drupal 7 using Twig, just a bit like in Drupal 8.
The TFD7 module provides a new theme engine 'twig' and all the templates have different extension: .tpl.twig instead of .tpl.php.

I'm also using $conf['theme_debug'] = TRUE; to see what are the theme suggestions that Drupal is offering for overriding a template.
The plugin Layouts from Panels allows you to define layouts that are used in the Panels suite modules.

I noticed that the template suggestions for those templates are always ending with .tpl.php and thus, it was impossible for us to use Twig templates for Panels Layouts, defined in a module or in a theme.

When using a theme engine different(with different file extension too), it's currently impossible to use a panel layouts with the right extension, the one associated to the current theme engine.

In order to find the problem, I analysed how Drupal is registering the plugins, then the templates suggestions and their extensions.

To get a template suggestions and its extension, the function theme() from theme.inc by default assign the '.tpl.php' extension. If the 'type' key of the theme hook is different from 'module', then it will get the extension from a particular function that can be defined in the theme engine file.

Until here, everything is ok.

One particular thing about Panels Layouts is that they can be defined in a module or in a theme. Then, the module Panels gather them through its hook_theme in panels.module::panels_theme().

To build the theme registry, theme.inc::_theme_build_registry() is calling _theme_process_registry() with different parameters.
The third parameter of that function is 'type'. This will be 'module', 'base_theme_engine', 'base_theme', 'theme_engine', 'theme', this 'type' key will be used to build the theme hook:

$result[$hook]['type'] = $type;

It means that Panels Layouts defined in a theme through the .info file:

plugins[panels][layouts] = panels/layouts

are considered as if they were defined in a module, because they are gathered through panels.module::panels_theme().
And thus, it's impossible for those hooks to use the right theme engine extension.

If we want to fix this behavior, we have two options:

Patch theme.inc from Drupal core only

* Remove the condition in theme.inc::theme()
By removing the condition, templates will use the current theme engine implementation if it exists.
I tried to understand this condition and I wasn't able to find it's utility.

Patch theme.inc from Drupal core and panels.module from Panels

* Take in account the 'type' key from the plugin (can be one of 'module', 'theme_engine', 'base_theme_engine', 'theme', or 'base_theme') in panels.module::panels_theme():

    if (isset($data['type'])) {
      $theme[$data[$callback]]['type'] = $data['type'];
    }

* Use the 'type' key if it exists in theme.inc::_theme_process_registry():

$result[$hook]['type'] = isset($info['type']) ? $info['type'] : $type;

I wrote this issue to get feedback from the community on how we could fix this.

Let me know what you think and if there are better options to fix this issue.

Thanks.

CommentFileSizeAuthor
#13 custom_layouts.zip5.19 KBpol
#4 issue-2824536.patch1013 bytespol

Comments

Pol created an issue. See original summary.

pol’s picture

Title: Defined theme plugins are unabled to use the right theme engine extension » Defined hook theme plugins are unable to use the right theme engine extension
pol’s picture

Issue summary: View changes
pol’s picture

StatusFileSize
new1013 bytes

Here's a patch who remove the if condition in theme.inc::theme().

pol’s picture

Status: Active » Needs review
pounard’s picture

pol’s picture

Hi Pounard,

Sorry but your patch doesn't fix the current issue even if I think this patch is more than needed.

The if condition is still there and prevent us to use templates properly when another engine is used.

pounard’s picture

Wouldn't this cause bugs a side effect, let's say if you use a twig engine, but a module provides a template using .tpl.php, won't it be skipped since it does not match the engine ?

pol’s picture

Hi,

Indeed, this is a problem and I'm unable to find a workaround.
Let's say you want to use Views, with TFD7, you have to rewrite every Views templates with Twig in your template.
Actually it make sense. But imagine the work you have to do if you want to rewrite every template of every contrib and Drupal core...
The question is still open... should we fully support the new theme engine, and fallback on the default one or not ?

But but but... We've just made a breakthrough for my particular problem described here.
I removed the Panels Layouts from the theme and created a custom module for them.
The custom module contains only the Panels Layouts, with their .tpl.php files, and in the theme, we are able to override them with a .tpl.twig file without any problem.

pounard’s picture

It's weird you actually experience this bug, using the other patch I linked above, it works gracefully when a module provides templates either in twig or phtml, since the template discovery matches the templates using their extension.

pounard’s picture

Could you give me an easy to setup reproducible test case I could debug into ?

damienmckenna’s picture

I think this needs some input from the theme system maintainers.

pol’s picture

StatusFileSize
new5.19 KB

Hi,

Here's a very basic module providing a panels Layout I just made.
It's using a twig template.

Try to use it in Panels, you won't be able to until you change the .tpl.twig into .tpl.php.

pounard’s picture

@DamienMcKenna sure, it probably does, at they should first look at #1545964: Do not copy over the owner and engine of a theme if the child theme uses a different engine than the base theme but it seems they are on strike since a few years :)

pol’s picture

@pounard:

I just made another discovery.

If you want to get the layouts I just sent you previously working, add this code into the .module file:

/**
 * Implements hook_theme_registry_alter().
 */
function custom_layouts_theme_registry_alter(&$theme_registry) {
  $custom_templates = array(
    'layout_default',
  );
 
  foreach ($custom_templates as $hook) {
    if (isset($theme_registry[$hook])) {
      $theme_registry[$hook]['type'] = 'theme';
    }
  }
}

Status: Needs review » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.