File Coverage

lib/Search/QS/Filter.pm
Criterion Covered Total %
statement 53 53 100.0
branch 12 14 85.7
condition n/a
subroutine 8 8 100.0
pod 3 3 100.0
total 76 78 97.4


line stmt bran cond sub pod time code
1             package Search::QS::Filter;
2             $Search::QS::Filter::VERSION = '0.03';
3 5     5   65462 use v5.14;
  5         27  
4 5     5   470 use Moose;
  5         399982  
  5         31  
5              
6             # ABSTRACT: Incapsulation of a single filter element
7              
8              
9             has 'name' => (is => 'rw');
10             has 'operator' => (is => 'rw', default => '=');
11             has 'value' => (is => 'rw', isa => 'ArrayRef', default => sub { return [] } );
12             has 'tag' => (is => 'rw');
13             has 'andGroup' => (is => 'rw');
14             has 'orGroup' => (is => 'rw');
15              
16              
17             sub parse() {
18 50     50 1 114 my $s = shift;
19 50         61 my $val = shift;
20              
21 50 100       101 if (ref($val) ne 'ARRAY') {
22 18         29 push @{$s->value}, $val;
  18         358  
23 18         32 return $s;
24             }
25              
26 32         56 foreach (@$val) {
27             #print $_ . "\n";
28 69         87 given($_) {
29 69         97 when(/^\$op/) { $s->operator($s->_extract_double_dots($_)) }
  5         13  
30 64         114 when(/^\$and/) { $s->andGroup($s->_extract_double_dots($_)) }
  20         39  
31 44         67 when(/^\$or/) { $s->orGroup($s->_extract_double_dots($_)) }
  8         18  
32 36         44 default { push @{$s->value}, $_ }
  36         35  
  36         727  
33             }
34             }
35 32         54 return $s;
36             }
37              
38             sub to_qs() {
39 39     39 1 1018 my $s = shift;
40              
41              
42 39         52 my $ret = '';
43              
44 39         44 foreach (@{$s->value}) {
  39         825  
45 42         72 $ret .= $s->_to_qs_name . '=' . $_ . '&';
46             }
47             # remove last &
48 39 50       86 chop($ret) if (length($ret) > 0);
49 39 100       787 $ret.= '&' . $s->_to_qs_name . '=$op:' . $s->operator if ($s->operator ne '=');
50 39 100       760 $ret.= '&' . $s->_to_qs_name . '=$and:' . $s->andGroup if ($s->andGroup);
51 39 100       739 $ret.= '&' . $s->_to_qs_name . '=$or:' . $s->orGroup if ($s->orGroup);
52              
53 39         451 return $ret;
54             }
55              
56             sub to_sql {
57 11     11 1 15 my $s = shift;
58              
59 11         13 my $ret = '(';
60              
61 11         12 foreach (@{$s->value}) {
  11         228  
62 12         227 $ret .= $s->name . ' ' . $s->operator . ' ' . $_ . ' OR ';
63             }
64              
65             # strip last OR
66 11 50       32 $ret = substr($ret,0, length($ret) - 4) if (length($ret) >0);
67 11         14 $ret .=')';
68              
69              
70 11         34 return $ret;
71             }
72              
73             sub _to_qs_name {
74 68     68   111 my $s = shift;
75              
76 68         1258 my $ret = 'flt[' . $s->name;
77 68 100       1539 $ret.=':' . $s->tag if ($s->tag);
78 68         91 $ret.=']';
79              
80 68         621 return $ret;
81              
82             }
83              
84             sub _extract_double_dots {
85 33     33   39 my $s = shift;
86 33         41 my $val = shift;
87              
88 33         69 my @ret = split(/:/, $val);
89              
90 33         1038 return $ret[1];
91             }
92              
93              
94              
95 5     5   30421 no Moose;
  5         11  
  5         32  
96             __PACKAGE__->meta->make_immutable;
97              
98             1;
99              
100             __END__
101              
102             =pod
103              
104             =encoding UTF-8
105              
106             =head1 NAME
107              
108             Search::QS::Filter - Incapsulation of a single filter element
109              
110             =head1 VERSION
111              
112             version 0.03
113              
114             =head1 SYNOPSIS
115              
116             use Search::QS::Filter;
117              
118             my $flt = new Search::QS::Filter;
119             # parse query_string
120             $flt->parse_qs($qs);
121             # reconvert object to query_string
122             print $flt->to_qs;
123              
124             =head1 DESCRIPTION
125              
126             This object incapsulate a single filter element. Think of it about a single
127             search element in an SQL string. Like
128              
129             fullname = "Joe"
130              
131             it has a fied L</"name()"> "fullname", an L</"operator()"> "=" and a
132             L</"value()"> "Joe".
133              
134             =head1 METHODS
135              
136             =head2 name()
137              
138             The field name to search
139              
140             =head2 operator()
141              
142             The operator to use between field and value
143              
144             =head2 value()
145              
146             An ARRAYREF with values to search in field name. It should be expanded with OR
147             concatenation. As an example,
148              
149             fld[x]=1&fld[x]=2
150              
151             after parsing produce
152              
153             name => 'x', values => [1,2]
154              
155             and in SQL syntax must be written like
156              
157             x=1 or x=2
158              
159             =head2 tag()
160              
161             In field name it can be use ":" to separe field name by a tag. The idea is to
162             distinguish different operation with same field name.
163              
164             As an example
165              
166             fld[a:1]=1&fld[a:1]=$op:>&fld[a:2]=5&fld[a:2]=$op:<
167              
168             must be
169              
170             a>1 and a<5
171              
172             =head2 andGroup()
173              
174             If you set a field with $and:$groupvalue you set that this field in a AND group
175             with other fields with same $groupvalue
176              
177             As an example to
178              
179             flt[d:1]=9&flt[d:1]=$and:1&flt[c:1]=2&flt[c:1]=$and:1&flt[d:2]=3&flt[d:2]=$and:2&flt[c:2]=1&flt[c:2]=$and:2
180              
181             is traslated in
182              
183             ( d=9 AND c=2 ) OR ( d=3 and c=1 )
184              
185             =head2 orGroup()
186              
187             Like L</"andGroup()"> but for OR operator
188              
189             =head2 parse($perl_struct)
190              
191             $perl_struct is an HASHREF which represents a query string like
192             the one returned by L<URI::Encode/"url_params_mixed">.
193             It parses the struct and extract filter informations
194              
195             =head2 to_qs()
196              
197             Return a query string of the internal rappresentation of the object
198              
199             =head2 to_sql
200              
201             Return this object as a SQL search
202              
203             =head1 AUTHOR
204              
205             Emiliano Bruni <info@ebruni.it>
206              
207             =head1 COPYRIGHT AND LICENSE
208              
209             This software is copyright (c) 2019 by Emiliano Bruni.
210              
211             This is free software; you can redistribute it and/or modify it under
212             the same terms as the Perl 5 programming language system itself.
213              
214             =cut