View | Details | Raw Unified | Return to bug 21393
Collapse All | Expand All

(-)a/t/lib/QA/TemplateFilters.pm (+133 lines)
Line 0 Link Here
1
package t::lib::QA::TemplateFilters;
2
3
use Modern::Perl;
4
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
);
28
29
sub missing_filters {
30
    my ($content) = @_;
31
    my ( $use_raw, $has_use_raw );
32
    my @errors;
33
    for my $line ( split "\n", $content ) {
34
        if ( $line =~ m{\[%[^%]+%\]} ) {
35
36
            # handle exceptions first
37
            $use_raw = 1
38
              if $line =~ m{|\s*\$raw};    # Is the file use the raw filter?
39
40
            # Do we have Asset without the raw filter?
41
            if ( $line =~ m{^\s*\[% Asset} ) {
42
                push @errors, { error => 'asset_must_be_raw', line => $line }
43
                  and next
44
                  unless $line =~ m{\|\s*\$raw};
45
            }
46
47
            $has_use_raw++
48
              if $line =~ m{\[% USE raw %\]};    # Does [% Use raw %] exist?
49
50
            # Loop on TT blocks
51
            while (
52
                $line =~ m{
53
                    \[%
54
                    (?<pre_chomp>(\s|\-|~)*)
55
                    (?<tt_block>[^%\-~]+)
56
                    (?<post_chomp>(\s|\-|~)*)
57
                    %\]}gmxs
58
              )
59
            {
60
                my $tt_block = $+{tt_block};
61
62
                # It's a TT directive, no filters needed
63
                next if grep { $tt_block =~ $_ } @tt_directives;
64
65
                next
66
                  if $tt_block =~ m{\s?\|\s?\$KohaDates\s?$}
67
                  ;    # We could escape it but should be safe
68
                next if $tt_block =~ m{^\#};    # Is a comment, skip it
69
70
                push @errors, { error => 'missing_filter', line => $line }
71
                  if $tt_block !~ m{\|\s?\$raw}   # already escaped correctly with raw
72
                  && $tt_block !~ m{=}            # assignment, maybe we should require to use SET (?)
73
                  && $tt_block !~ m{\|\s?ur(l|i)} # already has url or uri filter
74
                  && $tt_block !~ m{\|\s?html}    # already has html filter
75
                  && $tt_block !~ m{^(?<before>\S+)\s+UNLESS\s+(?<after>\S+)} # Specific for [% foo UNLESS bar %]
76
                ;
77
            }
78
        }
79
    }
80
81
    return @errors;
82
}
83
84
1;
85
86
=head1 NAME
87
88
t::lib::QA::TemplateFilters - Module used by tests and QA script to catch missing filters in template files
89
90
=head1 SYNOPSIS
91
92
    my $content = read_file($filename);
93
    my @e = t::lib::QA::TemplateFilters::missing_filters($content);
94
95
=head1 DESCRIPTION
96
97
The goal of this module is to make the subroutine reusable from the QA scripts
98
and to not duplicate the code.
99
100
=head1 METHODS
101
102
=head2 missing_filters
103
104
    Take a template content file in parameter and return an array of errors.
105
    An error is a hashref with 2 keys, error and line.
106
    * error can be:
107
    asset_must_be_raw - When Asset is called without using raw
108
    missing_filter    - When a TT variable is displayed without filter
109
110
    * line is the line where the error has been found.
111
112
=head1 AUTHORS
113
114
Jonathan Druart <jonathan.druart@bugs.koha-community.org>
115
116
=head1 COPYRIGHT
117
118
Copyright 2017 - Koha Development Team
119
120
=head1 LICENSE
121
122
This file is part of Koha.
123
124
Koha is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
125
the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
126
127
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.
128
129
You should have received a copy of the GNU General Public License along with Koha; if not, see <http://www.gnu.org/licenses>.
130
131
=cut
132
133
1;
(-)a/xt/find-missing-filters.t (-82 / +2 lines)
Lines 20-25 use Test::More tests => 1; Link Here
20
use File::Find;
20
use File::Find;
21
use File::Slurp;
21
use File::Slurp;
22
use Data::Dumper;
22
use Data::Dumper;
23
use t::lib::QA::TemplateFilters;
23
24
24
my @themes;
25
my @themes;
25
26
Lines 46-137 sub wanted { Link Here
46
        if $name =~ m[\.(tt|inc)$] and -f $name;
47
        if $name =~ m[\.(tt|inc)$] and -f $name;
47
}
48
}
48
49
49
my @tt_directives = (
50
    qr{^\s*INCLUDE},
51
    qr{^\s*USE},
52
    qr{^\s*IF},
53
    qr{^\s*UNLESS},
54
    qr{^\s*ELSE},
55
    qr{^\s*ELSIF},
56
    qr{^\s*END},
57
    qr{^\s*SET},
58
    qr{^\s*FOR},
59
    qr{^\s*FOREACH},
60
    qr{^\s*MACRO},
61
    qr{^\s*SWITCH},
62
    qr{^\s*CASE},
63
    qr{^\s*PROCESS},
64
    qr{^\s*DEFAULT},
65
    qr{^\s*TRY},
66
    qr{^\s*CATCH},
67
    qr{^\s*BLOCK},
68
    qr{^\s*FILTER},
69
    qr{^\s*STOP},
70
    qr{^\s*NEXT},
71
);
72
73
sub process_tt_content {
74
    my ($content) = @_;
75
    my ( $use_raw, $has_use_raw );
76
    my @errors;
77
    for my $line ( split "\n", $content ) {
78
        if ( $line =~ m{\[%[^%]+%\]} ) {
79
80
            # handle exceptions first
81
            $use_raw = 1
82
              if $line =~ m{|\s*\$raw};    # Is the file use the raw filter?
83
84
            # Do we have Asset without the raw filter?
85
            if ( $line =~ m{^\s*\[% Asset} ) {
86
                push @errors, { error => 'asset_must_be_raw', line => $line }
87
                  and next
88
                  unless $line =~ m{\|\s*\$raw};
89
            }
90
91
            $has_use_raw++
92
              if $line =~ m{\[% USE raw %\]};    # Does [% Use raw %] exist?
93
94
            # Loop on TT blocks
95
            while (
96
                $line =~ m{
97
                    \[%
98
                    (?<pre_chomp>(\s|\-|~)*)
99
                    (?<tt_block>[^%\-~]+)
100
                    (?<post_chomp>(\s|\-|~)*)
101
                    %\]}gmxs
102
              )
103
            {
104
                my $tt_block = $+{tt_block};
105
106
                # It's a TT directive, no filters needed
107
                next if grep { $tt_block =~ $_ } @tt_directives;
108
109
                next
110
                  if $tt_block =~ m{\s?\|\s?\$KohaDates\s?$}
111
                  ;    # We could escape it but should be safe
112
                next if $tt_block =~ m{^\#};    # Is a comment, skip it
113
114
                push @errors, { error => 'missing_filter', line => $line }
115
                  if $tt_block !~ m{\|\s?\$raw}   # already escaped correctly with raw
116
                  && $tt_block !~ m{=}            # assignment, maybe we should require to use SET (?)
117
                  && $tt_block !~ m{\|\s?ur(l|i)} # already has url or uri filter
118
                  && $tt_block !~ m{\|\s?html}    # already has html filter
119
                  && $tt_block !~ m{^(?<before>\S+)\s+UNLESS\s+(?<after>\S+)} # Specific for [% foo UNLESS bar %]
120
                ;
121
            }
122
        }
123
    }
124
125
    return @errors;
126
}
127
128
find({ wanted => \&wanted, no_chdir => 1 }, @themes );
50
find({ wanted => \&wanted, no_chdir => 1 }, @themes );
129
51
130
my @errors;
52
my @errors;
131
for my $file ( @files ) {
53
for my $file ( @files ) {
132
    say $file;
133
    my $content = read_file($file);
54
    my $content = read_file($file);
134
    my @e = process_tt_content($content);
55
    my @e = t::lib::QA::TemplateFilters::missing_filters($content);
135
    push @errors, { file => $file, errors => \@e } if @e;
56
    push @errors, { file => $file, errors => \@e } if @e;
136
}
57
}
137
58
138
- 

Return to bug 21393