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 54     54   20292 use strict;
  54         80  
  54         1455  
4 54     54   170 use warnings;
  54         1682  
  54         1784  
5              
6 54     54   201 use URI ();
  54         60  
  54         897  
7 54     54   195 use URI::Escape qw(uri_unescape);
  54         77  
  54         3426  
8 54     54   290 use Scalar::Util ();
  54         10534  
  54         83788  
9              
10             our $VERSION = '5.35';
11              
12             sub query
13             {
14 780     780 0 1295 my $self = shift;
15 780 50       3374 $$self =~ m,^([^?\#]*)(?:\?([^\#]*))?(.*)$,s or die;
16              
17 780 100       1316 if (@_) {
18 110         128 my $q = shift;
19 110         212 $$self = $1;
20 110 100       196 if (defined $q) {
21 89         709 $q =~ s/([^$URI::uric])/ URI::Escape::escape_char($1)/ego;
  20         37  
22 89         227 utf8::downgrade($q);
23 89         155 $$self .= "?$q";
24             }
25 110         238 $$self .= $3;
26             }
27 780         1769 $2;
28             }
29              
30             # Handle ...?foo=bar&bar=foo type of query
31             sub query_form {
32 517     517 0 7201 my $self = shift;
33 517         774 my $old = $self->query;
34 517 100       867 if (@_) {
35             # Try to set query string
36 55         63 my $delim;
37 55         72 my $r = $_[0];
38 55 100       129 if (_is_array($r)) {
    100          
39 24         160 $delim = $_[1];
40 24         60 @_ = @$r;
41             }
42             elsif (ref($r) eq "HASH") {
43 4         7 $delim = $_[1];
44 4         18 @_ = map { $_ => $r->{$_} } sort keys %$r;
  8         16  
45             }
46 55 100       179 $delim = pop if @_ % 2;
47              
48 55         58 my @query;
49 55         172 while (my($key,$vals) = splice(@_, 0, 2)) {
50 106 50       167 $key = '' unless defined $key;
51 106         183 $key =~ s/([;\/?:@&=+,\$\[\]%])/ URI::Escape::escape_char($1)/eg;
  7         15  
52 106         123 $key =~ s/ /+/g;
53 106 100       143 $vals = [_is_array($vals) ? @$vals : $vals];
54 106         266 for my $val (@$vals) {
55 118 100       162 if (defined $val) {
56 115         185 $val =~ s/([;\/?:@&=+,\$\[\]%])/ URI::Escape::escape_char($1)/eg;
  19         30  
57 115         141 $val =~ s/ /+/g;
58 115         371 push(@query, "$key=$val");
59             }
60             else {
61 3         15 push(@query, $key);
62             }
63             }
64             }
65 55 100       80 if (@query) {
66 44 100       86 unless ($delim) {
67 39 100 100     161 $delim = $1 if $old && $old =~ /([&;])/;
68 39   100     139 $delim ||= $URI::DEFAULT_QUERY_FORM_DELIMITER || "&";
      66        
69             }
70 44         126 $self->query(join($delim, @query));
71             }
72             else {
73 11         20 $self->query(undef);
74             }
75             }
76 517 100 100     1887 return if !defined($old) || !length($old) || !defined(wantarray);
      100        
77 457 100       943 return unless $old =~ /=/; # not a form
78 2260 100       2687 map { ( defined ) ? do { s/\+/ /g; uri_unescape($_) } : undef }
  2207         2361  
  2207         2911  
79 456 100       1382 map { /=/ ? split(/=/, $_, 2) : ($_ => undef)} split(/[&;]/, $old);
  1130         2565  
80             }
81              
82             # Handle ...?dog+bones type of query
83             sub query_keywords
84             {
85 16     16 0 3563 my $self = shift;
86 16         41 my $old = $self->query;
87 16 100       41 if (@_) {
88             # Try to set query string
89 12         39 my @copy = @_;
90 12 100 100     59 @copy = @{$copy[0]} if @copy == 1 && _is_array($copy[0]);
  4         74  
91 12         98 for (@copy) { s/([;\/?:@&=+,\$\[\]%])/ URI::Escape::escape_char($1)/eg; }
  21         100  
  6         19  
92 12 100       59 $self->query(@copy ? join('+', @copy) : undef);
93             }
94 16 100 100     90 return if !defined($old) || !defined(wantarray);
95 4 100       22 return if $old =~ /=/; # not keywords, but a form
96 2         9 map { uri_unescape($_) } split(/\+/, $old, -1);
  8         18  
97             }
98              
99             # Some URI::URL compatibility stuff
100 22     22 0 87 sub equery { goto &query }
101              
102             sub query_param {
103 422     422 0 507 my $self = shift;
104 422         645 my @old = $self->query_form;
105              
106 422 100       884 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         504 my $key = shift;
113 421   100     2463 my @i = grep $_ % 2 == 0 && $old[$_] eq $key, 0 .. $#old;
114              
115 421 100       744 if (@_) {
116 11         20 my @new = @old;
117 11         10 my @new_i = @i;
118 11 100       13 my @vals = map { _is_array($_) ? @$_ : $_ } @_;
  19         22  
119              
120 11         75 while (@new_i > @vals) {
121 11         19 splice @new, pop @new_i, 2;
122             }
123 11 100       17 if (@vals > @new_i) {
124 5 100       8 my $i = @new_i ? $new_i[-1] + 2 : @new;
125 5         9 my @splice = splice @vals, @new_i, @vals - @new_i;
126              
127 5         6 splice @new, $i, 0, map { $key => $_ } @splice;
  10         18  
128             }
129 11 100       18 if (@vals) {
130             #print "SET $new_i[0]\n";
131 2         6 @new[ map $_ + 1, @new_i ] = @vals;
132             }
133              
134 11         14 $self->query_form(\@new);
135             }
136              
137 421 100       1517 return wantarray ? @old[map $_+1, @i] : @i ? $old[$i[0]+1] : undef;
    100          
138             }
139              
140             sub query_param_append {
141 2     2 0 2 my $self = shift;
142 2         4 my $key = shift;
143 2 50       3 my @vals = map { _is_array($_) ? @$_ : $_ } @_;
  4         6  
144 2         6 $self->query_form($self->query_form, $key => \@vals); # XXX
145 2         5 return;
146             }
147              
148             sub query_param_delete {
149 3     3 0 4 my $self = shift;
150 3         4 my $key = shift;
151 3         5 my @old = $self->query_form;
152 3         5 my @vals;
153              
154 3         8 for (my $i = @old - 2; $i >= 0; $i -= 2) {
155 8 100       14 next if $old[$i] ne $key;
156 5         10 push(@vals, (splice(@old, $i, 2))[1]);
157             }
158 3 50       9 $self->query_form(\@old) if @vals;
159 3 50       9 return wantarray ? reverse @vals : $vals[-1];
160             }
161              
162             sub query_form_hash {
163 2     2 0 8 my $self = shift;
164 2         6 my @old = $self->query_form;
165 2 100       12 if (@_) {
166 1 50       3 $self->query_form(@_ == 1 ? %{shift(@_)} : @_);
  1         4  
167             }
168 2         4 my %hash;
169 2         6 while (my($k, $v) = splice(@old, 0, 2)) {
170 6 100       9 if (exists $hash{$k}) {
171 2         5 for ($hash{$k}) {
172 2 50       3 $_ = [$_] unless _is_array($_);
173 2         7 push(@$_, $v);
174             }
175             }
176             else {
177 4         11 $hash{$k} = $v;
178             }
179             }
180 2         11 return \%hash;
181             }
182              
183             sub _is_array {
184             return(
185 193   100 193   976 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;