X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FController%2FHelper%2FParseFilter.pm;h=ac086f594259f24ee9139cb8b486d9e6b65ebd9b;hb=d0535d474013611f57691dee2e4542115a4f0123;hp=96d3b329603899d007b56a4e9f407d07158809d4;hpb=e340c9571ec7d544f038b4226ab98f6a8038bbfa;p=kivitendo-erp.git diff --git a/SL/Controller/Helper/ParseFilter.pm b/SL/Controller/Helper/ParseFilter.pm index 96d3b3296..ac086f594 100644 --- a/SL/Controller/Helper/ParseFilter.pm +++ b/SL/Controller/Helper/ParseFilter.pm @@ -36,32 +36,36 @@ 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, - @$objects ? ( with_objects => [ uniq @$objects ]) : (); + ($query && @$query ? (query => $query) : ()), + ($objects && @$objects ? ( with_objects => [ uniq @$objects ]) : ()); } 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; - $with_objects = []; + return (undef, $with_objects) unless 'HASH' eq ref $filter; + $with_objects ||= []; my @result; @@ -146,9 +150,9 @@ search target. A search for sales orders may be filtered by the name of the customer. L alloes you to search for these by filtering them prefixed with their table: query => [ - customer.name => 'John Doe', - department.description => [ ilike => '%Sales%' ], - orddate => [ lt => DateTime->today ], + 'customer.name' => 'John Doe', + 'department.description' => [ ilike => '%Sales%' ], + 'orddate' => [ lt => DateTime->today ], ] Unfortunately, if you specify them in you form as these strings, the form @@ -171,7 +175,7 @@ providing suffixes for common search patterns. =over 4 -=item parse_amount \%FILTER, [ %PARAMS ] +=item C First argument is the filter from form. It is highly recommended that you put all filter attributes into a named container as to not confuse them with the @@ -181,14 +185,14 @@ Nested structures will be parsed and interpreted as foreign references. For example if you search for Ls, this input will search for those with a specific L: - [% L.select_tag('filter.salesman.id', ... + [% L.select_tag('filter.salesman.id', ...) %] Additionally you can add modifier to the name to set a certain method: - [% L.input_tag('filter.department.description:substr::ilike' ... + [% L.input_tag('filter.department.description:substr::ilike', ...) %] -This will add the "% .. %" wildcards for substr matching in sql, and add an C<[ -ilike => $value ]> block around it to match case insensitively. +This will add the "% .. %" wildcards for substr matching in SQL, and add an +C<< ilike => $value >> block around it to match case insensitively. As a rule all value filters require a single colon and must be placed before match method suffixes, which are appended with 2 colons. See below for a full @@ -207,17 +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 1> as a -parameter. A full select_tag then loks like this: +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, 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 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 :) @@ -227,15 +252,15 @@ The following filters are built in, and can be used. =item date -Parses the input string with DateTime->from_lxoffice +Parses the input string with C<< DateTime->from_lxoffice >> =item number -Pasres the input string with Form->parse_amount +Pasres the input string with C<< Form->parse_amount >> =item percent -Parses the input string with Form->parse_amount / 100 +Parses the input string with C<< Form->parse_amount / 100 >> =item head @@ -277,8 +302,8 @@ customer, or are linked to a L with this customer, the following will not work as you expect: # does not work! - L.input_tag('customer.name:substr::ilike', ... - L.input_tag('invoice.customer.name:substr::ilike', ... + L.input_tag('customer.name:substr::ilike', ...) + L.input_tag('invoice.customer.name:substr::ilike', ...) This will sarch for orders whoe invoice has the _same_ customer, which matches both inputs. This is because tables are aliased by their name and not by their