File Coverage

blib/lib/Dancer/Config/Object.pm
Criterion Covered Total %
statement 57 58 98.2
branch 12 16 75.0
condition n/a
subroutine 13 13 100.0
pod 0 1 0.0
total 82 88 93.1


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.3521';
5 193     193   1296 use strict;
  193         414  
  193         5595  
6 193     193   968 use warnings;
  193         436  
  193         4903  
7              
8 193     193   987 use base 'Exporter';
  193         415  
  193         18108  
9 193     193   1451 use Carp 'croak';
  193         513  
  193         10334  
10 193     193   2758 use Dancer::Exception qw(:all);
  193         719  
  193         23633  
11 193     193   1802 use Scalar::Util 'blessed';
  193         424  
  193         87340  
12              
13             register_exception('BadConfigMethod',
14             message_pattern =>
15             qq{Can't locate config attribute "%s".\nAvailable attributes: %s});
16              
17             our @EXPORT_OK = qw(hashref_to_object);
18              
19             {
20             my $index = 1;
21              
22             sub hashref_to_object {
23 10     10 0 20 my ($hashref) = @_;
24 10         19 my $class = __PACKAGE__;
25 10         22 my $target = "${class}::__ANON__$index";
26 10         17 $index++;
27 10 100       27 if ('HASH' ne ref $hashref) {
28 1 50       7 if ( blessed $hashref ) {
29             # we have already converted this to an object. This can happen
30             # in cases where Dancer::Config->load is called more than
31             # once.
32 1         6 return $hashref;
33             }
34             else {
35             # should never happen
36 0         0 raise 'Core::Config' => "Argument to $class must be a hashref";
37             }
38             }
39 9         76 my $object = bless $hashref => $target;
40 9         34 _add_methods($object);
41              
42 9         32 return $object;
43             }
44             }
45              
46              
47             sub _add_methods {
48 9     9   15 my ($object) = @_;
49 9         17 my $target = ref $object;
50              
51 9         31 foreach my $key ( keys %$object ) {
52 35         108 my $value = $object->{$key};
53 35 100       89 if ( 'HASH' eq ref $value ) {
    100          
54 6         54 $value = hashref_to_object($value);
55             }
56             elsif ( 'ARRAY' eq ref $value ) {
57 1         5 foreach (@$value) {
58 2 50       20 $_ = 'HASH' eq ref($_) ? hashref_to_object($_) : $_;
59             }
60             }
61              
62             # match a (more or less) valid identifier
63 35 100       234 next unless $key =~ qr/^[[:alpha:]_][[:word:]]*$/;
64 33         83 my $method = "${target}::$key";
65 193     193   1612 no strict 'refs';
  193         395  
  193         18820  
66 33     7   222 *$method = sub {$value};
  7         41  
67             }
68 9         36 _setup_bad_method_trap($target);
69             }
70              
71             # AUTOLOAD will only be called if a non-existent method is called. It's used
72             # to generate the list of available methods. It's slow, but we're going to
73             # die. Who wants to die quickly?
74             sub _setup_bad_method_trap {
75 9     9   17 my ($target) = @_;
76 193     193   1269 no strict; ## no critic (ProhibitNoStrict)
  193         460  
  193         41566  
77 9         44 *{"${target}::AUTOLOAD"} = sub {
78 1     1   10 $AUTOLOAD =~ /.*::(.*)$/;
79              
80             # should never happen
81 1 50       6 my $bad_method = $1 ## no critic (ProhibitCaptureWithoutTest)
82             or croak "Could not determine method called via $AUTOLOAD";
83 1 50       6 return if 'DESTROY' eq $bad_method;
84 1         4 my $symbol_table = "${target}::";
85              
86             # In these fake classes, we only have methods
87             my $methods =
88 1         14 join ', ' => grep { !/^(?:AUTOLOAD|DESTROY|$bad_method)$/ }
  4         55  
89             sort keys %$symbol_table;
90 1         9 raise BadConfigMethod => $bad_method, $methods;
91 9         46 };
92             }
93              
94             1;
95              
96             __END__