From d2550089aa9f5d321e025df59815b0eabc7037ab Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sven=20Sch=C3=B6ling?= Date: Mon, 27 May 2013 17:38:22 +0200 Subject: [PATCH] =?utf8?q?Besseres=20Objektverhalten=20und=20bessere=20Dok?= =?utf8?q?u=20f=C3=BCr=20ParseFilter?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit ausserdem Arraylaundering --- SL/Controller/Helper/ParseFilter.pm | 52 ++++++++++++++++++++-------- t/controllers/helpers/parse_filter.t | 2 +- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/SL/Controller/Helper/ParseFilter.pm b/SL/Controller/Helper/ParseFilter.pm index 8ccd83401..ea4eba0a0 100644 --- a/SL/Controller/Helper/ParseFilter.pm +++ b/SL/Controller/Helper/ParseFilter.pm @@ -33,10 +33,15 @@ sub parse_filter { my ($filter, %params) = @_; my $hint_objects = $params{with_objects} || []; + my $auto_objects = []; - my ($flattened, $objects) = _pre_parse($filter, $hint_objects, '', %params); + my ($flattened, $objects) = flatten($filter, $auto_objects, '', %params); - my $query = _parse_filter($flattened, %params); + if ($params{class}) { + $objects = $hint_objects; + } + + my $query = _parse_filter($flattened, $objects, %params); _launder_keys($filter, $params{launder_to}) unless $params{no_launder}; @@ -55,7 +60,7 @@ sub _launder_keys { if ('' eq ref $filter->{$orig}) { $launder_to->{$key} = $filter->{$orig}; } elsif ('ARRAY' eq ref $filter->{$orig}) { - $launder_to->{$key} = [ @{ $filter->{$orig} } ]; + $launder_to->{"${key}_"} = { map { $_ => 1 } @{ $filter->{$orig} } }; } else { $launder_to->{$key} ||= { }; _launder_keys($filter->{$key}, $launder_to->{$key}); @@ -63,7 +68,7 @@ sub _launder_keys { }; } -sub _pre_parse { +sub flatten { my ($filter, $with_objects, $prefix, %params) = @_; return (undef, $with_objects) unless 'HASH' eq ref $filter; @@ -74,7 +79,7 @@ sub _pre_parse { while (my ($key, $value) = each %$filter) { next if !defined $value || $value eq ''; # 0 is fine if ('HASH' eq ref $value) { - my ($query, $more_objects) = _pre_parse($value, $with_objects, _prefix($prefix, $key)); + my ($query, $more_objects) = flatten($value, $with_objects, _prefix($prefix, $key)); push @result, @$query if $query; push @$with_objects, _prefix($prefix, $key), ($more_objects ? @$more_objects : ()); } else { @@ -86,7 +91,7 @@ sub _pre_parse { } sub _parse_filter { - my ($flattened, %params) = @_; + my ($flattened, $with_objects, %params) = @_; return () unless 'ARRAY' eq ref $flattened; @@ -98,7 +103,7 @@ sub _parse_filter { ($key, $value) = _apply_all($key, $value, qr/\b:(\w+)/, { %filters, %{ $params{filters} || {} } }); ($key, $value) = _apply_all($key, $value, qr/\b::(\w+)/, { %methods, %{ $params{methods} || {} } }); - ($key, $value) = _dispatch_custom_filters($params{class}, $key, $value) if $params{class}; + ($key, $value) = _dispatch_custom_filters($params{class}, $with_objects, $key, $value) if $params{class}; push @result, $key, $value; } @@ -106,7 +111,7 @@ sub _parse_filter { } sub _dispatch_custom_filters { - my ($class, $key, $value) = @_; + my ($class, $with_objects, $key, $value) = @_; # the key should by now have no filters left # if it has, catch it here: @@ -126,15 +131,27 @@ sub _dispatch_custom_filters { } } - my $manager = $curr_class->meta->convention_manager->auto_manager_class_name; + my $manager = $curr_class->meta->convention_manager->auto_manager_class_name; + my $obj_path = join '.', @tokens; + my $obj_prefix = join '.', @tokens, ''; if ($manager->can('filter')) { - ($key, $value) = $manager->filter($last_token, $value, join '.', @tokens, ''); + ($key, $value, my $obj) = $manager->filter($last_token, $value, $obj_prefix); + _add_uniq($with_objects, $obj); + } else { + _add_uniq($with_objects, $obj_path); } return ($key, $value); } +sub _add_uniq { + my ($array, $what) = @_; + + $array //= []; + $array = [ uniq @$array, $what ]; +} + sub _collapse_indirect_filters { my ($flattened) = @_; @@ -270,15 +287,21 @@ 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 +Also Template has trouble when looking up the contents of arrays, so +these will get copied into a _ suffixed version as hashes: + + [% L.checkbox_tag('filter.ids[]', value=15, checked=filter.ids_.15) %] + +All of your original entries will stay intact. 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 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: +if you have a filter that looks like this: $filter = { 'price:number::lt' => '2,30', - 'closed => '1', + closed => '1', + type => [ 'part', 'assembly' ], } and parse it with @@ -290,7 +313,8 @@ like this: $filter = { 'price_number__lt' => '2,30', - 'closed => '1', + closed => '1', + 'type_' => { part => 1, assembly => 1 }, } =head1 INDIRECT FILTER METHODS diff --git a/t/controllers/helpers/parse_filter.t b/t/controllers/helpers/parse_filter.t index 9bcbeb8eb..1069dac0d 100644 --- a/t/controllers/helpers/parse_filter.t +++ b/t/controllers/helpers/parse_filter.t @@ -142,7 +142,7 @@ test { ] }, { 'sellprice:number' => [ '123,4', '2,34', '0,4' ], - 'sellprice_number' => [ '123,4', '2,34', '0,4' ], + 'sellprice_number' => { '123,4' => 1, '2,34' => 1, '0,4' => 1 }, }, 'laundering with array', target => 'filter'; my %args = ( -- 2.20.1