File Coverage

blib/lib/Project/Easy/Config.pm
Criterion Covered Total %
statement 56 69 81.1
branch 34 42 80.9
condition 14 29 48.2
subroutine 6 7 85.7
pod 0 4 0.0
total 110 151 72.8


line stmt bran cond sub pod time code
1             package Project::Easy::Config;
2              
3 3     3   1843 use Class::Easy;
  3         18175  
  3         29  
4              
5             our %nonexistent_keys_in_config = ();
6             our @curr_patch_config_path = ();
7              
8             #sub patch ($$);
9              
10             sub parse {
11 0     0 0 0 my $class = shift;
12 0         0 my $core = shift;
13 0         0 my $instance = shift;
14            
15 0         0 my $path = $core->conf_path;
16 0         0 my $fixup = $core->fixup_path_instance ($instance);
17            
18             # TODO: replace to real splitpath and join '/' for windows users
19 0         0 my $root_path = $core->root->path;
20 0         0 $root_path =~ s/\\/\//g;
21              
22             # here we want to expand some generic params
23 0         0 my $expansion = {
24             root => $root_path,
25             id => $core->id,
26             instance => $core->instance,
27             };
28            
29 0         0 my $conf = $path->deserialize ($expansion);
30 0         0 my $alt = $fixup->deserialize ($expansion);
31            
32 0         0 patch ($conf, $alt);
33            
34 0         0 return $conf;
35             }
36              
37             my $ext_syn = {
38             'pl' => 'perl',
39             'js' => 'json',
40             };
41              
42             sub serializer {
43 10     10 0 1347 shift;
44 10         12 my $type = shift;
45            
46 10 100       33 $type = $ext_syn->{$type}
47             if exists $ext_syn->{$type};
48            
49 10         20 my $pack = "Project::Easy::Config::Format::$type";
50            
51 10 50       27 die ('no such serializer: ', $type)
52             unless try_to_use ($pack);
53            
54 10         1158 return $pack->new;
55             }
56              
57             sub string_from_template {
58              
59 2     2 0 5 my $template = shift;
60 2         4 my $expansion = shift;
61              
62 2 50       7 return unless $template;
63              
64 2         9 foreach (keys %$expansion) {
65 2 50       6 next unless defined $expansion->{$_};
66              
67 2         25 $template =~ s/\{\$$_\}/$expansion->{$_}/sg;
68             }
69              
70 2         8 return $template;
71             }
72              
73             sub patch {
74 14     14 0 991 my $struct = shift;
75 14         18 my $patch = shift;
76 14   100     45 my $algorithm = shift || 'ordinary_patch';
77            
78             # $algorithm = ordinary_patch || undef_keys_in_patch || store_nonexistent_keys_in_struct
79            
80 14 100 66     139 return if ref $struct ne 'HASH' and ref $patch ne 'HASH';
81              
82 8 100       25 unless ( scalar keys %$struct ) {
83 1         7 %$struct = %$patch;
84 1         4 return;
85             }
86            
87 7         27 my $algo_id = {
88             ordinary_patch => 1,
89             undef_keys_in_patch => 2,
90             store_nonexistent_keys_in_struct => 3,
91             };
92            
93 7         17 foreach my $k (keys %$patch) {
94            
95 11         20 push @curr_patch_config_path, $k;
96              
97 11 100 66     76 if (! exists $struct->{$k}) {
    100 66        
    50 66        
    0 33        
      66        
      33        
      0        
      0        
98 3 100       11 if ( $algo_id->{$algorithm} == 2 ) {
    100          
99 1         3 $struct->{$k} = _recursive_undef_struct($patch->{$k});
100             }
101             elsif ( $algo_id->{$algorithm} == 3 ) {
102 1         4 _recursive_traverse_struct($patch->{$k}, join('.', @curr_patch_config_path));
103             }
104             else {
105 1         6 $struct->{$k} = $patch->{$k};
106             }
107            
108             } elsif (
109             (! ref $patch->{$k} && ! ref $struct->{$k})
110             || (ref $patch->{$k} eq 'ARRAY' && (ref $struct->{$k} eq 'ARRAY'))
111             || (ref $patch->{$k} eq 'Regexp' && (ref $struct->{$k} eq 'Regexp'))
112             ) {
113 7 100       18 if ( $algo_id->{$algorithm} == 2 ) {
114 4         19 patch ($struct->{$k}, $patch->{$k}, $algorithm);
115             }
116             else {
117 3         17 $struct->{$k} = $patch->{$k};
118             }
119             } elsif (ref $patch->{$k} eq 'HASH' && (ref $struct->{$k} eq 'HASH')) {
120 1         3 patch ($struct->{$k}, $patch->{$k}, $algorithm);
121             } elsif (ref $patch->{$k} eq 'CODE' && (ref $struct->{$k} eq 'CODE' || ! defined $struct->{$k})) {
122 0         0 $struct->{$k} = $patch->{$k};
123             }
124             }
125             }
126              
127             sub _recursive_undef_struct {
128 21     21   18 my $data = shift;
129            
130 21 100       35 if ( ! ref $data ) {
131 15         15 $data = undef;
132             }
133             else {
134 6 100       20 if ( ref $data eq 'ARRAY' ) {
    50          
135 3         5 @$data = map { _recursive_undef_struct($_) } @$data;
  11         20  
136             }
137             elsif ( ref $data eq 'HASH' ) {
138 3         17 %$data = map { $_ => _recursive_undef_struct($data->{$_}) } keys %$data;
  6         19  
139             }
140             }
141            
142 21         57 return $data;
143             }
144              
145             sub _recursive_traverse_struct {
146 11     11   14 my $data = shift;
147 11         11 my $name = shift;
148            
149 11 100       28 if ( ! ref $data) {
    100          
    50          
150 6         14 $nonexistent_keys_in_config{$name} = 1;
151             }
152             elsif ( ref $data eq 'ARRAY' ) {
153 1         2 foreach my $element (@$data) {
154 4 100       8 if (! ref $element) {
155 3         8 $nonexistent_keys_in_config{$name} = 'ARRAY of ' . scalar @$data . ' elements';
156             }
157             else {
158 1         2 _recursive_traverse_struct($element, $name);
159             }
160             }
161             }
162             elsif ( ref $data eq 'HASH' ) {
163 4         9 foreach my $key ( keys %$data ) {
164 8 100       37 $nonexistent_keys_in_config{"$name.$key"} = 1 if (! ref $data->{$key});
165              
166 8         24 _recursive_traverse_struct($data->{$key}, "$name.$key");
167             }
168             }
169              
170 11         24 return $data;
171             }
172              
173             1;