1 package SL::Controller::Helper::GetModels::Sorted;
 
   4 use parent 'SL::Controller::Helper::GetModels::Base';
 
   7 use List::MoreUtils qw(uniq);
 
   9 use Rose::Object::MakeMethods::Generic (
 
  10   scalar => [ qw(by dir specs form_data) ],
 
  11   'scalar --get_set_init' => [ qw(form_params) ],
 
  15   my ($self, %specs) = @_;
 
  17   $self->set_get_models(delete $specs{get_models});
 
  18   my %model_sort_spec   = $self->get_models->manager->_sort_spec;
 
  20   if (my $default = delete $specs{_default}) {
 
  21     $self->by ($default->{by});
 
  22     $self->dir($default->{dir});
 
  24     $self->by ($model_sort_spec{default}[0]);
 
  25     $self->dir($model_sort_spec{default}[1]);
 
  28   while (my ($column, $spec) = each %specs) {
 
  29     next if $column =~ m/^[A-Z_]+$/;
 
  31     $spec = $specs{$column} = { title => $spec } if (ref($spec) || '') ne 'HASH';
 
  33     $spec->{model}        ||= $self->get_models->model;
 
  34     $spec->{model_column} ||= $column;
 
  36   $self->specs(\%specs);
 
  38   $self->get_models->register_handlers(
 
  39     callback   => sub { shift; $self->_callback_handler_for_sorted(@_) },
 
  42 #   $::lxdebug->dump(0, "CONSPEC", \%specs);
 
  46   my ($self, %params) = @_;
 
  48   return %{ $self->form_data } if $self->form_data;
 
  51   my ($by, $dir) = @{ $self->form_params };
 
  52   my $source = $self->get_models->source;
 
  54   if ($source->{ $by }) {
 
  56       sort_by  => $source->{$by},
 
  57       sort_dir => defined($source->{$dir}) ? $source->{$dir} * 1 : undef,
 
  59   } elsif (!$self->by) {
 
  60     %sort_params = %params;
 
  64       sort_dir => $self->dir,
 
  68   $self->form_data(\%sort_params);
 
  74   my ($self, %params) = @_;
 
  76   my %sort_params     = $self->read_params;
 
  77   my $sort_spec       = $self->specs->{ $sort_params{sort_by} };
 
  79   $params{sort_by}    = "SL::DB::Manager::$sort_spec->{model}"->make_sort_string(sort_by => $sort_spec->{model_column}, sort_dir => $sort_params{sort_dir});
 
  84 sub set_report_generator_sort_options {
 
  85   my ($self, %params) = @_;
 
  87   $params{$_} or croak("Missing parameter '$_'") for qw(report sortable_columns);
 
  89   my %current_sort_params = $self->read_params;
 
  91   foreach my $col (@{ $params{sortable_columns} }) {
 
  92     $params{report}->{columns}->{$col}->{link} = $self->get_models->get_callback(
 
  94       sort_dir => ($current_sort_params{sort_by} eq $col ? 1 - $current_sort_params{sort_dir} : $current_sort_params{sort_dir}),
 
  98   $params{report}->set_sort_indicator($current_sort_params{sort_by}, 1 - $current_sort_params{sort_dir});
 
 100   if ($params{report}->{export}) {
 
 101     $params{report}->{export}->{variable_list} = [ uniq(
 
 102       @{ $params{report}->{export}->{variable_list} },
 
 103       @{ $self->form_params }
 
 112 sub _callback_handler_for_sorted {
 
 113   my ($self, %params) = @_;
 
 114   my %spec = $self->read_params;
 
 116   if ($spec{sort_by}) {
 
 117     $params{ $self->form_params->[0] } = $spec{sort_by};
 
 118     $params{ $self->form_params->[1] } = $spec{sort_dir};
 
 121   # $::lxdebug->dump(0, "CB handler for sorted; params nach modif:", \%params);
 
 126 sub init_form_params {
 
 127   [ qw(sort_by sort_dir) ]
 
 139 SL::Controller::Helper::Sorted - A helper for semi-automatic handling
 
 140 of sorting lists of database models in a controller
 
 146   SL::Controller::Helper::GetModels->new(
 
 153       error        => $::locale->text('Error'),
 
 154       package_name => $::locale->text('Package name'),
 
 155       run_at       => $::locale->text('Run at'),
 
 165     <th>[% L.sortable_table_header('package_name') %]</th>
 
 166     <th>[% L.sortable_table_header('run_at') %]</th>
 
 167     <th>[% L.sortable_table_header('error') %]</th>
 
 170    [% FOREACH entry = ENTRIES %]
 
 172      <td>[% HTML.escape(entry.package_name) %]</td>
 
 173      <td>[% HTML.escape(entry.run_at) %]</td>
 
 174      <td>[% HTML.escape(entry.error) %]</td>
 
 181 This C<GetModels> plugin enables controllers to display a
 
 182 sortable list of database models with as few lines as possible.
 
 184 For this to work the controller has to provide the information which
 
 185 indexes are eligible for sorting etc. through it's configuration of
 
 188 A template can then use the method C<sortable_table_header> from the layout
 
 191 This module requires that the Rose model managers use their
 
 192 C<SL::DB::Helper::Sorted> helper.
 
 198 =item * C<_default HASHREF>
 
 200 Optional. If it exists, it is expected to contain the keys C<by> and C<dir> and
 
 201 will be used to set the default sorting if nothing is found in C<source>.
 
 203 Defaults to the underlying database model's default.
 
 205 =item * C<form_params>
 
 207 Optional. An array reference with exactly two strings that name the
 
 208 indexes in C<source> in which the sort index (the first element in
 
 209 the array) and sort direction (the second element in the array) are
 
 212 Defaults to the values C<sort_by> and C<sort_dir> if missing.
 
 216 All other keys can be used for sorting. Each value to such a key can be either
 
 217 a string or a hash reference containing certain elements. If the value is only
 
 218 a string then such a hash reference is constructed, and the string is
 
 219 used as the value for the C<title> key.
 
 221 These possible elements are:
 
 227 Required. A user-displayable title to be used by functions like the
 
 228 layout helper's C<sortable_table_header>. Does not have a default
 
 231 Note that this string must be the untranslated English version of the
 
 232 string. The titles will be translated whenever they're requested.
 
 236 Optional. The name of a Rose database model this sort index refers
 
 237 to. If missing then the value of C<$sort_spec{MODEL}> is used.
 
 239 =item * C<model_column>
 
 241 Optional. The name of the Rose database model column this sort index
 
 242 refers to. It must be one of the columns named by the model's
 
 243 C<Sorted> helper (not to be confused with the controller's C<Sorted>
 
 246 If missing it defaults to the key in C<%sort_spec> for which this hash
 
 247 reference is the value.
 
 253 =head1 INSTANCE FUNCTIONS
 
 255 These functions are called on a C<GetModels> instance and delegating to this plugin.
 
 259 =item C<get_sort_spec>
 
 261 Returns a hash containing the currently active sort parameters.
 
 263 The key C<by> contains the active sort index referring to the
 
 264 C<%sort_spec> given by the configuration.
 
 266 The key C<dir> is either C<1> or C<0>.
 
 268 =item C<get_current_sort_params>
 
 270 Returns a hash reference to the sort spec structure given in the configuration
 
 271 after normalization (hash reference construction, applying default parameters
 
 274 =item C<set_report_generator_sort_options %params>
 
 276 This function does three things with an instance of
 
 277 L<SL::ReportGenerator>:
 
 281 =item 1. it sets the sort indicator,
 
 283 =item 2. it sets the the links for those column headers that are
 
 286 =item 3. it adds the C<form_params> fields to the list of variables in
 
 287 the report generator's export options.
 
 291 The report generator instance must be passed as the parameter
 
 292 C<report>. The parameter C<sortable_columns> must be an array
 
 293 reference of column names that are sortable.
 
 295 The report generator instance must already have its columns and export
 
 296 options set via calls to its L<SL::ReportGenerator::set_columns> and
 
 297 L<SL::ReportGenerator::set_export_options> functions.
 
 307 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
 
 309 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>