POD for Order role
[catagits/Reaction.git] / lib / Reaction / UI / ViewPort / Collection / Role / Order.pm
1 package Reaction::UI::ViewPort::Collection::Role::Order;
2
3 use Reaction::Role;
4
5 use namespace::clean -except => [ qw(meta) ];
6
7 has enable_order_by => (is => 'rw', isa => 'ArrayRef');
8 has coerce_order_by => (isa => 'HashRef', is => 'rw');
9
10 has order_by => (
11   isa => 'Str',
12   is => 'rw',
13   trigger_adopt('order_by'),
14   clearer => 'clear_order_by'
15 );
16
17 has order_by_desc => (
18   isa => 'Int',
19   is => 'rw',
20   trigger_adopt('order_by'),
21   lazy_build => 1
22 );
23
24 sub _build_order_by_desc { 0 }
25
26 sub adopt_order_by {
27   shift->clear_current_collection;
28 }
29
30 sub can_order_by {
31   my ($self,$order_by) = @_;
32   return 1 unless $self->has_enable_order_by;
33   return scalar grep { $order_by eq $_ } @{ $self->enable_order_by };
34 }
35
36 sub _order_search_attrs {
37   my $self = shift;
38   my %attrs;
39   if ($self->has_order_by) {
40     my $order_by = $self->order_by;
41     if( $self->has_coerce_order_by ){
42       $order_by = $self->coerce_order_by->{$order_by}
43         if exists $self->coerce_order_by->{$order_by};
44     }
45     my $key = $self->order_by_desc ? '-desc' : '-asc';
46     $attrs{order_by} = { $key => $order_by };
47   }
48   return \%attrs;
49 }
50
51 after clear_order_by => sub {
52   my ($self) = @_;
53   $self->order_by_desc(0);
54   $self->clear_current_collection;
55 };
56
57 around _build_current_collection => sub {
58   my $orig = shift;
59   my ($self) = @_;
60   my $collection = $orig->(@_);
61   return $collection->where(undef, $self->_order_search_attrs);
62 };
63
64 around accept_events => sub { ('order_by', 'order_by_desc', shift->(@_)); };
65
66 1;
67
68 __END__;
69
70 =head1 NAME
71
72 Reaction::UI::ViewPort::Collection::Role::Order - Order support for collections
73
74 =head1 DESCRIPTION
75
76 Role to add order support to collection viewports.
77
78 =head1 ATTRIBUTES
79
80 =head2 enable_order_by
81
82 Re-writable array reference. Optionally use this to manually specify a list of
83 fields that support ordering, instead of the default of all fields. This is
84 useful to exclude computed values or non-indexed columns from being sortable.
85
86 =head2 coerce_order_by
87
88 Re-writeable hash reference. Optionally use this to manually specify the way in
89 which a field should be ordered. This is useful when the field name and the
90 query to sort it differ. E.g. for a belongs_to item:
91
92     coerce_order_by => { foo => ['foo.last_name', 'foo.first_name'] },
93
94 =head2  order_by
95
96 Re-writeable string. Optionally set it to dictate which field to use when
97 sorting.
98
99 =head2 order_by_desc
100
101 Re-writeable boolean. Optionally use descending order when sorting. Defaults to false.
102
103 =head1 METHODS
104
105 =head2 can_order_by $field_name
106
107 Returns true if sorting by that field is supported, false otherwise.
108
109 =head1 AUTHORS
110
111 See L<Reaction::Class> for authors.
112
113 =head1 LICENSE
114
115 See L<Reaction::Class> for the license.
116
117 =cut