1 package t::lib::QA::TemplateFilters;
38 return _process_tt_content( @_ )->{new_content};
42 return @{_process_tt_content( @_ )->{errors}};
46 sub _process_tt_content {
48 my ( $use_raw, $has_use_raw );
52 for my $line ( split "\n", $content ) {
55 if ( $line =~ m{\[%[^%]+%\]} ) {
57 # handle exceptions first
58 if ( $line =~ m{\|\s*\$raw} ) { # Is the file use the raw filter?
62 # Do we have Asset without the raw filter?
63 if ( $line =~ m{^\s*\[% Asset} && $line !~ m{\|\s*\$raw} ) {
66 error => 'asset_must_be_raw',
68 line_number => $line_number
70 $new_line =~ s/\)\s*%]/) | \$raw %]/;
72 push @new_lines, $new_line;
77 if $line =~ m{\[%(\s|-|~)*USE raw(\s|-|~)*%\]}; # Does [% Use raw %] exist?
80 if ( $line =~ qr{<a href="([^"]+)} ) {
81 my $to_uri_escape = $1;
85 (?<pre_chomp>(\s|\-|~)*)
87 (?<post_chomp>(\s|\-|~)*)
91 ( $new_line, $e ) = process_tt_block($new_line, { %+, filter => 'uri' });
92 push @errors, { line => $line, line_number => $line_number, error => $e } if $e;
100 (?<pre_chomp>(\s|\-|~)*)
101 (?<tt_block>[^%\-~]+)
102 (?<post_chomp>(\s|\-|~)*)
106 ( $new_line, $e ) = process_tt_block($new_line, \%+);
107 push @errors, { line => $line, line_number => $line_number, error => $e } if $e;
110 push @new_lines, $new_line;
113 push @new_lines, $new_line;
118 # Adding [% USE raw %] on top if the filter is used
119 @new_lines = ( '[% USE raw %]', @new_lines )
120 if $use_raw and not $has_use_raw;
122 my $new_content = join "\n", @new_lines;
123 return { errors => \@errors, new_content => $new_content };
126 sub process_tt_block {
127 my ( $line, $params ) = @_;
128 my $tt_block = $params->{tt_block};
129 my $pre_chomp = $params->{pre_chomp};
130 my $post_chomp = $params->{post_chomp};
131 my $filter = $params->{filter} || 'html';
134 return ( $line, $error ) if
135 # It's a TT directive, no filters needed
136 grep { $tt_block =~ $_ } @tt_directives
139 or grep { $tt_block =~ $_ } @tt_methods
142 or $tt_block =~ m{^\#}
144 # Already escaped with a special filter
145 # We could escape it but should be safe
146 or $tt_block =~ m{\s?\|\s?\$KohaDates[^\|]*$}
147 or $tt_block =~ m{\s?\|\s?\$Price[^\|]*$}
148 or $tt_block =~ m{\s?\|\s?\$HtmlTags[^\|]*$}
149 or $tt_block =~ m{\s?\|\s?\$HtmlId[^\|]*$}
151 # Already escaped correctly with raw
152 or $tt_block =~ m{\|\s?\$raw}
154 # Assignment, maybe we should require to use SET (?)
155 or ( $tt_block =~ m{=} and not $tt_block =~ m{\s\|\s} )
157 # Already has url or uri filter
158 or $tt_block =~ m{\|\s?ur(l|i)}
160 # Specific for [% foo UNLESS bar %]
161 or $tt_block =~ m{^(?<before>\S+)\s+UNLESS\s+(?<after>\S+)}
174 ? $post_chomp =~ m|-|
176 : $post_chomp =~ m|~|
181 if ( $tt_block =~ m{\s?\|\s?\$KohaDates[^\|]*\|.*$}
182 or $tt_block =~ m{\s?\|\s?\$Price[^\|]*\|.*$}
183 or $tt_block =~ m{\s?\|\s?\$HtmlTags[^\|]*\|.*$}
186 s/\s*\|\s*(uri|url|html)\s*$//; # Could be another filter...
190 \Q$tt_block\E\s*\|\s*(uri|url|html)
193 }{[%$pre_chomp$tt_block$post_chomp%]}xms;
195 return ( $line, 'extra_filter_not_needed' );
199 # Use the uri filter is needed
200 # If html filtered or not filtered
204 or ($tt_block =~ m{\|\s?html} and not $tt_block =~ m{\|\s?html_entity})
205 or $tt_block !~ m{\s*|\s*(uri|url)}
208 $tt_block =~ s/^\s*|\s*$//g; # trim
209 $tt_block =~ s/\s*\|\s*html\s*//;
213 \Q$tt_block\E(\s*\|\s*html)?
216 }{[%$pre_chomp$tt_block | uri$post_chomp%]}xms;
218 $error = 'wrong_html_filter';
221 $tt_block !~ m{\|\s?html} # already has html filter
224 $tt_block =~ s/^\s*|\s*$//g; # trim
231 }{[%$pre_chomp$tt_block | html$post_chomp%]}xms;
233 $error = 'missing_filter';
235 return ( $line, $error );
242 t::lib::QA::TemplateFilters - Module used by tests and QA script to catch missing filters in template files
246 my $content = read_file($filename);
247 my $new_content = t::lib::QA::TemplateFilters::fix_filters($content);
248 my $errors = t::lib::QA::TemplateFilters::missing_filters($content);
252 The goal of this module is to make the subroutine reusable from the QA scripts
253 and to not duplicate the code.
259 Take a template content file in parameter and return the same content with
260 the correct (guessed) filters.
261 It will also add the [% USE raw %] statement if it is needed.
263 =head2 missing_filters
265 Take a template content file in parameter and return an arrayref of errors.
267 An error is a hashref with 3 keys, error and line, line_number.
269 asset_must_be_raw - When Asset is called without using raw
270 missing_filter - When a TT variable is displayed without filter
271 wrong_html_filter - When a TT variable is using the html filter when uri (or url)
272 should be used instead.
274 * line is the line where the error has been found.
275 * line_number is the line number where the error has been found.
280 Jonathan Druart <jonathan.druart@bugs.koha-community.org>
284 Copyright 2017 - Koha Development Team
288 This file is part of Koha.
290 Koha is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
291 the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
293 Koha is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
295 You should have received a copy of the GNU General Public License along with Koha; if not, see <http://www.gnu.org/licenses>.