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.3520';
5 193     193   1370 use strict;
  193         446  
  193         5628  
6 193     193   1003 use warnings;
  193         424  
  193         5125  
7              
8 193     193   995 use base 'Exporter';
  193         474  
  193         18189  
9 193     193   1311 use Carp 'croak';
  193         562  
  193         10849  
10 193     193   2695 use Dancer::Exception qw(:all);
  193         796  
  193         23834  
11 193     193   1497 use Scalar::Util 'blessed';
  193         443  
  193         88587  
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         17 my $class = __PACKAGE__;
25 10         19 my $target = "${class}::__ANON__$index";
26 10         18 $index++;
27 10 100       23 if ('HASH' ne ref $hashref) {
28 1 50       12 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         3 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         61 my $object = bless $hashref => $target;
40 9         42 _add_methods($object);
41              
42 9         24 return $object;
43             }
44             }
45              
46              
47             sub _add_methods {
48 9     9   14 my ($object) = @_;
49 9         16 my $target = ref $object;
50              
51 9         34 foreach my $key ( keys %$object ) {
52 35         106 my $value = $object->{$key};
53 35 100       101 if ( 'HASH' eq ref $value ) {
    100          
54 6         20 $value = hashref_to_object($value);
55             }
56             elsif ( 'ARRAY' eq ref $value ) {
57 1         6 foreach (@$value) {
58 2 50       10 $_ = 'HASH' eq ref($_) ? hashref_to_object($_) : $_;
59             }
60             }
61              
62             # match a (more or less) valid identifier
63 35 100       210 next unless $key =~ qr/^[[:alpha:]_][[:word:]]*$/;
64 33         93 my $method = "${target}::$key";
65 193     193   1595 no strict 'refs';
  193         397  
  193         19382  
66 33     7   222 *$method = sub {$value};
  7         38  
67             }
68 9         24 _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   20 my ($target) = @_;
76 193     193   1248 no strict; ## no critic (ProhibitNoStrict)
  193         468  
  193         42472  
77 9         53 *{"${target}::AUTOLOAD"} = sub {
78 1     1   6 $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       4 return if 'DESTROY' eq $bad_method;
84 1         3 my $symbol_table = "${target}::";
85              
86             # In these fake classes, we only have methods
87             my $methods =
88 1         10 join ', ' => grep { !/^(?:AUTOLOAD|DESTROY|$bad_method)$/ }
  4         53  
89             sort keys %$symbol_table;
90 1         12 raise BadConfigMethod => $bad_method, $methods;
91 9         30 };
92             }
93              
94             1;
95              
96             __END__