1 package SL::DB::Helpers::Sorted;
6 our @ISA = qw(Exporter);
7 our @EXPORT = qw(get_all_sorted make_sort_string);
11 sub make_sort_string {
12 my ($class, %params) = @_;
14 %sort_spec = $class->_sort_spec unless %sort_spec;
16 my $sort_dir = defined($params{sort_dir}) ? $params{sort_dir} * 1 : $sort_spec{default}->[1];
17 my $sort_dir_str = $sort_dir ? 'ASC' : 'DESC';
19 my $sort_by = $params{sort_by};
20 $sort_by = $sort_spec{default}->[0] unless $sort_spec{columns}->{$sort_by};
23 if ($sort_spec{nulls}) {
24 $nulls_str = ref($sort_spec{nulls}) ? ($sort_spec{nulls}->{$sort_by} || $sort_spec{nulls}->{default}) : $sort_spec{nulls};
25 $nulls_str = " NULLS ${nulls_str}" if $nulls_str;
28 my $sort_by_str = $sort_spec{columns}->{$sort_by};
29 $sort_by_str = [ $sort_by_str ] unless ref($sort_by_str) eq 'ARRAY';
30 $sort_by_str = join(', ', map { "${_} ${sort_dir_str}${nulls_str}" } @{ $sort_by_str });
32 return wantarray ? ($sort_by, $sort_dir, $sort_by_str) : $sort_by_str;
36 my ($class, %params) = @_;
37 my $sort_str = $class->make_sort_string(sort_by => delete($params{sort_by}), sort_dir => delete($params{sort_dir}));
39 return $class->get_all(sort_by => $sort_str, %params);
50 SL::DB::Helpers::Sorted - Mixin for a manager class that handles
51 sorting of database records
55 package SL::DB::Manager::Message;
57 use SL::DB::Helpers::Sorted;
60 return ( columns => { recipient_id => [ 'CASE
61 WHEN recipient_group_id IS NULL THEN lower(recipient.name)
62 ELSE lower(recipient_group.name)
64 sender_id => [ 'lower(sender.name)', ],
65 created_at => [ 'created_at', ],
66 subject => [ 'lower(subject)', ],
67 status => [ 'NOT COALESCE(unread, FALSE)', 'created_at' ],
69 default => [ 'status', 1 ],
70 nulls => { default => 'LAST',
76 package SL::Controller::Message;
79 my $messages = SL::DB::Manager::Message->get_all_sorted(sort_by => $::form->{sort_by},
80 sort_dir => $::form->{sort_dir});
83 =head1 CLASS FUNCTIONS
87 =item C<make_sort_string %params>
89 Evaluates C<$params{sort_by}> and C<$params{sort_dir}> and returns an
90 SQL string suitable for sorting. The package this package is mixed
91 into has to provide a method L</_sort_spec> that returns a hash whose
92 structure is explained below. That hash is authoritive in which
93 columns may be sorted, which column to sort by by default and how to
94 handle C<NULL> values.
96 Returns the SQL string in scalar context. In array context it returns
97 three values: the actual column it sorts by (suitable for another call
98 to L</make_sort_string>), the actual sort direction (either 0 or 1)
101 =item C<get_all_sorted %params>
103 Returns C<< $class->get_all >> with C<sort_by> set to the value
104 returned by c<< $class->make_sort_string(%params) >>.
108 =head1 CLASS FUNCTIONS PROVIDED BY THE MIXING PACKAGE
114 This method is actually not part of this package but must be provided
115 by the package this helper is mixed into.
117 Returns a has with the following keys:
123 A two-element array containing the name and direction by which to sort
124 in default cases. Example:
126 default => [ 'name', 1 ],
130 A hash reference. Its keys are column names, and its values are SQL
131 strings by which to sort. Example:
133 columns => { transaction_description => 'oe.transaction_description',
134 customer_name => 'lower(customer.name)',
137 If sorting by a column is requested that is not a key in this hash
138 then the default column name will be used.
140 The value can be either a scalar or an array reference. If it's the
141 latter then both the sort direction as well as the null handling will
142 be appended to each of its members.
146 Either a scalar or a hash reference determining where C<NULL> values
147 will be sorted. If undefined then the decision is left to the
150 If it is a scalar then all the same value will be used for all
151 classes. The value is either C<FIRST> or C<LAST>.
153 If it is a hash reference then its keys are column names (not SQL
154 names). The values are either C<FIRST> or C<LAST>. If a column name is
155 not found in this hash then the special keu C<default> will be looked
156 up and used if it is found.
160 nulls => { transaction_description => 'FIRST',
161 customer_name => 'FIRST',
175 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>