You are here: Foswiki>Tasks Web>Item10890 (05 Jul 2015, GeorgeClark)Edit Attach

Item10890: Template parser makes it impossible to override some .tmpl templates with TopicTemplates.

pencil
Priority: Urgent
Current State: Closed
Released In: 2.0.0
Target Release: major
Applies To: Engine
Component:
Branches:
Reported By: ArthurClemens
Waiting For:
Last Change By: GeorgeClark
For BaseSkin I would like to implement the template files as txt files in System web. Unfortunately, this does not work for a template like formtables.

Let's say I have a skin path mycompany,basejs,basecssgrid,basecss,base,pattern.

This is what happens in the parser:
name=formtables
   template=/Users/me/Sites/foswiki/core/templates/$web/$name.$skin.tmpl
      file=/Users/me/Sites/foswiki/core/templates/Main/formtables.lostboys.tmpl
      file=/Users/me/Sites/foswiki/core/templates/Main/formtables.basejs.tmpl
      file=/Users/me/Sites/foswiki/core/templates/Main/formtables.basecssgrid.tmpl
      file=/Users/me/Sites/foswiki/core/templates/Main/formtables.basecss.tmpl
      file=/Users/me/Sites/foswiki/core/templates/Main/formtables.base.tmpl
      file=/Users/me/Sites/foswiki/core/templates/Main/formtables.pattern.tmpl
   template=/Users/me/Sites/foswiki/core/templates/$name.$skin.tmpl
      file=/Users/me/Sites/foswiki/core/templates/formtables.lostboys.tmpl
      file=/Users/me/Sites/foswiki/core/templates/formtables.basejs.tmpl
      file=/Users/me/Sites/foswiki/core/templates/formtables.basecssgrid.tmpl
      file=/Users/me/Sites/foswiki/core/templates/formtables.basecss.tmpl
      file=/Users/me/Sites/foswiki/core/templates/formtables.base.tmpl
      file=/Users/me/Sites/foswiki/core/templates/formtables.pattern.tmpl

So it stops at formtables.pattern.tmpl, without looking further in System.BaseSkinFormtablesTemplate, even if base is written before pattern.

The documentation on TemplatePath says: "This path is expanded to a sequence of file names. The first file on this list that is found is taken to be the requested template file."

So literally taken it looks like it works as intended. But was this also intended to prevent txt files to override tmpl files? I cannot expect users to change their TemplatePath setting.

-- ArthurClemens - 17 Jun 2011

Diving further into the code. The way it is programmed looks orderly but is in fact not what you would expect, as skin author. I feel backed by this comment in TemplateTests.pm, "It sure is counter-intuitive to not consider the skin templates first":
sub test_directLookupInUsertopic {
    my $this = shift;
    my $data;

    # To verify a use case raised by Michael Daum: $web.$script looks up
    # template topic $script in $web, no further searching is done
    # Note the order in which templates are found. It sure is
    # counter-intuitive to not consider the skin templates first.

This has also been voiced in Item4463 (without followup). That topic lists an older discussion at TemplatePathIsCounterintuitive, where the original problem was not resolved.

But this is the crux: consider the skin templates first.

So you need to discern:
  1. Skin templates, such as System.MyskinViewTemplate, view.myskin.tmpl, etc.
  2. Fallback templates, such as view.tmpl

We also need to consider the skin path before the template path.

The changes I propose to the template parsing takes care of this. The basic idea is:
  1. Collect candidate template files
  2. Sort the candidate template files on
    1. Having 'skin' in the template path: yes has highest priority
    2. The order in the skin path: more specific has higher priority
    3. The order in the template path
  3. Go through the sorted candidates and pick the first one that is a valid file

This results in one unit test change (in test_directLookupInUsertopic):
    write_topic( 'Web', 'SkinSkinTestTemplate',
        'the Web.SkinSkinTestTemplate template' );
    $data = $tmpls->readTemplate( 'web.test', skins => 'skin' );
    $this->assert_str_equals( 'the Web.SkinSkinTestTemplate template', $data );

    write_template( 'web.test', 'the web.test.tmpl template' );
    $data = $tmpls->readTemplate( 'web.test', skins => 'skin' );
    $this->assert_str_equals( 'the web.test.tmpl template', $data );
becomes the way around:
    write_template( 'web.test', 'the web.test.tmpl template' );
    $data = $tmpls->readTemplate( 'web.test', skins => 'skin' );
    $this->assert_str_equals( 'the web.test.tmpl template', $data );

    write_topic( 'Web', 'SkinSkinTestTemplate',
        'the Web.SkinSkinTestTemplate template' );
    $data = $tmpls->readTemplate( 'web.test', skins => 'skin' );
    $this->assert_str_equals( 'the Web.SkinSkinTestTemplate template', $data );

In other words:
  • if the 2 template files templates/web.test.tmpl and Web.SkinSkinTestTemplate exist,
  • if the skin path is skin,
  • in the old situation: templates/web.test.tmpl was used (because templates was earlier in the template path)
  • in the new situation: Web.SkinSkinTestTemplate is used (because skin is defined in the skin path)

And:
  • if the 2 template files templates/formtables.default.tmpl and System.NewSkinFormtablesTemplate exist,
  • if the skin path is new,default,
  • in the old situation: templates/default.tmpl was used (because templates was earlier in the template path)
  • in the new situation: Web.SkinSkinTestTemplate is used (because new is defined earlier in the skin path)

The skin path has precedence over the template path in finding the template file.

-- ArthurClemens - 17 Jun 2011

 

ItemTemplate edit

Summary Template parser makes it impossible to override some .tmpl templates with TopicTemplates.
ReportedBy ArthurClemens
Codebase 1.1.3, trunk
SVN Range
AppliesTo Engine
Component
Priority Urgent
CurrentState Closed
WaitingFor
Checkins distro:d2a630255957 distro:44a2abce8ccd
TargetRelease major
ReleasedIn 2.0.0
Topic revision: r9 - 05 Jul 2015, GeorgeClark
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy