1 package SL::Controller::Helper::GetModels::Filtered;
4 use parent 'SL::Controller::Helper::GetModels::Base';
6 use Exporter qw(import);
7 use SL::Controller::Helper::ParseFilter ();
8 use List::MoreUtils qw(uniq);
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) ],
16 my ($self, %specs) = @_;
18 $self->set_get_models(delete $specs{get_models});
19 $self->SUPER::init(%specs);
21 $self->get_models->register_handlers(
22 callback => sub { shift; $self->_callback_handler_for_filtered(@_) },
23 get_models => sub { shift; $self->_get_models_handler_for_filtered(@_) },
26 # $::lxdebug->dump(0, "CONSPEC", \%specs);
30 my ($self, %params) = @_;
32 return %{ $self->filter_params } if $self->filter_params;
33 my $source = $self->get_models->source;
35 my $filter = $params{filter} // $source->{ $self->form_params } // {};
36 $self->orig_filter($filter);
38 my %filter_args = $self->_get_filter_args;
39 my %parse_filter_args = (
40 class => $self->get_models->manager,
41 with_objects => $params{with_objects},
44 if ($self->launder_to eq '__INPLACE__') {
46 } elsif ($self->launder_to) {
48 $parse_filter_args{launder_to} = $laundered;
50 $parse_filter_args{no_launder} = 1;
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);
57 if ($self->get_models->controller->can($self->launder_to)) {
58 $self->get_models->controller->${\ $self->launder_to }($laundered);
60 $self->get_models->controller->{$self->launder_to} = $laundered;
64 # $::lxdebug->dump(0, "get_current_filter_params: ", \%calculated_params);
66 $self->filter_params(\%calculated_params);
68 return %calculated_params;
72 my ($self, %params) = @_;
75 %filter_params = $self->read_params(%params) if $self->is_enabled;
77 # $::lxdebug->dump(0, "GM handler for filtered; params nach modif (is_enabled? " . $self->is_enabled . ")", \%params);
79 return $self->merge_args(\%params, \%filter_params);
86 sub _get_filter_args {
87 my ($self, $spec) = @_;
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() } }
94 sub _callback_handler_for_filtered {
95 my ($self, %params) = @_;
97 if ($self->is_enabled) {
98 my ($flattened) = SL::Controller::Helper::ParseFilter::flatten($self->orig_filter, $self->form_params);
99 %params = (%params, @{ $flattened || [] });
102 # $::lxdebug->dump(0, "CB handler for filtered; params after flatten:", \%params);
107 sub init_form_params {
111 sub init_launder_to {
126 SL::Controller::Helper::Filtered - A helper for semi-automatic handling
127 of filtered lists of database models in a controller
133 use SL::Controller::Helper::GetModels;
134 use SL::Controller::Helper::Filtered;
136 __PACKAGE__->make_filter(
138 ONLY => [ qw(list) ],
139 FORM_PARAMS => [ qw(filter) ],
145 my $filtered_models = $self->get_models(%addition_filters);
146 $self->render('controller/list', ENTRIES => $filtered_models);
152 This helper module enables use of the L<SL::Controller::Helper::ParseFilter>
153 methods in conjunction with the L<SL::Controller::Helper::GetModels> style of
154 plugins. Additional filters can be defined in the database models and filtering
155 can be reduced to a minimum of work.
157 This plugin can be combined with L<SL::Controller::Sorted> and
158 L<SL::Controller::Paginated> for filtered, sorted and paginated lists.
160 The controller has to provive information where to look for filter information
161 at compile time. This call is L<make_filtered>.
163 The underlying functionality that enables the use of more than just
164 the paginate helper is provided by the controller helper
165 C<GetModels>. See the documentation for L<SL::Controller::Sorted> for
166 more information on it.
168 =head1 PACKAGE FUNCTIONS
172 =item C<make_filtered %filter_spec>
174 This function must be called by a controller at compile time. It is
175 uesd to set the various parameters required for this helper to do its
178 Careful: If you want to use this in conjunction with
179 L<SL:Controller::Helper::Paginated>, you need to call C<make_filtered> first,
180 or the paginating will not get all the relevant information to estimate the
181 number of pages correctly. To ensure this does not happen, this module will
182 croak when it detects such a scenario.
184 The hash C<%filter_spec> can include the following parameters:
190 Optional. A string: the name of the Rose database model that is used
191 as a default in certain cases. If this parameter is missing then it is
192 derived from the controller's package (e.g. for the controller
193 C<SL::Controller::BackgroundJobHistory> the C<MODEL> would default to
194 C<BackgroundJobHistory>).
196 =item * C<FORM_PARAMS>
198 Optional. Indicates a key in C<$::form> to be used as filter.
200 Defaults to the values C<filter> if missing.
202 =item * C<LAUNDER_TO>
204 Option. Indicates a target for laundered filter arguments in the controller.
205 Can be set to C<undef> to disable laundering, and can be set to method named or
206 hash keys of the controller. In the latter case the laundered structure will be
209 Defaults to inplace laundering which is not normally settable.
213 Optional. An array reference containing a list of action names for
214 which the paginate parameters should be saved. If missing or empty then
215 all actions invoked on the controller are monitored.
221 =head1 INSTANCE FUNCTIONS
223 These functions are called on a controller instance.
227 =item C<get_current_filter_params>
229 Returns a hash to be used in manager C<get_all> calls or to be passed on to
230 GetModels. Will only work if the get_models chain has been called at least
231 once, because only then the full parameters can get parsed and stored. Will
234 =item C<disable_filtering>
236 Disable filtering for the duration of the current action. Can be used
237 when using the attribute C<ONLY> to L<make_filtered> does not
248 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>