X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FController%2FHelper%2FGetModels%2FFiltered.pm;fp=SL%2FController%2FHelper%2FGetModels%2FFiltered.pm;h=3374471ccda92e43c8dcbdf087f93f745d3a645d;hb=ec3a4636c1d58339915614120cd82759150d7641;hp=0000000000000000000000000000000000000000;hpb=cf826cc8c8faf50d2d2d1d1bfdb68ad45a8b1cba;p=kivitendo-erp.git diff --git a/SL/Controller/Helper/GetModels/Filtered.pm b/SL/Controller/Helper/GetModels/Filtered.pm new file mode 100644 index 000000000..3374471cc --- /dev/null +++ b/SL/Controller/Helper/GetModels/Filtered.pm @@ -0,0 +1,279 @@ +package SL::Controller::Helper::GetModels::Filtered; + +use strict; +use parent 'SL::Controller::Helper::GetModels::Base'; + +use Exporter qw(import); +use SL::Controller::Helper::ParseFilter (); +use List::MoreUtils qw(uniq); + +use Rose::Object::MakeMethods::Generic ( + scalar => [ qw(disabled filter_args filter_params) ], + 'scalar --get_set_init' => [ qw(form_params launder_to) ], +); + +sub init { + my ($self, %specs) = @_; + + $self->set_get_models(delete $specs{get_models}); + $self->SUPER::init(%specs); + + $self->get_models->register_handlers( + callback => sub { shift; $self->_callback_handler_for_filtered(@_) }, + get_models => sub { shift; $self->_get_models_handler_for_filtered(@_) }, + ); + + # $::lxdebug->dump(0, "CONSPEC", \%specs); +} + +sub get_current_filter_params { + my ($self) = @_; + + return $self->filter_params if $self->filter_params; + + require Carp; + Carp::confess('It seems a GetModels plugin tries to access filter params before they got calculated. Make sure your make_filtered call comes first.'); +} + +sub _make_current_filter_params { + my ($self, %params) = @_; + +# my $spec = $self->get_filter_spec; + my $filter = $params{filter} // $::form->{ $self->form_params } // {}, + my %filter_args = $self->_get_filter_args; + my %parse_filter_args = ( + class => $self->get_models->manager, + with_objects => $params{with_objects}, + ); + my $laundered; + if ($self->launder_to eq '__INPLACE__') { + # nothing to do + } elsif ($self->launder_to) { + $laundered = {}; + $parse_filter_args{launder_to} = $laundered; + } else { + $parse_filter_args{no_launder} = 1; + } + + my %calculated_params = SL::Controller::Helper::ParseFilter::parse_filter($filter, %parse_filter_args); + %calculated_params = $self->merge_args(\%calculated_params, \%filter_args, \%params); + +# $calculated_params{query} = [ +# @{ $calculated_params{query} || [] }, +# @{ $filter_args{ query} || [] }, +# @{ $params{ query} || [] }, +# ]; +# +# $calculated_params{with_objects} = [ +# uniq +# @{ $calculated_params{with_objects} || [] }, +# @{ $filter_args{ with_objects} || [] }, +# @{ $params{ with_objects} || [] }, +# ]; + + if ($laundered) { + if ($self->get_models->controller->can($self->launder_to)) { + $self->get_models->controller->${\ $self->launder_to }($laundered); + } else { + $self->get_models->controller->{$self->launder_to} = $laundered; + } + } + + # $::lxdebug->dump(0, "get_current_filter_params: ", \%calculated_params); + + $self->filter_params(\%calculated_params); + + return %calculated_params; +} + +sub disable_filtering { + my ($self) = @_; + $self->disabled(1); +} + +# +# private functions +# + +sub _get_filter_args { + my ($self, $spec) = @_; + + my %filter_args = ref($self->filter_args) eq 'CODE' ? %{ $self->filter_args->($self) } + : $self->filter_args ? do { my $sub = $self->filter_args; %{ $self->get_models->controller->$sub() } } + : (); +} + +sub _callback_handler_for_filtered { + my ($self, %params) = @_; + + if ($self->is_enabled) { + my ($flattened) = SL::Controller::Helper::ParseFilter::flatten($::form->{ $self->form_params }, $self->form_params); + %params = (%params, @{ $flattened || [] }); + } + + # $::lxdebug->dump(0, "CB handler for filtered; params after flatten:", \%params); + + return %params; +} + +sub _get_models_handler_for_filtered { + my ($self, %params) = @_; + + # $::lxdebug->dump(0, "params in get_models_for_filtered", \%params); + + my %filter_params; + %filter_params = $self->_make_current_filter_params(%params) if $self->is_enabled; + + # $::lxdebug->dump(0, "GM handler for filtered; params nach modif (is_enabled? " . $self->is_enabled . ")", \%params); + + return (%params, %filter_params); +} + +sub is_enabled { + !$_[0]->disabled; +} + +sub init_form_params { + 'filter' +} + +sub init_launder_to { + 'filter' +} + + +1; + +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::Controller::Helper::Filtered - A helper for semi-automatic handling +of filtered lists of database models in a controller + +=head1 SYNOPSIS + +In a controller: + + use SL::Controller::Helper::GetModels; + use SL::Controller::Helper::Filtered; + + __PACKAGE__->make_filter( + MODEL => 'Part', + ONLY => [ qw(list) ], + FORM_PARAMS => [ qw(filter) ], + ); + + sub action_list { + my ($self) = @_; + + my $filtered_models = $self->get_models(%addition_filters); + $self->render('controller/list', ENTRIES => $filtered_models); + } + + +=head1 OVERVIEW + +This helper module enables use of the L +methods in conjunction with the L style of +plugins. Additional filters can be defined in the database models and filtering +can be reduced to a minimum of work. + +This plugin can be combined with L and +L for filtered, sorted and paginated lists. + +The controller has to provive information where to look for filter information +at compile time. This call is L. + +The underlying functionality that enables the use of more than just +the paginate helper is provided by the controller helper +C. See the documentation for L for +more information on it. + +=head1 PACKAGE FUNCTIONS + +=over 4 + +=item C + +This function must be called by a controller at compile time. It is +uesd to set the various parameters required for this helper to do its +magic. + +Careful: If you want to use this in conjunction with +L, you need to call C first, +or the paginating will not get all the relevant information to estimate the +number of pages correctly. To ensure this does not happen, this module will +croak when it detects such a scenario. + +The hash C<%filter_spec> can include the following parameters: + +=over 4 + +=item * C + +Optional. A string: the name of the Rose database model that is used +as a default in certain cases. If this parameter is missing then it is +derived from the controller's package (e.g. for the controller +C the C would default to +C). + +=item * C + +Optional. Indicates a key in C<$::form> to be used as filter. + +Defaults to the values C if missing. + +=item * C + +Option. Indicates a target for laundered filter arguments in the controller. +Can be set to C to disable laundering, and can be set to method named or +hash keys of the controller. In the latter case the laundered structure will be +put there. + +Defaults to inplace laundering which is not normally settable. + +=item * C + +Optional. An array reference containing a list of action names for +which the paginate parameters should be saved. If missing or empty then +all actions invoked on the controller are monitored. + +=back + +=back + +=head1 INSTANCE FUNCTIONS + +These functions are called on a controller instance. + +=over 4 + +=item C + +Returns a hash to be used in manager C calls or to be passed on to +GetModels. Will only work if the get_models chain has been called at least +once, because only then the full parameters can get parsed and stored. Will +croak otherwise. + +=item C + +Disable filtering for the duration of the current action. Can be used +when using the attribute C to L does not +cover all cases. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Sven Schöling Es.schoeling@linet-services.deE + +=cut