1 | package Mojolicious::Plugin::Config;
|
---|
2 | use Mojo::Base 'Mojolicious::Plugin';
|
---|
3 |
|
---|
4 | use Mojo::File 'path';
|
---|
5 | use Mojo::Util 'decode';
|
---|
6 |
|
---|
7 | sub load { $_[0]->parse(decode('UTF-8', path($_[1])->slurp), @_[1, 2, 3]) }
|
---|
8 |
|
---|
9 | sub parse {
|
---|
10 | my ($self, $content, $file, $conf, $app) = @_;
|
---|
11 |
|
---|
12 | # Run Perl code in sandbox
|
---|
13 | my $config = eval 'package Mojolicious::Plugin::Config::Sandbox; no warnings;'
|
---|
14 | . "sub app; local *app = sub { \$app }; use Mojo::Base -strict; $content";
|
---|
15 | die qq{Can't load configuration from file "$file": $@} if $@;
|
---|
16 | die qq{Configuration file "$file" did not return a hash reference.\n}
|
---|
17 | unless ref $config eq 'HASH';
|
---|
18 |
|
---|
19 | return $config;
|
---|
20 | }
|
---|
21 |
|
---|
22 | sub register {
|
---|
23 | my ($self, $app, $conf) = @_;
|
---|
24 |
|
---|
25 | # Override
|
---|
26 | $app->defaults(config => $app->config);
|
---|
27 | return $app->config if $app->config->{config_override};
|
---|
28 |
|
---|
29 | # Config file
|
---|
30 | my $file = $conf->{file} || $ENV{MOJO_CONFIG};
|
---|
31 | $file ||= $app->moniker . '.' . ($conf->{ext} || 'conf');
|
---|
32 |
|
---|
33 | # Mode specific config file
|
---|
34 | my $mode = $file =~ /^(.*)\.([^.]+)$/ ? join('.', $1, $app->mode, $2) : '';
|
---|
35 |
|
---|
36 | my $home = $app->home;
|
---|
37 | $file = $home->child($file) unless path($file)->is_abs;
|
---|
38 | $mode = $home->child($mode) if $mode && !path($mode)->is_abs;
|
---|
39 | $mode = undef unless $mode && -e $mode;
|
---|
40 |
|
---|
41 | # Read config file
|
---|
42 | my $config = {};
|
---|
43 | if (-e $file) { $config = $self->load($file, $conf, $app) }
|
---|
44 |
|
---|
45 | # Check for default and mode specific config file
|
---|
46 | elsif (!$conf->{default} && !$mode) {
|
---|
47 | die qq{Configuration file "$file" missing, maybe you need to create it?\n};
|
---|
48 | }
|
---|
49 |
|
---|
50 | # Merge everything
|
---|
51 | $config = {%$config, %{$self->load($mode, $conf, $app)}} if $mode;
|
---|
52 | $config = {%{$conf->{default}}, %$config} if $conf->{default};
|
---|
53 | return $app->config($config)->config;
|
---|
54 | }
|
---|
55 |
|
---|
56 | 1;
|
---|
57 |
|
---|
58 | =encoding utf8
|
---|
59 |
|
---|
60 | =head1 NAME
|
---|
61 |
|
---|
62 | Mojolicious::Plugin::Config - Perl-ish configuration plugin
|
---|
63 |
|
---|
64 | =head1 SYNOPSIS
|
---|
65 |
|
---|
66 | # myapp.conf (it's just Perl returning a hash)
|
---|
67 | {
|
---|
68 | # Just a value
|
---|
69 | foo => "bar",
|
---|
70 |
|
---|
71 | # Nested data structures are fine too
|
---|
72 | baz => ['â¥'],
|
---|
73 |
|
---|
74 | # You have full access to the application
|
---|
75 | music_dir => app->home->child('music')
|
---|
76 | };
|
---|
77 |
|
---|
78 | # Mojolicious
|
---|
79 | my $config = $app->plugin('Config');
|
---|
80 | say $config->{foo};
|
---|
81 |
|
---|
82 | # Mojolicious::Lite
|
---|
83 | my $config = plugin 'Config';
|
---|
84 | say $config->{foo};
|
---|
85 |
|
---|
86 | # foo.html.ep
|
---|
87 | %= $config->{foo}
|
---|
88 |
|
---|
89 | # The configuration is available application-wide
|
---|
90 | my $config = app->config;
|
---|
91 | say $config->{foo};
|
---|
92 |
|
---|
93 | # Everything can be customized with options
|
---|
94 | my $config = plugin Config => {file => '/etc/myapp.stuff'};
|
---|
95 |
|
---|
96 | =head1 DESCRIPTION
|
---|
97 |
|
---|
98 | L<Mojolicious::Plugin::Config> is a Perl-ish configuration plugin.
|
---|
99 |
|
---|
100 | The application object can be accessed via C<$app> or the C<app> function,
|
---|
101 | L<strict>, L<warnings>, L<utf8> and Perl 5.10 L<features|feature> are
|
---|
102 | automatically enabled. A default configuration filename in the application home
|
---|
103 | directory will be generated from the value of L<Mojolicious/"moniker">
|
---|
104 | (C<$moniker.conf>). You can extend the normal configuration file
|
---|
105 | C<$moniker.conf> with C<mode> specific ones like C<$moniker.$mode.conf>, which
|
---|
106 | will be detected automatically.
|
---|
107 |
|
---|
108 | If the configuration value C<config_override> has been set in
|
---|
109 | L<Mojolicious/"config"> when this plugin is loaded, it will not do anything.
|
---|
110 |
|
---|
111 | The code of this plugin is a good example for learning to build new plugins,
|
---|
112 | you're welcome to fork it.
|
---|
113 |
|
---|
114 | See L<Mojolicious::Plugins/"PLUGINS"> for a list of plugins that are available
|
---|
115 | by default.
|
---|
116 |
|
---|
117 | =head1 OPTIONS
|
---|
118 |
|
---|
119 | L<Mojolicious::Plugin::Config> supports the following options.
|
---|
120 |
|
---|
121 | =head2 default
|
---|
122 |
|
---|
123 | # Mojolicious::Lite
|
---|
124 | plugin Config => {default => {foo => 'bar'}};
|
---|
125 |
|
---|
126 | Default configuration, making configuration files optional.
|
---|
127 |
|
---|
128 | =head2 ext
|
---|
129 |
|
---|
130 | # Mojolicious::Lite
|
---|
131 | plugin Config => {ext => 'stuff'};
|
---|
132 |
|
---|
133 | File extension for generated configuration filenames, defaults to C<conf>.
|
---|
134 |
|
---|
135 | =head2 file
|
---|
136 |
|
---|
137 | # Mojolicious::Lite
|
---|
138 | plugin Config => {file => 'myapp.conf'};
|
---|
139 | plugin Config => {file => '/etc/foo.stuff'};
|
---|
140 |
|
---|
141 | Path to configuration file, absolute or relative to the application home
|
---|
142 | directory, defaults to the value of the C<MOJO_CONFIG> environment variable or
|
---|
143 | C<$moniker.conf> in the application home directory.
|
---|
144 |
|
---|
145 | =head1 METHODS
|
---|
146 |
|
---|
147 | L<Mojolicious::Plugin::Config> inherits all methods from L<Mojolicious::Plugin>
|
---|
148 | and implements the following new ones.
|
---|
149 |
|
---|
150 | =head2 load
|
---|
151 |
|
---|
152 | $plugin->load($file, $conf, $app);
|
---|
153 |
|
---|
154 | Loads configuration file and passes the content to L</"parse">.
|
---|
155 |
|
---|
156 | sub load {
|
---|
157 | my ($self, $file, $conf, $app) = @_;
|
---|
158 | ...
|
---|
159 | return $self->parse($content, $file, $conf, $app);
|
---|
160 | }
|
---|
161 |
|
---|
162 | =head2 parse
|
---|
163 |
|
---|
164 | $plugin->parse($content, $file, $conf, $app);
|
---|
165 |
|
---|
166 | Parse configuration file.
|
---|
167 |
|
---|
168 | sub parse {
|
---|
169 | my ($self, $content, $file, $conf, $app) = @_;
|
---|
170 | ...
|
---|
171 | return $hash;
|
---|
172 | }
|
---|
173 |
|
---|
174 | =head2 register
|
---|
175 |
|
---|
176 | my $config = $plugin->register(Mojolicious->new);
|
---|
177 | my $config = $plugin->register(Mojolicious->new, {file => '/etc/app.conf'});
|
---|
178 |
|
---|
179 | Register plugin in L<Mojolicious> application and merge configuration.
|
---|
180 |
|
---|
181 | =head1 SEE ALSO
|
---|
182 |
|
---|
183 | L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
|
---|
184 |
|
---|
185 | =cut
|
---|