File Coverage

blib/lib/constant/override.pm
Criterion Covered Total %
statement 74 74 100.0
branch 26 26 100.0
condition 3 3 100.0
subroutine 16 16 100.0
pod n/a
total 119 119 100.0


line stmt bran cond sub pod time code
1             package constant::override;
2              
3 3     3   35801 use warnings;
  3         8  
  3         138  
4 3     3   18 use strict;
  3         7  
  3         105  
5              
6 3     3   3050 use Sub::Uplevel;
  3         3533  
  3         18  
7              
8 3     3   116 use Carp;
  3         6  
  3         341  
9 3     3   15 use constant;
  3         7  
  3         2686  
10              
11             our $VERSION = '0.01';
12              
13             my $has_been_called = 0; ## no critic
14              
15             sub _substituted_import
16             {
17 165     165   499 my ($original_import, $default_functionality, $substitute,
18             $ignore, $substitute_fn, $class, @args) = @_;
19              
20 165 100       362 if (not @args) {
21 1         23 return;
22             }
23              
24 164         485 my $pkg = caller(1);
25              
26 164         10974 my $multiple = ref $args[0];
27 164 100 100     631 if ($multiple and ref $args[0] ne 'HASH') {
28 1         36 croak("Invalid reference type '".$multiple."' ".
29             "(must be 'HASH').");
30             }
31              
32 163         166 my %constants;
33 163 100       284 if ($multiple) {
34 15         16 %constants = %{$args[0]};
  15         56  
35             }
36             else {
37 148         318 $constants{$args[0]} = undef;
38             }
39              
40 163         348 for my $name (keys %constants) {
41 178         338 my $full_name = $pkg.'::'.$name;
42              
43 178 100       777 if (exists $substitute->{$full_name}) {
    100          
    100          
    100          
    100          
44 1         5 $substitute_fn->($full_name, $substitute->{$full_name});
45             }
46             elsif (exists $substitute->{$name}) {
47 3         8 $substitute_fn->($full_name, $substitute->{$name});
48             }
49             elsif (exists $ignore->{$full_name}) {
50 1         25 next;
51             }
52             elsif (exists $ignore->{$name}) {
53 2         77 next;
54             }
55             elsif ($default_functionality) {
56 72 100       197 my @values =
57             ($multiple)
58             ? $constants{$name}
59             : @args[1..$#args];
60 72         143 $substitute_fn->($full_name, @values);
61             }
62             else {
63 99         294 uplevel 2, $original_import, ($class, @args);
64             }
65             }
66             }
67              
68             sub import
69             {
70 6     6   547 my $class = shift;
71 6         16 my %args = @_;
72              
73 6         15 my ($ignore, $substitute) = @args{qw(ignore substitute)};
74            
75 6 100       10 my %ignore = map { $_ => 1 } @{$args{'ignore'} || []};
  3         12  
  6         40  
76 6 100       9 my %substitute = %{$args{'substitute'} || {}};
  6         37  
77              
78             my $value_to_fn = sub {
79 76     76   119 my (@values) = @_;
80             (@values == 1)
81             ? (ref $values[0] eq 'CODE')
82             ? $values[0]
83 18     18   20599 : sub () { $values[0] }
84 2     2   327 : sub () { @values }
85 6 100       49 };
  76 100       422  
86             my $substitute_fn = sub {
87 76     76   117 my ($binding, @values) = @_;
88 3     3   21 no warnings;
  3         6  
  3         125  
89 3     3   16 no strict 'refs'; ## no critic
  3         6  
  3         213  
90 76         143 *{$binding} = $value_to_fn->(@values);
  76         7681  
91 6         22 };
92              
93 6         14 my $default_functionality = (not $has_been_called);
94 6         13 $has_been_called = 1;
95              
96             ## no critic
97              
98 3     3   24 no warnings;
  3         6  
  3         123  
99 3     3   17 no strict 'refs';
  3         3  
  3         399  
100              
101 6         10 my $original_import = \&{'constant::import'};
  6         18  
102 6         20 *{'constant::import'} = sub {
103 165     165   78992 _substituted_import($original_import,
104             $default_functionality,
105             \%substitute,
106             \%ignore, $substitute_fn, @_)
107 6         24 };
108              
109 6         136 return 1;
110             }
111              
112             1;
113              
114             __END__