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.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__