More work on 'conversion' script for HTML::Toolkit to Template::Tolkit
[koha.git] / installer / html-template-to-template-toolkit.pl
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use Carp;
6 use Data::Dumper;
7
8 use Getopt::Long;
9 use File::Basename;
10 use File::Copy;
11
12 my $help_msg = <<EOH;
13 This script does a first-cut conversion of koha HTML::Template template files (.tmpl).
14 It creates a mirror of koha-tmpl called koha-tt where converted files will be placed.
15 By default all files will be converted: use the --file (-f) argument to specify
16   individual files to process.
17
18 Options:
19     --koharoot (-r): Root directory of koha installation.
20     --type (-t): template file extenstions to match
21         (defaults to tmpl|inc|xsl).
22     --copyall (-c): Also copy across all files in template directory
23     --file (-f): specify individual files to process
24     --debug (-d): output more information.
25 EOH
26
27 my $tmpl_in_dir      = 'koha-tmpl';
28 my $tmpl_out_dir     = 'koha-tt';
29
30 # Arguments:
31 my $KOHA_ROOT;
32 my $tmpl_extn_match  = "tmpl|inc|xsl"; # Type match defaults to *.tmpl plus *.inc if not specified
33 my $copy_other_files = 0;
34 my @template_files;
35 my @files_w_tmpl_loops;
36 my $verbose          = 0;
37 GetOptions (
38     "koharoot=s"        => \$KOHA_ROOT,
39     "type|t=s"          => \$tmpl_extn_match,
40     "copyall|c"         => \$copy_other_files,
41     "file|f=s"          => \@template_files,         # array of filenames
42     "verbose+"          => \$verbose,                # incremental flag
43 ) or die $help_msg;
44
45 if ( ! $KOHA_ROOT || ! -d $KOHA_ROOT ) {
46     croak "Koha root not passed or is not correct.";
47 }
48 if ( ! -d "$KOHA_ROOT/$tmpl_in_dir" ) {
49     croak "Cannot find template dir ($tmpl_in_dir)";
50 }
51
52 # Attempt to create koha-tt dir..
53 if ( ! -d "$KOHA_ROOT/$tmpl_out_dir" ) {
54     mkdir("$KOHA_ROOT/$tmpl_out_dir") #, '0755'
55        or croak "Cannot create $tmpl_out_dir directory in $KOHA_ROOT: $!";
56 }
57
58 # Obtain list of files to process - go recursively through tmpl_in_dir and subdirectories..
59 unless ( scalar(@template_files) ) {
60     @template_files = mirror_template_dir_structure_return_files("$KOHA_ROOT/$tmpl_in_dir", "$tmpl_extn_match");
61 }
62 foreach my $file (@template_files) {
63     (my $new_path = $file) =~ s/$tmpl_in_dir/$tmpl_out_dir/;
64     $new_path = "$KOHA_ROOT/$new_path" unless ( $new_path =~ m/^$KOHA_ROOT/ );
65
66     open my $ITMPL, '<', $file or croak "Can't open $file for input: $!";
67     open my $OTT, '>', $new_path or croak "Can't open $new_path for output: $!";
68
69     # Slurp in input file..
70     my $input_tmpl = do { local $/; <$ITMPL> };
71     close $ITMPL;
72
73     # Process..
74     # NB: if you think you're seeing double, you probably are, *some* (read:most) patterns appear twice: once with quotations marks, once without.
75     #     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
76     # variables
77     $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]\s*(\w*?)\s*['"]\s+ESCAPE=['"]?(\w*?)['"]?\s*-*>/[% $1 |$2%]/ig;
78     $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?(\w*?)\s+ESCAPE=['"]?(\w*?)['"]?\s*-*>/[% $1 |$2%]/ig;
79     $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+ESCAPE=['"]?(\w*?)['"]?\s+NAME\s?=\s?['"]?([\w-]*?)['"]?\s*-*>/[% $1 |$2%]/ig;
80     $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?(\w*?)['"]?\s+DEFAULT=['"](.*?)['"]\s*-*>/[% DEFAULT $1="$2"%]/ig; # if a value being assigned is wrapped in quotes, keep them intact
81     $input_tmpl =~ s/<[!-]*\s*TMPL_VAR\s+NAME\s?=\s?['"]?\s*(\w*?)\s*['"]?\s+DEFAULT=(.*?)\s*-*>/[% DEFAULT $1=$2%]/ig;
82     $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+NAME\s?=\s?['"]?(\w*?)['"]?\s*-*>/[% $1 %]/ig;
83     $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
84     $input_tmpl =~ s/<[!-]*\s*TMPL[_\s]VAR\s+EXPR\s?=\s?(.*?)\s*-*>/[% $1 %]/ig;
85     # if, elseif and unless blocks
86     $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% IF ( $1 ) %]/ig;
87     $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+EXPR\s?=\s?(.*?)\s*-*>/[% IF ( $1 ) %]/ig;
88     $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+NAME\s?=\s?['"]\s*(\w*?)\s*['"]\s*-*>/[% IF ( $1 ) %]/ig;
89     $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+NAME\s?=\s?(\w*?)\s*-*>/[% IF ( $1 ) %]/ig;
90     $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+['"](.*?)['"]\s*-*>/[% IF ( $1 ) %]/ig;
91     $input_tmpl =~ s/<[!-]*\s*TMPL_IF\s+([\w\s]*?)\s*-*>/[% IF ( $1 ) %]/ig;
92
93     $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+EXPR\s?=\s?['"](.*?)['"]\s*-*>/[% ELSEIF ( $1 ) %]/ig;
94     $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+EXPR\s?=\s?(.*?)\s*-*>/[% ELSEIF ( $1 ) %]/ig;
95     $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+NAME\s?=\s?['"](\w*?)['"]\s*-*>/[% ELSEIF ( $1 ) %]/ig;
96     $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+NAME\s?=\s?(\w*?)\s*-*>/[% ELSEIF ( $1 ) %]/ig;
97     $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+['"](\w*?)['"]\s*-*>/[% ELSEIF ( $1 ) %]/ig;
98     $input_tmpl =~ s/<[!-]*\s*TMPL_ELSIF\s+(\w*?)\s*-*>/[% ELSEIF ( $1 ) %]/ig;
99
100     $input_tmpl =~ s/<[!-]*\s*TMPL_ELSE\s*-*>/[% ELSE %]/ig;
101     $input_tmpl =~ s/<[!-]*\s*\/TMPL_IF\s*-*>/[% END %]/ig;
102
103     $input_tmpl =~ s/<[!-]*\s*TMPL_UNLESS\s+NAME\s?=\s?['"]?(\w*?)['"]?\s*-*>/[% IF ( $1 ) %]/ig;
104     $input_tmpl =~ s/<[!-]*\s*\/TMPL_UNLESS\s*-*>/[% END %]/ig;
105     # includes
106     $input_tmpl =~ s/<[!-]*\s*TMPL_INCLUDE\s+NAME\s?=\s?"(.*?\.inc)"\s*-*>/[% INCLUDE '$1' %]/ig;
107     $input_tmpl =~ s/<[!-]*\s*TMPL_INCLUDE\s+NAME\s?=\s?"(.*?)"\s*-*>/[% INCLUDE $1 %]/ig;
108
109     if ( $input_tmpl =~ m/<!--[\s\/]*TMPL_LOOP\s*-->/i ) {
110         push(@files_w_tmpl_loops, $new_path);
111     }
112
113     $input_tmpl =~ s/<[!-]*\s*TMPL_LOOP\s+NAME\s?=\s?['"](.*?)['"]\s*-*>/"[% FOREACH ".substr($1, 0 , -1)." = ".$1." %]"/ieg;
114     $input_tmpl =~ s/<[!-]*\s*TMPL_LOOP\s+NAME\s?=\s?(.*?)\s*-*>/"[% FOREACH ".substr($1, 0 , -1)." = ".$1." %]"/ieg;
115     $input_tmpl =~ s/<[!-]*\s*\/TMPL_LOOP\s*-*>/[% END %]/ig;
116
117     # misc 'patches'
118     $input_tmpl =~ s/\seq\s/ == /ig;
119     $input_tmpl =~ s/HTML/html/ig;
120     $input_tmpl =~ s/URL/url/ig;
121
122     # Write out..
123     print $OTT $input_tmpl;
124     close $OTT;
125 }
126
127 if ( scalar(@files_w_tmpl_loops) && $verbose ) {
128     print "\nThese files contain TMPL_LOOPs that need double checking:\n";
129     foreach my $file (@files_w_tmpl_loops) {
130         print "$file\n";
131     }
132 }
133
134 ## SUB-ROUTINES ##
135
136 # Create new directory structure and return list of template files
137 sub mirror_template_dir_structure_return_files {
138     my($dir, $type) = @_;
139
140     my @files = ();
141     if ( opendir(DIR, $dir) ) {
142         my @dirent = readdir DIR;   # because DIR is shared when recursing
143         closedir DIR;
144         for my $dirent (@dirent) {
145             my $path = "$dir/$dirent";
146             if ( $dirent =~ /^\./ ) {
147               ;
148             }
149             elsif ( -f $path ) {
150                 (my $new_path = $path) =~ s/$tmpl_in_dir/$tmpl_out_dir/;
151                 $new_path = "$KOHA_ROOT/$new_path" unless ( $new_path =~ m/^$KOHA_ROOT/ );
152                 if ( !defined $type || $dirent =~ /\.(?:$type)$/) {
153                     push(@files, $path);
154                 }
155                 elsif ( $copy_other_files ) {
156                     copy($path, $new_path)
157                       or croak "Failed to copy $path to $new_path: $!";
158                 }
159             }
160             elsif ( -d $path ) {
161                 (my $new_path = $path) =~ s/$tmpl_in_dir/$tmpl_out_dir/;
162                 $new_path = "$KOHA_ROOT/$new_path" unless ( $new_path =~ m/^$KOHA_ROOT/ );
163                 if ( ! -d $new_path ) {
164                     mkdir($new_path) #, '0755'
165                       or croak "Failed to create " . $new_path ." directory: $!";
166                 }
167                 my @sub_files = mirror_template_dir_structure_return_files($path, $type);
168                 push(@files, @sub_files) if ( scalar(@sub_files) );
169             }
170         }
171     } else {
172         warn("Cannot open $dir: $! ... skipping");
173     }
174
175     return @files;
176 }