File Coverage

blib/lib/Web/App/Lib/EntityCollection.pm
Criterion Covered Total %
statement 12 75 16.0
branch 5 28 17.8
condition 0 8 0.0
subroutine 2 6 33.3
pod 0 5 0.0
total 19 122 15.5


line stmt bran cond sub pod time code
1             package Web::App::Lib::EntityCollection;
2              
3 1     1   1503 use Class::Easy;
  1         2  
  1         9  
4              
5             sub entity_collection_from_params {
6 0     0 0 0 my $class = shift;
7 0         0 my $app = shift;
8 0         0 my $params = shift;
9            
10 0         0 my $entity_type = delete $params->{entity};
11             # deprecated
12 0 0       0 $entity_type = delete $params->{entity_type}
13             unless defined $entity_type;
14            
15 0 0       0 critical "no entity type defined by controller param entity(_type)?"
16             unless defined $entity_type;
17            
18 0         0 my $collection_pack = $app->project->collection ($entity_type);
19 0         0 my $collection = $collection_pack->new;
20            
21 0 0       0 if ($params->{fieldset}) {
22 0         0 my $method = "fieldset_$params->{fieldset}";
23 0         0 my $record = $collection_pack->record_package;
24 0 0       0 critical "can't use fieldset $params->{fieldset} because no ${record}->$method method available"
25             unless $record->can ($method);
26 0         0 $collection->fieldset ($record->$method);
27             } else {
28 0         0 my $method = "fieldset_default";
29 0         0 my $record = $collection_pack->record_package;
30 0 0       0 $collection->fieldset ($record->$method)
31             if $record->can ($method);
32             }
33            
34 0         0 return $collection;
35             }
36              
37             sub statement_from_params {
38 1     1 0 476 my $class = shift;
39 1         2 my $app = shift;
40 1         3 my $params = shift;
41            
42             # allowed: filter.* => where, group_by, sort.(field|order) => sort_(field|order)
43             # limit, offset
44            
45 1         3 my $result = {where => {}};
46            
47 1         5 foreach my $k (%$params) {
48 8 50       37 if ($k =~ /^group_by$/) {
    100          
    100          
49 0         0 $result->{$k} = $params->{$k}
50             } elsif ($k =~ /^sort\.(field|order)$/) {
51 2         7 $result->{"sort_$1"} = $params->{$k}
52             } elsif ($k =~ /^filter\.(.*)$/) {
53 2         12 $result->{where}->{$1} = $params->{$k};
54             }
55             }
56            
57 1         3 return $result;
58             }
59              
60             sub records {
61 0     0 0   my $class = shift;
62            
63 0           my $collection = $class->entity_collection_from_params (@_);
64 0           my $statement = $class->statement_from_params (@_);
65            
66 0           my $list = $collection->records (%$statement);
67            
68 0           return $list;
69             }
70              
71             sub embed_record {
72 0     0 0   my $class = shift;
73            
74 0           my $collection = $class->entity_collection_from_params (@_);
75 0           my $statement = $class->statement_from_params (@_);
76            
77 0           my $to = $_[1]->{to};
78 0           my $by = $_[1]->{by};
79 0           my $key = $_[1]->{key};
80            
81             # TODO: check for to and by emptiness
82            
83 0           my $to_ids = {};
84            
85 0           foreach my $rec_to (@$to) {
86             # TODO: also check availability of $by in $rec_to
87 0           push @{$to_ids->{$rec_to->$by}}, $rec_to;
  0            
88             }
89            
90 0 0         return unless scalar keys %$to_ids;
91            
92 0           $statement->{where}->{$collection->_pk_} = [keys %$to_ids];
93            
94 0           my $list = $collection->records (%$statement);
95            
96 0           foreach my $rec (@$list) {
97 0           my $pk = $rec->_pk_;
98 0 0         next unless exists $to_ids->{$rec->$pk};
99            
100 0           foreach my $rec_to (@{$to_ids->{$rec->$pk}}) {
  0            
101 0           $rec_to->{$key} = {%$rec};
102             }
103            
104             }
105            
106 0           return;
107            
108             }
109              
110             sub page {
111 0     0 0   my $class = shift;
112              
113 0           my $collection = $class->entity_collection_from_params (@_);
114 0           my $statement = $class->statement_from_params (@_);
115              
116 0           my $app = shift;
117 0           my $params = shift;
118            
119 0           my $count = $collection->count ($statement->{where});
120              
121             # by default i want 20 last records ordered by primary key
122            
123 0   0       my $page_num = $params->{num} || 1;
124            
125 0   0       $statement->{limit} = $params->{length} || 20;
126 0           $statement->{offset} = ($page_num - 1) * $statement->{limit};
127              
128             # Sort field
129 0   0       $statement->{sort_field} = $params->{sort_field} || '';
130            
131             # When using LIMIT, it is important to use an ORDER BY clause that
132             # constrains the result rows into a unique order. Otherwise you will
133             # get an unpredictable subset of the query's rows. You might be asking
134             # for the tenth through twentieth rows, but tenth through twentieth
135             # in what ordering? The ordering is unknown, unless you specified ORDER BY.
136 0 0         $statement->{sort_field} = $collection->_pk_
137             unless $statement->{sort_field};
138              
139 0 0         $statement->{sort_order} = 'desc'
140             unless $statement->{sort_order};
141            
142             # check for overflow
143 0 0         if ($count < $statement->{offset}) {
144             # TODO: return 404
145 0           $statement->{offset} = 0;
146             }
147            
148 0 0         if (300 < $statement->{limit}) {
149             # TODO: return 404
150 0           $statement->{limit} = 20;
151             }
152            
153 0           my $list = $collection->records (%$statement);
154            
155 0   0       my $paging = {
156             page_size => $statement->{limit},
157             count => $count,
158             page_num => $page_num,
159             pages_to_show => $params->{pager_size} || 8
160             };
161              
162 0           my $pager = $collection->pager ($paging);
163            
164             return {
165 0           items => $list,
166             total_count => $count,
167             version => 1,
168             pager => $pager,
169             page_size => $statement->{limit},
170             page_num => $page_num,
171             };
172             }
173              
174              
175             1;