File Coverage

blib/lib/Parqus.pm
Criterion Covered Total %
statement 44 45 97.7
branch 14 16 87.5
condition n/a
subroutine 9 9 100.0
pod 0 1 0.0
total 67 71 94.3


line stmt bran cond sub pod time code
1             package Parqus;
2             $Parqus::VERSION = '0.05';
3 1     1   64234 use Moo;
  1         9662  
  1         5  
4 1     1   1699 use namespace::autoclean;
  1         11404  
  1         3  
5 1     1   1160 use Regexp::Grammars;
  1         21951  
  1         9  
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             die"$_[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             die "$_[0] is not a Regexp!"
52             unless ref $_[0] eq 'Regexp';
53             },
54             );
55              
56             sub _build_parser {
57 4     4   44 my ($self) = @_;
58              
59 4         6 my %keywords = %{ $self->keywords };
  4         58  
60 4         92 my $value_regex = $self->value_regex;
61 4         31 my @string_delimiters = @{ $self->string_delimiters };
  4         54  
62 1     1   6 return eval q{
  1     1   2  
  1     1   41  
  1     1   10  
  1         1  
  1         39  
  1         10  
  1         2  
  1         45  
  1         8  
  1         2  
  1         56  
  4         308  
63             use re 'eval'; # for perl <= 5.16.3
64             qr/
65            
66             ^
67             <.ws>
68             <[query]>*
69             <.ws>
70             $
71            
72             |
73            
74             |
75            
76             :<.ws>?
77            
78             <%keywords>
79            
80             [@string_delimiters]
81            
82             |
83             /xms};
84             }
85              
86             sub process {
87 17     17 0 14439 my ( $self, $query ) = @_;
88              
89 17         31 my %keywords = ();
90 17         25 my @words = ();
91 17         29 my @errors = ();
92 17 100       338 if ( $query =~ $self->parser ) {
93 14         24 for my $item ( @{ $/{query} } ) {
  14         38  
94 19 100       47 if ( exists $item->{item}{keyvalue} ) {
    50          
95 7         14 my $key = $item->{item}{keyvalue}{key};
96             my $value =
97             exists $item->{item}{keyvalue}{value}
98             ? $item->{item}{keyvalue}{value}
99 7 50       18 : '';
100 7         11 push( @{ $keywords{$key} }, $value );
  7         19  
101             }
102             elsif ( exists $item->{item}{value} ) {
103 12         32 push( @words, $item->{item}{value} );
104             }
105             else {
106 0         0 push( @errors, "Parse Error: neither word nor keyvalue" );
107             }
108             }
109             }
110             else {
111 3         92 push( @errors, "Parse Error: Invalid search query." );
112             }
113              
114 17 100       50 push( @errors, @! )
115             if @!;
116              
117             return {
118 17 100       115 ( scalar @words ? (words => \@words) : () ),
    100          
    100          
119             ( scalar keys %keywords ? (keywords => \%keywords) : () ),
120             ( scalar @errors ? (errors => \@errors) : () ),
121             };
122             }
123              
124             1;
125              
126             __END__