File Coverage

blib/lib/Maypole/Plugin/Config/Apache.pm
Criterion Covered Total %
statement 32 54 59.2
branch 16 32 50.0
condition n/a
subroutine 5 6 83.3
pod 1 1 100.0
total 54 93 58.0


line stmt bran cond sub pod time code
1             package Maypole::Plugin::Config::Apache;
2              
3 2     2   51200 use warnings;
  2         5  
  2         64  
4 2     2   10 use strict;
  2         3  
  2         72  
5              
6 2     2   2324 use NEXT;
  2         10500  
  2         1665  
7              
8             our $VERSION = '0.21';
9              
10             =head1 NAME
11              
12             Maypole::Plugin::Config::Apache - read config settings from httpd.conf
13              
14             =head1 SYNOPSIS
15              
16             use Maypole::Application qw( Config::Apache -Setup );
17            
18            
19             # in httpd.conf
20            
21             # same as $config->application_name( "The Beer Database" )
22             PerlSetVar MaypoleApplicationName "The Beer Database"
23            
24             PerlSetVar MaypoleDsn dbi:mysql:BeerDB
25             PerlSetVar MaypoleUser username
26             PerlSetVar MaypolePass password
27            
28             # same as $config->display_tables( [ qw( beer brewery pub style ) ] )
29             PerlAddVar MaypoleDisplayTables beer
30             PerlAddVar MaypoleDisplayTables brewery
31             PerlAddVar MaypoleDisplayTables pub
32             PerlAddVar MaypoleDisplayTables style
33            
34             # same as $config->masonx( { data_dir => '/home/beerdb/www/beerdb/mdata',
35             # in_package => 'BeerDB::TestApp',
36             # comp_root => [ [ factory => '/usr/local/www/maypole/factory' ] ],
37             # } )
38             PerlAddVar MaypoleMasonx "data_dir => '/home/beerdb/www/beerdb/mdata'"
39             PerlAddVar MaypoleMasonx "in_package => 'BeerDB::TestApp'"
40             PerlAddVar MaypoleMasonx "comp_root => [ [ factory => '/usr/local/www/maypole/factory' ] ]"
41            
42             # set something from arbitrary Perl code
43             PerlSetVar MaypoleEvalDisplayTables "[ qw( beer brewery pub style ) ]"
44            
45             # merging a hash of hashes -
46             # $config->session( { args => { Directory => '/tmp/sessions/beerdb',
47             # LockDirectory => '/tmp/sessionlocks/beerdb',
48             # }
49             # } )
50             PerlAddVar MaypoleSession "args => { Directory => '/tmp/sessions/beerdb' }"
51             PerlAddVar MaypoleSession "args => { LockDirectory => '/tmp/sessionlocks/beerdb' }"
52            
53            
54             # merging a hash of arrayrefs involves a nasty hack...
55             # $config->masonx->{comp_root} = [ [ factory => '/usr/local/www/maypole/factory' ],
56             # [ library => '/usr/local/www/mason/lib' ],
57             # ];
58             PerlAddVar MaypoleMasonx "comp_root => [ [ factory => '/usr/local/www/maypole/factory' ] ]"
59             PerlAddVar MaypoleMasonx "comp_root => [ library => '/usr/local/www/mason/lib' ]"
60            
61             # ...more clearly shown here. To build up a hash of arrayrefs, the first value must
62             # be an array ref (to set up the value as an arrayref), while subsequent items are scalars
63             # and are pushed onto the arrayref:
64             # $config->masonx->{plugins} = [ MasonX::Plugin::Foo->new,
65             # MasonX::Plugin::Bar->new,
66             # MasonX::Plugin::Baz->new,
67             # ];
68             PerlAddVar MaypoleMasonx "plugins => [ MasonX::Plugin::Foo->new ]"
69             PerlAddVar MaypoleMasonx "plugins => MasonX::Plugin::Bar->new"
70             PerlAddVar MaypoleMasonx "plugins => MasonX::Plugin::Baz->new"
71            
72            
73              
74             =head1 DESCRIPTION
75              
76             Anything starting with C or C is taken to be a config setting for Maypole.
77             Everything after the C or C is the variable name, in StudlyCaps form.
78              
79             Values from C variables are run through an C, allowing arbitrarily complex
80             data structures to be set, including coderefs, if anything needed that.
81              
82             Any value from a C that contains a C<< => >> symbol is also run through an eval, so any
83             valid perl expression for a hash value can be used.
84              
85             An attempt is made to intelligently merge hash entries in multiple PerlAddVar statements. Multiple
86             entries with the same key are merged into a single hashref or arrayref value.
87              
88             Put C at the front of the Maypole::Application call, so that later plugins
89             have access to the configuration settings. If your httpd.conf contains all of your Maypole
90             settings, you can add the C<-Setup> flag, which calls C<< __PACKAGE__->setup >> for you.
91              
92             =head1 METHODS
93              
94             =over 4
95              
96             =item setup
97              
98             =back
99              
100             =cut
101              
102             sub setup
103             {
104 0     0 1 0 my $r = shift;
105            
106 0 0       0 warn "Running " . __PACKAGE__ . " setup for $r" if $r->debug;
107            
108             # an Apache::Table object
109 0         0 my $apache_cfg = Apache->server->dir_config;
110            
111 0         0 my $config = {};
112            
113 0         0 foreach my $k ( grep { /^Maypole/ } keys %$apache_cfg )
  0         0  
114             {
115 0         0 my @v = $apache_cfg->get( $k );
116            
117             # change from MaypoleVarName into var_name - stolen from HTML::Mason::ApacheHandler::studly_form()
118 0         0 my $new_k = $k;
119 0         0 $new_k =~ s/^Maypole//;
120 0 0       0 $new_k =~ s/(^|.)([A-Z])/$1 ? "$1\L_$2" : "\L$2"/ge;
  0         0  
121            
122 0 0       0 if ( $k =~ /^MaypoleEval/ )
123             {
124 0         0 $config->{ $new_k } = eval $v[0];
125 0 0       0 die "Error constructing config value for $k from code: $@" if $@;
126             }
127             else
128             {
129             #$config->{ $new_k } = @v > 1 ? _fixup_addvar( $k, @v ) : $v[0];
130 0         0 $config->{ $new_k } = _fixup( $k, @v );
131             }
132             }
133            
134 0 0       0 if ( $r->debug > 1 )
135             {
136 0 0       0 Data::Dumper->require || die "Failed to load Data::Dumper for debug output: $@";
137 0         0 warn "Maypole config from Apache config file: " . Data::Dumper::Dumper( $config );
138             }
139            
140 0         0 Maypole::Config->mk_accessors( keys %$config );
141            
142 0         0 $r->config( Maypole::Config->new( $config ) );
143            
144 0         0 $r->NEXT::DISTINCT::setup(@_);
145             }
146            
147             sub _fixup
148             {
149 12     12   13963 my ( $StudlyVarName, @strings ) = @_;
150            
151             # counting '=>' matches would be wrong, because each string could have > 1
152 12         23 my @got_hash_sep = grep { /=>/ } @strings;
  21         72  
153            
154 12 100       66 return @strings == 1 ? $strings[0] : [ @strings ] unless @got_hash_sep;
    100          
155            
156 7 100       50 die "'=>' present in some but not all values of $StudlyVarName" if @got_hash_sep ne @strings;
157              
158 5         8 my %hash;
159            
160             my $merge = sub
161             {
162 11     11   16 my ( $str ) = @_;
163 11         841 my ( $k, @v ) = eval $str;
164 11 100       102 die "Error extracting value for $StudlyVarName: $@" if $@;
165 9 100       25 if ( exists $hash{ $k } )
166             {
167 3 50       9 if ( my $type = ref $hash{ $k } )
168             {
169 3 100       14 if ( $type eq 'ARRAY' )
    50          
170             {
171 2         3 push @{ $hash{ $k } }, @v;
  2         13  
172             }
173             elsif ( $type eq 'HASH' )
174             {
175 1 50       4 my %v = @v == 1 ? %{ $v[0] } : @v;
  1         6  
176 1         3 %{ $hash{ $k } } = ( %{ $hash{ $k } }, %v );
  1         9  
  1         7  
177             }
178             }
179             else
180             {
181             # The key already holds a plain scalar value.
182             # Convert it to an arrayref.
183 0         0 $hash{ $k } = [ $hash{ $k }, @v ];
184             }
185             }
186             else
187             {
188             #$hash{ $k } = [];
189             #push @{ $hash{ $k } }, @v;
190 6 50       41 $hash{ $k } = @v > 1 ? [ @v ] : $v[0];
191             }
192 5         35 };
193            
194 5         21 $merge->( $_ ) for @strings;
195            
196 3         45 return \%hash;
197             }
198              
199             =head1 EXAMPLE
200              
201             With all the config moved to C, the actual driver is reduced to a few lines of code.
202             Why not inline that in C too?
203              
204            
205            
206             ServerName beerdb.riverside-cms.co.uk
207             ServerAdmin cpan@riverside-cms.co.uk
208            
209             DocumentRoot /home/beerdb/www/beerdb/htdocs
210            
211             #
212             # Set up Maypole via Maypole::Plugin::Config::Apache
213             #
214             PerlSetVar MaypoleApplicationName "The Beer Database"
215             PerlSetVar MaypoleUriBase /beerdb
216             PerlSetVar MaypoleTemplateRoot /home/beerdb/www/beerdb/htdocs
217             PerlSetVar MaypoleRowsPerPage 10
218            
219             PerlSetVar MaypoleDsn "dbi:mysql:BeerDB"
220             PerlSetVar MaypoleUser username
221             PerlSetVar MaypolePass password
222            
223             PerlAddVar MaypoleDisplayTables beer
224             PerlAddVar MaypoleDisplayTables brewery
225             PerlAddVar MaypoleDisplayTables pub
226             PerlAddVar MaypoleDisplayTables style
227            
228             PerlAddVar MaypoleMasonx "comp_root => [ [ factory => '/usr/local/www/maypole/factory' ] ]"
229             PerlAddVar MaypoleMasonx "data_dir => '/home/beerdb/www/beerdb/mdata'"
230             PerlAddVar MaypoleMasonx "in_package => 'BeerDB::TestApp'"
231            
232             PerlAddVar MaypoleRelationships "a brewery produces beers"
233             PerlAddVar MaypoleRelationships "a style defines beers"
234             PerlAddVar MaypoleRelationships "a pub has beers on handpumps"
235            
236            
237             Allow from all
238             AllowOverride none
239             Order allow,deny
240            
241            
242             {
243             package BeerDB;
244             use Maypole::Application qw( Config::Apache MasonX AutoUntaint Relationship -Setup -Debug2 );
245             BeerDB->auto_untaint;
246             BeerDB->init;
247             }
248            
249            
250             SetHandler perl-script
251             PerlHandler BeerDB
252            
253            
254             CustomLog /home/beerdb/www/beerdb/logs/access.log combined env=log
255             ErrorLog /home/beerdb/www/beerdb/logs/error.log
256            
257            
258              
259             Watch out for the chicken and the egg. The C section defining the C package must
260             come after all the Maypole config settings (or else the settings won't yet exist when BeerDB
261             tries to read them), but before the C directive (because the package needs
262             to exist by then).
263            
264             =head1 AUTHOR
265              
266             David Baird, C<< >>
267              
268             =head1 BUGS
269              
270             Won't work for config variables with capital letters in them.
271              
272             Strange things will happen to anything containing '=>' that should not be interpreted as a hash entry.
273              
274             Please report any bugs or feature requests to
275             C, or through the web interface at
276             L.
277             I will be notified, and then you'll automatically be notified of progress on
278             your bug as I make changes.
279              
280             =head1 ACKNOWLEDGEMENTS
281              
282             =head1 COPYRIGHT & LICENSE
283              
284             Copyright 2005 David Baird, All Rights Reserved.
285              
286             This program is free software; you can redistribute it and/or modify it
287             under the same terms as Perl itself.
288              
289             =cut
290              
291             1; # End of Maypole::Plugin::Config::Apache