File Coverage

blib/lib/ElasticSearch/Util.pm
Criterion Covered Total %
statement 33 56 58.9
branch 3 12 25.0
condition 2 5 40.0
subroutine 7 9 77.7
pod 1 4 25.0
total 46 86 53.4


line stmt bran cond sub pod time code
1             package ElasticSearch::Util;
2             $ElasticSearch::Util::VERSION = '0.68';
3 2     2   12 use strict;
  2         3  
  2         68  
4 2     2   11 use warnings FATAL => 'all';
  2         4  
  2         67  
5 2     2   1917 use ElasticSearch::Error();
  2         6  
  2         2525  
6              
7             require Exporter;
8             our @ISA = qw(Exporter);
9             our @EXPORT_OK = qw(filter_keywords parse_params throw build_error);
10              
11             #===================================
12             sub filter_keywords {
13             #===================================
14 0     0 1 0 local $_ = shift;
15              
16 0         0 s{[^[:alpha:][:digit:] \-+'"*@\._]+}{ }g;
17              
18 0 0       0 return '' unless /[[:alpha:][:digit:]]/;
19              
20 0         0 s/\s*\b(?:and|or|not)\b\s*/ /gi;
21              
22             # remove '-' that don't have spaces before them
23 0         0 s/(?
24              
25             # remove the spaces after a + or -
26 0         0 s/([+-])\s+/$1/g;
27              
28             # remove + or - not followed by a letter, number or "
29 0         0 s/[+-](?![[:alpha:][:digit:]"])/ /g;
30              
31             # remove * without 3 char prefix
32 0         0 s/(?
33              
34 0         0 my $quotes = (tr/"//);
35 0 0       0 if ( $quotes % 2 ) { $_ .= '"' }
  0         0  
36              
37 0         0 s/^\s+//;
38 0         0 s/\s+$//;
39              
40 0         0 return $_;
41             }
42              
43             #===================================
44             sub parse_params {
45             #===================================
46 196     196 0 274 my $self = shift;
47 196         219 my %params;
48 196 50       483 if ( @_ % 2 ) {
49 0 0       0 $self->throw(
50             "Param",
51             'Expecting a HASH ref or a list of key-value pairs',
52             { params => \@_ }
53             ) unless ref $_[0] eq 'HASH';
54 0         0 %params = %{ shift() };
  0         0  
55             }
56             else {
57 196         530 %params = @_;
58             }
59 196         703 return ( $self, \%params );
60             }
61              
62             #===================================
63             sub throw {
64             #===================================
65 58     58 0 145 my ( $self, $type, $msg, $vars ) = @_;
66 58         132 die build_error( $self, $type, $msg, $vars, 1 );
67             }
68              
69             #===================================
70             sub build_error {
71             #===================================
72 58     58 0 72 my $self = shift;
73 58         72 my $type = shift;
74 58         70 my $msg = shift;
75 58         71 my $vars = shift;
76 58   50     139 my $caller = shift || 0;
77              
78 58   33     140 my $class = ref $self || $self;
79 58         92 my $error_class = 'ElasticSearch::Error::' . $type;
80              
81 58 50       121 $msg = 'Unknown error' unless defined $msg;
82 58         265 $msg =~ s/\n/\n /g;
83              
84 58         285 my ( undef, $file, $line ) = caller($caller);
85 58         365 my $error_params = {
86             -text => $msg,
87             -line => $line,
88             -file => $file,
89             -vars => $vars,
90             };
91             {
92 2     2   24 no warnings 'once';
  2         5  
  2         644  
  58         75  
93 58 50       130 $error_params->{-stacktrace} = _stack_trace()
94             if $ElasticSearch::DEBUG;
95             }
96 58         477 return bless $error_params, $error_class;
97              
98             }
99              
100             #===================================
101             sub _stack_trace {
102             #===================================
103 0     0     my $i = 2;
104 0           my $line = ( '-' x 60 ) . "\n";
105 0           my $o = $line
106             . sprintf( "%-4s %-30s %-5s %s\n",
107             ( '#', 'Package', 'Line', 'Sub-routine' ) )
108             . $line;
109 0           while ( my @caller = caller($i) ) {
110 0           $o .= sprintf( "%-4d %-30s %4d %s\n", $i++, @caller[ 0, 2, 3 ] );
111             }
112 0           return $o .= $line;
113             }
114              
115             =head1 NAME
116              
117             ElasticSearch::Util - Util subs for ElasticSearch
118              
119             =head1 DESCRIPTION
120              
121             ElasticSearch::Util provides various subs useful to other modules in
122             ElasticSearch.
123              
124             The only sub useful to users is L, which can be
125             exported.
126              
127             =head1 SYNOPSIS
128              
129             use ElasticSearch::Util qw(filter_keywords);
130              
131             my $filtered = filter_keywords($unfiltered)
132              
133             =head1 SUBROUTINES
134              
135             =head2 filter_keywords()
136              
137             This tidies up a string to be used as a query string in (eg)
138             L so that user input won't cause a search query
139             to return an error.
140              
141             It is not flexible at all, and may or may not be useful to you.
142              
143             Have a look at L which gives you much more control
144             over your query strings.
145              
146             The current implementation does the following:
147              
148             =over
149              
150             =item * Removes any character which isn't a letter, a number, a space or
151             C<-+'"*@._>.
152              
153             =item * Removes C, C and C
154              
155             =item * Removes any C<-> that doesn't have a space in front of it ( "foo -bar")
156             is acceptable as it means C<'foo' but not with 'bar'>
157              
158             =item * Removes any space after a C<+> or C<->
159              
160             =item * Removes any C<+> or C<-> which is not followed by a letter, number
161             or a double quote
162              
163             =item * Removes any C<*> that doesn't have at least 3 letters before it, ie
164             we only allow wildcard searches on words with at least 3 characters
165              
166             =item * Closes any open double quotes
167              
168             =item * Removes leading and trailing whitespace
169              
170             =back
171              
172             YMMV
173              
174             =head1 LICENSE AND COPYRIGHT
175              
176             Copyright 2010 - 2011 Clinton Gormley.
177              
178             This program is free software; you can redistribute it and/or modify it
179             under the terms of either: the GNU General Public License as published
180             by the Free Software Foundation; or the Artistic License.
181              
182             See http://dev.perl.org/licenses/ for more information.
183              
184              
185             =cut
186              
187             1;
188