A bunch of tweaks inspired by comments from Dave Howorth.
[dbsrgits/DBIx-Class-Tree.git] / lib / DBIx / Class / Tree / AdjacencyList / Ordered.pm
CommitLineData
57f04bd5 1# vim: ts=8:sw=4:sts=4:et
c11aa533 2package DBIx::Class::Tree::AdjacencyList::Ordered;
57f04bd5 3use strict;
4use warnings;
5use base qw( DBIx::Class );
6use Carp qw( croak );
7
8__PACKAGE__->load_components(qw(
c11aa533 9 Ordered
9717d3ca 10 Tree::AdjacencyList
57f04bd5 11));
12
13=head1 NAME
14
c11aa533 15DBIx::Class::Tree::AdjacencyList::Ordered - Glue DBIx::Class::Ordered and DBIx::Class::Tree::AdjacencyList together. (EXPERIMENTAL)
57f04bd5 16
17=head1 SYNOPSIS
18
19Create a table for your tree data.
20
c11aa533 21 CREATE TABLE items (
22 item_id INTEGER PRIMARY KEY AUTOINCREMENT,
82958127 23 parent_id INTEGER NOT NULL DEFAULT 0,
57f04bd5 24 position INTEGER NOT NULL,
25 name TEXT NOT NULL
26 );
27
c11aa533 28In your Schema or DB class add Tree::AdjacencyList::Ordered
9717d3ca 29to the front of the component list.
57f04bd5 30
c11aa533 31 __PACKAGE__->load_components(qw( Tree::AdjacencyList::Ordered ... ));
57f04bd5 32
33Specify the column that contains the parent ID and position of each row.
34
35 package My::Employee;
82958127 36 __PACKAGE__->position_column('position');
c11aa533 37 __PACKAGE__->parent_column('parent_id');
57f04bd5 38
39This module provides a few extra methods beyond what
c11aa533 40L<DBIx::Class::Ordered> and L<DBIx::Class::Tree::AdjacencyList>
57f04bd5 41already provide.
42
c11aa533 43 my $parent = $item->parent();
44 $item->parent( $parent_obj );
45 $item->parent( $parent_id );
57f04bd5 46
c11aa533 47 my $children_rs = $item->children();
48 my @children = $item->children();
57f04bd5 49
50 $parent->append_child( $child );
51 $parent->prepend_child( $child );
52
53 $this->attach_before( $that );
54 $this->attach_after( $that );
55
56=head1 DESCRIPTION
57
c11aa533 58This module provides methods for working with adjacency lists and ordered
59rows. All of the methods that L<DBIx::Class::Ordered> and
60L<DBIx::Class::Tree::AdjacencyList> provide are available with this module.
57f04bd5 61
62=head1 METHODS
63
82958127 64=head2 parent_column
65
66 __PACKAGE__->parent_column('parent_id');
67
68Works the same as AdjacencyList's parent_column() method, but it
69declares the children() has many relationship to be ordered by the
70position column.
71
72=cut
73
74sub parent_column {
75 my $class = shift;
9717d3ca 76 my $position_col = $class->position_column() || croak('You must call position_column() before calling parent_column()');
82958127 77 if (@_) {
9717d3ca 78 $class->grouping_column( @_ );
79 $class->next::method( @_ );
80 $class->relationship_info('children')->{attrs}->{order_by} = $position_col;
82958127 81 return 1;
82 }
9717d3ca 83 return $class->grouping_column;
82958127 84}
85
57f04bd5 86=head2 parent
87
c11aa533 88 my $parent = $item->parent();
89 $item->parent( $parent_obj );
90 $item->parent( $parent_id );
57f04bd5 91
82958127 92This method overrides AdjacencyList's parent() method but
93modifies it so that the object is moved to the last position,
94then the parent is changed, and then it is moved to the last
c11aa533 95position of the new list, thus maintaining the intergrity of
96the ordered lists.
57f04bd5 97
98=cut
99
100sub parent {
82958127 101 my $self = shift;
102 if (@_) {
103 my $new_parent = shift;
104 my $parent_col = $self->_parent_column();
57f04bd5 105 if (ref($new_parent)) {
82958127 106 $new_parent = $new_parent->id() || croak('Parent object does not have an ID');;
57f04bd5 107 }
82958127 108 return 0 if ($new_parent == ($self->get_column($parent_col)||0));
109 $self->move_last;
110 $self->set_column( $parent_col => $new_parent );
57f04bd5 111 $self->set_column(
e338251b 112 $self->position_column() =>
113 $self->result_source->resultset->search(
c11aa533 114 {$self->_grouping_clause()}
e338251b 115 )->count() + 1
57f04bd5 116 );
117 $self->update();
118 return 1;
119 }
82958127 120 return $self->_parent();
57f04bd5 121}
122
123=head2 children
124
c11aa533 125 my $children_rs = $item->children();
126 my @children = $item->children();
57f04bd5 127
128This method works just like it does in the
129DBIx::Class::Tree::AdjacencyList module except it
130orders the children by there position.
131
57f04bd5 132=head2 append_child
133
134 $parent->append_child( $child );
135
136Sets the child to have the specified parent and moves the
137child to the last position.
138
139=cut
140
141sub append_child {
142 my( $self, $child ) = @_;
143 $child->parent( $self );
144}
145
146=head2 prepend_child
147
148 $parent->prepend_child( $child );
149
150Sets the child to have the specified parent and moves the
151child to the first position.
152
153=cut
154
155sub prepend_child {
156 my( $self, $child ) = @_;
157 $child->parent( $self );
158 $child->move_first();
159}
160
161=head2 attach_before
162
163 $this->attach_before( $that );
164
165Attaches the object at the position just before the
166calling object's position.
167
168=cut
169
170sub attach_before {
171 my( $self, $sibling ) = @_;
172 $sibling->parent( $self->parent() );
173 $sibling->move_to( $self->get_column($self->position_column()) );
174}
175
176=head2 attach_after
177
178 $this->attach_after( $that );
179
180Attaches the object at the position just after the
181calling object's position.
182
183=cut
184
185sub attach_after {
186 my( $self, $sibling ) = @_;
187 $sibling->parent( $self->parent() );
188 $sibling->move_to( $self->get_column($self->position_column()) + 1 );
189}
190
9717d3ca 1911;
192__END__
e338251b 193
9717d3ca 194=head1 INHERITED METHODS
57f04bd5 195
9717d3ca 196This module inherits all methods from L<DBIx::Class::Ordered>.
57f04bd5 197
9717d3ca 198 siblings
199 first_sibling
200 last_sibling
201 previous_sibling
202 next_sibling
203 move_previous
204 move_next
205 move_first
206 move_last
207 move_to
208 insert
209 delete
57f04bd5 210
9717d3ca 211And L<DBIx::Class::Tree::AdjacencyList>.
57f04bd5 212
9717d3ca 213 attach_child
214 attach_sibling
57f04bd5 215
216=head1 AUTHOR
217
218Aran Clary Deltac <bluefeet@cpan.org>
219
220=head1 LICENSE
221
222You may distribute this code under the same terms as Perl itself.
223