File Coverage

blib/lib/URI/_query.pm
Criterion Covered Total %
statement 133 133 100.0
branch 69 76 90.7
condition 28 29 96.5
subroutine 14 14 100.0
pod 0 8 0.0
total 244 260 93.8


line stmt bran cond sub pod time code
1             package URI::_query;
2              
3 53     53   28398 use strict;
  53         126  
  53         2069  
4 53     53   267 use warnings;
  53         2264  
  53         2590  
5              
6 53     53   273 use URI ();
  53         89  
  53         1250  
7 53     53   289 use URI::Escape qw(uri_unescape);
  53         106  
  53         4582  
8 53     53   425 use Scalar::Util ();
  53         102  
  53         116058  
9              
10             our $VERSION = '5.34';
11              
12             sub query
13             {
14 765     765 0 3116 my $self = shift;
15 765 50       4462 $$self =~ m,^([^?\#]*)(?:\?([^\#]*))?(.*)$,s or die;
16              
17 765 100       1612 if (@_) {
18 110         175 my $q = shift;
19 110         277 $$self = $1;
20 110 100       303 if (defined $q) {
21 89         974 $q =~ s/([^$URI::uric])/ URI::Escape::escape_char($1)/ego;
  20         60  
22 89         291 utf8::downgrade($q);
23 89         214 $$self .= "?$q";
24             }
25 110         334 $$self .= $3;
26             }
27 765         2265 $2;
28             }
29              
30             # Handle ...?foo=bar&bar=foo type of query
31             sub query_form {
32 517     517 0 16458 my $self = shift;
33 517         1059 my $old = $self->query;
34 517 100       3872 if (@_) {
35             # Try to set query string
36 55         121 my $delim;
37 55         135 my $r = $_[0];
38 55 100       138 if (_is_array($r)) {
    100          
39 24         303 $delim = $_[1];
40 24         69 @_ = @$r;
41             }
42             elsif (ref($r) eq "HASH") {
43 4         11 $delim = $_[1];
44 4         30 @_ = map { $_ => $r->{$_} } sort keys %$r;
  8         27  
45             }
46 55 100       258 $delim = pop if @_ % 2;
47              
48 55         104 my @query;
49 55         279 while (my($key,$vals) = splice(@_, 0, 2)) {
50 106 50       202 $key = '' unless defined $key;
51 106         205 $key =~ s/([;\/?:@&=+,\$\[\]%])/ URI::Escape::escape_char($1)/eg;
  7         27  
52 106         181 $key =~ s/ /+/g;
53 106 100       190 $vals = [_is_array($vals) ? @$vals : $vals];
54 106         412 for my $val (@$vals) {
55 118 100       209 if (defined $val) {
56 115         278 $val =~ s/([;\/?:@&=+,\$\[\]%])/ URI::Escape::escape_char($1)/eg;
  19         50  
57 115         217 $val =~ s/ /+/g;
58 115         519 push(@query, "$key=$val");
59             }
60             else {
61 3         19 push(@query, $key);
62             }
63             }
64             }
65 55 100       128 if (@query) {
66 44 100       645 unless ($delim) {
67 39 100 100     288 $delim = $1 if $old && $old =~ /([&;])/;
68 39   100     191 $delim ||= $URI::DEFAULT_QUERY_FORM_DELIMITER || "&";
      66        
69             }
70 44         254 $self->query(join($delim, @query));
71             }
72             else {
73 11         34 $self->query(undef);
74             }
75             }
76 517 100 100     2647 return if !defined($old) || !length($old) || !defined(wantarray);
      100        
77 457 100       1242 return unless $old =~ /=/; # not a form
78 2260 100       3778 map { ( defined ) ? do { s/\+/ /g; uri_unescape($_) } : undef }
  2207         3486  
  2207         4194  
79 456 100       1843 map { /=/ ? split(/=/, $_, 2) : ($_ => undef)} split(/[&;]/, $old);
  1130         3716  
80             }
81              
82             # Handle ...?dog+bones type of query
83             sub query_keywords
84             {
85 16     16 0 7274 my $self = shift;
86 16         49 my $old = $self->query;
87 16 100       47 if (@_) {
88             # Try to set query string
89 12         34 my @copy = @_;
90 12 100 100     64 @copy = @{$copy[0]} if @copy == 1 && _is_array($copy[0]);
  4         829  
91 12         108 for (@copy) { s/([;\/?:@&=+,\$\[\]%])/ URI::Escape::escape_char($1)/eg; }
  21         104  
  6         30  
92 12 100       72 $self->query(@copy ? join('+', @copy) : undef);
93             }
94 16 100 100     128 return if !defined($old) || !defined(wantarray);
95 4 100       27 return if $old =~ /=/; # not keywords, but a form
96 2         12 map { uri_unescape($_) } split(/\+/, $old, -1);
  8         25  
97             }
98              
99             # Some URI::URL compatibility stuff
100 22     22 0 77 sub equery { goto &query }
101              
102             sub query_param {
103 422     422 0 685 my $self = shift;
104 422         820 my @old = $self->query_form;
105              
106 422 100       1269 if (@_ == 0) {
107             # get keys
108 1         2 my (%seen, $i);
109 1   100     20 return grep !($i++ % 2 || $seen{$_}++), @old;
110             }
111              
112 421         669 my $key = shift;
113 421   100     3655 my @i = grep $_ % 2 == 0 && $old[$_] eq $key, 0 .. $#old;
114              
115 421 100       956 if (@_) {
116 11         22 my @new = @old;
117 11         13 my @new_i = @i;
118 11 100       23 my @vals = map { _is_array($_) ? @$_ : $_ } @_;
  19         22  
119              
120 11         82 while (@new_i > @vals) {
121 11         19 splice @new, pop @new_i, 2;
122             }
123 11 100       16 if (@vals > @new_i) {
124 5 100       10 my $i = @new_i ? $new_i[-1] + 2 : @new;
125 5         9 my @splice = splice @vals, @new_i, @vals - @new_i;
126              
127 5         7 splice @new, $i, 0, map { $key => $_ } @splice;
  10         17  
128             }
129 11 100       17 if (@vals) {
130             #print "SET $new_i[0]\n";
131 2         6 @new[ map $_ + 1, @new_i ] = @vals;
132             }
133              
134 11         18 $self->query_form(\@new);
135             }
136              
137 421 100       2189 return wantarray ? @old[map $_+1, @i] : @i ? $old[$i[0]+1] : undef;
    100          
138             }
139              
140             sub query_param_append {
141 2     2 0 3 my $self = shift;
142 2         2 my $key = shift;
143 2 50       4 my @vals = map { _is_array($_) ? @$_ : $_ } @_;
  4         7  
144 2         5 $self->query_form($self->query_form, $key => \@vals); # XXX
145 2         6 return;
146             }
147              
148             sub query_param_delete {
149 3     3 0 5 my $self = shift;
150 3         4 my $key = shift;
151 3         6 my @old = $self->query_form;
152 3         6 my @vals;
153              
154 3         10 for (my $i = @old - 2; $i >= 0; $i -= 2) {
155 8 100       13 next if $old[$i] ne $key;
156 5         15 push(@vals, (splice(@old, $i, 2))[1]);
157             }
158 3 50       8 $self->query_form(\@old) if @vals;
159 3 50       14 return wantarray ? reverse @vals : $vals[-1];
160             }
161              
162             sub query_form_hash {
163 2     2 0 16 my $self = shift;
164 2         11 my @old = $self->query_form;
165 2 100       8 if (@_) {
166 1 50       5 $self->query_form(@_ == 1 ? %{shift(@_)} : @_);
  1         6  
167             }
168 2         4 my %hash;
169 2         8 while (my($k, $v) = splice(@old, 0, 2)) {
170 6 100       12 if (exists $hash{$k}) {
171 2         5 for ($hash{$k}) {
172 2 50       5 $_ = [$_] unless _is_array($_);
173 2         10 push(@$_, $v);
174             }
175             }
176             else {
177 4         15 $hash{$k} = $v;
178             }
179             }
180 2         15 return \%hash;
181             }
182              
183             sub _is_array {
184             return(
185 193   100 193   1297 defined($_[0]) &&
186             ( Scalar::Util::reftype($_[0]) || '' ) eq "ARRAY" &&
187             !(
188             Scalar::Util::blessed( $_[0] ) &&
189             overload::Method( $_[0], '""' )
190             )
191             );
192             }
193              
194             1;