use strict;
use Exporter qw(import);
-our @EXPORT = qw(make_paginated get_paginate_spec get_current_paginate_params _save_current_paginate_params _get_models_handler_for_paginated _callback_handler_for_paginated);
+our @EXPORT = qw(make_paginated get_paginate_spec get_current_paginate_params _save_current_paginate_params _get_models_handler_for_paginated _callback_handler_for_paginated disable_pagination);
use constant PRIV => '__paginatedhelper_priv';
-my $controller_paginate_spec;
+use List::Util qw(min);
+
+my %controller_paginate_spec;
sub make_paginated {
- my ($class, %specs) = @_;
+ my ($class, %specs) = @_;
- $specs{MODEL} ||= $class->_controller_name;
- $specs{MODEL} =~ s{ ^ SL::DB:: (?: .* :: )? }{}x;
- $specs{PER_PAGE} ||= "SL::DB::Manager::$specs{MODEL}"->default_objects_per_page;
- $specs{FORM_PARAMS} ||= [ qw(page per_page) ];
- $specs{ONLY} ||= [];
- $specs{ONLY} = [ $specs{ONLY} ] if !ref $specs{ONLY};
+ $specs{MODEL} ||= $class->controller_name;
+ $specs{MODEL} =~ s{ ^ SL::DB:: (?: .* :: )? }{}x;
+ $specs{PER_PAGE} ||= "SL::DB::Manager::$specs{MODEL}"->default_objects_per_page;
+ $specs{FORM_PARAMS} ||= [ qw(page per_page) ];
+ $specs{PAGINATE_ARGS} ||= '__FILTER__';
+ $specs{ONLY} ||= [];
+ $specs{ONLY} = [ $specs{ONLY} ] if !ref $specs{ONLY};
+ $specs{ONLY_MAP} = @{ $specs{ONLY} } ? { map { ($_ => 1) } @{ $specs{ONLY} } } : { '__ALL__' => 1 };
- $controller_paginate_spec = \%specs;
+ $controller_paginate_spec{$class} = \%specs;
- my %hook_params = @{ $specs{ONLY} } ? ( only => $specs{ONLY} ) : ();
+ my %hook_params = @{ $specs{ONLY} } ? ( only => $specs{ONLY} ) : ();
$class->run_before('_save_current_paginate_params', %hook_params);
SL::Controller::Helper::GetModels::register_get_models_handlers(
sub get_paginate_spec {
my ($class_or_self) = @_;
- return $controller_paginate_spec;
+ return $controller_paginate_spec{ref($class_or_self) || $class_or_self};
}
sub get_current_paginate_params {
my $spec = $self->get_paginate_spec;
- my $priv = $self->{PRIV()} || {};
+ my $priv = _priv($self);
$params{page} = $priv->{page} unless defined $params{page};
$params{per_page} = $priv->{per_page} unless defined $params{per_page};
per_page => ($params{per_page} * 1) || $spec->{PER_PAGE},
);
- my $calculated_params = "SL::DB::Manager::$spec->{MODEL}"->paginate(%paginate_params, args => {});
- %paginate_params = (
- %paginate_params,
- num_pages => $calculated_params->{max},
- common_pages => $calculated_params->{common},
- );
+ # 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($spec->{PAGINATE_ARGS}) eq 'CODE' ? %{ $spec->{PAGINATE_ARGS}->($self) }
+ : $spec->{PAGINATE_ARGS} eq '__FILTER__'
+ && $self->can('get_current_filter_params') ? $self->get_current_filter_params
+ : $spec->{PAGINATE_ARGS} ne '__FILTER__' ? do { my $sub = $spec->{PAGINATE_ARGS}; %{ $self->$sub() } }
+ : ();
+ my $calculated_params = "SL::DB::Manager::$spec->{MODEL}"->paginate(%paginate_params, args => \%paginate_args);
- # $::lxdebug->dump(0, "get_current_paginate_params: ", \%paginate_params);
+ # $::lxdebug->dump(0, "get_current_paginate_params: ", $calculated_params);
+
+ return %{ $calculated_params };
+}
- return %paginate_params;
+sub disable_pagination {
+ my ($self) = @_;
+ _priv($self)->{disabled} = 1;
}
#
sub _save_current_paginate_params {
my ($self) = @_;
+ return if !_is_enabled($self);
+
my $paginate_spec = $self->get_paginate_spec;
$self->{PRIV()} = {
page => $::form->{ $paginate_spec->{FORM_PARAMS}->[0] } || 1,
sub _callback_handler_for_paginated {
my ($self, %params) = @_;
- my $priv = $self->{PRIV()} || {};
+ my $priv = _priv($self);
- if ($priv->{page}) {
+ if (_is_enabled($self) && $priv->{page}) {
my $paginate_spec = $self->get_paginate_spec;
$params{ $paginate_spec->{FORM_PARAMS}->[0] } = $priv->{page};
$params{ $paginate_spec->{FORM_PARAMS}->[1] } = $priv->{per_page} if $priv->{per_page};
sub _get_models_handler_for_paginated {
my ($self, %params) = @_;
- $params{model} ||= $self->get_paginate_spec->{MODEL};
+ my $spec = $self->get_paginate_spec;
+ $params{model} ||= $spec->{MODEL};
- "SL::DB::Manager::$params{model}"->paginate($self->get_current_paginate_params, args => \%params);
+ "SL::DB::Manager::$params{model}"->paginate($self->get_current_paginate_params, args => \%params) if _is_enabled($self);
- # $::lxdebug->dump(0, "GM handler for paginated; params nach modif:", \%params);
+ # $::lxdebug->dump(0, "GM handler for paginated; params nach modif (is_enabled? " . _is_enabled($self) . ")", \%params);
return %params;
}
+sub _priv {
+ my ($self) = @_;
+ $self->{PRIV()} ||= {};
+ return $self->{PRIV()};
+}
+
+sub _is_enabled {
+ my ($self) = @_;
+ return !_priv($self)->{disabled} && ($self->get_paginate_spec->{ONLY_MAP}->{$self->action_name} || $self->get_paginate_spec->{ONLY_MAP}->{'__ALL__'});
+}
+
1;
__END__
C<SL::Controller::BackgroundJobHistory> the C<MODEL> would default to
C<BackgroundJobHistory>).
+=item * C<PAGINATE_ARGS>
+
+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<get_all>
+function.
+
+This can be used e.g. when filtering is used.
+
=item * C<PER_PAGE>
Optional. An integer: the number of models to return per page.
to L<make_paginated> after normalization (hash reference construction,
applying default parameters etc).
+=item C<disable_pagination>
+
+Disable pagination for the duration of the current action. Can be used
+when using the attribute C<ONLY> to L<make_paginated> does not
+cover all cases.
+
=back
=head1 BUGS