| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package URI::FromHash; | 
| 2 |  |  |  |  |  |  | { | 
| 3 |  |  |  |  |  |  | $URI::FromHash::VERSION = '0.04'; | 
| 4 |  |  |  |  |  |  | } | 
| 5 |  |  |  |  |  |  | BEGIN { | 
| 6 | 1 |  |  | 1 |  | 25168 | $URI::FromHash::AUTHORITY = 'cpan:DROLSKY'; | 
| 7 |  |  |  |  |  |  | } | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 1 |  |  | 1 |  | 10 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 33 |  | 
| 10 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 69 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 | 1 |  |  | 1 |  | 1144 | use Params::Validate qw( validate SCALAR ARRAYREF HASHREF ); | 
|  | 1 |  |  |  |  | 14489 |  | 
|  | 1 |  |  |  |  | 107 |  | 
| 13 | 1 |  |  | 1 |  | 266377 | use URI; | 
|  | 1 |  |  |  |  | 10473 |  | 
|  | 1 |  |  |  |  | 38 |  | 
| 14 | 1 |  |  | 1 |  | 1712 | use URI::QueryParam; | 
|  | 1 |  |  |  |  | 1126 |  | 
|  | 1 |  |  |  |  | 296 |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 | 1 |  |  | 1 |  | 8 | use Exporter qw( import ); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 948 |  | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | our @EXPORT_OK = qw( uri uri_object ); | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | my %BaseParams = ( | 
| 21 |  |  |  |  |  |  | scheme   => { type => SCALAR,            optional => 1 }, | 
| 22 |  |  |  |  |  |  | username => { type => SCALAR,            optional => 1 }, | 
| 23 |  |  |  |  |  |  | password => { type => SCALAR,            default  => '' }, | 
| 24 |  |  |  |  |  |  | host     => { type => SCALAR,            optional => 1 }, | 
| 25 |  |  |  |  |  |  | port     => { type => SCALAR,            optional => 1 }, | 
| 26 |  |  |  |  |  |  | path     => { type => SCALAR | ARRAYREF, optional => 1 }, | 
| 27 |  |  |  |  |  |  | query    => { type => HASHREF,           default  => {} }, | 
| 28 |  |  |  |  |  |  | fragment => { type => SCALAR,            optional => 1 }, | 
| 29 |  |  |  |  |  |  | ); | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | sub uri_object { | 
| 32 | 17 |  |  | 17 | 1 | 573 | my %p = validate( @_, \%BaseParams ); | 
| 33 | 17 |  |  |  |  | 259 | _check_required( \%p ); | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 17 |  |  |  |  | 76 | my $uri = URI->new(); | 
| 36 |  |  |  |  |  |  |  | 
| 37 | 17 | 100 |  |  |  | 153 | $uri->scheme( $p{scheme} ) | 
| 38 | 17 | 100 |  |  |  | 9479 | if grep { defined && length } $p{scheme}; | 
| 39 |  |  |  |  |  |  |  | 
| 40 | 17 | 100 |  |  |  | 5877 | if ( grep { defined && length } $p{username}, $p{password} ) { | 
|  | 34 | 100 |  |  |  | 160 |  | 
| 41 | 3 |  | 50 |  |  | 34 | $p{username} ||= ''; | 
| 42 | 3 |  | 100 |  |  | 14 | $p{password} ||= ''; | 
| 43 | 3 | 50 | 33 |  |  | 34 | if ( $uri->can('user') && $uri->can('password') ) { | 
| 44 | 0 |  |  |  |  | 0 | $uri->user( $p{username} ); | 
| 45 | 0 |  |  |  |  | 0 | $uri->password( $p{password} ); | 
| 46 |  |  |  |  |  |  | } | 
| 47 |  |  |  |  |  |  | else { | 
| 48 | 3 |  |  |  |  | 21 | $uri->userinfo("$p{username}:$p{password}"); | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  | } | 
| 51 |  |  |  |  |  |  |  | 
| 52 | 17 |  |  |  |  | 231 | for my $k (qw( host port )) { | 
| 53 | 34 | 100 |  |  |  | 219 | $uri->$k( $p{$k} ) | 
| 54 | 34 | 100 |  |  |  | 906 | if grep { defined && length } $p{$k}; | 
| 55 |  |  |  |  |  |  | } | 
| 56 |  |  |  |  |  |  |  | 
| 57 | 17 | 100 |  |  |  | 96 | if ( $p{path} ) { | 
| 58 | 7 | 100 |  |  |  | 19 | if ( ref $p{path} ) { | 
| 59 | 5 |  |  |  |  | 8 | $uri->path( join '/', grep { defined } @{ $p{path} } ); | 
|  | 22 |  |  |  |  | 54 |  | 
|  | 5 |  |  |  |  | 10 |  | 
| 60 |  |  |  |  |  |  | } | 
| 61 |  |  |  |  |  |  | else { | 
| 62 | 2 |  |  |  |  | 7 | $uri->path( $p{path} ); | 
| 63 |  |  |  |  |  |  | } | 
| 64 |  |  |  |  |  |  | } | 
| 65 |  |  |  |  |  |  |  | 
| 66 | 17 |  |  |  |  | 232 | while ( my ( $k, $v ) = each %{ $p{query} } ) { | 
|  | 23 |  |  |  |  | 899 |  | 
| 67 | 6 |  |  |  |  | 33 | $uri->query_param( $k => $v ); | 
| 68 |  |  |  |  |  |  | } | 
| 69 |  |  |  |  |  |  |  | 
| 70 | 17 | 100 |  |  |  | 128 | $uri->fragment( $p{fragment} ) | 
| 71 | 17 | 100 |  |  |  | 123 | if grep { defined && length } $p{fragment}; | 
| 72 |  |  |  |  |  |  |  | 
| 73 | 17 |  |  |  |  | 118 | return $uri; | 
| 74 |  |  |  |  |  |  | } | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | { | 
| 77 |  |  |  |  |  |  | my $spec = { | 
| 78 |  |  |  |  |  |  | %BaseParams, | 
| 79 |  |  |  |  |  |  | query_separator => { type => SCALAR, default => ';' }, | 
| 80 |  |  |  |  |  |  | }; | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | sub uri { | 
| 83 | 18 |  |  | 18 | 1 | 18407 | my %p = validate( | 
| 84 |  |  |  |  |  |  | @_, | 
| 85 |  |  |  |  |  |  | $spec, | 
| 86 |  |  |  |  |  |  | ); | 
| 87 | 18 |  |  |  |  | 142 | _check_required( \%p ); | 
| 88 |  |  |  |  |  |  |  | 
| 89 | 16 |  |  |  |  | 47 | my $sep = delete $p{query_separator}; | 
| 90 | 16 |  |  |  |  | 53 | my $uri = uri_object(%p); | 
| 91 |  |  |  |  |  |  |  | 
| 92 | 16 | 100 | 66 |  |  | 121 | if ( $sep ne '&' && $uri->query() ) { | 
| 93 | 4 |  |  |  |  | 55 | my $query = $uri->query(); | 
| 94 | 4 |  |  |  |  | 42 | $query =~ s/&/$sep/g; | 
| 95 | 4 |  |  |  |  | 16 | $uri->query($query); | 
| 96 |  |  |  |  |  |  | } | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | # force stringification | 
| 99 | 16 |  |  |  |  | 255 | return $uri->canonical() . ''; | 
| 100 |  |  |  |  |  |  | } | 
| 101 |  |  |  |  |  |  | } | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | sub _check_required { | 
| 104 | 35 |  |  | 35 |  | 62 | my $p = shift; | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | return | 
| 107 |  |  |  |  |  |  | if ( | 
| 108 | 70 | 100 |  |  |  | 568 | grep { defined and length } | 
|  | 70 |  |  |  |  | 192 |  | 
| 109 | 35 | 100 |  |  |  | 61 | map { $p->{$_} } qw( host fragment ) | 
| 110 |  |  |  |  |  |  | ); | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | return | 
| 113 | 7 |  |  |  |  | 24 | if ref $p->{path} | 
| 114 | 10 | 100 | 66 |  |  | 47 | ? @{ $p->{path} } | 
|  |  | 100 |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | : defined $p->{path} && length $p->{path}; | 
| 116 |  |  |  |  |  |  |  | 
| 117 | 2 | 50 |  |  |  | 4 | return if keys %{ $p->{query} }; | 
|  | 2 |  |  |  |  | 7 |  | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 2 |  |  |  |  | 16 | require Carp; | 
| 120 | 2 |  |  |  |  | 5 | local $Carp::CarpLevel = 1; | 
| 121 | 2 |  |  |  |  | 805 | Carp::croak( 'None of the required parameters ' | 
| 122 |  |  |  |  |  |  | . '(host, path, fragment, or query) were given' ); | 
| 123 |  |  |  |  |  |  | } | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | 1; | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | # ABSTRACT: Build a URI from a set of named parameters | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | __END__ |