File Coverage

blib/lib/Parqus.pm
Criterion Covered Total %
statement 32 33 96.9
branch 14 16 87.5
condition n/a
subroutine 5 5 100.0
pod 0 1 0.0
total 51 55 92.7


line stmt bran cond sub pod time code
1             package Parqus;
2             $Parqus::VERSION = '0.04';
3 1     1   77387 use Moo;
  1         11418  
  1         5  
4 1     1   1890 use namespace::autoclean;
  1         13721  
  1         3  
5 1     1   1385 use Regexp::Grammars;
  1         25956  
  1         8  
6              
7             # ABSTRACT: parse a search query string
8              
9              
10             has keywords => (
11             is => 'lazy',
12             isa => sub {
13             die "$_[0] is not a HashRef!"
14             if ref $_[0] ne 'HASH';
15             },
16             coerce => sub {
17             if ( ref $_[0] eq 'ARRAY' ) {
18             my %hash = map { $_ => 1 } @{ $_[0] };
19             return \%hash;
20             }
21             else {
22             return $_[0];
23             }
24             },
25             default => sub { {} }
26             );
27              
28              
29             has value_regex => (
30             is => 'lazy',
31             isa => sub {
32             "$_[0] is not a Regexp!"
33             unless ref $_[0] eq 'Regexp';
34             },
35             default => sub { qr![\w-]+!xms },
36             );
37              
38             has string_delimiters => (
39             is => 'lazy',
40             isa => sub {
41             die "$_[0] is not a ArrayRef!"
42             if ref $_[0] ne 'ARRAY';
43             },
44             default => sub { [qw/'"/] }
45             );
46              
47             has parser => (
48             is => 'lazy',
49             init_arg => undef,
50             isa => sub {
51             "$_[0] is not a Regexp!"
52             unless ref $_[0] eq 'Regexp';
53             },
54             );
55              
56             sub _build_parser {
57 4     4   53 my ($self) = @_;
58              
59 4         8 my %keywords = %{ $self->keywords };
  4         70  
60 4         109 my $value_regex = $self->value_regex;
61 4         47 my @string_delimiters = @{ $self->string_delimiters };
  4         83  
62 4         239 return eval q{qr/
63            
64             ^
65             <.ws>
66             <[query]>*
67             <.ws>
68             $
69            
70             |
71            
72             |
73            
74             :<.ws>?
75            
76             <%keywords>
77            
78             [@string_delimiters]
79            
80             |
81             /xms};
82             }
83              
84             sub process {
85 17     17 0 19827 my ( $self, $query ) = @_;
86              
87 17         35 my %keywords = ();
88 17         32 my @words = ();
89 17         26 my @errors = ();
90 17 100       421 if ( $query =~ $self->parser ) {
91 14         32 for my $item ( @{ $/{query} } ) {
  14         49  
92 19 100       59 if ( exists $item->{item}{keyvalue} ) {
    50          
93 7         16 my $key = $item->{item}{keyvalue}{key};
94             my $value =
95             exists $item->{item}{keyvalue}{value}
96             ? $item->{item}{keyvalue}{value}
97 7 50       20 : '';
98 7         12 push( @{ $keywords{$key} }, $value );
  7         25  
99             }
100             elsif ( exists $item->{item}{value} ) {
101 12         36 push( @words, $item->{item}{value} );
102             }
103             else {
104 0         0 push( @errors, "Parse Error: neither word nor keyvalue" );
105             }
106             }
107             }
108             else {
109 3         170 push( @errors, "Parse Error: Invalid search query." );
110             }
111              
112 17 100       57 push( @errors, @! )
113             if @!;
114              
115             return {
116 17 100       151 ( scalar @words ? (words => \@words) : () ),
    100          
    100          
117             ( scalar keys %keywords ? (keywords => \%keywords) : () ),
118             ( scalar @errors ? (errors => \@errors) : () ),
119             };
120             }
121              
122             1;
123              
124             __END__