File Coverage

blib/lib/Eve/Uri.pm
Criterion Covered Total %
statement 110 111 99.1
branch 13 14 92.8
condition n/a
subroutine 27 27 100.0
pod 10 10 100.0
total 160 162 98.7


line stmt bran cond sub pod time code
1             package Eve::Uri;
2              
3 1     1   6392 use parent qw(Eve::Class);
  1         2  
  1         9  
4              
5 1     1   49 use strict;
  1         1  
  1         42  
6 1     1   4 use warnings;
  1         2  
  1         31  
7              
8 1     1   1097 use URI;
  1         4513  
  1         29  
9 1     1   1485 use URI::QueryParam;
  1         736  
  1         33  
10              
11 1     1   8 use Eve::Exception;
  1         2  
  1         687  
12              
13             =head1 NAME
14              
15             B - a URI automation class.
16              
17             =head1 SYNOPSIS
18              
19             use Eve::Uri;
20              
21             my $uri = Eve::Uri->new(
22             string => 'http://domain.com/path/script?foo=bar&baz=1&baz=2');
23              
24             my $string = $uri->string;
25             my $host = $uri->host;
26             my $fragment = $uri->fragment;
27             my $query_string = $uri->query;
28              
29             my $query_parameter = $uri->get_query_parameter(name => 'foo');
30             my @query_parameter_list = $uri->get_query_parameter(name => 'baz');
31              
32             $uri->set_query_parameter(name => 'foo', value => 'some');
33             $uri->set_query_parameter(name => 'baz', value => [3, 4]);
34              
35             $uri->set_query_hash(hash => {'name' => 'foo', 'value' => 'some'});
36             $uri->set_query_hash(
37             hash => {'name' => 'foo', 'value' => 'some'}, delimiter => '&');
38             my $query_hash = $uri->get_query_hash();
39              
40             my $another_uri = $uri->clone();
41              
42             my $matches_hash = $uri->match($another_uri) # empty hash - no placeholders
43              
44             $another_uri->query = 'another=query';
45             $matches_hash = $uri->match($another_uri); # undef
46              
47             $another_uri->path_concat('/some/deeper/path');
48              
49             my $placeholder_uri = Eve::Uri->new(
50             string => 'http://domain.com/:placeholder/:another');
51              
52             my $substituted_uri = $placeholder_uri->substitute(
53             hash => {
54             'placeholder' => 'first_value',
55             'another' => 'another_value'});
56              
57             print $substituted_uri->string;
58             # http://domain.com/first_value/another_value
59              
60             my $uri_is_relative = $uri->is_relative();
61              
62             =head1 DESCRIPTION
63              
64             The class provides automation for different common operations with
65             URIs. A URI is automaticaly brought to the canonical form after
66             creation or after using any setter method.
67              
68             =head3 Attributes
69              
70             =over 4
71              
72             =item C
73              
74             a fragment part of the URI.
75              
76             =item C
77              
78             a query string part of the URI
79              
80             =item C
81              
82             an URI as a string
83              
84             =back
85              
86             =head3 Constructor arguments
87              
88             =over 4
89              
90             =item C
91              
92             a string that can contain placeholders that are preceded with a
93             semicolon character (':').
94              
95             =back
96              
97             =head1 METHODS
98              
99             =head2 B
100              
101             =cut
102              
103             sub init {
104 71     71 1 263 my ($self, %arg_hash) = @_;
105 71         331 Eve::Support::arguments(\%arg_hash, my $string);
106              
107 71         940 $self->{'_uri'} = URI->new($string)->canonical();
108              
109             # Dummy properties for URI parts
110 71         23260 $self->{'string'} = undef;
111 71         133 $self->{'path'} = undef;
112 71         115 $self->{'host'} = undef;
113 71         121 $self->{'query'} = undef;
114 71         232 $self->{'fragment'} = undef;
115             }
116              
117             # Getter for the path property
118             sub _get_path {
119 4     4   8 my $self = shift;
120              
121 4         17 return $self->_uri->path();
122             }
123              
124             # Setter for the path property
125             sub _set_path {
126 2     2   5 my ($self, $string) = @_;
127              
128 2         111 $self->_uri->path($string);
129              
130 2         81 return $self->path;
131             }
132              
133             # Getter for the string property
134             sub _get_string {
135 65     65   80 my $self = shift;
136              
137 65         314 return $self->_uri->as_string();
138             }
139              
140             # Setter for the string property
141             sub _set_string {
142 2     2   4 my ($self, $string) = @_;
143              
144 2         8 $self->_uri = URI->new($string)->canonical();
145              
146 2         28 return $self->string;
147             }
148              
149             # Getter for the host property
150             sub _get_host {
151 4     4   5 my $self = shift;
152              
153 4 50       19 if (not $self->_uri->scheme()) {
154 0         0 return;
155             }
156              
157 4         103 return $self->_uri->host();
158             }
159              
160             # Setter for the host property
161             sub _set_host {
162 2     2   5 my ($self, $string) = @_;
163              
164 2         13 $self->_uri->scheme('http');
165              
166 2         244 $self->_uri->host($string);
167              
168 2         209 return $self->host;
169             }
170              
171             # Getter for the query property
172             sub _get_query {
173 20     20   29 my $self = shift;
174              
175 20         88 return $self->_uri->query();
176             }
177              
178             # Setter for the query property
179             sub _set_query {
180 18     18   29 my ($self, $string) = @_;
181              
182 18         85 $self->_uri->query($string);
183              
184 18         974 return $self->query;
185             }
186              
187             # Getter for the fragment property
188             sub _get_fragment {
189 20     20   244 my $self = shift;
190              
191 20         92 return $self->_uri->fragment();
192             }
193              
194             # Setter for the fragment property
195             sub _set_fragment {
196 18     18   37 my ($self, $string) = @_;
197              
198 18         89 $self->_uri->fragment($string);
199              
200 18         451 return $self->fragment;
201             }
202              
203             =head2 B
204              
205             Clones and returns the object.
206              
207             =head3 Returns
208              
209             The object identical to self.
210              
211             =cut
212              
213             sub clone {
214 17     17 1 31 my ($self) = @_;
215              
216 17         119 return $self->new(string => $self->string);
217             }
218              
219             =head2 B
220              
221             Matches self against other URI.
222              
223             =head3 Arguments
224              
225             =over 4
226              
227             =item C
228              
229             a URI instance to match with.
230              
231             =back
232              
233             =head3 Returns
234              
235             If it matches then a substitutions hash is returned, otherwise -
236             undef. If no placeholders in the URI empty hash is returned. Note that
237             the method ignores query and fragment parts of URI.
238              
239             =cut
240              
241             sub match {
242 8     8 1 69 my ($self, %arg_hash) = @_;
243 8         30 Eve::Support::arguments(\%arg_hash, my $uri);
244              
245 8         99 my $pattern_uri = $self->clone();
246 8         143 my $matching_uri = $uri->clone();
247              
248 8         90 $pattern_uri->query = undef;
249 8         127 $pattern_uri->fragment = undef;
250 8         104 $matching_uri->query = undef;
251 8         105 $matching_uri->fragment = undef;
252              
253 8         103 my $pattern = $pattern_uri->string;
254 8         143 $pattern =~ s/\:([a-zA-Z]\w+)/(?<$1>\\w+)/g;
255              
256 8         13 my $group;
257 8 100       46 if ($matching_uri->string =~ /^$pattern\/?$/) {
258 6         59 $group = {};
259 1 100   1   846 if (%+) {
  1         806  
  1         798  
  6         59  
260 2         35 %$group = %+;
261             }
262             }
263              
264 8         247 return $group;
265             }
266              
267             =head2 B
268              
269             Concatenates the url path with another path.
270              
271             =head3 Arguments
272              
273             =over 4
274              
275             =item C
276              
277             =back
278              
279             =cut
280              
281             sub path_concat {
282 2     2 1 15 my ($self, %arg_hash) = @_;
283 2         8 Eve::Support::arguments(\%arg_hash, my $string);
284              
285 2         90 my $segments = [
286             $self->_uri->path_segments(),
287             $self->_uri->new($string)->path_segments()];
288 2         242 $self->_uri->path_segments(grep($_, @{$segments}));
  2         114  
289              
290 2         167 return $self;
291             }
292              
293             =head2 B
294              
295             Substitutes values to the URI placeholders.
296              
297             =head3 Arguments
298              
299             =over 4
300              
301             =item C
302              
303             a hash of substitutions.
304              
305             =back
306              
307             =head3 Throws
308              
309             =over 4
310              
311             =item C
312              
313             when not enough or redundant substitutions are specified.
314              
315             =back
316              
317             =cut
318              
319             sub substitute {
320 5     5 1 148 my ($self, %arg_hash) = @_;
321 5         15 Eve::Support::arguments(\%arg_hash, my $hash);
322              
323 5         80 my $string = $self->string;
324              
325 5         42 for my $key (keys %{$hash}) {
  5         15  
326 5         8 my $value = $hash->{$key};
327 5 100       104 if ($string =~ s/\:$key/$value/g) {
328             # It is okay
329             } else {
330 1         10 Eve::Error::Value->throw(
331             message => 'Redundant substitutions are specified');
332             }
333             }
334              
335 4 100       19 if ($string =~ /\:([a-zA-Z]\w+)/) {
336 1         18 Eve::Error::Value->throw(
337             message => 'Not enough substitutions are specified');
338             }
339              
340 3         11 return $self->new(string => $string);
341             }
342              
343             =head2 B
344              
345             Returns a query parameter value for a certain parameter name.
346              
347             =head3 Arguments
348              
349             =over 4
350              
351             =item C
352              
353             =back
354              
355             =cut
356              
357             sub get_query_parameter {
358 6     6 1 1140 my ($self, %arg_hash) = @_;
359 6         25 Eve::Support::arguments(\%arg_hash, my $name);
360              
361 6         106 return $self->_uri->query_param($name);
362             }
363              
364             =head2 B
365              
366             Sets a query parameter value or a list of values for a certain
367             parameter name.
368              
369             =head3 Arguments
370              
371             =over 4
372              
373             =item C
374              
375             =item C
376              
377             If a scalar value is passed, it is assigned as a single value for the
378             parameter name. If a list reference is passed, the parameter is
379             assigned as a list.
380              
381             =back
382              
383             =cut
384              
385             sub set_query_parameter {
386 6     6 1 57 my ($self, %arg_hash) = @_;
387 6         31 Eve::Support::arguments(\%arg_hash, my ($name, $value));
388              
389 6         59 my $result;
390 6 100       16 if (not defined $value) {
391 1         8 $result = $self->_uri->query_param_delete($name);
392             } else {
393 5         40 $result = $self->_uri->query_param($name, $value);
394             }
395              
396 6         1334 return $result;
397             }
398              
399             =head2 B
400              
401             Gets query string parameters as a hash.
402              
403             =cut
404              
405             sub get_query_hash {
406 2     2 1 10 my $self = shift;
407              
408 2         16 my %result = $self->_uri->query_form();
409              
410 2         182 return \%result;
411             }
412              
413             =head2 B
414              
415             Sets query string parameters as a hash.
416              
417             =head3 Arguments
418              
419             =over 4
420              
421             =item C
422              
423             =item C
424              
425             =back
426              
427             =cut
428              
429             sub set_query_hash {
430 3     3 1 29 my ($self, %arg_hash) = @_;
431 3         13 Eve::Support::arguments(\%arg_hash, my $hash, my $delimiter = '&');
432              
433 3         49 $self->_uri->query_form($hash, $delimiter);
434              
435 3         705 return $self->_uri->query;
436             }
437              
438             =head2 B
439              
440             Returns 0 or 1 depending on the URI.
441              
442             =head3 Returns
443              
444             =over 4
445              
446             =item C<1>
447              
448             the URI is relative, e.g. C
449              
450             =item C<0>
451              
452             the URI is absolute, e.g. C
453              
454             =back
455              
456             =cut
457              
458             sub is_relative {
459 4     4 1 16 my $self = shift;
460              
461 4 100       28 return ($self->_uri->scheme() ? 0 : 1);
462             }
463              
464             =head1 SEE ALSO
465              
466             =over 4
467              
468             =item C
469              
470             =back
471              
472             =head1 LICENSE AND COPYRIGHT
473              
474             Copyright 2012 Igor Zinovyev.
475              
476             This program is free software; you can redistribute it and/or modify it
477             under the terms of either: the GNU General Public License as published
478             by the Free Software Foundation; or the Artistic License.
479              
480             See http://dev.perl.org/licenses/ for more information.
481              
482              
483             =head1 AUTHOR
484              
485             =over 4
486              
487             =item L
488              
489             =item L
490              
491             =back
492              
493             =cut
494              
495             1;