File Coverage

blib/lib/URI/Nested.pm
Criterion Covered Total %
statement 62 77 80.5
branch 26 34 76.4
condition 5 9 55.5
subroutine 18 30 60.0
pod 7 22 31.8
total 118 172 68.6


line stmt bran cond sub pod time code
1             package URI::Nested;
2              
3 2     2   178750 use strict;
  2         5  
  2         64  
4 2     2   30 use 5.8.1;
  2         6  
  2         160  
5             our $VERSION = '0.10';
6 2     2   12 use overload '""' => 'as_string', fallback => 1;
  2         10  
  2         21  
7              
8             sub prefix {
9 7   33 7 1 60 my $class = ref $_[0] || shift;
10 7         39 return (split /::/ => $class)[-1];
11             }
12              
13 6     6 1 22 sub nested_class { undef }
14              
15             sub new {
16 9     9 1 6198 my ($class, $str, $base) = @_;
17 9         27 my $prefix = $class->prefix;
18 9         27 my $scheme;
19 9 100       26 if ($base) {
20             # Remove prefix and grab the scheme to use for the nested URI.
21 7         56 $base =~ s/^\Q$prefix://;
22 7         82 ($scheme) = $base =~ /^($URI::scheme_re):/;
23             }
24 9         42 my $uri = URI->new($str, $base);
25 9 50       3681 return $uri if $uri->isa(__PACKAGE__);
26              
27             # Convert to a nested URI and assign the scheme, if needed.
28 9 100 66     34 $uri->scheme($scheme) if $scheme && !$uri->scheme;
29 9 50       1721 if ( my $nested_class = $class->nested_class ) {
30 9 50       89 bless $uri => $nested_class unless $uri->isa($nested_class);
31             }
32              
33 9         64 bless [ $prefix => $uri ] => $class;
34             }
35              
36             sub new_abs {
37 8     8 0 19889 my ($class, $uri, $base) = @_;
38 8         34 $uri = URI->new($uri);
39             # No change if already have a scheme.
40 8 100       1120 return $uri if $uri->scheme;
41 5         157 $base = URI->new($base);
42             # Return non-nested absolute.
43 5 100       7146 return $uri->abs($base) unless $base->isa(__PACKAGE__);
44             # Return nested absolute.
45 2 100       10 $uri = $uri->abs( $base->[1] ) if $base->[1];
46 2         718 $base->[1] = $uri;
47 2         15 return $base;
48             }
49              
50             sub _init {
51 17     17   15703 my ($class, $str, $scheme) = @_;
52 17         73 my $prefix = quotemeta $class->prefix;
53              
54 17 50       193 if ($str =~ s/^($prefix)://i) {
55 17         42 $scheme = $1;
56             }
57 17         75 return $class->_nested_init($scheme, $str);
58             }
59              
60             sub _nested_init {
61 17     17   37 my ($class, $scheme, $str) = @_;
62 17         68 my $uri = URI->new($str);
63 17 100       14415 if ( my $nested_class = $class->nested_class ) {
64 11 50       147 bless $uri => $nested_class unless $uri->isa($nested_class);
65             }
66 17         130 bless [ $scheme, $uri ] => $class;
67             }
68              
69 13     13 1 824 sub nested_uri { shift->[1] }
70              
71             sub scheme {
72 9     9 1 406 my $self = shift;
73 9 100       211 return lc $self->[0] unless @_;
74 2         4 my $new = shift;
75 2         6 my $old = $self->[0];
76             # Cannot change $self from array ref to scalar ref, so reject other schemes.
77 2 100       9 Carp::croak('Cannot change ', ref $self, ' scheme' )
78             if lc $new ne $self->prefix;
79 1         7 $self->[0] = $new;
80 1         7 return $old;
81             }
82              
83             sub as_string {
84 33     33 0 4036 return join ':', @{ +shift };
  33         389  
85             }
86              
87             sub clone {
88 3     3 0 13533 my $self = shift;
89 3         30 bless [$self->[0], $self->[1]->clone], ref $self;
90             }
91              
92 1     1 1 7 sub abs { shift }
93 1     1 1 1149 sub rel { shift }
94              
95             sub eq {
96 8     8 0 1858 my ($self, $other) = @_;
97 8 100       49 $other = URI->new($other) unless ref $other;
98 8   66     760 return ref $self eq ref $other && $self->[1]->eq($other->[1]);
99             }
100              
101 2     2   235 sub _init_implementor {}
102              
103             # Hard-code common accessors and methods.
104 0     0 0 0 sub opaque { shift->[1]->opaque(@_) }
105 0     0 0 0 sub path { shift->[1]->path(@_) }
106 0     0 0 0 sub fragment { shift->[1]->fragment(@_) }
107 0     0 0 0 sub host { shift->[1]->host(@_) }
108 0     0 0 0 sub port { shift->[1]->port(@_) }
109 0     0   0 sub _port { shift->[1]->_port(@_) }
110 0     0 0 0 sub authority { shift->[1]->authority(@_) }
111 0     0 0 0 sub path_query { shift->[1]->path_query(@_) }
112 0     0 0 0 sub path_segments { shift->[1]->path_segments(@_) }
113 0     0 0 0 sub query { shift->[1]->query(@_) }
114 0     0 0 0 sub userinfo { shift->[1]->userinfo(@_) }
115              
116             # Catch any missing methods.
117             our $AUTOLOAD;
118             sub AUTOLOAD {
119 0     0   0 my $self = shift;
120 0         0 my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::')+2);
121 0 0       0 return if $method eq 'DESTROY';
122 0         0 $self->[1]->$method(@_);
123             }
124              
125             sub can { # override UNIVERSAL::can
126 2     2 0 1119 my $self = shift;
127 2 50       77 $self->SUPER::can(@_) || (
    100          
128             ref($self) ? $self->[1]->can(@_) : undef
129             );
130             }
131              
132             1;
133             __END__