Index: lib/TWiki/Templates.pm =================================================================== --- lib/TWiki/Templates.pm (revision 12220) +++ lib/TWiki/Templates.pm (working copy) @@ -131,6 +131,8 @@ Recursively expands any contained TMPL:P tags. +#SMELL - there is no recursion detection - if you define 2 blocks in terms of each other, you kill your server :( + Note that it would be trivial to add template parameters to this, simply by iterating over the other parameters (other than _DEFAULT, context, then and else) and doing a s/// in the template for that parameter value. This @@ -207,10 +209,47 @@ =cut +sub saveTemplateToCache { + my( $this, $cacheName, $name, $skins, $web, $tmplText ) = @_; + $skins = '' unless (defined($skins)); + $web = '' unless (defined($web)); + + my $tmpl_cachedir = $TWiki::cfg{TemplateDir}.$cacheName; + mkdir($tmpl_cachedir) unless (-e $tmpl_cachedir); + my $filename = TWiki::Sandbox::untaintUnchecked($tmpl_cachedir.'/'.$name.'__'.$skins.'__'.$web.'.tmpl'); + + unless ( open( FILE, ">$filename" ) ) { + die "Can't create file $filename - $!\n"; + } + print FILE $tmplText; + close( FILE); +} +sub getTemplateFromCache { + my( $this, $name, $skins, $web ) = @_; + $skins = '' unless (defined($skins)); + $web = '' unless (defined($web)); + + my $tmpl_cachedir = $TWiki::cfg{TemplateDir}.'_cache'; + mkdir($tmpl_cachedir) unless (-e $tmpl_cachedir); + my $filename = TWiki::Sandbox::untaintUnchecked($tmpl_cachedir.'/'.$name.'__'.$skins.'__'.$web.'.tmpl'); + + if (-e $filename) { + open( IN_FILE, "<$filename" ) || return; + local $/ = undef; # set to read to EOF + my $data = ; + close( IN_FILE ); + return $data; + } +} + sub readTemplate { my( $this, $name, $skins, $web ) = @_; ASSERT($this->isa( 'TWiki::Templates')) if DEBUG; +# my $cache = $this->getTemplateFromCache($name, $skins, $web); +# return $cache if($cache); +# print STDERR "template file cache miss - recreating ($name, $skins, $web)"; + $this->{files} = (); # recursively read template file(s) @@ -220,12 +259,15 @@ $text =~ s/%TMPL\:INCLUDE{[\s\"]*(.*?)[\"\s]*}%/$this->_readTemplateFile( $1, $skins, $web )/geo; } + $this->saveTemplateToCache('_postinclude', $name, $skins, $web, $text); + # Kill comments, marked by %{ ... }% $text =~ s/%{.*?}%//sg; if( ! ( $text =~ /%TMPL\:/s ) ) { # no template processing $text =~ s|^(( {3})+)|"\t" x (length($1)/3)|geom; # leading spaces to tabs + $this->saveTemplateToCache('_cache', $name, $skins, $web, $text); return $text; } @@ -263,6 +305,9 @@ $result =~ s/(%TMPL\:P{.*?}%)/$this->_expandTrivialTemplate($1)/geo; $result =~ s|^(( {3})+)|"\t" x (length($1)/3)|geom; # leading spaces to tabs + + $this->saveTemplateToCache('_cache', $name, $skins, $web, $result); + return $result; } @@ -285,7 +330,8 @@ # if the name ends in .tmpl, then this is an explicit include from # the templates directory. No further searching required. if( $name =~ /\.tmpl$/ ) { - return TWiki::readFile( $TWiki::cfg{TemplateDir}.'/'.$name ); + my $filename = $TWiki::cfg{TemplateDir}.'/'.$name; + return " %{ INCLUDED($filename) $name, $skins, $web }% \n".TWiki::readFile( $filename ); } my $userdirweb = $web; @@ -297,7 +343,7 @@ # if the name can be parsed into $web.$name, then this is an attempt # to explicit include that topic. No further searching required. if( validateTopic($session,$store,$session->{user},$userdirname,$userdirweb )) { - return retrieveTopic( $store, $userdirweb, $userdirname ); + return " %{ INCLUDED(topic:$userdirweb, $userdirname) $name, $skins, $web }% \n".retrieveTopic( $store, $userdirweb, $userdirname ); } } else { @@ -344,14 +390,14 @@ next if (defined($this->{files}->{$name1})); #recursion prevention. $this->{files}->{$name1} = 1; - return retrieveTopic( $store, $web1, $name1 ); + return " %{ INCLUDED(topic:$web1, $name1) $name, $skins, $web }% \n".retrieveTopic( $store, $web1, $name1 ); } } else { if( validateFile( $file )) { next if (defined($this->{files}->{$name})); #recursion prevention. $this->{files}->{$name} = 1; - return TWiki::readFile( $file ); + return " %{ INCLUDED($file) $name, $skins, $web }% \n".TWiki::readFile( $file ); } } } @@ -360,9 +406,9 @@ # SMELL: should really #throw Error::Simple( 'Template '.$name.' was not found' ); # instead of - #print STDERR "Template $name could not be found anywhere\n"; + print STDERR "Template $name could not be found anywhere\n"; #Is Failing Silently the best option here? - return ''; + return " %{INCLUDED( not found) $name, $skins, $web}% "; } sub validateFile {