ffzg/recall_notices.pl: added --interval and --dedup
[koha.git] / installer / html-template-to-template-toolkit.pl
index 6f3b53e..60cd951 100755 (executable)
@@ -1,7 +1,6 @@
 #!/usr/bin/perl
 
-use strict;
-use warnings;
+use Modern::Perl;
 use Carp;
 use Data::Dumper;
 
@@ -27,6 +26,14 @@ EOH
 my $tmpl_in_dir      = 'koha-tmpl';
 my $tmpl_out_dir     = 'koha-tt';
 
+# template toolkit variables NOT to scope, in other words, variables that need to remain global (case sensitive)
+my @globals = ("themelang","JacketImages","OPACAmazonCoverImages","GoogleJackets","BakerTaylorEnabled",
+"SyndeticsEnabled", "OpacRenewalAllowed", "item_level_itypes","noItemTypeImages",
+"virtualshelves", "RequestOnOpac", "COinSinOPACResults", "OPACXSLTResultsDisplay",
+"OPACItemsResultsDisplay", "LibraryThingForLibrariesID", "opacuserlogin", "TagsEnabled",
+"TagsShowOnList", "TagsInputOnList","loggedinusername","opacbookbag",
+"OPACAmazonEnabled", "SyndeticsCoverImages","using_https");
+
 # Arguments:
 my $KOHA_ROOT;
 my $tmpl_extn_match  = "tmpl|inc|xsl"; # Type match defaults to *.tmpl plus *.inc if not specified
@@ -67,106 +74,117 @@ foreach my $file (@template_files) {
     open my $ITMPL, '<', $file or croak "Can't open $file for input: $!";
     open my $OTT, '>', $new_path or croak "Can't open $new_path for output: $!";
 
-    # Slurp in input file..
-##    my $input_tmpl = do { local $/; <$ITMPL> };
-##    close $ITMPL;
-
     # allows 'proper' handling of for loop scope
+    # cur_scope is a stack of scopes, the last being the current
+    #   when opening a for loop push scope onto end, when closing for loop pop
     my @cur_scope = ("");
-    my @cur_scope_count = (0);
-
-    for my $input_tmpl(<$ITMPL>){
+    # flag representing if we've found a for loop this iteration
     my $for_loop_found = 0;
 
-    # handle poorly names variable such as f1!, f1+, f1-, f1| and mod
-    $input_tmpl =~ s/"(\w+)\|"/"$1pipe"/ig;
-    $input_tmpl =~ s/"(\w+)\+"/"$1plus"/ig;
-    $input_tmpl =~ s/"(\w+)\-"/"$1minus"/ig;
-    $input_tmpl =~ s/"(\w+)!"/"$1exclamation"/ig;
-    $input_tmpl =~ s/"(\w+),(\w+)"/"$1comma$2"/ig;
-    $input_tmpl =~ s/NAME="mod"/NAME="modname"/ig;
-    # handle 'naked' TMPL_VAR "parameter" by turning them into what they should be, TMPL_VAR NAME="parameter"
-    $input_tmpl =~ s/TMPL_VAR\s+"(\w+)"/TMPL_VAR NAME="$1"/ig;
-    # make an end (ESCAPE NAME DEFAULT) into a ned (NAME ESCAPE DEFAULT)
-    $input_tmpl =~ s/ESCAPE="(\w+?)"\s+NAME=['"](\w+?)['"]\s+DEFAULT=['"](.+?)['"]/NAME="$2" ESCAPE="$1" DEFAULT="$3"/ig;
-
-    # Process..
-    # NB: if you think you're seeing double, you probably are, *some* (read:most) patterns appear twice: once with quotations marks, once without.
-    #     trying to combine them into a single pattern proved troublesome as a regex like ['"]?(.*?)['"]? was causing problems and fixing the problem caused (alot) more complex regex
-
-    # variables
-    $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s+ESCAPE=['"](\w*?)['"]\s+DEFAULT=['"]?(.*?)['"]?\s*-*>/[% DEFAULT $cur_scope[-1]$1="$3" |$2 %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]\s*(\w*?)\s*['"]\s+ESCAPE=['"]?(\w*?)['"]?\s*-*>/[% $cur_scope[-1]$1 |$2 %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?(\w*?)\s+ESCAPE=['"]?(\w*?)['"]?\s*-*>/[% $cur_scope[-1]$1 |$2 %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+ESCAPE=['"]?(\w*?)['"]?\s+NAME\s?=\s?['"]?([\w-]*?)['"]?\s*-*>/[% $cur_scope[-1]$2 |$1 %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?(\w*?)['"]?\s+DEFAULT=['"](.*?)['"]\s*-*>/[% DEFAULT $cur_scope[-1]$1="$2" %]/ig; # if a value being assigned is wrapped in quotes, keep them intact
-    $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s+DEFAULT=(.*?)\s*-*>/[% DEFAULT $cur_scope[-1]$1=$2 %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s*-*>/[% $cur_scope[-1]$1 %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% $1 %]/ig;     # TMPL_VAR NAME and TMPL_VAR EXPR are logically equiv, see http://search.cpan.org/~samtregar/HTML-Template-Expr-0.07/Expr.pm
-    $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+EXPR\s?=\s?(.*?)\s*-*>/[% $1 %]/ig;
-
-    # if, elseif and unless blocks
-    $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% IF ( $1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+EXPR\s?=\s?(.*?)\s*-*>/[% IF ( $1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+NAME\s?=\s?['"]\s*(\w*?)\s*['"]\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+NAME\s?=\s?(\w*?)\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+['"](.*?)['"]\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+([\w\s]*?)\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
-
-    $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% ELSIF ( $1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+EXPR\s?=\s?(.*?)\s*-*>/[% ELSIF ( $1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+NAME\s?=\s?['"](\w*?)['"]\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+NAME\s?=\s?(\w*?)\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+['"](\w*?)['"]\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+(\w*?)\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
-
-    $input_tmpl =~ s/<[!-]*\s*TMPL_ELSE\s*-*>/[% ELSE %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*\/TMPL_IF\s*-*>/[% END %]/ig;
-
-    $input_tmpl =~ s/<[!-]*\s*TMPL_UNLESS\s+NAME\s?=\s?['"]?(\w*?)['"]?\s*-*>/[% UNLESS ( $cur_scope[-1]$1 ) %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*\/TMPL_UNLESS\s*-*>/[% END %]/ig;
-    # includes
-    $input_tmpl =~ s/<[!-]*\s*TMPL_INCLUDE\s+NAME\s?=\s?"(.*?\.inc)"\s*-*>/[% INCLUDE '$1' %]/ig;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_INCLUDE\s+NAME\s?=\s?"(.*?)"\s*-*>/[% INCLUDE $1 %]/ig;
-
-    if ($input_tmpl =~ m/<[!-]*\s*TMPL_LOOP/i ){
-       $for_loop_found = 1;
-    }
-
-    $input_tmpl =~ s/<[!-]*\s*TMPL_LOOP\s+NAME\s?=\s?['"](?<SCOPE>.*?)['"]\s*-*>/"[% FOREACH " . substr($+{SCOPE}, 0, -1) . " IN $cur_scope[-1]$1 %]"/ieg;
-    $input_tmpl =~ s/<[!-]*\s*TMPL_LOOP\s+NAME\s?=\s?(?<SCOPE>.*?)\s*-*>/"[% FOREACH " . substr($+{SCOPE}, 0, -1) . " IN $cur_scope[-1]$1 %]"/ieg;
-
-    # handle for loop scope
-    if($for_loop_found){
-       my $scope = substr($+{SCOPE}, 0, -1) . ".";
-       push(@cur_scope, $scope);
+    for my $input_tmpl(<$ITMPL>){
+        my @parts = split "<", $input_tmpl;
+        for( my $i=0; $i<=$#parts; ++$i ){
+            my $input_tmpl = $i ? "<" . $parts[$i] : $parts[$i]; # add < sign back in to every part except the first
        $for_loop_found = 0;
-    }
-
-    # handle loops
-    if ( $input_tmpl =~ m/<!--[\s\/]*TMPL_LOOP\s*-->/i ) {
-        push(@files_w_tmpl_loops, $new_path);
-       pop(@cur_scope);
-    }
 
-    $input_tmpl =~ s/<[!-]*\s*\/TMPL_LOOP\s*-*>/[% END %]/ig;
-
-    # misc 'patches'
-    $input_tmpl =~ s/\seq\s/ == /ig;
-    $input_tmpl =~ s/HTML/html/ig;
-    $input_tmpl =~ s/URL/url/ig;
-    $input_tmpl =~ s/\w*\.__first__/loop.first/ig;
-    $input_tmpl =~ s/\w*\.__last__/loop.last/ig;
-    $input_tmpl =~ s/\w*\.__odd__/loop.odd/ig;
-    $input_tmpl =~ s/\w*\.__even__/loop.even/ig;
-    $input_tmpl =~ s/\w*\.__counter__/loop.count/ig; #loop.count gives the range (0..max) whereas loop.index gives the range (1..max+1), __counter__ is unknown
+       # handle poorly names variable such as f1!, f1+, f1-, f1| and mod
+       $input_tmpl =~ s/"(\w+)\|"/"$1pipe"/ig;
+       $input_tmpl =~ s/"(\w+)\+"/"$1plus"/ig;
+       $input_tmpl =~ s/"(\w+)\-"/"$1minus"/ig;
+       $input_tmpl =~ s/"(\w+)!"/"$1exclamation"/ig;
+       $input_tmpl =~ s/"(\w+),(\w+)"/"$1comma$2"/ig; #caused a problem in patron search
+       $input_tmpl =~ s/NAME="mod"/NAME="modname"/ig;
+       # handle 'naked' TMPL_VAR "parameter" by turning them into what they should be, TMPL_VAR NAME="parameter"
+       $input_tmpl =~ s/TMPL_VAR\s+"(\w+)"/TMPL_VAR NAME="$1"/ig;
+       # make an end (ESCAPE NAME DEFAULT) into a ned (NAME ESCAPE DEFAULT)
+       $input_tmpl =~ s/ESCAPE="(\w+?)"\s+NAME=['"](\w+?)['"]\s+DEFAULT=['"](.+?)['"]/NAME="$2" ESCAPE="$1" DEFAULT="$3"/ig;
+
+       # Process..
+       # NB: if you think you're seeing double, you probably are, *some* (read:most) patterns appear twice: once with quotations marks, once without.
+    #     trying to combine them into a single pattern proved troublesome as a regex like ['"]?(.*?)['"]? was causing problems and fixing the problem caused (a lot) more complex regex
+
+       # variables
+       $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s+ESCAPE=['"](\w*?)['"]\s+DEFAULT=['"]?(.*?)['"]?\s*-*>/[% DEFAULT $cur_scope[-1]$1="$3" |$2 %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]\s*(\w*?)\s*['"]\s+ESCAPE=['"]?(\w*?)['"]?\s*-*>/[% $cur_scope[-1]$1 |$2 %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?(\w*?)\s+ESCAPE=['"]?(\w*?)['"]?\s*-*>/[% $cur_scope[-1]$1 |$2 %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+ESCAPE=['"]?(\w*?)['"]?\s+NAME\s?=\s?['"]?([\w-]*?)['"]?\s*-*>/[% $cur_scope[-1]$2 |$1 %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?(\w*?)['"]?\s+DEFAULT=['"](.*?)['"]\s*-*>/[% DEFAULT $cur_scope[-1]$1="$2" %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s+DEFAULT=(.*?)\s*-*>/[% DEFAULT $cur_scope[-1]$1=$2 %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s*-*>/[% $cur_scope[-1]$1 %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% $1 %]/ig;     # TMPL_VAR NAME and TMPL_VAR EXPR are logically equiv
+       $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+EXPR\s?=\s?(.*?)\s*-*>/[% $1 %]/ig;
+
+       # if, elseif and unless blocks
+       $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% IF ( $1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+EXPR\s?=\s?(.*?)\s*-*>/[% IF ( $1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+NAME\s?=\s?['"]\s*(\w*?)\s*['"]\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+NAME\s?=\s?(\w*?)\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+['"](.*?)['"]\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+([\w\s]*?)\s*-*>/[% IF ( $cur_scope[-1]$1 ) %]/ig;
+
+       $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% ELSIF ( $1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+EXPR\s?=\s?(.*?)\s*-*>/[% ELSIF ( $1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+NAME\s?=\s?['"](\w*?)['"]\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+NAME\s?=\s?(\w*?)\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+['"](\w*?)['"]\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+(\w*?)\s*-*>/[% ELSIF ( $cur_scope[-1]$1 ) %]/ig;
+
+       $input_tmpl =~ s/<[!-]*\s*TMPL_ELSE\s*-*>/[% ELSE %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*\/TMPL_IF\s*-*>/[% END %]/ig;
+
+       $input_tmpl =~ s/<[!-]*\s*TMPL_UNLESS\s+NAME\s?=\s?['"]?(\w*?)['"]?\s*-*>/[% UNLESS ( $cur_scope[-1]$1 ) %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*\/TMPL_UNLESS\s*-*>/[% END %]/ig;
+       # includes
+       $input_tmpl =~ s/<[!-]*\s*TMPL_INCLUDE\s+NAME\s?=\s?"(.*?\.inc)"\s*-*>/[% INCLUDE '$1' %]/ig;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_INCLUDE\s+NAME\s?=\s?"(.*?)"\s*-*>/[% INCLUDE $1 %]/ig;
+
+        #reverse scoping bug fix
+        for my $tag (@globals){
+            next unless $cur_scope[-1];
+            $input_tmpl =~ s/$cur_scope[-1]$tag/$tag/g;
+        }
 
-    #hack to get around lack of javascript filter
-    $input_tmpl =~ s/\|JS/|replace("'", "\\'") |replace('"', '\\"') |replace('\\n', '\\\\n') |replace('\\r', '\\\\r')/ig;
+       if ($input_tmpl =~ m/<[!-]*\s*TMPL_LOOP/i ){
+           $for_loop_found = 1;
+       }
+
+       $input_tmpl =~ s/<[!-]*\s*TMPL_LOOP\s+NAME\s?=\s?['"](?<SCOPE>.*?)['"]\s*-*>/"[% FOREACH " . substr($+{SCOPE}, 0, -1) . " IN $cur_scope[-1]$1 %]"/ieg;
+       $input_tmpl =~ s/<[!-]*\s*TMPL_LOOP\s+NAME\s?=\s?(?<SCOPE>.*?)\s*-*>/"[% FOREACH " . substr($+{SCOPE}, 0, -1) . " IN $cur_scope[-1]$1 %]"/ieg;
+
+       # handle new scope
+       if($for_loop_found){
+           my $scope = substr($+{SCOPE}, 0, -1) . ".";
+           push(@cur_scope, $scope);
+           $for_loop_found = 0;
+       }
+
+       # handle loops and old scope
+       if ( $input_tmpl =~ m/<!--[\s\/]*TMPL_LOOP\s*-->/i ) {
+           push(@files_w_tmpl_loops, $new_path);
+           pop(@cur_scope);
+       }
+
+       $input_tmpl =~ s/<[!-]*\s*\/TMPL_LOOP\s*-*>/[% END %]/ig;
+
+       # misc 'patches'
+       $input_tmpl =~ s/\seq\s/ == /ig;
+       $input_tmpl =~ s/HTML/html/g;
+       $input_tmpl =~ s/URL/url/g;
+        $input_tmpl =~ s/dhtmlcalendar_dateformat/DHTMLcalendar_dateformat/ig;
+       $input_tmpl =~ s/\w*\.__first__/loop.first/ig;
+       $input_tmpl =~ s/\w*\.__last__/loop.last/ig;
+       $input_tmpl =~ s/\w*\.__odd__/loop.odd/ig;
+       $input_tmpl =~ s/\w*\.__even__/loop.even/ig;
+       $input_tmpl =~ s/\w*\.__counter__/loop.count/ig; #loop.count gives the range (0..max) whereas loop.index gives the range (1..max+1), __counter__ is unknown
+
+       # hack to get around lack of javascript filter
+       $input_tmpl =~ s/\|\s*JS/|replace("'", "\\'") |replace('"', '\\"') |replace('\\n', '\\\\n') |replace('\\r', '\\\\r')/ig;
     
-    # Write out..
-    print $OTT $input_tmpl;
+       # Write out..
+        print $OTT $input_tmpl;
+        }
     }
+    close $ITMPL;
     close $OTT;
 }