File Coverage

blib/lib/PlackX/Framework/Config.pm
Criterion Covered Total %
statement 67 67 100.0
branch 11 18 61.1
condition 4 12 33.3
subroutine 11 11 100.0
pod 0 5 0.0
total 93 113 82.3


line stmt bran cond sub pod time code
1 2     2   1349 use v5.36;
  2         8  
2             package PlackX::Framework::Config {
3 2     2   11 use Carp qw(croak);
  2         4  
  2         457  
4              
5 4     4   55 sub import ($class, @options) {
  4         8  
  4         10  
  4         7  
6 4         24 my $config = $class->load_config(@options);
7 4         44 $class->export_config($config);
8             }
9              
10 4     4 0 9 sub load_config ($class, @options) {
  4         9  
  4         39  
  4         7  
11 4         22 my $env_prefix = $class->class_to_env_key_prefix;
12 4   33     17 my $fn = shift @options || $ENV{$env_prefix};
13              
14 4 50 33     120 croak "$class - No config file specified, maybe try \$ENV{'$env_prefix'}"
15             unless defined $fn and length $fn;
16              
17 4 50       103 croak "$class - Config file $fn does not exist"
18             unless -e $fn;
19              
20 4         10 my $type = eval {
21 2     2   14 no warnings;
  2         5  
  2         609  
22 4 100       24 return 'pl' if lc(substr($fn, -3, 3)) eq '.pl';
23 1 50       8 return 'pl' if $ENV{$env_prefix.'_CONFIG_TYPE'} =~ m/^PL|PERL$/i;
24 1         4 return '';
25             };
26              
27 4 100       25 return $class->load_pl_config($fn) if $type eq 'pl';
28 1         11 return $class->load_other_config($fn);
29             }
30              
31 4     4 0 9 sub export_config ($class, $config) {
  4         9  
  4         7  
  4         6  
32 4         33 my ($namespace) = $class =~ m/^(.+)::Config/;
33 4     19   17 my $sub = sub { $config };
  19         3980  
34              
35 2     2   16 no strict 'refs';
  2         4  
  2         903  
36 4         9 *{$namespace.'::config'} = $sub;
  4         32  
37 4         11 *{$namespace.'::Config::config'} = $sub;
  4         18  
38 4         212 return;
39             }
40              
41 4     4 0 6 sub class_to_env_key_prefix ($class) {
  4         9  
  4         5  
42 4         22 $class =~ s/::/_/g;
43 4         14 return uc($class);
44             }
45              
46 3     3 0 4 sub load_pl_config ($class, $fn) {
  3         5  
  3         6  
  3         7  
47 3         7 local @INC = ();
48 3         739 my $result = do $fn;
49 3 50       63 croak "$class - Error reading config file $fn:\n$!"
50             unless $result;
51 3 50 33     23 croak "$class - Config file $fn did not return a hashref"
52             unless ref $result and ref $result eq 'HASH';
53 3         12 return $result;
54             }
55              
56 1     1 0 3 sub load_other_config ($class, $fn) {
  1         2  
  1         3  
  1         2  
57 1         3 my $result = eval {
58 1         8 require Config::Any;
59 1         11 Config::Any->load_files({ use_ext => 1, files => [$fn] })->[0]->{$fn};
60             };
61 1 50       16535 croak "$class - Error reading config file $fn:\n$@$!"
62             unless $result;
63 1 50 33     10 croak "$class - Config file $fn did not result in a hashref"
64             unless ref $result and ref $result eq 'HASH';
65 1         7 return $result;
66             }
67              
68             }
69              
70             1;
71              
72             =pod
73              
74             This module is offered as a convenience to the user, and is not used to
75             configure PlackX::Framework directly.
76              
77             It will load and parse the specific configuration file and make the resulting
78             data structure available in a config() method/functino of your application's
79             main class, and also a ::Config class.
80              
81             IMPORT: This module does NOT export the config() function to the caller, but
82             rather to your application's namespace! See the examples below for
83             clarification!
84              
85             Option one is to have PXF automatically generate your ::Config subclass.
86              
87             Store your config filename in an environment variable, in accordance with the
88             convention described below:
89              
90             My::Web::App => $ENV{'MY_WEB_APP_CONFIG'}
91              
92             or pass it in your use statement.
93              
94             Example 1:
95              
96             package My::WebApp {
97             use PlackX::Framework qw(:config);
98             use My::WebApp::Config '/path/to/config_file';
99              
100             my $some_value = config->{some_key};
101              
102             # May also be written as:
103             # My::WebApp->config
104             # My::WebApp::config()
105             # My::WebApp::Config->config
106             # My::WebApp::Config::config()
107             }
108              
109             Alternatively, create an empty ::Config subclass. This technique must be used
110             if you want to load your configuration before loading the rest of your app.
111              
112             Example 2:
113              
114             # You must create a subclass of PlackX::Framework::Config!
115             # It MUST be named [NameOfApp]::Config!
116              
117             # My/WebApp/Config.pm:
118             package My::WebApp::Config {
119             use parent 'PlackX::Framework::Config';
120             }
121              
122             # My/WebApp.pm
123             package My::WebApp {
124             use PlackX::Framework;
125             use My::WebApp::Router;
126             use Data::Dumper;
127             route '/' => sub ($request, $response) {
128             $response->print(Dumper config());
129             }
130             }
131              
132             # app.psgi
133             use My::WebApp::Config '/path/to/config_file';
134             use My::WebApp;
135              
136             If the config file ends in .pl or if $ENV{MYAPP_CONFIG_TYPE} is set to
137             'PERL', or 'PL', this module will use perl to "do" the file and return
138             a perl data structure; otherwise Config::Any will be loaded to attempt
139             to parse the file based on its extension.
140              
141             If you would like to write your own custom config-file parsing routine,
142             override load_config() in your ::Config subclass, returning a reference
143             to the perl data structure.
144              
145             package My::WebApp::Config {
146             use parent 'PlackX::Framework::Config';
147             sub load_config ($class, @options) {
148             my $fname = shift @options || $ENV{..};
149             require My::Parser::Module;
150             my $config = My::Parser::Module->parse($fname);
151             return $config;
152             }
153             }