[32205] | 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
|
---|