Bug 23168: Enable plugins using plain SQL
[koha.git] / t / lib / QA / TemplateFilters.pm
blobdad22df4b824de1d8ddbe8fe9c3260563e7c57ac
1 package t::lib::QA::TemplateFilters;
3 use Modern::Perl;
5 our @tt_directives = (
6 qr{^\s*INCLUDE},
7 qr{^\s*USE},
8 qr{^\s*IF},
9 qr{^\s*UNLESS},
10 qr{^\s*ELSE},
11 qr{^\s*ELSIF},
12 qr{^\s*END},
13 qr{^\s*SET},
14 qr{^\s*FOR},
15 qr{^\s*FOREACH},
16 qr{^\s*MACRO},
17 qr{^\s*SWITCH},
18 qr{^\s*CASE},
19 qr{^\s*PROCESS},
20 qr{^\s*DEFAULT},
21 qr{^\s*TRY},
22 qr{^\s*CATCH},
23 qr{^\s*BLOCK},
24 qr{^\s*FILTER},
25 qr{^\s*STOP},
26 qr{^\s*NEXT},
27 qr{^\s*LAST},
30 our @tt_methods = (
31 qr{\.push\(},
34 sub fix_filters {
35 return _process_tt_content( @_ )->{new_content};
38 sub missing_filters {
39 return @{_process_tt_content( @_ )->{errors}};
43 sub _process_tt_content {
44 my ($content) = @_;
45 my ( $use_raw, $has_use_raw );
46 my @errors;
47 my @new_lines;
48 my $line_number;
49 for my $line ( split "\n", $content ) {
50 my $new_line = $line;
51 $line_number++;
52 if ( $line =~ m{\[%[^%]+%\]} ) {
54 # handle exceptions first
55 if ( $line =~ m{\|\s*\$raw} ) { # Is the file use the raw filter?
56 $use_raw = 1;
59 # Do we have Asset without the raw filter?
60 if ( $line =~ m{^\s*\[% Asset} && $line !~ m{\|\s*\$raw} ) {
61 push @errors,
63 error => 'asset_must_be_raw',
64 line => $line,
65 line_number => $line_number
67 $new_line =~ s/\)\s*%]/) | \$raw %]/;
68 $use_raw = 1;
69 push @new_lines, $new_line;
70 next;
73 $has_use_raw++
74 if $line =~ m{\[%(\s|-|~)*USE raw(\s|-|~)*%\]}; # Does [% Use raw %] exist?
76 my $e;
77 if ( $line =~ qr{<a href="([^"]+)} ) {
78 my $to_uri_escape = $1;
79 while (
80 $to_uri_escape =~ m{
81 \[%
82 (?<pre_chomp>(\s|\-|~)*)
83 (?<tt_block>[^%\-~]+)
84 (?<post_chomp>(\s|\-|~)*)
85 %\]}gmxs
88 ( $new_line, $e ) = process_tt_block($new_line, { %+, filter => 'uri' });
89 push @errors, { line => $line, line_number => $line_number, error => $e } if $e;
93 # Loop on TT blocks
94 while (
95 $line =~ m{
96 \[%
97 (?<pre_chomp>(\s|\-|~)*)
98 (?<tt_block>[^%\-~]+)
99 (?<post_chomp>(\s|\-|~)*)
100 %\]}gmxs
103 ( $new_line, $e ) = process_tt_block($new_line, \%+);
104 push @errors, { line => $line, line_number => $line_number, error => $e } if $e;
107 push @new_lines, $new_line;
109 else {
110 push @new_lines, $new_line;
115 # Adding [% USE raw %] on top if the filter is used
116 @new_lines = ( '[% USE raw %]', @new_lines )
117 if $use_raw and not $has_use_raw;
119 my $new_content = join "\n", @new_lines;
120 return { errors => \@errors, new_content => $new_content };
123 sub process_tt_block {
124 my ( $line, $params ) = @_;
125 my $tt_block = $params->{tt_block};
126 my $pre_chomp = $params->{pre_chomp};
127 my $post_chomp = $params->{post_chomp};
128 my $filter = $params->{filter} || 'html';
129 my $error;
131 return ( $line, $error ) if
132 # It's a TT directive, no filters needed
133 grep { $tt_block =~ $_ } @tt_directives
135 # It's a TT method
136 or grep { $tt_block =~ $_ } @tt_methods
138 # It is a comment
139 or $tt_block =~ m{^\#}
141 # Already escaped with a special filter
142 # We could escape it but should be safe
143 or $tt_block =~ m{\s?\|\s?\$KohaDates[^\|]*$}
144 or $tt_block =~ m{\s?\|\s?\$Price[^\|]*$}
145 or $tt_block =~ m{\s?\|\s?\$HtmlTags[^\|]*$}
147 # Already escaped correctly with raw
148 or $tt_block =~ m{\|\s?\$raw}
150 # Assignment, maybe we should require to use SET (?)
151 or ( $tt_block =~ m{=} and not $tt_block =~ m{\s\|\s} )
153 # Already has url or uri filter
154 or $tt_block =~ m{\|\s?ur(l|i)}
156 # Specific for [% foo UNLESS bar %]
157 or $tt_block =~ m{^(?<before>\S+)\s+UNLESS\s+(?<after>\S+)}
160 $pre_chomp =
161 $pre_chomp
162 ? $pre_chomp =~ m|-|
163 ? q|- |
164 : $pre_chomp =~ m|~|
165 ? q|~ |
166 : q| |
167 : q| |;
168 $post_chomp =
169 $post_chomp
170 ? $post_chomp =~ m|-|
171 ? q| -|
172 : $post_chomp =~ m|~|
173 ? q| ~|
174 : q| |
175 : q| |;
177 if ( $tt_block =~ m{\s?\|\s?\$KohaDates[^\|]*\|.*$}
178 or $tt_block =~ m{\s?\|\s?\$Price[^\|]*\|.*$}
179 or $tt_block =~ m{\s?\|\s?\$HtmlTags[^\|]*\|.*$}
181 $tt_block =~
182 s/\s*\|\s*(uri|url|html)\s*$//; # Could be another filter...
183 $line =~ s{
185 \s*$pre_chomp\s*
186 \Q$tt_block\E\s*\|\s*(uri|url|html)
187 \s*$post_chomp\s*
189 }{[%$pre_chomp$tt_block$post_chomp%]}xms;
191 return ( $line, 'extra_filter_not_needed' );
194 if (
195 # Use the uri filter is needed
196 # If html filtered or not filtered
197 $filter ne 'html'
198 and (
199 $tt_block !~ m{\|}
200 or ($tt_block =~ m{\|\s?html} and not $tt_block =~ m{\|\s?html_entity})
201 or $tt_block !~ m{\s*|\s*(uri|url)}
204 $tt_block =~ s/^\s*|\s*$//g; # trim
205 $tt_block =~ s/\s*\|\s*html\s*//;
206 $line =~ s{
208 \s*$pre_chomp\s*
209 \Q$tt_block\E(\s*\|\s*html)?
210 \s*$post_chomp\s*
212 }{[%$pre_chomp$tt_block | uri$post_chomp%]}xms;
214 $error = 'wrong_html_filter';
216 elsif (
217 $tt_block !~ m{\|\s?html} # already has html filter
220 $tt_block =~ s/^\s*|\s*$//g; # trim
221 $line =~ s{
223 \s*$pre_chomp\s*
224 \Q$tt_block\E
225 \s*$post_chomp\s*
227 }{[%$pre_chomp$tt_block | html$post_chomp%]}xms;
229 $error = 'missing_filter';
231 return ( $line, $error );
236 =head1 NAME
238 t::lib::QA::TemplateFilters - Module used by tests and QA script to catch missing filters in template files
240 =head1 SYNOPSIS
242 my $content = read_file($filename);
243 my $new_content = t::lib::QA::TemplateFilters::fix_filters($content);
244 my $errors = t::lib::QA::TemplateFilters::missing_filters($content);
246 =head1 DESCRIPTION
248 The goal of this module is to make the subroutine reusable from the QA scripts
249 and to not duplicate the code.
251 =head1 METHODS
253 =head2 fix_filters
255 Take a template content file in parameter and return the same content with
256 the correct (guessed) filters.
257 It will also add the [% USE raw %] statement if it is needed.
259 =head2 missing_filters
261 Take a template content file in parameter and return an arrayref of errors.
263 An error is a hashref with 3 keys, error and line, line_number.
264 * error can be:
265 asset_must_be_raw - When Asset is called without using raw
266 missing_filter - When a TT variable is displayed without filter
267 wrong_html_filter - When a TT variable is using the html filter when uri (or url)
268 should be used instead.
270 * line is the line where the error has been found.
271 * line_number is the line number where the error has been found.
274 =head1 AUTHORS
276 Jonathan Druart <jonathan.druart@bugs.koha-community.org>
278 =head1 COPYRIGHT
280 Copyright 2017 - Koha Development Team
282 =head1 LICENSE
284 This file is part of Koha.
286 Koha is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
287 the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
289 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.
291 You should have received a copy of the GNU General Public License along with Koha; if not, see <http://www.gnu.org/licenses>.
293 =cut