X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FController%2FHelper%2FGetModels%2FPaginated.pm;h=86b248c20155fc43283a2f247113859240f09e6c;hb=0aab038387d45ae06b77892e0ea60f955bec22d6;hp=a40acaef975e3615371e36a3f8cd3665e15270a3;hpb=ec3a4636c1d58339915614120cd82759150d7641;p=kivitendo-erp.git diff --git a/SL/Controller/Helper/GetModels/Paginated.pm b/SL/Controller/Helper/GetModels/Paginated.pm index a40acaef9..86b248c20 100644 --- a/SL/Controller/Helper/GetModels/Paginated.pm +++ b/SL/Controller/Helper/GetModels/Paginated.pm @@ -6,7 +6,7 @@ use parent 'SL::Controller::Helper::GetModels::Base'; use List::Util qw(min); use Rose::Object::MakeMethods::Generic ( - scalar => [ qw(disabled per_page) ], + scalar => [ qw(per_page form_data paginated_args calculated_params) ], 'scalar --get_set_init' => [ qw(form_params paginate_args) ], ); @@ -20,46 +20,20 @@ sub init { $self->get_models->register_handlers( callback => sub { shift; $self->_callback_handler_for_paginated(@_) }, - get_models => sub { shift; $self->_get_models_handler_for_paginated(@_) }, ); # $::lxdebug->dump(0, "CONSPEC", \%specs); } -sub get_current_paginate_params { - my ($self, %args) = @_; - return () unless $self->is_enabled; - - my %paginate_params = $self->final_params(%args); - - # try to use Filtered if available and nothing else is configured, but don't - # blow up if the controller does not use Filtered - my %paginate_args = ref($self->paginate_args) eq 'CODE' ? %{ $self->paginate_args->($self) } - : $self->paginate_args eq '__FILTER__' - && $self->get_models->filtered ? %{ $self->get_models->filtered->get_current_filter_params } - : $self->paginate_args ne '__FILTER__' ? do { my $sub = $self->paginate_args; %{ $self->get_models->controller->$sub() } } - : (); - - %args = $self->merge_args(\%args, \%paginate_args); - - my $calculated_params = $self->get_models->manager->paginate(%paginate_params, args => \%args); - - # $::lxdebug->dump(0, "get_current_paginate_params: ", $calculated_params); - - return %{ $calculated_params }; -} - -sub disable_pagination { - my ($self) = @_; - $self->disabled(1); -} - -sub final_params { +sub read_params { my ($self, %params) = @_; + return %{ $self->form_data } if $self->form_data; + my $source = $self->get_models->source; + my $from_form = { - page => $::form->{ $self->form_params->[0] } || 1, - per_page => $::form->{ $self->form_params->[1] } * 1, + page => $source->{ $self->form_params->[0] } || 1, + per_page => ($source->{ $self->form_params->[1] } // 0) * 1, }; # my $priv = _priv($self); @@ -69,25 +43,48 @@ sub final_params { $params{page} = ($params{page} * 1) || 1; $params{per_page} = ($params{per_page} * 1) || $self->per_page; + $self->form_data(\%params); + %params; } -# -# private functions -# +sub finalize { + my ($self, %args) = @_; -sub init_form_params { - [ qw(page per_page) ] + if ($self->is_enabled) { + my %paginate_params = $self->read_params; + + # try to use Filtered if available and nothing else is configured, but don't + # blow up if the controller does not use Filtered + my %paginate_args = ref($self->paginate_args) eq 'CODE' ? %{ $self->paginate_args->($self) } + : $self->paginate_args ne '__FILTER__' ? do { my $sub = $self->paginate_args; %{ $self->get_models->controller->$sub() } } + : (); + + %args = $self->merge_args(\%args, \%paginate_args); + + my $calculated_params = $self->get_models->manager->paginate(%paginate_params, args => \%args); + + $self->calculated_params($calculated_params); + } + + $self->paginated_args(\%args); + + return %args; } -sub init_paginate_args { - '__FILTER__' +sub get_current_paginate_params { + my ($self, %args) = @_; + return () unless $self->is_enabled; + %{ $self->calculated_params }; } +# +# private functions +# + sub _callback_handler_for_paginated { my ($self, %params) = @_; - my %form_params = $self->final_params; -# my $priv = _priv($self); + my %form_params = $self->read_params; if ($self->is_enabled && $form_params{page}) { $params{ $self->form_params->[0] } = $form_params{page}; @@ -99,19 +96,12 @@ sub _callback_handler_for_paginated { return %params; } -sub _get_models_handler_for_paginated { - my ($self, %params) = @_; - - $self->get_models->manager->paginate($self->final_params, args => \%params) if $self->is_enabled; - - # $::lxdebug->dump(0, "GM handler for paginated; params nach modif (is_enabled? " . _is_enabled($self) . ")", \%params); - - return %params; +sub init_form_params { + [ qw(page per_page) ] } -sub is_enabled { - my ($self) = @_; - return !$self->disabled; +sub init_paginate_args { + '__FILTER__' } 1; @@ -130,59 +120,30 @@ of paginating lists of database models in a controller In a controller: - use SL::Controller::Helper::GetModels; - use SL::Controller::Helper::Paginated; - - __PACKAGE__->make_paginated( - MODEL => 'BackgroundJobHistory', - ONLY => [ qw(list) ], - FORM_PARAMS => [ qw(page per_page) ], + SL::Controller::Helper::GetModels->new( + .. + paginated => { + form_params => [ qw(page per_page) ], + per_page => 20, + } ); - sub action_list { - my ($self) = @_; - - my $paginated_models = $self->get_models; - $self->render('controller/list', ENTRIES => $paginated_models); - } - In said template: - [% USE L %] - - - - - ... - - - - - [% FOREACH entry = ENTRIES %] - - ... - - [% END %] - -
- [% L.paginate_controls %] =head1 OVERVIEW -This specialized helper module enables controllers to display a -paginatable list of database models with as few lines as possible. It -can also be combined trivially with the L -helper for sortable lists. +This C plugin enables controllers to display a +paginatable list of database models with as few lines as possible. For this to work the controller has to provide the information which -indexes are eligible for paginateing etc. by a call to -L at compile time. +indexes are eligible for paginateing etc. during C creation. 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. +C. See the documentation for L +for more information on it. A template can use the method C from the layout helper module C which renders the links for navigation between the @@ -191,53 +152,18 @@ pages. This module requires that the Rose model managers use their C helper. -The C helper hooks into the controller call to the action via -a C hook. This is done so that it can remember the paginate -parameters that were used in the current view. - -=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. - -The hash C<%paginate_spec> can include the following parameters: +=head1 OPTIONS =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. Either a code reference or the name of function to be called -on the controller importing this helper. - -If this funciton is given then the paginate helper calls it whenever -it has to count the total number of models for calculating the number -of pages to display. The function must return a hash reference with -elements suitable for passing to a Rose model manager's C -function. - -This can be used e.g. when filtering is used. - -=item * C +=item * C -Optional. An integer: the number of models to return per page. +Optional. The number of models to return per page. Defaults to the underlying database model's default number of models per page. -=item * C +=item * C Optional. An array reference with exactly two strings that name the indexes in C<$::form> in which the current page's number (the first @@ -246,19 +172,11 @@ element in the array) are stored. Defaults to the values C and C if missing. -=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. +These functions are called on a C instance and delegated here. =over 4 @@ -293,24 +211,26 @@ displayed). =item C -Returns a hash reference to the paginate spec structure given in the call -to L after normalization (hash reference construction, +Returns a hash reference to the paginate spec structure given in the +configuration after normalization (hash reference construction, applying default parameters etc). -=item C - -Disable pagination 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. +C generates an array with an entry for every page, which gets +slow if there are a lot of entries. Current observation holds that up to about +1000 pages there is no noticable slowdown, but at about 10000 it gets +noticable. At 100k-500k pages it's takes way too long and should be remodelled. + +This case currently only applies for databases with very large amounts of parts +that get paginated, but BackgroundJobHistory can also accumulate. =head1 AUTHOR Moritz Bunkus Em.bunkus@linet-services.deE +Sven Schöling Es.schoeling@linet-services.deE + =cut