File Coverage

blib/lib/DBIx/Class/Tree/AdjacencyList/Ordered.pm
Criterion Covered Total %
statement 32 44 72.7
branch 6 8 75.0
condition 4 8 50.0
subroutine 6 10 60.0
pod 6 6 100.0
total 54 76 71.0


line stmt bran cond sub pod time code
1             package DBIx::Class::Tree::AdjacencyList::Ordered;
2             # vim: ts=8:sw=4:sts=4:et
3              
4 1     1   135550 use strict;
  1         2  
  1         29  
5 1     1   3 use warnings;
  1         1  
  1         21  
6              
7 1     1   3 use base qw( DBIx::Class );
  1         1  
  1         71  
8 1     1   4 use Carp qw( croak );
  1         1  
  1         355  
9              
10             __PACKAGE__->load_components(qw(
11             Ordered
12             Tree::AdjacencyList
13             ));
14              
15             =head1 NAME
16              
17             DBIx::Class::Tree::AdjacencyList::Ordered - Glue DBIx::Class::Ordered and DBIx::Class::Tree::AdjacencyList together.
18              
19             =head1 SYNOPSIS
20              
21             Create a table for your tree data.
22              
23             CREATE TABLE items (
24             item_id INTEGER PRIMARY KEY AUTOINCREMENT,
25             parent_id INTEGER NOT NULL DEFAULT 0,
26             position INTEGER NOT NULL,
27             name TEXT NOT NULL
28             );
29              
30             In your Schema or DB class add Tree::AdjacencyList::Ordered
31             to the front of the component list.
32              
33             __PACKAGE__->load_components(qw( Tree::AdjacencyList::Ordered ... ));
34              
35             Specify the column that contains the parent ID and position of each row.
36              
37             package My::Employee;
38             __PACKAGE__->position_column('position');
39             __PACKAGE__->parent_column('parent_id');
40              
41             This module provides a few extra methods beyond what
42             L and L
43             already provide.
44              
45             my $parent = $item->parent();
46             $item->parent( $parent_obj );
47             $item->parent( $parent_id );
48            
49             my $children_rs = $item->children();
50             my @children = $item->children();
51            
52             $parent->append_child( $child );
53             $parent->prepend_child( $child );
54            
55             $this->attach_before( $that );
56             $this->attach_after( $that );
57              
58             =head1 DESCRIPTION
59              
60             This module provides methods for working with adjacency lists and ordered
61             rows. All of the methods that L and
62             L provide are available with this module.
63              
64             =head1 METHODS
65              
66             =head2 parent_column
67              
68             __PACKAGE__->parent_column('parent_id');
69              
70             Works the same as AdjacencyList's parent_column() method, but it
71             declares the children() has many relationship to be ordered by the
72             position column.
73              
74             =cut
75              
76             sub parent_column {
77 1     1 1 195 my $class = shift;
78 1   33     23 my $position_col = $class->position_column() || croak('You must call position_column() before calling parent_column()');
79 1 50       27 if (@_) {
80 1         21 $class->grouping_column( @_ );
81 1         10 $class->next::method( @_ );
82 1         19 $class->relationship_info('children')->{attrs}->{order_by} = $position_col;
83 1         441 return 1;
84             }
85 0         0 return $class->grouping_column;
86             }
87              
88             =head2 parent
89              
90             my $parent = $item->parent();
91             $item->parent( $parent_obj );
92             $item->parent( $parent_id );
93              
94             This method overrides AdjacencyList's parent() method but
95             modifies it so that the object is moved to the last position,
96             then the parent is changed, and then it is moved to the last
97             position of the new list, thus maintaining the intergrity of
98             the ordered lists.
99              
100             =cut
101              
102             sub parent {
103 94     94 1 438801 my $self = shift;
104 94 100       312 if (@_) {
105 83         116 my $new_parent = shift;
106 83         2305 my $parent_col = $self->_parent_column();
107 83 100       1690 if (ref($new_parent)) {
108 3   33     34 $new_parent = $new_parent->id() || croak('Parent object does not have an ID');;
109             }
110 83 50 100     364 return 0 if ($new_parent == ($self->get_column($parent_col)||0));
111 83         1540 $self->move_last;
112 83         319799 $self->set_column( $parent_col => $new_parent );
113 83         7462 $self->set_column(
114             $self->position_column() =>
115             $self->result_source->resultset->search(
116             {$self->_grouping_clause()}
117             )->count() + 1
118             );
119 83         241254 $self->update();
120 83         695196 return 1;
121             }
122 11         184 return $self->_parent();
123             }
124              
125             =head2 children
126              
127             my $children_rs = $item->children();
128             my @children = $item->children();
129              
130             This method works just like it does in the
131             DBIx::Class::Tree::AdjacencyList module except it
132             orders the children by there position.
133              
134             =head2 append_child
135              
136             $parent->append_child( $child );
137              
138             Sets the child to have the specified parent and moves the
139             child to the last position.
140              
141             =cut
142              
143             sub append_child {
144 0     0 1   my( $self, $child ) = @_;
145 0           $child->parent( $self );
146             }
147              
148             =head2 prepend_child
149              
150             $parent->prepend_child( $child );
151              
152             Sets the child to have the specified parent and moves the
153             child to the first position.
154              
155             =cut
156              
157             sub prepend_child {
158 0     0 1   my( $self, $child ) = @_;
159 0           $child->parent( $self );
160 0           $child->move_first();
161             }
162              
163             =head2 attach_before
164              
165             $this->attach_before( $that );
166              
167             Attaches the object at the position just before the
168             calling object's position.
169              
170             =cut
171              
172             sub attach_before {
173 0     0 1   my( $self, $sibling ) = @_;
174 0           $sibling->parent( $self->parent() );
175 0           $sibling->move_to( $self->get_column($self->position_column()) );
176             }
177              
178             =head2 attach_after
179              
180             $this->attach_after( $that );
181              
182             Attaches the object at the position just after the
183             calling object's position.
184              
185             =cut
186              
187             sub attach_after {
188 0     0 1   my( $self, $sibling ) = @_;
189 0           $sibling->parent( $self->parent() );
190 0           $sibling->move_to( $self->get_column($self->position_column()) + 1 );
191             }
192              
193             1;
194             __END__