Commit | Line | Data |
b4a6fa62 |
1 | package Catalyst::Container; |
2 | use Bread::Board; |
3 | use Moose; |
4 | use Config::Any; |
5 | use Data::Visitor::Callback; |
6 | use Catalyst::Utils (); |
7 | |
8 | extends 'Bread::Board::Container'; |
9 | |
10 | has config_local_suffix => ( |
11 | is => 'rw', |
12 | isa => 'Str', |
13 | default => 'local', |
14 | ); |
15 | |
16 | has driver => ( |
17 | is => 'rw', |
18 | isa => 'HashRef', |
19 | default => sub { +{} }, |
20 | ); |
21 | |
22 | has file => ( |
23 | is => 'rw', |
24 | isa => 'Str', |
25 | default => '', |
26 | ); |
27 | |
28 | has substitutions => ( |
29 | is => 'rw', |
30 | isa => 'HashRef', |
31 | default => sub { +{} }, |
32 | ); |
33 | |
34 | has name => ( |
35 | is => 'rw', |
36 | isa => 'Str', |
37 | default => 'TestApp', |
38 | ); |
39 | |
40 | sub BUILD { |
41 | my $self = shift; |
42 | |
43 | container $self => as { |
44 | service name => $self->name; |
45 | service driver => $self->driver; |
46 | service file => $self->file; |
47 | service substitutions => $self->substitutions; |
48 | |
49 | service extensions => ( |
50 | block => sub { |
51 | return \@{Config::Any->extensions}; |
52 | }, |
53 | ); |
54 | |
55 | service prefix => ( |
56 | block => sub { |
57 | return Catalyst::Utils::appprefix( shift->param('name') ); |
58 | }, |
59 | dependencies => [ depends_on('name') ], |
60 | ); |
61 | |
62 | service path => ( |
63 | block => sub { |
64 | my $s = shift; |
65 | |
66 | return Catalyst::Utils::env_value( $s->param('name'), 'CONFIG' ) |
67 | || $s->param('file') |
68 | || $s->param('name')->path_to( $s->param('prefix') ); |
69 | }, |
70 | dependencies => [ depends_on('file'), depends_on('name'), depends_on('prefix') ], |
71 | ); |
72 | |
73 | service config => ( |
74 | block => sub { |
75 | my $s = shift; |
76 | |
77 | my $v = Data::Visitor::Callback->new( |
78 | plain_value => sub { |
79 | return unless defined $_; |
80 | return $self->_config_substitutions( $s->param('name'), $s->param('substitutions'), $_ ); |
81 | } |
82 | |
83 | ); |
84 | $v->visit( $s->param('raw_config') ); |
85 | }, |
86 | dependencies => [ depends_on('name'), depends_on('raw_config'), depends_on('substitutions') ], |
87 | ); |
88 | |
89 | service raw_config => ( |
90 | block => sub { |
91 | my $s = shift; |
92 | |
93 | my @global = @{$s->param('global_config')}; |
94 | my @locals = @{$s->param('local_config')}; |
95 | |
96 | my $config = {}; |
97 | for my $cfg (@global, @locals) { |
98 | for (keys %$cfg) { |
99 | $config = Catalyst::Utils::merge_hashes( $config, $cfg->{$_} ); |
100 | } |
101 | } |
102 | return $config; |
103 | }, |
104 | dependencies => [ depends_on('global_config'), depends_on('local_config') ], |
105 | ); |
106 | |
107 | service global_files => ( |
108 | block => sub { |
109 | my $s = shift; |
110 | |
111 | my ( $path, $extension ) = @{$s->param('config_path')}; |
112 | |
113 | my @extensions = @{$s->param('extensions')}; |
114 | |
115 | my @files; |
116 | if ( $extension ) { |
117 | die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions; |
118 | push @files, $path; |
119 | } else { |
120 | @files = map { "$path.$_" } @extensions; |
121 | } |
122 | return \@files; |
123 | }, |
124 | dependencies => [ depends_on('extensions'), depends_on('config_path') ], |
125 | ); |
126 | |
127 | service local_files => ( |
128 | block => sub { |
129 | my $s = shift; |
130 | |
131 | my ( $path, $extension ) = @{$s->param('config_path')}; |
132 | my $suffix = $s->param('config_local_suffix'); |
133 | |
134 | my @extensions = @{$s->param('extensions')}; |
135 | |
136 | my @files; |
137 | if ( $extension ) { |
138 | die "Unable to handle files with the extension '${extension}'" unless grep { $_ eq $extension } @extensions; |
139 | $path =~ s{\.$extension}{_$suffix.$extension}; |
140 | push @files, $path; |
141 | } else { |
142 | @files = map { "${path}_${suffix}.$_" } @extensions; |
143 | } |
144 | return \@files; |
145 | }, |
146 | dependencies => [ depends_on('extensions'), depends_on('config_path'), depends_on('config_local_suffix') ], |
147 | ); |
148 | |
149 | service global_config => ( |
150 | block => sub { |
151 | my $s = shift; |
152 | |
f228c263 |
153 | return Config::Any->load_files({ |
154 | files => $s->param('global_files'), |
b4a6fa62 |
155 | filter => \&_fix_syntax, |
156 | use_ext => 1, |
157 | driver_args => $s->param('driver'), |
158 | }); |
b4a6fa62 |
159 | }, |
160 | dependencies => [ depends_on('global_files') ], |
161 | ); |
162 | |
163 | service local_config => ( |
164 | block => sub { |
165 | my $s = shift; |
166 | |
f228c263 |
167 | return Config::Any->load_files({ |
168 | files => $s->param('local_files'), |
b4a6fa62 |
169 | filter => \&_fix_syntax, |
170 | use_ext => 1, |
171 | driver_args => $s->param('driver'), |
172 | }); |
b4a6fa62 |
173 | }, |
174 | dependencies => [ depends_on('local_files') ], |
175 | ); |
176 | |
177 | service config_path => ( |
178 | block => sub { |
179 | my $s = shift; |
180 | |
181 | my $path = $s->param('path'); |
182 | my $prefix = $s->param('prefix'); |
183 | |
184 | my ( $extension ) = ( $path =~ m{\.(.{1,4})$} ); |
185 | |
186 | if ( -d $path ) { |
187 | $path =~ s{[\/\\]$}{}; |
188 | $path .= "/$prefix"; |
189 | } |
190 | |
191 | return [ $path, $extension ]; |
192 | }, |
193 | dependencies => [ depends_on('prefix'), depends_on('path') ], |
194 | ); |
195 | |
196 | service config_local_suffix => ( |
197 | block => sub { |
198 | my $s = shift; |
199 | my $suffix = Catalyst::Utils::env_value( $s->param('name'), 'CONFIG_LOCAL_SUFFIX' ) || $self->config_local_suffix; |
200 | |
201 | return $suffix; |
202 | }, |
203 | dependencies => [ depends_on('name') ], |
204 | ); |
205 | |
206 | }; |
207 | } |
208 | |
209 | sub _fix_syntax { |
210 | my $config = shift; |
211 | my @components = ( |
212 | map +{ |
213 | prefix => $_ eq 'Component' ? '' : $_ . '::', |
214 | values => delete $config->{ lc $_ } || delete $config->{ $_ } |
215 | }, |
216 | grep { ref $config->{ lc $_ } || ref $config->{ $_ } } |
217 | qw( Component Model M View V Controller C Plugin ) |
218 | ); |
219 | |
220 | foreach my $comp ( @components ) { |
221 | my $prefix = $comp->{ prefix }; |
222 | foreach my $element ( keys %{ $comp->{ values } } ) { |
223 | $config->{ "$prefix$element" } = $comp->{ values }->{ $element }; |
224 | } |
225 | } |
226 | } |
227 | |
228 | sub _config_substitutions { |
f228c263 |
229 | my ($self, $name, $subs) = @_; |
b4a6fa62 |
230 | |
231 | $subs->{ HOME } ||= sub { shift->path_to( '' ); }; |
232 | $subs->{ ENV } ||= |
233 | sub { |
234 | my ( $c, $v ) = @_; |
235 | if (! defined($ENV{$v})) { |
236 | Catalyst::Exception->throw( message => |
237 | "Missing environment variable: $v" ); |
238 | return ""; |
239 | } else { |
240 | return $ENV{ $v }; |
241 | } |
242 | }; |
243 | $subs->{ path_to } ||= sub { shift->path_to( @_ ); }; |
244 | $subs->{ literal } ||= sub { return $_[ 1 ]; }; |
245 | my $subsre = join( '|', keys %$subs ); |
246 | |
247 | for ( @_ ) { |
248 | my $arg = $_; |
249 | $arg =~ s{__($subsre)(?:\((.+?)\))?__}{ $subs->{ $1 }->( $name, $2 ? split( /,/, $2 ) : () ) }eg; |
250 | return $arg; |
251 | } |
252 | } |
253 | |
254 | 1; |