File Coverage

lib/DBIx/EAV/EntityType.pm
Criterion Covered Total %
statement 118 132 89.3
branch 52 68 76.4
condition 6 9 66.6
subroutine 18 20 90.0
pod 1 16 6.2
total 195 245 79.5


line stmt bran cond sub pod time code
1             package DBIx::EAV::EntityType;
2              
3 10     10   34 use Moo;
  10         12  
  10         65  
4 10     10   2177 use strictures 2;
  10         58  
  10         398  
5              
6              
7              
8             has 'core', is => 'ro', required => 1;
9             has 'id', is => 'ro', required => 1;
10             has 'name', is => 'ro', required => 1;
11             has 'parent', is => 'ro', predicate => 1;
12             has '_static_attributes', is => 'ro', init_arg => undef, lazy => 1, builder => 1;
13             has '_attributes', is => 'ro', init_arg => 'attributes', default => sub { {} };
14             has '_relationships', is => 'ro', init_arg => undef, default => sub { {} };
15              
16              
17             sub _build__static_attributes {
18 20     20   2600 my $self = shift;
19             +{
20 67         273 map { $_ => {name => $_, is_static => 1} }
21 20         29 @{$self->core->table('entities')->columns}
  20         330  
22             }
23             }
24              
25             sub load {
26 4     4 0 6 my ($class, $row) = @_;
27 4 50       9 die "load() is a class method" if ref $class;
28              
29 4         81 my $self = $class->new($row);
30              
31             # load attributes
32 4         92 my $sth = $self->core->table('attributes')->select({ entity_type_id => $self->id });
33              
34 4         116 while (my $attr = $sth->fetchrow_hashref) {
35 12         153 $self->_attributes->{$attr->{name}} = $attr;
36             }
37              
38             # load relationships
39 4         96 $sth = $self->core->table('relationships')->select({ left_entity_type_id => $self->id });
40              
41 4         111 while (my $rel = $sth->fetchrow_hashref) {
42 4         17 $self->_install_relationship($rel);
43             }
44              
45 4         36 $self;
46             }
47              
48             sub parents {
49 6     6 0 5333 my ($self) = @_;
50 6 50       20 return () unless $self->has_parent;
51 6         5 my @parents;
52 6         9 my $parent = $self->parent;
53 6         14 while ($parent) {
54 9         12 push @parents, $parent;
55 9         18 $parent = $parent->parent;
56             }
57              
58 6         12 @parents;
59             }
60              
61             sub is_type($) {
62 51     51 0 4103 my ($self, $type) = @_;
63 51 100       258 return 1 if $self->name eq $type;
64 5         14 foreach my $parent ($self->parents) {
65 6 100       29 return 1 if $parent->name eq $type;
66             }
67 0         0 0;
68             }
69              
70              
71              
72              
73             sub has_attribute {
74 161     161 0 1237 my ($self, $name) = @_;
75 161 100 66     1541 return 1 if exists $self->_attributes->{$name} || exists $self->_static_attributes->{$name};
76 31 100       279 return 0 unless $self->has_parent;
77              
78 12         21 my $parent = $self->parent;
79 12         28 while ($parent) {
80 16 100       32 return 1 if $parent->has_own_attribute($name);
81 5         56 $parent = $parent->parent;
82             }
83              
84 1         4 0;
85             }
86              
87             sub has_static_attribute {
88 408     408 0 2786 my ($self, $name) = @_;
89 408         6340 exists $self->_static_attributes->{$name};
90             }
91              
92             sub has_own_attribute {
93 19     19 0 37 my ($self, $name) = @_;
94 19 100       296 exists $self->_attributes->{$name} || exists $self->_static_attributes->{$name};
95             }
96              
97             sub has_inherited_attribute {
98 5     5 0 427 my ($self, $name) = @_;
99 5 50       15 return 0 unless $self->has_parent;
100 5         9 my $parent = $self->parent;
101 5         9 while ($parent) {
102 5 50       21 return 1 if exists $parent->_attributes->{$name};
103 0         0 $parent = $parent->parent;
104             }
105 0         0 0;
106             }
107              
108             sub attribute {
109 782     782 0 791 my ($self, $name) = @_;
110              
111             # our attr
112             return $self->_attributes->{$name}
113 782 100       2172 if exists $self->_attributes->{$name};
114              
115             return $self->_static_attributes->{$name}
116 120 100       2895 if exists $self->_static_attributes->{$name};
117              
118             # parent attr
119 113         830 my $parent = $self->parent;
120 113         253 while ($parent) {
121             return $parent->_attributes->{$name}
122 168 100       574 if exists $parent->_attributes->{$name};
123 55         104 $parent = $parent->parent;
124             }
125              
126             # unknown attribute
127 0         0 die sprintf("Entity '%s' does not have attribute '%s'.", $self->name, $name);
128             }
129              
130             sub attributes {
131 118     118 1 227 my ($self, %options) = @_;
132 118         105 my @items;
133              
134             # static
135 1         20 push @items, values %{$self->_static_attributes}
136 118 100       203 unless $options{no_static};
137              
138             # own
139 118         282 push @items, values %{$self->_attributes}
140 118 50       199 unless $options{no_own};
141              
142             # inherited
143 118 50       201 unless ($options{no_inherited}) {
144              
145 118         137 my $parent = $self->parent;
146 118         197 while ($parent) {
147 23         21 push @items, values %{$parent->_attributes};
  23         55  
148 23         69 $parent = $parent->parent;
149             }
150             }
151              
152 118 100       228 return $options{names} ? map { $_->{name} } @items : @items;
  446         747  
153             }
154              
155              
156              
157              
158             sub has_own_relationship {
159 88     88 0 93 my ($self, $name) = @_;
160 88         251 exists $self->_relationships->{$name};
161             }
162              
163             sub has_relationship {
164 579     579 0 1529 my ($self, $name) = @_;
165 579 100       1405 return 1 if exists $self->_relationships->{$name};
166 494 100       1637 return 0 unless $self->has_parent;
167              
168 59         70 my $parent = $self->parent;
169 59         96 while ($parent) {
170 88 100       122 return 1 if $parent->has_own_relationship($name);
171 80         191 $parent = $parent->parent;
172             }
173              
174 51         131 0;
175             }
176              
177             sub relationship {
178 157     157 0 150 my ($self, $name) = @_;
179              
180             # our
181             return $self->_relationships->{$name}
182 157 100       431 if exists $self->_relationships->{$name};
183              
184             # parent
185 15         20 my $parent = $self->parent;
186 15         24 while ($parent) {
187             return $parent->_relationships->{$name}
188 15 50       51 if exists $parent->_relationships->{$name};
189 0         0 $parent = $parent->parent;
190             }
191              
192             # unknown
193 0         0 die sprintf("Entity '%s' does not have relationship '%s'.", $self->name, $name);
194             }
195              
196             sub relationships {
197 24     24 0 38 my ($self, %options) = @_;
198              
199             # ours
200 24         22 my @items = values %{$self->_relationships};
  24         71  
201              
202             # inherited
203 24 50       51 unless ($options{no_inherited}) {
204              
205 24         33 my $parent = $self->parent;
206 24         48 while ($parent) {
207 3         4 push @items, values %{$parent->_relationships};
  3         10  
208 3         11 $parent = $parent->parent;
209             }
210             }
211              
212 24 50       75 return $options{names} ? map { $_->{name} } @items : @items;
  0         0  
213             }
214              
215              
216             sub register_relationship {
217 34     34 0 44 my ($self, $reltype, $params) = @_;
218              
219             # scalar: entity
220 34 100       90 $params = { entity => $params } unless ref $params;
221              
222             # array: name => Entity [, incoming_name ]
223 34 100       74 if (ref $params eq 'ARRAY') {
224              
225 8         33 $params = {
226             name => $params->[0],
227             entity => $params->[1],
228             incoming_name => $params->[2],
229             };
230             }
231              
232             die sprintf("Error: invalid %s relationship for entity '%s': missing 'entity' parameter.", $reltype, $self->name)
233 34 50       68 unless $params->{entity};
234              
235 34         89 my $other_entity = $self->core->type($params->{entity});
236              
237 34 100 66     265 $params->{name} ||= $reltype =~ /_many$/ ? lc Lingua::EN::Inflect::PL($other_entity->name)
238             : lc $other_entity->name;
239              
240 34 100 66     23119 $params->{incoming_name} ||= $reltype eq 'many_to_many' ? lc Lingua::EN::Inflect::PL($self->name)
241             : lc $self->name;
242              
243             my %rel = (
244             left_entity_type_id => $self->id,
245             right_entity_type_id => $other_entity->id,
246             name => $params->{name},
247             incoming_name => $params->{incoming_name},
248 34         2053 "is_$reltype" => 1
249             );
250              
251             # update or insert
252 34         744 my $relationships_table = $self->core->table('relationships');
253             my $existing_rel = $relationships_table->select_one({
254             left_entity_type_id => $self->id,
255             name => $rel{name},
256 34         233 });
257              
258 34 50       393 if ($existing_rel) {
259              
260 0         0 $rel{id} = $existing_rel->{id};
261              
262             # update
263 0         0 my %changed_cols = map { $_ => $rel{$_} }
264 0         0 grep { $rel{$_} ne $existing_rel->{$_} }
  0         0  
265             keys %rel;
266              
267             $relationships_table->update(\%changed_cols, { id => $rel{id} })
268 0 0       0 if keys %changed_cols > 0;
269             }
270             else {
271 34         108 my $id = $relationships_table->insert(\%rel);
272             die sprintf("Database error while registering '%s -> %s' relationship.", $self->name, $rel{name})
273 34 50       84 unless $id;
274              
275 34         74 $rel{id} = $id;
276             }
277              
278             # install relationship
279 34         104 $self->_install_relationship(\%rel);
280             }
281              
282             sub _install_relationship {
283 38     38   95 my ($self, $rel) = @_;
284 38         58 my $relname = $rel->{name};
285              
286 38 50       84 die sprintf("Entity '%s' already has relationship '%s'.", $self->name, $relname)
287             if $self->has_relationship($relname);
288              
289 38         147 my $other_entity = $self->core->type_by_id($rel->{right_entity_type_id});
290              
291             # install our side
292 38         234 $self->_relationships->{$relname} = {
293             %$rel,
294             entity => $other_entity->name
295             };
296              
297             # install their side
298             die sprintf("Entity '%s' already has relationship '%s'.", $self->name, $relname)
299 38 50       102 if $other_entity->has_relationship($rel->{incoming_name});
300              
301             $other_entity->_relationships->{$rel->{incoming_name}} = {
302             %$rel,
303             entity => $self->name,
304             is_right_entity => 1,
305             name => $rel->{incoming_name},
306             incoming_name => $rel->{name},
307 38         436 };
308             }
309              
310              
311             # sub _install_relationship {
312             # my ($self, $relname, $rel) = @_;
313             #
314             # die sprintf("Entity '%s' already has relationship '%s'.", $self->name, $relname)
315             # if exists $self->_relationships->{$relname};
316             #
317             # $self->_relationships->{$relname} = $rel;
318             # }
319              
320              
321              
322             sub prune_attributes {
323 0     0 0   my ($self, $names) = @_;
324             # TODO implement prune_attributes
325             }
326              
327             sub prune_relationships {
328 0     0 0   my ($self, $names) = @_;
329             # TODO implement prune_relationships
330             }
331              
332              
333              
334              
335              
336              
337              
338              
339              
340             1;
341              
342              
343             __END__