rest vom get_models callback entfernt
[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) ],
12   'scalar --get_set_init' => [ qw(form_params launder_to) ],
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            = $params{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   my $laundered;
43   if ($self->launder_to eq '__INPLACE__') {
44     # nothing to do
45   } elsif ($self->launder_to) {
46     $laundered = {};
47     $parse_filter_args{launder_to} = $laundered;
48   } else {
49     $parse_filter_args{no_launder} = 1;
50   }
51
52   my %calculated_params = SL::Controller::Helper::ParseFilter::parse_filter($filter, %parse_filter_args);
53   %calculated_params = $self->merge_args(\%calculated_params, \%filter_args, \%params);
54
55   if ($laundered) {
56     if ($self->get_models->controller->can($self->launder_to)) {
57       $self->get_models->controller->${\ $self->launder_to }($laundered);
58     } else {
59       $self->get_models->controller->{$self->launder_to} = $laundered;
60     }
61   }
62
63   # $::lxdebug->dump(0, "get_current_filter_params: ", \%calculated_params);
64
65   $self->filter_params(\%calculated_params);
66
67   return %calculated_params;
68 }
69
70 sub finalize {
71   my ($self, %params) = @_;
72
73   my %filter_params;
74   %filter_params = $self->read_params(%params)  if $self->is_enabled;
75
76   # $::lxdebug->dump(0, "GM handler for filtered; params nach modif (is_enabled? " . $self->is_enabled . ")", \%params);
77
78   return $self->merge_args(\%params, \%filter_params);
79 }
80
81 #
82 # private functions
83 #
84
85 sub _get_filter_args {
86   my ($self, $spec) = @_;
87
88   my %filter_args   = ref($self->filter_args) eq 'CODE' ? %{ $self->filter_args->($self) }
89                     :     $self->filter_args            ? do { my $sub = $self->filter_args; %{ $self->get_models->controller->$sub() } }
90                     :                                       ();
91 }
92
93 sub _callback_handler_for_filtered {
94   my ($self, %params) = @_;
95
96   if ($self->is_enabled) {
97     my ($flattened) = SL::Controller::Helper::ParseFilter::flatten($self->orig_filter, $self->form_params);
98     %params         = (%params, @{ $flattened || [] });
99   }
100
101   # $::lxdebug->dump(0, "CB handler for filtered; params after flatten:", \%params);
102
103   return %params;
104 }
105
106 sub init_form_params {
107   'filter'
108 }
109
110 sub init_launder_to {
111   'filter'
112 }
113
114
115 1;
116
117 __END__
118
119 =pod
120
121 =encoding utf8
122
123 =head1 NAME
124
125 SL::Controller::Helper::Filtered - A helper for semi-automatic handling
126 of filtered lists of database models in a controller
127
128 =head1 SYNOPSIS
129
130 In a controller:
131
132   use SL::Controller::Helper::GetModels;
133   use SL::Controller::Helper::Filtered;
134
135   __PACKAGE__->make_filter(
136     MODEL       => 'Part',
137     ONLY        => [ qw(list) ],
138     FORM_PARAMS => [ qw(filter) ],
139   );
140
141   sub action_list {
142     my ($self) = @_;
143
144     my $filtered_models = $self->get_models(%addition_filters);
145     $self->render('controller/list', ENTRIES => $filtered_models);
146   }
147
148
149 =head1 OVERVIEW
150
151 This helper module enables use of the L<SL::Controller::Helper::ParseFilter>
152 methods in conjunction with the L<SL::Controller::Helper::GetModels> style of
153 plugins. Additional filters can be defined in the database models and filtering
154 can be reduced to a minimum of work.
155
156 This plugin can be combined with L<SL::Controller::Sorted> and
157 L<SL::Controller::Paginated> for filtered, sorted and paginated lists.
158
159 The controller has to provive information where to look for filter information
160 at compile time. This call is L<make_filtered>.
161
162 The underlying functionality that enables the use of more than just
163 the paginate helper is provided by the controller helper
164 C<GetModels>. See the documentation for L<SL::Controller::Sorted> for
165 more information on it.
166
167 =head1 PACKAGE FUNCTIONS
168
169 =over 4
170
171 =item C<make_filtered %filter_spec>
172
173 This function must be called by a controller at compile time. It is
174 uesd to set the various parameters required for this helper to do its
175 magic.
176
177 Careful: If you want to use this in conjunction with
178 L<SL:Controller::Helper::Paginated>, you need to call C<make_filtered> first,
179 or the paginating will not get all the relevant information to estimate the
180 number of pages correctly. To ensure this does not happen, this module will
181 croak when it detects such a scenario.
182
183 The hash C<%filter_spec> can include the following parameters:
184
185 =over 4
186
187 =item * C<MODEL>
188
189 Optional. A string: the name of the Rose database model that is used
190 as a default in certain cases. If this parameter is missing then it is
191 derived from the controller's package (e.g. for the controller
192 C<SL::Controller::BackgroundJobHistory> the C<MODEL> would default to
193 C<BackgroundJobHistory>).
194
195 =item * C<FORM_PARAMS>
196
197 Optional. Indicates a key in C<$::form> to be used as filter.
198
199 Defaults to the values C<filter> if missing.
200
201 =item * C<LAUNDER_TO>
202
203 Option. Indicates a target for laundered filter arguments in the controller.
204 Can be set to C<undef> to disable laundering, and can be set to method named or
205 hash keys of the controller. In the latter case the laundered structure will be
206 put there.
207
208 Defaults to inplace laundering which is not normally settable.
209
210 =item * C<ONLY>
211
212 Optional. An array reference containing a list of action names for
213 which the paginate parameters should be saved. If missing or empty then
214 all actions invoked on the controller are monitored.
215
216 =back
217
218 =back
219
220 =head1 INSTANCE FUNCTIONS
221
222 These functions are called on a controller instance.
223
224 =over 4
225
226 =item C<get_current_filter_params>
227
228 Returns a hash to be used in manager C<get_all> calls or to be passed on to
229 GetModels. Will only work if the get_models chain has been called at least
230 once, because only then the full parameters can get parsed and stored. Will
231 croak otherwise.
232
233 =item C<disable_filtering>
234
235 Disable filtering for the duration of the current action. Can be used
236 when using the attribute C<ONLY> to L<make_filtered> does not
237 cover all cases.
238
239 =back
240
241 =head1 BUGS
242
243 Nothing here yet.
244
245 =head1 AUTHOR
246
247 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
248
249 =cut