ParseFilter: Laundering in explizite Ziele
authorSven Schöling <s.schoeling@linet-services.de>
Wed, 14 Dec 2011 14:47:10 +0000 (15:47 +0100)
committerSven Schöling <s.schoeling@linet-services.de>
Wed, 14 Dec 2011 15:27:52 +0000 (16:27 +0100)
SL/Controller/Helper/ParseFilter.pm
t/controllers/helpers/parse_filter.t

index 3753d16..ac086f5 100644 (file)
@@ -36,7 +36,7 @@ sub parse_filter {
 
   my $query = _parse_filter($flattened, %params);
 
-  _launder_keys($filter) unless $params{no_launder};
+  _launder_keys($filter, $params{launder_to}) unless $params{no_launder};
 
   return
     ($query   && @$query   ? (query => $query) : ()),
@@ -44,23 +44,27 @@ sub parse_filter {
 }
 
 sub _launder_keys {
-  my ($filter) = @_;
+  my ($filter, $launder_to) = @_;
+  $launder_to ||= $filter;
   return unless ref $filter eq 'HASH';
-  my @keys = keys %$filter;
-  for my $key (@keys) {
+  for my $key (keys %$filter) {
     my $orig = $key;
     $key =~ s/:/_/g;
-    $filter->{$key} = $filter->{$orig};
-    _launder_keys($filter->{$key});
+    if ('' eq ref $filter->{$orig}) {
+      $launder_to->{$key} = $filter->{$orig};
+    } elsif ('ARRAY' eq ref $filter->{$orig}) {
+      $launder_to->{$key} = [ @{ $filter->{$orig} } ];
+    } else {
+      $launder_to->{$key} ||= { };
+      _launder_keys($filter->{$key}, $launder_to->{$key});
+    }
   };
-
-  return $filter;
 }
 
 sub _pre_parse {
   my ($filter, $with_objects, $prefix, %params) = @_;
 
-  return () unless 'HASH'  eq ref $filter;
+  return (undef, $with_objects) unless 'HASH'  eq ref $filter;
   $with_objects ||= [];
 
   my @result;
@@ -207,18 +211,38 @@ and later
 The special empty method will be used to set the method for the previous
 method-less input.
 
-=item Laundering filter
+=back
+
+=head1 LAUNDERING
 
 Unfortunately Template cannot parse the postfixes if you want to
 rerender the filter. For this reason all colons filter keys are by
-default laundered into underscores. If you don't want this to happen
-pass C<< no_launder => 1 >> as a parameter. A full select_tag then
-loks like this:
+default laundered into underscores, so you can use them like this:
 
   [% L.input_tag('filter.price:number::lt', filter.price_number__lt) %]
 
+All of your original entries will stay intactg. If you don't want this to
+happen pass C<< no_launder => 1 >> as a parameter.  Additionally you can pass a
+different target for the laundered values with the C<launder_to>  parameter. It
+takes an hashref and will deep copy all values in your filter to the target. So
+if you have a filter that looks liek this:
 
-=back
+  $filter = {
+    'price:number::lt' => '2,30',
+    'closed            => '1',
+  }
+
+and parse it with
+
+  parse_filter($filter, launder_to => $laundered_filter = { })
+
+the original filter will be unchanged, and C<$laundered_filter> will end up
+like this:
+
+  $filter = {
+    'price_number__lt' => '2,30',
+    'closed            => '1',
+  }
 
 =head1 FILTERS (leading with :)
 
index 84547e0..179c236 100644 (file)
@@ -1,6 +1,6 @@
 use lib 't';
 
-use Test::More tests => 13;
+use Test::More tests => 17;
 use Test::Deep;
 use Data::Dumper;
 
@@ -12,14 +12,19 @@ undef *::any; # Test::Deep exports any (for junctions) and MoreCommon exports an
 Support::TestSetup::login();
 my ($filter, $expected);
 
-sub test ($$$) {
-  my $got = { parse_filter($_[0]) };
+sub test ($$$;%) {
+  my ($filter, $expect, $msg, %params) = @_;
+  my $target = delete $params{target};
+  my $args = { parse_filter($filter, %params) };
+  my $got  = $args;
+     $got = $filter             if $target =~ /filter/;
+     $got = $params{launder_to} if $target =~ /launder/;
   cmp_deeply(
     $got,
-    $_[1],
-    $_[2]
+    $expect,
+    $msg,
   ) or do {
-    print STDERR "expected => ", Dumper($_[1]), "\ngot: => ", Dumper($got), $/;
+    print STDERR "expected => ", Dumper($expect), "\ngot: => ", Dumper($got), $/;
   }
 }
 
@@ -126,3 +131,49 @@ test {
   ],
 }, 'arrays with filter';
 
+
+########### laundering
+
+test {
+  'sellprice:number' => [
+    '123,4', '2,34', '0,4',
+  ]
+}, {
+  'sellprice:number' => [ '123,4', '2,34', '0,4' ],
+  'sellprice_number' => [ '123,4', '2,34', '0,4' ],
+}, 'laundering with array', target => 'filter';
+
+my %args = (
+  'sellprice:number' => [
+    '123,4', '2,34', '0,4',
+  ],
+);
+test {
+  %args,
+}, {
+  %args
+}, 'laundering into launder does not alter filter', target => 'filter', launder_to => {};
+
+
+test {
+  part => {
+   'sellprice:number' => '123,4',
+  }
+}, {
+  part => {
+    'sellprice:number' => '123,4',
+    'sellprice_number' => '123,4'
+  }
+}, 'deep laundering', target => 'filter';
+
+
+test {
+  part => {
+   'sellprice:number' => '123,4',
+  }
+}, {
+  part => {
+    'sellprice_number' => '123,4'
+  }
+}, 'deep laundering, check for laundered hash', target => 'launder', launder_to => { };
+