File Coverage

blib/lib/Mojolicious/Plugin/ConfigGeneral.pm
Criterion Covered Total %
statement 77 84 91.6
branch 18 42 42.8
condition 14 44 31.8
subroutine 11 11 100.0
pod 1 1 100.0
total 121 182 66.4


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::ConfigGeneral;
2              
3             =encoding utf8
4              
5             =head1 NAME
6              
7             Mojolicious::Plugin::ConfigGeneral - Config::General Configuration Plugin for Mojolicious
8              
9             =head1 SYNOPSIS
10              
11             use Mojolicious::Plugin::ConfigGeneral;
12              
13             # Mojolicious
14             my $config = $app->plugin('ConfigGeneral');
15             say $config->{foo};
16              
17             # Mojolicious::Lite
18             my $config = plugin 'ConfigGeneral';
19             say $config->{foo};
20              
21             # The configuration is available application-wide
22             my $config = app->config;
23             say $config->{foo};
24              
25             # Everything can be customized with options
26             my $config = plugin ConfigGeneral => {file => '/etc/myapp.conf'};
27              
28             =head1 DESCRIPTION
29              
30             Mojolicious::Plugin::ConfigGeneral is a L Configuration Plugin for Mojolicious
31              
32             =head1 OPTIONS
33              
34             This plugin supports the following options
35              
36             =head2 defaults
37              
38             # Mojolicious::Lite
39             plugin ConfigGeneral => {defaults => {foo => 'bar'}};
40              
41             Default configuration
42              
43             =head2 file
44              
45             # Mojolicious::Lite
46             plugin ConfigGeneral => {file => 'myapp.conf'};
47             plugin ConfigGeneral => {file => '/etc/foo.stuff'};
48              
49             Path to configuration file, absolute or relative to the application home directory, defaults to the value of the
50             C environment variable or C<$moniker.conf> in the application home directory.
51              
52             =head2 noload
53              
54             plugin ConfigGeneral => {noload => 1};
55              
56             This option disables loading config file
57              
58             =head2 options
59              
60             # Mojolicious::Lite
61             plugin ConfigGeneral => {options => {'-AutoTrue' => 0}};
62             plugin ConfigGeneral => {options => {'-AutoTrue' => 0}};
63              
64             Sets the L options directly
65              
66             =head1 METHODS
67              
68             This plugin inherits all methods from L and implements the following new ones
69              
70             =head2 register
71              
72             my $config = $plugin->register(Mojolicious->new);
73             my $config = $plugin->register(Mojolicious->new, {file => '/etc/foo.conf'});
74              
75             Register plugin in L application and set configuration.
76              
77             =head1 HELPERS
78              
79             All helpers of this plugin are allows get access to configuration parameters by path-pointers.
80             See L and L
81              
82             =over 8
83              
84             =item conf-Eget
85              
86             say $self->conf->get('/datadir');
87              
88             Returns configuration value by path
89              
90             =item conf-Efirst
91              
92             dumper $self->conf->first('/foo'); # ['first', 'second', 'third']
93             # 'first'
94              
95             Returns an first value of found values from configuration
96              
97             =item conf-Elatest
98              
99             dumper $self->conf->latest('/foo'); # ['first', 'second', 'third']
100             # 'third'
101              
102             Returns an latest value of found values from configuration
103              
104             =item conf-Earray, conf-Elist
105              
106             dumper $self->conf->array('/foo'); # ['first', 'second', 'third']
107             # ['first', 'second', 'third']
108             dumper $self->conf->array('/foo'); # 'value'
109             # ['value']
110              
111             Returns an array of found values from configuration
112              
113             =item conf-Ehash, conf-Eobject
114              
115             dumper $self->conf->array('/foo'); # { foo => 'first', bar => 'second' }
116             # { foo => 'first', bar => 'second' }
117              
118             Returns an hash of found values from configuration
119              
120             =back
121              
122             =head1 HISTORY
123              
124             See C file
125              
126             =head1 TO DO
127              
128             See C file
129              
130             =head1 SEE ALSO
131              
132             L, L
133              
134             =head1 AUTHOR
135              
136             Serż Minus (Sergey Lepenkov) L Eabalama@cpan.orgE
137              
138             =head1 COPYRIGHT
139              
140             Copyright (C) 1998-2026 D&D Corporation
141              
142             =head1 LICENSE
143              
144             This program is distributed under the terms of the Artistic License Version 2.0
145              
146             See the C file or L for details
147              
148             =cut
149              
150             our $VERSION = '1.05';
151              
152 2     2   1212039 use Mojo::Base 'Mojolicious::Plugin';
  2         8908  
  2         16  
153 2     2   3035 use Config::General qw//;
  2         35099  
  2         83  
154 2     2   583 use Mojo::File qw/path/;
  2         262948  
  2         157  
155 2     2   859 use Mojo::JSON::Pointer qw//;
  2         1210  
  2         88  
156              
157 2         2815 use constant DEFAULT_CG_OPTS => {
158             '-ApacheCompatible' => 1, # Makes possible to tweak all options in a way that Apache configs can be parsed
159             '-LowerCaseNames' => 1, # All options found in the config will be converted to lowercase
160             '-UTF8' => 1, # All files will be opened in utf8 mode
161             '-AutoTrue' => 1, # All options in your config file, whose values are set to true or false values, will be normalised to 1 or 0 respectively
162 2     2   12 };
  2         5  
163              
164             has 'config_pointer' => sub { Mojo::JSON::Pointer->new };
165              
166             sub register {
167 1     1 1 55 my ($self, $app, $args) = @_;
168              
169             # NoLoad
170 1   50     7 my $noload = $args->{noload} || 0;
171              
172             # Config file
173 1   33     4 my $file = $args->{file} || $ENV{MOJO_CONFIG};
174 1   33     3 $file ||= $app->home->child($app->moniker . '.conf'); # Relative to the home directory by default
175 1 50       4 unless ($noload) {
176             # Configuration file not found
177 1 50       25 $noload = 1 unless -r $file;
178             }
179              
180             # Config::General Options
181 1   50     6 my $opts = $args->{options} || $args->{opts} || {};
182 1 50       4 $opts = {} unless ref($opts) eq 'HASH';
183 1         2 my %options = (%{DEFAULT_CG_OPTS()}, %$opts); # Merge everything
  1         15  
184 1         2 $options{'-ConfigFile'} = $file;
185              
186             # Load
187 1         2 my %config = ();
188 1         2 my @files = ();
189 1 50       2 unless ($noload) {
190 1         2 my $cfg = eval { Config::General->new(%options) };
  1         5  
191 1 50       1587 die sprintf("Can't load configuration from file \"%s\": %s", $file, $@) if $@;
192 1 50       4 die sprintf("Configuration file \"%s\" did not return a Config::General object", $file)
193             unless ref $cfg eq 'Config::General';
194 1         5 %config = $cfg->getall;
195 1         12 @files = $cfg->files;
196             }
197              
198             # Merge defaults
199 1   50     28 my $defaults = $args->{defaults} || $args->{default} || {};
200 1 50 50     6 %config = (%$defaults, %config) if (ref($defaults) eq 'HASH') && scalar keys %$defaults;
201              
202             # Add system values
203 1         3 $config{'_config_files'} = [@files];
204 1         2 $config{'_config_loaded'} = scalar @files;
205              
206             # Set config data
207 1         12 $app->config(\%config);
208 1         29 $self->config_pointer->data(\%config);
209              
210             # Helpers
211             my $_conf_get = sub {
212 1     1   1860 my $this = shift;
213 1         2 my $key = shift;
214 1         3 return $self->config_pointer->get($key);
215 1         20 };
216             my $_conf_fisrt = sub {
217 1     1   751 my $this = shift;
218 1 50 33     6 return undef unless defined($_[0]) && length($_[0]);
219 1         3 my $node = $self->config_pointer->get($_[0]);
220 1 50 33     31 if ($node && ref($node) eq 'ARRAY') { # Array
    0 0        
221 1 50       7 return exists($node->[0]) ? $node->[0] : undef;
222             } elsif (defined($node) && !ref($node)) { # Scalar
223 0         0 return $node;
224             }
225 0         0 return undef;
226 1         2 };
227             my $_conf_latest = sub {
228 1     1   128 my $this = shift;
229 1 50 33     10 return undef unless defined($_[0]) && length($_[0]);
230 1         6 my $node = $self->config_pointer->get($_[0]);
231 1 50 33     46 if ($node && ref($node) eq 'ARRAY') { # Array
    0 0        
232 1 50       7 return exists($node->[0]) ? $node->[-1] : undef;
233             } elsif (defined($node) && !ref($node)) { # Scalar
234 0         0 return $node;
235             }
236 0         0 return undef;
237 1         30 };
238             my $_conf_array = sub {
239 1     1   90 my $this = shift;
240 1 50 33     6 return undef unless defined($_[0]) && length($_[0]);
241 1         4 my $node = $self->config_pointer->get($_[0]);
242 1 50 33     34 if ($node && ref($node) eq 'ARRAY') { # Array
    0          
243 1         5 return $node;
244             } elsif (defined($node)) {
245 0         0 return [$node];
246             }
247 0         0 return [];
248 1         7 };
249             my $_conf_hash = sub {
250 1     1   92 my $this = shift;
251 1 50 33     6 return undef unless defined($_[0]) && length($_[0]);
252 1         4 my $node = $self->config_pointer->get($_[0]);
253 1 50 33     27 if ($node && ref($node) eq 'HASH') { # Hash
254 1         5 return $node;
255             }
256 0         0 return {};
257 1         2 };
258              
259             # Set conf helpers
260 1         8 $app->helper('conf.get' => $_conf_get);
261 1         444 $app->helper('conf.first' => $_conf_fisrt);
262 1         286 $app->helper('conf.latest' => $_conf_latest);
263 1         257 $app->helper('conf.array' => $_conf_array);
264 1         271 $app->helper('conf.list' => $_conf_array);
265 1         352 $app->helper('conf.hash' => $_conf_hash);
266 1         302 $app->helper('conf.object' => $_conf_hash);
267              
268             # Return
269 1 50       332 return wantarray ? (%config) : \%config;
270             }
271              
272             1;
273              
274             __END__