849c0e065ac85311559c7943ee141156cde31f34
[kivitendo-erp.git] / SL / Controller / Helper / GetModels / Filtered.pm
1 package SL::Controller::Helper::GetModels::Filtered;
2
3 use strict;
4 use parent 'SL::Controller::Helper::GetModels::Base';
5
6 use Exporter qw(import);
7 use SL::Controller::Helper::ParseFilter ();
8 use List::MoreUtils qw(uniq);
9
10 use Rose::Object::MakeMethods::Generic (
11   scalar => [ qw(filter_args filter_params orig_filter filter no_launder) ],
12   'scalar --get_set_init' => [ qw(form_params laundered) ],
13 );
14
15 sub init {
16   my ($self, %specs)             = @_;
17
18   $self->set_get_models(delete $specs{get_models});
19   $self->SUPER::init(%specs);
20
21   $self->get_models->register_handlers(
22     callback   => sub { shift; $self->_callback_handler_for_filtered(@_) },
23   );
24
25   # $::lxdebug->dump(0, "CONSPEC", \%specs);
26 }
27
28 sub read_params {
29   my ($self, %params)   = @_;
30
31   return %{ $self->filter_params } if $self->filter_params;
32   my $source = $self->get_models->source;
33
34   my $filter            = $self->filter // $source->{ $self->form_params } // {};
35   $self->orig_filter($filter);
36
37   my %filter_args       = $self->_get_filter_args;
38   my %parse_filter_args = (
39     class        => $self->get_models->manager,
40     with_objects => $params{with_objects},
41   );
42
43   # Store laundered result in $self->laundered.
44
45   if (!$self->no_launder) {
46     $self->laundered({});
47     $parse_filter_args{launder_to} = $self->laundered;
48   } else {
49     $self->laundered(undef);
50     $parse_filter_args{no_launder} = 1;
51   }
52
53   my %calculated_params = SL::Controller::Helper::ParseFilter::parse_filter($filter, %parse_filter_args);
54   %calculated_params = $self->merge_args(\%calculated_params, \%filter_args, \%params);
55
56   if ($self->laundered) {
57     if ($self->get_models->controller->can('filter')) {
58       $self->get_models->controller->filter($self->laundered);
59     } else {
60       $self->get_models->controller->{filter} = $self->laundered;
61     }
62   }
63
64   # $::lxdebug->dump(0, "get_current_filter_params: ", \%calculated_params);
65
66   $self->filter_params(\%calculated_params);
67
68   return %calculated_params;
69 }
70
71 sub finalize {
72   my ($self, %params) = @_;
73
74   my %filter_params;
75   %filter_params = $self->read_params(%params)  if $self->is_enabled;
76
77   # $::lxdebug->dump(0, "GM handler for filtered; params nach modif (is_enabled? " . $self->is_enabled . ")", \%params);
78
79   return $self->merge_args(\%params, \%filter_params);
80 }
81
82 #
83 # private functions
84 #
85
86 sub _get_filter_args {
87   my ($self, $spec) = @_;
88
89   my %filter_args   = ref($self->filter_args) eq 'CODE' ? %{ $self->filter_args->($self) }
90                     :     $self->filter_args            ? do { my $sub = $self->filter_args; %{ $self->get_models->controller->$sub() } }
91                     :                                       ();
92 }
93
94 sub _callback_handler_for_filtered {
95   my ($self, %params) = @_;
96
97   if ($self->is_enabled) {
98     my ($flattened) = SL::Controller::Helper::ParseFilter::flatten($self->orig_filter, $self->form_params);
99     %params         = (%params, @{ $flattened || [] });
100   }
101
102   # $::lxdebug->dump(0, "CB handler for filtered; params after flatten:", \%params);
103
104   return %params;
105 }
106
107 sub init_form_params {
108   'filter'
109 }
110
111 sub init_laundered {
112   my ($self) = @_;
113
114   $self->get_models->finalize;
115   return $self->{laundered};
116 }
117
118 1;
119
120 __END__
121
122 =pod
123
124 =encoding utf8
125
126 =head1 NAME
127
128 SL::Controller::Helper::GetModels::Filtered - Filter handling plugin for GetModels
129
130 =head1 SYNOPSIS
131
132 In a controller:
133
134   SL::Controller::Helper::GetModels->new(
135     ...
136     filtered => {
137       filter      => HASHREF,
138       no_launder  => 0 | 1,
139     }
140
141     OR
142
143     filtered => 0,
144   );
145
146 =head1 OVERVIEW
147
148 This C<GetModels> plugin enables use of the
149 L<SL::Controller::Helper::ParseFilter> methods. Additional filters can be
150 defined in the database models and filtering can be reduced to a minimum of
151 work.
152
153 The underlying functionality that enables the use of more than just
154 the paginate helper is provided by the controller helper
155 C<GetModels>. See the documentation for L<SL::Controller::Helper::GetModels> for
156 more information on it.
157
158 =head1 OPTIONS
159
160 =over 4
161
162 =item * C<filter>
163
164 Optional. Indicates a key in C<source> to be used as filter.
165
166 Defaults to the value C<filter> if missing.
167
168 =item * C<no_launder>
169
170 Optional. If given and trueish then laundering is disabled.
171
172 =back
173
174 =head1 FILTER FORMAT
175
176 See L<SL::Controller::Helper::ParseFilter> for a description of the filter format.
177
178 =head1 CUSTOM FILTERS
179
180 C<Filtered> will honor custom filters defined in RDBO managers. See
181 L<SL::DB::Helper::Filtered> for an explanation fo those.
182
183 =head1 FUNCTIONS
184
185 =over 4
186
187 =item C<laundered>
188
189 Finalizes the object (which causes laundering of the filter structure)
190 and returns a hashref of the laundered filter. If the plugin is
191 configured not to launder then C<undef> will be returned.
192
193 =back
194
195 =head1 BUGS
196
197 =over 4
198
199 =item * There is currently no easy way to filter for CVars.
200
201 =back
202
203 =head1 AUTHOR
204
205 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
206
207 =cut