File Coverage

lib/DBIx/EAV/EntityType.pm
Criterion Covered Total %
statement 6 132 4.5
branch 0 68 0.0
condition 0 9 0.0
subroutine 2 20 10.0
pod 1 16 6.2
total 9 245 3.6


line stmt bran cond sub pod time code
1             package DBIx::EAV::EntityType;
2              
3 10     10   33 use Moo;
  10         11  
  10         53  
4 10     10   2075 use strictures 2;
  10         49  
  10         439  
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 0     0     my $self = shift;
19             +{
20 0           map { $_ => {name => $_, is_static => 1} }
21 0           @{$self->core->table('entities')->columns}
  0            
22             }
23             }
24              
25             sub load {
26 0     0 0   my ($class, $row) = @_;
27 0 0         die "load() is a class method" if ref $class;
28              
29 0           my $self = $class->new($row);
30              
31             # load attributes
32 0           my $sth = $self->core->table('attributes')->select({ entity_type_id => $self->id });
33              
34 0           while (my $attr = $sth->fetchrow_hashref) {
35 0           $self->_attributes->{$attr->{name}} = $attr;
36             }
37              
38             # load relationships
39 0           $sth = $self->core->table('relationships')->select({ left_entity_type_id => $self->id });
40              
41 0           while (my $rel = $sth->fetchrow_hashref) {
42 0           $self->_install_relationship($rel);
43             }
44              
45 0           $self;
46             }
47              
48             sub parents {
49 0     0 0   my ($self) = @_;
50 0 0         return () unless $self->has_parent;
51 0           my @parents;
52 0           my $parent = $self->parent;
53 0           while ($parent) {
54 0           push @parents, $parent;
55 0           $parent = $parent->parent;
56             }
57              
58 0           @parents;
59             }
60              
61             sub is_type($) {
62 0     0 0   my ($self, $type) = @_;
63 0 0         return 1 if $self->name eq $type;
64 0           foreach my $parent ($self->parents) {
65 0 0         return 1 if $parent->name eq $type;
66             }
67 0           0;
68             }
69              
70              
71              
72              
73             sub has_attribute {
74 0     0 0   my ($self, $name) = @_;
75 0 0 0       return 1 if exists $self->_attributes->{$name} || exists $self->_static_attributes->{$name};
76 0 0         return 0 unless $self->has_parent;
77              
78 0           my $parent = $self->parent;
79 0           while ($parent) {
80 0 0         return 1 if $parent->has_own_attribute($name);
81 0           $parent = $parent->parent;
82             }
83              
84 0           0;
85             }
86              
87             sub has_static_attribute {
88 0     0 0   my ($self, $name) = @_;
89 0           exists $self->_static_attributes->{$name};
90             }
91              
92             sub has_own_attribute {
93 0     0 0   my ($self, $name) = @_;
94 0 0         exists $self->_attributes->{$name} || exists $self->_static_attributes->{$name};
95             }
96              
97             sub has_inherited_attribute {
98 0     0 0   my ($self, $name) = @_;
99 0 0         return 0 unless $self->has_parent;
100 0           my $parent = $self->parent;
101 0           while ($parent) {
102 0 0         return 1 if exists $parent->_attributes->{$name};
103 0           $parent = $parent->parent;
104             }
105 0           0;
106             }
107              
108             sub attribute {
109 0     0 0   my ($self, $name) = @_;
110              
111             # our attr
112             return $self->_attributes->{$name}
113 0 0         if exists $self->_attributes->{$name};
114              
115             return $self->_static_attributes->{$name}
116 0 0         if exists $self->_static_attributes->{$name};
117              
118             # parent attr
119 0           my $parent = $self->parent;
120 0           while ($parent) {
121             return $parent->_attributes->{$name}
122 0 0         if exists $parent->_attributes->{$name};
123 0           $parent = $parent->parent;
124             }
125              
126             # unknown attribute
127 0           die sprintf("Entity '%s' does not have attribute '%s'.", $self->name, $name);
128             }
129              
130             sub attributes {
131 0     0 1   my ($self, %options) = @_;
132 0           my @items;
133              
134             # static
135 0           push @items, values %{$self->_static_attributes}
136 0 0         unless $options{no_static};
137              
138             # own
139 0           push @items, values %{$self->_attributes}
140 0 0         unless $options{no_own};
141              
142             # inherited
143 0 0         unless ($options{no_inherited}) {
144              
145 0           my $parent = $self->parent;
146 0           while ($parent) {
147 0           push @items, values %{$parent->_attributes};
  0            
148 0           $parent = $parent->parent;
149             }
150             }
151              
152 0 0         return $options{names} ? map { $_->{name} } @items : @items;
  0            
153             }
154              
155              
156              
157              
158             sub has_own_relationship {
159 0     0 0   my ($self, $name) = @_;
160 0           exists $self->_relationships->{$name};
161             }
162              
163             sub has_relationship {
164 0     0 0   my ($self, $name) = @_;
165 0 0         return 1 if exists $self->_relationships->{$name};
166 0 0         return 0 unless $self->has_parent;
167              
168 0           my $parent = $self->parent;
169 0           while ($parent) {
170 0 0         return 1 if $parent->has_own_relationship($name);
171 0           $parent = $parent->parent;
172             }
173              
174 0           0;
175             }
176              
177             sub relationship {
178 0     0 0   my ($self, $name) = @_;
179              
180             # our
181             return $self->_relationships->{$name}
182 0 0         if exists $self->_relationships->{$name};
183              
184             # parent
185 0           my $parent = $self->parent;
186 0           while ($parent) {
187             return $parent->_relationships->{$name}
188 0 0         if exists $parent->_relationships->{$name};
189 0           $parent = $parent->parent;
190             }
191              
192             # unknown
193 0           die sprintf("Entity '%s' does not have relationship '%s'.", $self->name, $name);
194             }
195              
196             sub relationships {
197 0     0 0   my ($self, %options) = @_;
198              
199             # ours
200 0           my @items = values %{$self->_relationships};
  0            
201              
202             # inherited
203 0 0         unless ($options{no_inherited}) {
204              
205 0           my $parent = $self->parent;
206 0           while ($parent) {
207 0           push @items, values %{$parent->_relationships};
  0            
208 0           $parent = $parent->parent;
209             }
210             }
211              
212 0 0         return $options{names} ? map { $_->{name} } @items : @items;
  0            
213             }
214              
215              
216             sub register_relationship {
217 0     0 0   my ($self, $reltype, $params) = @_;
218              
219             # scalar: entity
220 0 0         $params = { entity => $params } unless ref $params;
221              
222             # array: name => Entity [, incoming_name ]
223 0 0         if (ref $params eq 'ARRAY') {
224              
225 0           $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 0 0         unless $params->{entity};
234              
235 0           my $other_entity = $self->core->type($params->{entity});
236              
237 0 0 0       $params->{name} ||= $reltype =~ /_many$/ ? lc Lingua::EN::Inflect::PL($other_entity->name)
238             : lc $other_entity->name;
239              
240 0 0 0       $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 0           "is_$reltype" => 1
249             );
250              
251             # update or insert
252 0           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 0           });
257              
258 0 0         if ($existing_rel) {
259              
260 0           $rel{id} = $existing_rel->{id};
261              
262             # update
263 0           my %changed_cols = map { $_ => $rel{$_} }
264 0           grep { $rel{$_} ne $existing_rel->{$_} }
  0            
265             keys %rel;
266              
267             $relationships_table->update(\%changed_cols, { id => $rel{id} })
268 0 0         if keys %changed_cols > 0;
269             }
270             else {
271 0           my $id = $relationships_table->insert(\%rel);
272             die sprintf("Database error while registering '%s -> %s' relationship.", $self->name, $rel{name})
273 0 0         unless $id;
274              
275 0           $rel{id} = $id;
276             }
277              
278             # install relationship
279 0           $self->_install_relationship(\%rel);
280             }
281              
282             sub _install_relationship {
283 0     0     my ($self, $rel) = @_;
284 0           my $relname = $rel->{name};
285              
286 0 0         die sprintf("Entity '%s' already has relationship '%s'.", $self->name, $relname)
287             if $self->has_relationship($relname);
288              
289 0           my $other_entity = $self->core->type_by_id($rel->{right_entity_type_id});
290              
291             # install our side
292 0           $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 0 0         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 0           };
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__