X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FController%2FHelper%2FParseFilter.pm;h=0f7314179fcdddd9c31e84f5f6d738993f0cbe00;hb=c46d944c0f688128ee33b2989260f3d9390c61d5;hp=699011d01753bb8841f38ff944244206f76b7d29;hpb=585dc465bc6db6c1525563e64dbeb84da61b6fdf;p=kivitendo-erp.git diff --git a/SL/Controller/Helper/ParseFilter.pm b/SL/Controller/Helper/ParseFilter.pm index 699011d01..0f7314179 100644 --- a/SL/Controller/Helper/ParseFilter.pm +++ b/SL/Controller/Helper/ParseFilter.pm @@ -8,17 +8,27 @@ our @EXPORT = qw(parse_filter); use DateTime; use SL::Helper::DateTime; use List::MoreUtils qw(uniq); +use SL::Util qw(trim); use SL::MoreCommon qw(listify); use Data::Dumper; use Text::ParseWords; +sub _lazy_bool_eq { + my ($key, $value) = @_; + + return () if ($value // '') eq ''; + return (or => [ $key => undef, $key => 0 ]) if !$value; + return ($key => 1); +} + my %filters = ( date => sub { DateTime->from_lxoffice($_[0]) }, number => sub { $::form->parse_amount(\%::myconfig, $_[0]) }, percent => sub { $::form->parse_amount(\%::myconfig, $_[0]) / 100 }, - head => sub { $_[0] . '%' }, - tail => sub { '%' . $_[0] }, - substr => sub { '%' . $_[0] . '%' }, + head => sub { trim($_[0]) . '%' }, + tail => sub { '%' . trim($_[0]) }, + substr => sub { '%' . trim($_[0]) . '%' }, + trim => sub { trim($_[0]) }, ); my %methods = ( @@ -32,6 +42,10 @@ my %methods = ( } qw(similar match imatch regex regexp like ilike rlike is is_not ne eq lt gt le ge), ); +my %complex_methods = ( + lazy_bool_eq => \&_lazy_bool_eq, +); + sub parse_filter { my ($filter, %params) = @_; @@ -99,20 +113,22 @@ sub _parse_filter { $flattened = _collapse_indirect_filters($flattened); - my $all_filters = { %filters, %{ $params{filters} || {} } }; - my $all_methods = { %methods, %{ $params{methods} || {} } }; + my $all_filters = { %filters, %{ $params{filters} || {} } }; + my $all_methods = { %methods, %{ $params{methods} || {} } }; + my $all_complex = { %complex_methods, %{ $params{complex_methods} || {} } }; my @result; for (my $i = 0; $i < scalar @$flattened; $i += 2) { - my (@args, @filters, @methods); + my (@args, @filters, $method); my ($key, $value) = ($flattened->[$i], $flattened->[$i+1]); my ($type, $op) = $key =~ m{:(.+)::(.+)}; my $is_multi = $key =~ s/:multi//; - my @value_tokens = $is_multi ? parse_line('\s+', 0, $value) : ($value); + my $is_any = $key =~ s/:any//; + my @value_tokens = $is_multi || $is_any ? parse_line('\s+', 0, $value) : ($value); - ($key, @methods) = split m{::}, $key; + ($key, $method) = split m{::}, $key, 2; ($key, @filters) = split m{:}, $key; my $orig_key = $key; @@ -121,7 +137,8 @@ sub _parse_filter { $key = $orig_key; $value_token = _apply($value_token, $_, $all_filters) for @filters; - $value_token = _apply($value_token, $_, $all_methods) for @methods; + $value_token = _apply($value_token, $method, $all_methods) if $method && exists $all_methods->{$method}; + ($key, $value_token) = _apply_complex($key, $value_token, $method, $all_complex) if $method && exists $all_complex->{$method}; ($key, $value_token) = _dispatch_custom_filters($params{class}, $with_objects, $key, $value_token) if $params{class}; ($key, $value_token) = _apply_value_filters($key, $value_token, $type, $op); @@ -130,7 +147,7 @@ sub _parse_filter { next unless defined $key; - push @result, $is_multi ? (and => [ @args ]) : @args; + push @result, $is_multi ? (and => [ @args ]) : $is_any ? (or => [ @args ]) : @args; } return \@result; } @@ -246,10 +263,20 @@ sub _apply { return $filters->{$name}->($value); } +sub _apply_complex { + my ($key, $value, $name, $filters) = @_; + return $key, $value unless $name && $filters->{$name}; + return $filters->{$name}->($key, $value); +} + 1; __END__ +=pod + +=encoding utf8 + =head1 NAME SL::Controller::Helper::ParseFilter - Convert a form filter spec into a RDBO get_all filter @@ -257,10 +284,10 @@ SL::Controller::Helper::ParseFilter - Convert a form filter spec into a RDBO get =head1 SYNOPSIS use SL::Controller::Helper::ParseFilter; - SL::DB::Object->get_all(parse_filter($::form->{filter})); + SL::DB::Manager::Object->get_all(parse_filter($::form->{filter})); # or more complex - SL::DB::Object->get_all(parse_filter($::form->{filter}, + SL::DB::Manager::Object->get_all(parse_filter($::form->{filter}, with_objects => [ qw(part customer) ])); =head1 DESCRIPTION @@ -271,8 +298,8 @@ customer. L allows you to search for these by filtering them p query => [ 'customer.name' => 'John Doe', - 'department.description' => [ ilike => '%Sales%' ], - 'orddate' => [ lt => DateTime->today ], + 'department.description' => { ilike => '%Sales%' }, + 'orddate' => { lt => DateTime->today }, ] Unfortunately, if you specify them in your form as these strings, the form @@ -412,22 +439,22 @@ Pasres the input string with C<< Form->parse_amount >> Parses the input string with C<< Form->parse_amount / 100 >> +=item trim + +Removes whitespace characters (to be precice, characters with the \p{WSpace} +property from beginning and end of the value. + =item head -Adds "%" at the end of the string. +Adds "%" at the end of the string and applies C. =item tail -Adds "%" at the end of the string. +Adds "%" at the end of the string and applies C. =item substr -Adds "% .. %" around the search string. - -=item eq_ignore_empty - -Ignores this item if it's empty. Otherwise compares it with the -standard SQL C<=> operator. +Adds "% .. %" around the search string and applies C. =back @@ -445,6 +472,18 @@ standard SQL C<=> operator. All these are recognized like the L methods. +=item lazy_bool_eq + +If the value is undefined or an empty string then this parameter will +be completely removed from the query. Otherwise a falsish filter value +will match for C and C; trueish values will only match +C. + +=item eq_ignore_empty + +Ignores this item if it's empty. Otherwise compares it with the +standard SQL C<=> operator. + =back =head1 BUGS AND CAVEATS