Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision ef32afed

Von Moritz Bunkus vor etwa 12 Jahren hinzugefügt

  • ID ef32afedff7750a5ef937bad68d7fde5672d5d8a
  • Vorgänger 4a366d76
  • Nachfolger 07d65516

Controller-Helfer zum Paginaten von Listen

Unterschiede anzeigen:

SL/Controller/Helper/Paginated.pm
1
package SL::Controller::Helper::Paginated;
2

  
3
use strict;
4

  
5
use Exporter qw(import);
6
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);
7

  
8
my ($controller_paginate_spec, $current_page, $current_per_page);
9

  
10
sub make_paginated {
11
  my ($class, %specs)       = @_;
12

  
13
  $specs{MODEL}           ||=  $class->_controller_name;
14
  $specs{MODEL}             =~ s{ ^ SL::DB:: (?: .* :: )? }{}x;
15
  $specs{PER_PAGE}        ||= "SL::DB::Manager::$specs{MODEL}"->default_objects_per_page;
16
  $specs{FORM_PARAMS}     ||= [ qw(page per_page) ];
17
  $specs{ONLY}            ||= [];
18
  $specs{ONLY}              = [ $specs{ONLY} ] if !ref $specs{ONLY};
19

  
20
  $controller_paginate_spec = \%specs;
21

  
22
  my %hook_params           = @{ $specs{ONLY} } ? ( only => $specs{ONLY} ) : ();
23
  $class->run_before('_save_current_paginate_params', %hook_params);
24

  
25
  SL::Controller::Helper::GetModels::register_get_models_handlers(
26
    $class,
27
    callback   => '_callback_handler_for_paginated',
28
    get_models => '_get_models_handler_for_paginated',
29
    ONLY       => $specs{ONLY},
30
  );
31

  
32
  # $::lxdebug->dump(0, "CONSPEC", \%specs);
33
}
34

  
35
sub get_paginate_spec {
36
  my ($class_or_self) = @_;
37

  
38
  return $controller_paginate_spec;
39
}
40

  
41
sub get_current_paginate_params {
42
  my ($self, %params)   = @_;
43

  
44
  my $spec              = $self->get_paginate_spec;
45

  
46
  $params{page}         = $current_page     unless defined $params{page};
47
  $params{per_page}     = $current_per_page unless defined $params{per_page};
48

  
49
  my %paginate_params   =  (
50
    page                => ($params{page}     * 1) || 1,
51
    per_page            => ($params{per_page} * 1) || $spec->{PER_PAGE},
52
  );
53

  
54
  my $calculated_params = "SL::DB::Manager::$spec->{MODEL}"->paginate(%paginate_params, args => {});
55
  %paginate_params      = (
56
    %paginate_params,
57
    num_pages    => $calculated_params->{max},
58
    common_pages => $calculated_params->{common},
59
  );
60

  
61
  # $::lxdebug->dump(0, "get_current_paginate_params: ", \%paginate_params);
62

  
63
  return %paginate_params;
64
}
65

  
66
#
67
# private functions
68
#
69

  
70
sub _save_current_paginate_params {
71
  my ($self)        = @_;
72

  
73
  my $paginate_spec = $self->get_paginate_spec;
74
  $current_page     = $::form->{ $paginate_spec->{FORM_PARAMS}->[0] } || 1;
75
  $current_per_page = $::form->{ $paginate_spec->{FORM_PARAMS}->[1] } * 1;
76

  
77
  # $::lxdebug->message(0, "saving current paginate params to $current_page / $current_per_page");
78
}
79

  
80
sub _callback_handler_for_paginated {
81
  my ($self, %params) = @_;
82

  
83
  if ($current_page) {
84
    my $paginate_spec                             = $self->get_paginate_spec;
85
    $params{ $paginate_spec->{FORM_PARAMS}->[0] } = $current_page;
86
    $params{ $paginate_spec->{FORM_PARAMS}->[1] } = $current_per_page if $current_per_page;
87
  }
88

  
89
  # $::lxdebug->dump(0, "CB handler for paginated; params nach modif:", \%params);
90

  
91
  return %params;
92
}
93

  
94
sub _get_models_handler_for_paginated {
95
  my ($self, %params)    = @_;
96
  $params{model}       ||= $self->get_paginate_spec->{MODEL};
97

  
98
  "SL::DB::Manager::$params{model}"->paginate($self->get_current_paginate_params, args => \%params);
99

  
100
  # $::lxdebug->dump(0, "GM handler for paginated; params nach modif:", \%params);
101

  
102
  return %params;
103
}
104

  
105
1;
106
__END__
107

  
108
=pod
109

  
110
=encoding utf8
111

  
112
=head1 NAME
113

  
114
SL::Controller::Helper::Paginated - A helper for semi-automatic handling
115
of paginating lists of database models in a controller
116

  
117
=head1 SYNOPSIS
118

  
119
In a controller:
120

  
121
  use SL::Controller::Helper::GetModels;
122
  use SL::Controller::Helper::Paginated;
123

  
124
  __PACKAGE__->make_paginated(
125
    MODEL       => 'BackgroundJobHistory',
126
    ONLY        => [ qw(list) ],
127
    FORM_PARAMS => [ qw(page per_page) ],
128
  );
129

  
130
  sub action_list {
131
    my ($self) = @_;
132

  
133
    my $paginated_models = $self->get_models;
134
    $self->render('controller/list', ENTRIES => $paginated_models);
135
  }
136

  
137
In said template:
138

  
139
  [% USE L %]
140

  
141
  <table>
142
   <thead>
143
    <tr>
144
     ...
145
    </tr>
146
   </thead>
147

  
148
   <tbody>
149
    [% FOREACH entry = ENTRIES %]
150
     <tr>
151
      ...
152
     </tr>
153
    [% END %]
154
   </tbody>
155
  </table>
156

  
157
  [% L.paginate_controls %]
158

  
159
=head1 OVERVIEW
160

  
161
This specialized helper module enables controllers to display a
162
paginatable list of database models with as few lines as possible. It
163
can also be combined trivially with the L<SL::Controller::Sorted>
164
helper for sortable lists.
165

  
166
For this to work the controller has to provide the information which
167
indexes are eligible for paginateing etc. by a call to
168
L<make_paginated> at compile time.
169

  
170
The underlying functionality that enables the use of more than just
171
the paginate helper is provided by the controller helper
172
C<GetModels>. See the documentation for L<SL::Controller::Sorted> for
173
more information on it.
174

  
175
A template can use the method C<paginate_controls> from the layout
176
helper module C<L> which renders the links for navigation between the
177
pages.
178

  
179
This module requires that the Rose model managers use their C<Paginated>
180
helper.
181

  
182
The C<Paginated> helper hooks into the controller call to the action via
183
a C<run_before> hook. This is done so that it can remember the paginate
184
parameters that were used in the current view.
185

  
186
=head1 PACKAGE FUNCTIONS
187

  
188
=over 4
189

  
190
=item C<make_paginated %paginate_spec>
191

  
192
This function must be called by a controller at compile time. It is
193
uesd to set the various parameters required for this helper to do its
194
magic.
195

  
196
The hash C<%paginate_spec> can include the following parameters:
197

  
198
=over 4
199

  
200
=item * C<MODEL>
201

  
202
Optional. A string: the name of the Rose database model that is used
203
as a default in certain cases. If this parameter is missing then it is
204
derived from the controller's package (e.g. for the controller
205
C<SL::Controller::BackgroundJobHistory> the C<MODEL> would default to
206
C<BackgroundJobHistory>).
207

  
208
=item * C<PER_PAGE>
209

  
210
Optional. An integer: the number of models to return per page.
211

  
212
Defaults to the underlying database model's default number of models
213
per page.
214

  
215
=item * C<FORM_PARAMS>
216

  
217
Optional. An array reference with exactly two strings that name the
218
indexes in C<$::form> in which the current page's number (the first
219
element in the array) and the number of models per page (the second
220
element in the array) are stored.
221

  
222
Defaults to the values C<page> and C<per_page> if missing.
223

  
224
=item * C<ONLY>
225

  
226
Optional. An array reference containing a list of action names for
227
which the paginate parameters should be saved. If missing or empty then
228
all actions invoked on the controller are monitored.
229

  
230
=back
231

  
232
=back
233

  
234
=head1 INSTANCE FUNCTIONS
235

  
236
These functions are called on a controller instance.
237

  
238
=over 4
239

  
240
=item C<get_paginate_spec>
241

  
242
Returns a hash containing the currently active paginate
243
parameters. The following keys are returned:
244

  
245
=over 4
246

  
247
=item * C<page>
248

  
249
The currently active page number (numbering starts at 1).
250

  
251
=item * C<per_page>
252

  
253
Number of models per page (at least 1).
254

  
255
=item * C<num_pages>
256

  
257
Number of pages to display (at least 1).
258

  
259
=item * C<common_pages>
260

  
261
An array reference with one hash reference for each possible
262
page. Each hash ref contains the keys C<active> (C<1> if that page is
263
the currently active page), C<page> (the page number this hash
264
reference describes) and C<visible> (whether or not it should be
265
displayed).
266

  
267
=back
268

  
269
=item C<get_current_paginate_params>
270

  
271
Returns a hash reference to the paginate spec structure given in the call
272
to L<make_paginated> after normalization (hash reference construction,
273
applying default parameters etc).
274

  
275
=back
276

  
277
=head1 BUGS
278

  
279
Nothing here yet.
280

  
281
=head1 AUTHOR
282

  
283
Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
284

  
285
=cut
SL/Template/Plugin/L.pm
605 605
  return '<a href="' . $controller->get_callback(%params) . '">' . _H($title) . $image . '</a>';
606 606
}
607 607

  
608
sub paginate_controls {
609
  my ($self)          = @_;
610

  
611
  my $controller      = $self->{CONTEXT}->stash->get('SELF');
612
  my $paginate_spec   = $controller->get_paginate_spec;
613
  my %paginate_params = $controller->get_current_paginate_params;
614

  
615
  my %template_params = (
616
    pages             => {
617
      cur             => $paginate_params{page},
618
      max             => $paginate_params{num_pages},
619
      common          => $paginate_params{common_pages},
620
    },
621
    url_maker         => sub {
622
      my %url_params                                    = _hashify(@_);
623
      $url_params{ $paginate_spec->{FORM_PARAMS}->[0] } = delete $url_params{page};
624
      $url_params{ $paginate_spec->{FORM_PARAMS}->[1] } = delete $url_params{per_page} if exists $url_params{per_page};
625

  
626
      return $controller->get_callback(%url_params);
627
    },
628
  );
629

  
630
  my $output;
631
  $controller->_template_obj->process('templates/webpages/common/paginate.html', \%template_params, \$output);
632
  return $output;
633
}
634

  
608 635
1;
609 636

  
610 637
__END__
......
903 930
See the documentation of L<SL::Controller::Helper::Sorted> for an
904 931
overview and further usage instructions.
905 932

  
933
=item C<paginate_controls>
934

  
935
Create a set of links used to paginate a list view.
936

  
937
See the documentation of L<SL::Controller::Helper::Paginated> for an
938
overview and further usage instructions.
939

  
906 940
=back
907 941

  
908 942
=head2 CONVERSION FUNCTIONS
templates/webpages/common/paginate.html
1 1
[%- USE T8 %]
2
<span class='paginate'>
2
[%- MACRO build_url BLOCK %]
3
 [%- IF base_url %]
4
  [%- base_url %]&page=[% page %]
5
 [%- ELSE %]
6
  [% url_maker('page' => page) %]
7
 [%- END %]
8
[%- END %]
3 9
[%- IF pages.max > 1 %]
4
[%- IF pages.cur > 1 %]<a class='paginate-prev' href='[% base_url _ "&page=" _ (pages.cur - 1) %]'>&laquo; [% 'prev' | $T8 %]</a> [% ELSE %]<b>&laquo;</b> [% END %]
10
<span class='paginate'>
11
[%- IF pages.cur > 1 %]<a class='paginate-prev' href='[% build_url(page=pages.cur - 1) %]'>&laquo; [% 'prev' | $T8 %]</a> [% ELSE %]<b>&laquo;</b> [% END %]
5 12
[%- FOR p = pages.common %]
6 13
  [%- NEXT UNLESS p.visible %]
7
  [%- IF p.active %]<a class='paginate-page' href="[% base_url _ "&page=" _ p.page %]">[% p.page %]</a> [% ELSE %]<b>[% p.page %]</b> [%- END %]
14
  [%- IF p.active %]<a class='paginate-page' href="[% build_url(page=p.page) %]">[% p.page %]</a> [% ELSE %]<b>[% p.page %]</b> [%- END %]
8 15
[%- END %]
9
[%- IF pages.cur < pages.max %]<a class='paginate-next' href='[% base_url _ "&page=" _ (pages.cur + 1) %]'>[% 'next' | $T8 %] &raquo;</a>[% ELSE %]<b>&raquo;</b>[%- END %]
16
[%- IF pages.cur < pages.max %]<a class='paginate-next' href='[% build_url(page=pages.cur + 1) %]'>[% 'next' | $T8 %] &raquo;</a>[% ELSE %]<b>&raquo;</b>[%- END %]
17
</span>
10 18
[%- END %]
templates/webpages/delivery_plan/_list.html
38 38
  </tr>
39 39
  [%- END %]
40 40
 </table>
41
 <p align=right>[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(action='list', sort_dir=SELF.sort_dir, sort_by=SELF.sort_by) %]</p>
41
 [% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(action='list', sort_dir=SELF.sort_dir, sort_by=SELF.sort_by) %]
42 42

  
43 43
[%- END %]
44 44
</div>
templates/webpages/delivery_plan/report_bottom.html
1 1
[% SET report_bottom_url_args = {} %]
2 2
[%     report_bottom_url_args.import(SELF.flat_filter) %]
3 3
[%     report_bottom_url_args.import({action='list', sort_dir=SELF.sort_dir, sort_by=SELF.sort_by}) %]
4
<p align=right>[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(report_bottom_url_args) %]</p>
4
[% PROCESS 'common/paginate.html' pages=SELF.pages, base_url=SELF.url_for(report_bottom_url_args) %]

Auch abrufbar als: Unified diff