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(@_) },
25 # $::lxdebug->dump(0, "CONSPEC", \%specs);
29 my ($self, %params) = @_;
31 return %{ $self->filter_params } if $self->filter_params;
32 my $source = $self->get_models->source;
34 my $filter = $params{filter} // $source->{ $self->form_params } // {};
35 $self->orig_filter($filter);
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},
43 if ($self->launder_to eq '__INPLACE__') {
45 } elsif ($self->launder_to) {
47 $parse_filter_args{launder_to} = $laundered;
49 $parse_filter_args{no_launder} = 1;
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);
56 if ($self->get_models->controller->can($self->launder_to)) {
57 $self->get_models->controller->${\ $self->launder_to }($laundered);
59 $self->get_models->controller->{$self->launder_to} = $laundered;
63 # $::lxdebug->dump(0, "get_current_filter_params: ", \%calculated_params);
65 $self->filter_params(\%calculated_params);
67 return %calculated_params;
71 my ($self, %params) = @_;
74 %filter_params = $self->read_params(%params) if $self->is_enabled;
76 # $::lxdebug->dump(0, "GM handler for filtered; params nach modif (is_enabled? " . $self->is_enabled . ")", \%params);
78 return $self->merge_args(\%params, \%filter_params);
85 sub _get_filter_args {
86 my ($self, $spec) = @_;
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() } }
93 sub _callback_handler_for_filtered {
94 my ($self, %params) = @_;
96 if ($self->is_enabled) {
97 my ($flattened) = SL::Controller::Helper::ParseFilter::flatten($self->orig_filter, $self->form_params);
98 %params = (%params, @{ $flattened || [] });
101 # $::lxdebug->dump(0, "CB handler for filtered; params after flatten:", \%params);
106 sub init_form_params {
110 sub init_launder_to {
125 SL::Controller::Helper::Filtered - A helper for semi-automatic handling
126 of filtered lists of database models in a controller
132 use SL::Controller::Helper::GetModels;
133 use SL::Controller::Helper::Filtered;
135 __PACKAGE__->make_filter(
137 ONLY => [ qw(list) ],
138 FORM_PARAMS => [ qw(filter) ],
144 my $filtered_models = $self->get_models(%addition_filters);
145 $self->render('controller/list', ENTRIES => $filtered_models);
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.
156 This plugin can be combined with L<SL::Controller::Sorted> and
157 L<SL::Controller::Paginated> for filtered, sorted and paginated lists.
159 The controller has to provive information where to look for filter information
160 at compile time. This call is L<make_filtered>.
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.
167 =head1 PACKAGE FUNCTIONS
171 =item C<make_filtered %filter_spec>
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
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.
183 The hash C<%filter_spec> can include the following parameters:
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>).
195 =item * C<FORM_PARAMS>
197 Optional. Indicates a key in C<$::form> to be used as filter.
199 Defaults to the values C<filter> if missing.
201 =item * C<LAUNDER_TO>
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
208 Defaults to inplace laundering which is not normally settable.
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.
220 =head1 INSTANCE FUNCTIONS
222 These functions are called on a controller instance.
226 =item C<get_current_filter_params>
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
233 =item C<disable_filtering>
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
247 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>