| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Dancer::Config::Object; | 
| 2 |  |  |  |  |  |  | our $AUTHORITY = 'cpan:SUKRIA'; | 
| 3 |  |  |  |  |  |  | #ABSTRACT: Access the config via methods instead of hashrefs | 
| 4 |  |  |  |  |  |  | $Dancer::Config::Object::VERSION = '1.3514_04'; # TRIAL | 
| 5 |  |  |  |  |  |  | $Dancer::Config::Object::VERSION = '1.351404'; | 
| 6 | 194 |  |  | 194 |  | 1549 | use strict; | 
|  | 194 |  |  |  |  | 328 |  | 
|  | 194 |  |  |  |  | 4686 |  | 
| 7 | 194 |  |  | 194 |  | 853 | use warnings; | 
|  | 194 |  |  |  |  | 335 |  | 
|  | 194 |  |  |  |  | 4256 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 194 |  |  | 194 |  | 898 | use base 'Exporter'; | 
|  | 194 |  |  |  |  | 406 |  | 
|  | 194 |  |  |  |  | 16299 |  | 
| 10 | 194 |  |  | 194 |  | 1229 | use Carp 'croak'; | 
|  | 194 |  |  |  |  | 572 |  | 
|  | 194 |  |  |  |  | 9333 |  | 
| 11 | 194 |  |  | 194 |  | 2387 | use Dancer::Exception qw(:all); | 
|  | 194 |  |  |  |  | 401 |  | 
|  | 194 |  |  |  |  | 20940 |  | 
| 12 | 194 |  |  | 194 |  | 1219 | use Scalar::Util 'blessed'; | 
|  | 194 |  |  |  |  | 586 |  | 
|  | 194 |  |  |  |  | 71402 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | register_exception('BadConfigMethod', | 
| 15 |  |  |  |  |  |  | message_pattern => | 
| 16 |  |  |  |  |  |  | qq{Can't locate config attribute "%s".\nAvailable attributes: %s}); | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | our @EXPORT_OK = qw(hashref_to_object); | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | { | 
| 21 |  |  |  |  |  |  | my $index = 1; | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | sub hashref_to_object { | 
| 24 | 10 |  |  | 10 | 0 | 17 | my ($hashref) = @_; | 
| 25 | 10 |  |  |  |  | 15 | my $class = __PACKAGE__; | 
| 26 | 10 |  |  |  |  | 17 | my $target = "${class}::__ANON__$index"; | 
| 27 | 10 |  |  |  |  | 15 | $index++; | 
| 28 | 10 | 100 |  |  |  | 17 | if ('HASH' ne ref $hashref) { | 
| 29 | 1 | 50 |  |  |  | 8 | if ( blessed $hashref ) { | 
| 30 |  |  |  |  |  |  | # we have already converted this to an object. This can happen | 
| 31 |  |  |  |  |  |  | # in cases where Dancer::Config->load is called more than | 
| 32 |  |  |  |  |  |  | # once. | 
| 33 | 1 |  |  |  |  | 4 | return $hashref; | 
| 34 |  |  |  |  |  |  | } | 
| 35 |  |  |  |  |  |  | else { | 
| 36 |  |  |  |  |  |  | # should never happen | 
| 37 | 0 |  |  |  |  | 0 | raise 'Core::Config' => "Argument to $class must be a hashref"; | 
| 38 |  |  |  |  |  |  | } | 
| 39 |  |  |  |  |  |  | } | 
| 40 | 9 |  |  |  |  | 39 | my $object = bless $hashref => $target; | 
| 41 | 9 |  |  |  |  | 24 | _add_methods($object); | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 9 |  |  |  |  | 17 | return $object; | 
| 44 |  |  |  |  |  |  | } | 
| 45 |  |  |  |  |  |  | } | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | sub _add_methods { | 
| 49 | 9 |  |  | 9 |  | 12 | my ($object) = @_; | 
| 50 | 9 |  |  |  |  | 14 | my $target = ref $object; | 
| 51 |  |  |  |  |  |  |  | 
| 52 | 9 |  |  |  |  | 21 | foreach my $key ( keys %$object ) { | 
| 53 | 35 |  |  |  |  | 88 | my $value = $object->{$key}; | 
| 54 | 35 | 100 |  |  |  | 73 | if ( 'HASH' eq ref $value ) { | 
|  |  | 100 |  |  |  |  |  | 
| 55 | 6 |  |  |  |  | 13 | $value = hashref_to_object($value); | 
| 56 |  |  |  |  |  |  | } | 
| 57 |  |  |  |  |  |  | elsif ( 'ARRAY' eq ref $value ) { | 
| 58 | 1 |  |  |  |  | 4 | foreach (@$value) { | 
| 59 | 2 | 50 |  |  |  | 8 | $_ = 'HASH' eq ref($_) ? hashref_to_object($_) : $_; | 
| 60 |  |  |  |  |  |  | } | 
| 61 |  |  |  |  |  |  | } | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | # match a (more or less) valid identifier | 
| 64 | 35 | 100 |  |  |  | 187 | next unless $key =~ qr/^[[:alpha:]_][[:word:]]*$/; | 
| 65 | 33 |  |  |  |  | 70 | my $method = "${target}::$key"; | 
| 66 | 194 |  |  | 194 |  | 1319 | no strict 'refs'; | 
|  | 194 |  |  |  |  | 604 |  | 
|  | 194 |  |  |  |  | 15837 |  | 
| 67 | 33 |  |  | 7 |  | 183 | *$method = sub {$value}; | 
|  | 7 |  |  |  |  | 26 |  | 
| 68 |  |  |  |  |  |  | } | 
| 69 | 9 |  |  |  |  | 21 | _setup_bad_method_trap($target); | 
| 70 |  |  |  |  |  |  | } | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | # AUTOLOAD will only be called if a non-existent method is called. It's used | 
| 73 |  |  |  |  |  |  | # to generate the list of available methods. It's slow, but we're going to | 
| 74 |  |  |  |  |  |  | # die. Who wants to die quickly? | 
| 75 |  |  |  |  |  |  | sub _setup_bad_method_trap { | 
| 76 | 9 |  |  | 9 |  | 13 | my ($target) = @_; | 
| 77 | 194 |  |  | 194 |  | 1076 | no strict;    ## no critic (ProhibitNoStrict) | 
|  | 194 |  |  |  |  | 337 |  | 
|  | 194 |  |  |  |  | 32213 |  | 
| 78 | 9 |  |  |  |  | 33 | *{"${target}::AUTOLOAD"} = sub { | 
| 79 | 1 |  |  | 1 |  | 6 | $AUTOLOAD =~ /.*::(.*)$/; | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | # should never happen | 
| 82 | 1 | 50 |  |  |  | 6 | my $bad_method = $1    ## no critic (ProhibitCaptureWithoutTest) | 
| 83 |  |  |  |  |  |  | or croak "Could not determine method called via $AUTOLOAD"; | 
| 84 | 1 | 50 |  |  |  | 4 | return if 'DESTROY' eq $bad_method; | 
| 85 | 1 |  |  |  |  | 3 | my $symbol_table = "${target}::"; | 
| 86 |  |  |  |  |  |  |  | 
| 87 |  |  |  |  |  |  | # In these fake classes, we only have methods | 
| 88 |  |  |  |  |  |  | my $methods = | 
| 89 | 1 |  |  |  |  | 9 | join ', ' => grep { !/^(?:AUTOLOAD|DESTROY|$bad_method)$/ } | 
|  | 4 |  |  |  |  | 44 |  | 
| 90 |  |  |  |  |  |  | sort keys %$symbol_table; | 
| 91 | 1 |  |  |  |  | 5 | raise BadConfigMethod => $bad_method, $methods; | 
| 92 | 9 |  |  |  |  | 27 | }; | 
| 93 |  |  |  |  |  |  | } | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | 1; | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | __END__ |