Bug 21576: Preserve chomp chars for USE raw
[koha_ffzg] / t / lib / QA / TemplateFilters.pm
index 4b4a3d2..f2009cc 100644 (file)
@@ -24,30 +24,67 @@ our @tt_directives = (
     qr{^\s*FILTER},
     qr{^\s*STOP},
     qr{^\s*NEXT},
+    qr{^\s*LAST},
 );
 
+sub fix_filters {
+    return _process_tt_content( @_ )->{new_content};
+}
+
 sub missing_filters {
+    return @{_process_tt_content( @_ )->{errors}};
+
+}
+
+sub _process_tt_content {
     my ($content) = @_;
     my ( $use_raw, $has_use_raw );
     my @errors;
+    my @new_lines;
     my $line_number;
     for my $line ( split "\n", $content ) {
+        my $new_line = $line;
         $line_number++;
         if ( $line =~ m{\[%[^%]+%\]} ) {
 
             # handle exceptions first
-            $use_raw = 1
-              if $line =~ m{|\s*\$raw};    # Is the file use the raw filter?
+            if ( $line =~ m{\|\s*\$raw} ) {    # Is the file use the raw filter?
+                $use_raw = 1;
+            }
 
             # Do we have Asset without the raw filter?
-            if ( $line =~ m{^\s*\[% Asset} ) {
-                push @errors, { error => 'asset_must_be_raw', line => $line, line_number => $line_number }
-                  and next
-                  unless $line =~ m{\|\s*\$raw};
+            if ( $line =~ m{^\s*\[% Asset} && $line !~ m{\|\s*\$raw} ) {
+                push @errors,
+                  {
+                    error       => 'asset_must_be_raw',
+                    line        => $line,
+                    line_number => $line_number
+                  };
+                $new_line =~ s/\)\s*%]/) | \$raw %]/;
+                $use_raw = 1;
+                push @new_lines, $new_line;
+                next;
             }
 
             $has_use_raw++
-              if $line =~ m{\[% USE raw %\]};    # Does [% Use raw %] exist?
+              if $line =~ m{\[%(\s|-|~)*USE raw(\s|-|~)*%\]};    # Does [% Use raw %] exist?
+
+            my $e;
+            if ( $line =~ qr{<a href="([^"]+)} ) {
+                my $to_uri_escape = $1;
+                while (
+                    $to_uri_escape =~ m{
+                        \[%
+                        (?<pre_chomp>(\s|\-|~)*)
+                        (?<tt_block>[^%\-~]+)
+                        (?<post_chomp>(\s|\-|~)*)
+                        %\]}gmxs
+                  )
+                {
+                    ( $new_line, $e ) = process_tt_block($new_line, { %+, filter => 'uri' });
+                    push @errors, { line => $line, line_number => $line_number, error => $e } if $e;
+                }
+            }
 
             # Loop on TT blocks
             while (
@@ -59,28 +96,114 @@ sub missing_filters {
                     %\]}gmxs
               )
             {
-                my $tt_block = $+{tt_block};
-
-                # It's a TT directive, no filters needed
-                next if grep { $tt_block =~ $_ } @tt_directives;
-
-                next
-                  if $tt_block =~ m{\s?\|\s?\$KohaDates\s?$}
-                  ;    # We could escape it but should be safe
-                next if $tt_block =~ m{^\#};    # Is a comment, skip it
-
-                push @errors, { error => 'missing_filter', line => $line, line_number => $line_number }
-                  if $tt_block !~ m{\|\s?\$raw}   # already escaped correctly with raw
-                  && $tt_block !~ m{=}            # assignment, maybe we should require to use SET (?)
-                  && $tt_block !~ m{\|\s?ur(l|i)} # already has url or uri filter
-                  && $tt_block !~ m{\|\s?html}    # already has html filter
-                  && $tt_block !~ m{^(?<before>\S+)\s+UNLESS\s+(?<after>\S+)} # Specific for [% foo UNLESS bar %]
-                ;
+                ( $new_line, $e ) = process_tt_block($new_line, \%+);
+                push @errors, { line => $line, line_number => $line_number, error => $e } if $e;
             }
+
+            push @new_lines, $new_line;
         }
+        else {
+            push @new_lines, $new_line;
+        }
+
     }
 
-    return @errors;
+    # Adding [% USE raw %] on top if the filter is used
+    @new_lines = ( '[% USE raw %]', @new_lines )
+      if $use_raw and not $has_use_raw;
+
+    my $new_content = join "\n", @new_lines;
+    return { errors => \@errors, new_content => $new_content };
+}
+
+sub process_tt_block {
+    my ( $line, $params ) = @_;
+    my $tt_block   = $params->{tt_block};
+    my $pre_chomp  = $params->{pre_chomp};
+    my $post_chomp = $params->{post_chomp};
+    my $filter     = $params->{filter} || 'html';
+    my $error;
+
+    return ( $line, $error ) if
+        # It's a TT directive, no filters needed
+        grep { $tt_block =~ $_ } @tt_directives
+
+        # It is a comment
+        or $tt_block =~ m{^\#}
+
+        # Already escaped with a special filter
+        # We could escape it but should be safe
+        or $tt_block =~ m{\s?\|\s?\$KohaDates\s?$}
+        or $tt_block =~ m{\s?\|\s?\$Price\s?$}
+
+        # Already escaped correctly with raw
+        or $tt_block =~ m{\|\s?\$raw}
+
+        # Assignment, maybe we should require to use SET (?)
+        or $tt_block =~ m{=}
+
+        # Already has url or uri filter
+        or $tt_block =~ m{\|\s?ur(l|i)}
+
+        # Specific for [% foo UNLESS bar %]
+        or $tt_block =~ m{^(?<before>\S+)\s+UNLESS\s+(?<after>\S+)}
+    ;
+
+    $pre_chomp =
+        $pre_chomp
+      ? $pre_chomp =~ m|-|
+          ? q|- |
+          : $pre_chomp =~ m|~|
+            ? q|~ |
+            : q| |
+      : q| |;
+    $post_chomp =
+        $post_chomp
+      ? $post_chomp =~ m|-|
+          ? q| -|
+          : $post_chomp =~ m|~|
+            ? q| ~|
+            : q| |
+      : q| |;
+
+    if (
+        # Use the uri filter is needed
+        # If html filtered or not filtered
+        $filter ne 'html'
+            and (
+                    $tt_block !~ m{\|}
+                or  $tt_block =~ m{\|\s?html}
+                or $tt_block !~ m{\s*|\s*(uri|url)}
+      )
+    ) {
+        $tt_block =~ s/^\s*|\s*$//g;    # trim
+        $tt_block =~ s/\s*\|\s*html\s*//;
+        $line =~ s{
+                \[%
+                \s*$pre_chomp\s*
+                \Q$tt_block\E(\s*\|\s*html)?
+                \s*$post_chomp\s*
+                %\]
+            }{[%$pre_chomp$tt_block | uri$post_chomp%]}xms;
+
+        $error = 'wrong_html_filter';
+    }
+    elsif (
+        $tt_block !~ m{\|\s?html} # already has html filter
+      )
+    {
+        $tt_block =~ s/^\s*|\s*$//g; # trim
+        $line =~ s{
+            \[%
+            \s*$pre_chomp\s*
+            \Q$tt_block\E
+            \s*$post_chomp\s*
+            %\]
+        }{[%$pre_chomp$tt_block | html$post_chomp%]}xms;
+
+        $error = 'missing_filter';
+    }
+    return ( $line, $error );
 }
 
 1;
@@ -92,7 +215,8 @@ t::lib::QA::TemplateFilters - Module used by tests and QA script to catch missin
 =head1 SYNOPSIS
 
     my $content = read_file($filename);
-    my @e = t::lib::QA::TemplateFilters::missing_filters($content);
+    my $new_content = t::lib::QA::TemplateFilters::fix_filters($content);
+    my $errors      = t::lib::QA::TemplateFilters::missing_filters($content);
 
 =head1 DESCRIPTION
 
@@ -101,15 +225,26 @@ and to not duplicate the code.
 
 =head1 METHODS
 
+=head2 fix_filters
+
+    Take a template content file in parameter and return the same content with
+    the correct (guessed) filters.
+    It will also add the [% USE raw %] statement if it is needed.
+
 =head2 missing_filters
 
-    Take a template content file in parameter and return an array of errors.
-    An error is a hashref with 2 keys, error and line.
+    Take a template content file in parameter and return an arrayref of errors.
+
+    An error is a hashref with 3 keys, error and line, line_number.
     * error can be:
     asset_must_be_raw - When Asset is called without using raw
     missing_filter    - When a TT variable is displayed without filter
+    wrong_html_filter - When a TT variable is using the html filter when uri (or url)
+                        should be used instead.
 
     * line is the line where the error has been found.
+    * line_number is the line number where the error has been found.
+
 
 =head1 AUTHORS