File Coverage

lib/URI/Template/Restrict.pm
Criterion Covered Total %
statement 70 70 100.0
branch 14 18 77.7
condition 3 6 50.0
subroutine 16 16 100.0
pod 6 6 100.0
total 109 116 93.9


line stmt bran cond sub pod time code
1             package URI::Template::Restrict;
2              
3 5     5   3092 use 5.008_001;
  5         26  
  5         169  
4 5     5   45 use strict;
  5         9  
  5         147  
5 5     5   27 use warnings;
  5         8  
  5         121  
6 5     5   23 use base 'Class::Accessor::Fast';
  5         14  
  5         140  
7 5     5   34 use overload '""' => \&template, fallback => 1;
  5         10  
  5         54  
8 5     5   4989 use List::MoreUtils qw(uniq);
  5         5766  
  5         497  
9 5     5   4696 use Unicode::Normalize qw(NFKC);
  5         12043  
  5         450  
10 5     5   4701 use URI;
  5         21297  
  5         161  
11 5     5   65 use URI::Escape qw(uri_escape_utf8);
  5         14  
  5         300  
12 5     5   2412 use URI::Template::Restrict::Expansion;
  5         12  
  5         46  
13              
14             our $VERSION = '0.06';
15              
16             __PACKAGE__->mk_accessors(qw'template segments');
17              
18             sub new {
19 79     79 1 155 my ($class, $template) = @_;
20              
21 203 100       1130 my @segments =
22             map {
23 206 50       742 /^\{(.+?)\}$/
24             ? URI::Template::Restrict::Expansion->new($1)
25             : $_
26             }
27 79         597 grep { defined && length }
28             split /(\{.+?\})/, $template;
29              
30 79         382 my $self = { template => $template, segments => [@segments] };
31 79         295 return bless $self, $class;
32             }
33              
34             sub expansions {
35 47     47 1 67 return grep { ref $_ } @{ $_[0]->segments };
  122         494  
  47         144  
36             }
37              
38             sub variables {
39             return
40 9         46 uniq
41             sort
42 9 50       35 map { $_->name }
43 9         43 map { ref $_ eq 'ARRAY' ? @$_ : $_ }
44 3     3 1 23 map { $_->vars }
45             $_[0]->expansions;
46             }
47              
48             # ----------------------------------------------------------------------
49             # Draft 03 - 4.4. URI Template Substitution
50             # ----------------------------------------------------------------------
51             # * MUST convert every variable value into a sequence of characters in
52             # ( unreserved / pct-encoded ).
53             # * Normalizes the string using NFKC, converts it to UTF-8, and then
54             # every octet of the UTF-8 string that falls outside of ( unreserved )
55             # MUST be percent-encoded.
56             # ----------------------------------------------------------------------
57             sub process {
58 32     32 1 87 my $self = shift;
59 32         95 return URI->new($self->process_to_string(@_));
60             }
61              
62             sub process_to_string {
63 54     54 1 150 my $self = shift;
64 54 100       149 my $args = ref $_[0] ? shift : { @_ };
65 54         118 my $vars = {};
66              
67 54         193 for my $key (keys %$args) {
68 152         1851 my $value = $args->{$key};
69 152 50 66     502 next if ref $value and ref $value ne 'ARRAY';
70 102         1231 $vars->{$key} = ref $value
71 152 100       1004 ? [ map { uri_escape_utf8(NFKC($_)) } @$value ]
72             : uri_escape_utf8(NFKC($value));
73             }
74              
75 54 100       645 return join '', map { ref $_ ? $_->process($vars) : $_ } @{ $self->segments };
  137         992  
  54         221  
76             }
77              
78             sub extract {
79 44     44 1 78 my ($self, $uri) = @_;
80              
81 44 100       59 my $re = join '', map { ref $_ ? '('.$_->pattern.')' : quotemeta $_ } @{ $self->segments };
  104         686  
  44         164  
82 44         1333 my @match = $uri =~ /$re/;
83              
84 44         125 my @expansions = $self->expansions;
85 44 50 33     218 return unless @match and @match == @expansions;
86              
87 44         62 my @vars;
88 44         101 while (@match > 0) {
89 52         148 my $match = shift @match;
90 52         69 my $expansion = shift @expansions;
91 52         167 push @vars, $expansion->extract($match);
92             }
93              
94 44         345 return %{{ @vars }};
  44         319  
95             }
96              
97             1;
98              
99             =head1 NAME
100              
101             URI::Template::Restrict - restricted URI Templates handler
102              
103             =head1 SYNOPSIS
104              
105             use URI::Template::Restrict;
106              
107             my $template = URI::Template::Restrict->new(
108             'http://example.com/{foo}'
109             );
110              
111             my $uri = $template->process(foo => 'y');
112             # $uri: "http://example.com/y"
113              
114             my %result = $template->extract($uri);
115             # %result: (foo => 'y')
116              
117             =head1 DESCRIPTION
118              
119             This is a restricted URI Templates handler. URI Templates is described at
120             L.
121              
122             This module supports B except B<-opt> and
123             B<-neg> operators.
124              
125             =head1 METHODS
126              
127             =head2 new($template)
128              
129             Creates a new instance with the template.
130              
131             =head2 process(%vars)
132              
133             Given a hash of key-value pairs. It will URI escape the values,
134             substitute them in to the template, and return a L object.
135              
136             =head2 process_to_string(%vars)
137              
138             Processes input like the process method, but doesn't inflate the
139             result to a L object.
140              
141             =head2 extract($uri)
142              
143             Extracts variables from an uri based on the current template.
144             Returns a hash with the extracted values.
145              
146             =head1 PROPERTIES
147              
148             =head2 template
149              
150             Returns the original template string.
151              
152             =head2 variables
153              
154             Returns a list of unique variable names found in the template.
155              
156             =head2 expansions
157              
158             Returns a list of L objects found
159             in the template.
160              
161             =head1 AUTHOR
162              
163             NAKAGAWA Masaki Emasaki@cpan.orgE
164              
165             =head1 LICENSE
166              
167             This library is free software; you can redistribute it and/or modify
168             it under the same terms as Perl itself.
169              
170             =head1 SEE ALSO
171              
172             L, L
173              
174             =cut