File Coverage

blib/lib/Bigtop/Backend/HttpdConf/Gantry.pm
Criterion Covered Total %
statement 66 274 24.0
branch 0 62 0.0
condition 0 36 0.0
subroutine 22 42 52.3
pod 5 5 100.0
total 93 419 22.2


line stmt bran cond sub pod time code
1             package Bigtop::Backend::HttpdConf::Gantry;
2              
3 1     1   1204 use strict;
  1         1  
  1         31  
4              
5 1     1   389 use Bigtop::Backend::HttpdConf;
  1         3  
  1         28  
6 1     1   7 use Bigtop;
  1         2  
  1         22  
7 1     1   6 use Inline;
  1         2  
  1         8  
8              
9             sub what_do_you_make {
10             return [
11 0     0 1   [ 'docs/httpd.conf' => 'Include file for mod_perl apache conf' ],
12             ];
13             }
14              
15             sub backend_block_keywords {
16             return [
17 0     0 1   { keyword => 'no_gen',
18             label => 'No Gen',
19             descr => 'Skip everything for this backend',
20             type => 'boolean' },
21              
22             { keyword => 'gantry_conf',
23             label => 'Use Gantry::Conf',
24             descr => 'check here if you use the Conf Gantry backend',
25             type => 'boolean', },
26              
27             { keyword => 'skip_config',
28             label => 'Skip Config',
29             descr => 'do not generate PerlSetVar statements ' .
30             '[checking gantry_conf makes this true]',
31             type => 'boolean' },
32              
33             { keyword => 'full_use',
34             label => 'Full Use Statement',
35             descr => 'use Gantry qw( -Engine=... ); [defaults to true]',
36             type => 'boolean',
37             default => 'true'},
38              
39             { keyword => 'gen_root',
40             label => 'Generate Root Path',
41             descr => q!used to make a default root on request, !
42             . q!now you get defaults by defaul!,
43             type => 'deprecated' },
44              
45             { keyword => 'template',
46             label => 'Alternate Template',
47             descr => 'A custom TT template.',
48             type => 'text' },
49             ];
50             }
51              
52             sub gen_HttpdConf {
53 0     0 1   my $class = shift;
54 0           my $base_dir = shift;
55 0           my $tree = shift;
56              
57             # write main file
58 0           my $configs = $tree->get_app_configs();
59 0           my $controller_configs = $tree->get_controller_configs();
60 0           my $conf_content = $class->output_httpd_conf( $tree, $configs, 'base' );
61              
62 0           my $docs_dir = File::Spec->catdir( $base_dir, 'docs' );
63 0           mkdir $docs_dir;
64              
65 0           my $conf_file = File::Spec->catfile( $docs_dir, 'httpd.conf' );
66              
67 0           Bigtop::write_file( $conf_file, $conf_content );
68              
69             # write other files
70 0           ALT_CONF:
71 0           foreach my $alt_conf ( keys %{ $configs } ) {
72 0 0         next ALT_CONF if $alt_conf eq 'base';
73 0 0         next ALT_CONF if $alt_conf =~ /CGI/i;
74 0           $conf_content = $class->output_httpd_conf(
75             $tree, $configs, $alt_conf, $controller_configs
76             );
77              
78 0           $conf_file = File::Spec->catfile( $docs_dir, "httpd.$alt_conf.conf" );
79              
80 0           Bigtop::write_file( $conf_file, $conf_content );
81             }
82             }
83              
84             sub output_httpd_conf {
85 0     0 1   my $class = shift;
86 0           my $tree = shift;
87 0           my $configs = shift;
88 0           my $config_type = shift; # the name of the config we want
89 0           my $controller_configs = shift;
90              
91 0           my $config = $tree->get_config->{HttpdConf};
92              
93 0   0       my $skip_config = $config->{skip_config} || 0;
94 0   0       my $gconf = $config->{gantry_conf} || 0;
95              
96 0           my $instance;
97             my $conffile;
98              
99 0 0         if ( $gconf ) {
100 0           $skip_config = 1;
101 0           my $gantry_config = $tree->get_config->{Conf};
102 0           $instance = $gantry_config->{instance};
103 0           $conffile = $gantry_config->{conffile};
104             }
105              
106             # let old timers go as before
107 0   0       $instance ||= $config->{instance } || 0;
      0        
108 0   0       $conffile ||= $config->{conffile } || 0;
      0        
109              
110 0 0 0       if ( $instance and defined $config_type and $config_type ne 'base' ) {
      0        
111 0           $instance .= "_$config_type";
112             }
113              
114             # first find the base location
115 0           my $location_output = $tree->walk_postorder( 'output_location' );
116 0   0       my $location = $location_output->[0] || ''; # default to host root
117 0           $location =~ s{/+$}{};
118              
119             # then find out if we have a base controller
120 0           my $base_handler = $tree->walk_postorder( 'base_handler_anyone' );
121 0 0         $base_handler = ( $base_handler->[0] ) ? $tree->get_appname : 0;
122              
123             # now build the and blocks
124 0           my $perl_block_lines = $tree->walk_postorder(
125             'output_perl_block',
126             $tree->get_config()
127             );
128 0           my $httpd_walk_output = $tree->walk_postorder(
129             'output_httpd_conf_locations',
130             {
131             location => $location,
132             skip_config => $skip_config,
133             instance => $instance,
134             conffile => $conffile,
135             base_handler => $base_handler,
136             configs => $configs,
137             config_type => $config_type,
138             controller_configs => $controller_configs,
139             }
140             );
141              
142 0           my %divided_output;
143 0           foreach my $output_el ( @{ $httpd_walk_output } ) {
  0            
144 0           my ( $type, $value ) = %{ $output_el };
  0            
145 0           push @{ $divided_output{ $type } }, $value;
  0            
146             }
147              
148             my $conf_file = Bigtop::Backend::HttpdConf::Gantry::conf_file(
149             {
150             perl_block_lines => $perl_block_lines,
151             locations => $divided_output{ locations },
152             }
153 0           );
154              
155 0           my %config_pairs;
156             CONFIG_PAIR:
157 0           foreach my $config_wrapper ( @{ $divided_output{ configs } } ) {
  0            
158 0 0         if ( ref( $config_wrapper ) eq 'ARRAY' ) {
159 0           foreach my $config_set ( @{ $config_wrapper } ) {
  0            
160 0           foreach my $config_item ( split /\n/, $config_set ) {
161 0           my ( undef, undef, $name, $value ) =
162             split /\s+/, $config_item;
163 0           $config_pairs{ $name } = $value;
164             }
165             }
166             }
167             else {
168 0 0         next CONFIG_PAIR unless defined $config_wrapper;
169 0           foreach my $config_item ( split /\n/, $config_wrapper ) {
170 0           my ( undef, undef, $name, $value ) =
171             split /\s+/, $config_item;
172 0           $config_pairs{ $name } = $value;
173             }
174             }
175             }
176              
177 0           return $conf_file;
178             }
179              
180             our $template_is_setup = 0;
181             our $default_template_text = <<'EO_TT_BLOCKS';
182             [% BLOCK conf_file %]
183             [% FOREACH line IN perl_block_lines %]
184             [% line %]
185             [% END %][%# end of foreach line in perl_block_lines %]
186              
187             [% FOREACH line IN locations %]
188             [% line %]
189             [% END %][%# end of foreach line in locations %]
190             [% END %]
191              
192             [% BLOCK perl_block %]
193            
194             #![% perl_path +%]
195              
196             [% FOREACH line IN top_lines %]
197             [% line %]
198             [% END %]
199             [% IF full_base_use %]
200             use [% base_module %] qw{
201             -PluginNamespace=[% base_module +%][% IF engine %]
202              
203             -Engine=[% engine %][% END %][% IF template_engine %]
204              
205             -TemplateEngine=[% template_engine %][% END %][% IF plugins %]
206              
207             [% plugins %]
208             [% END %][%# end of IF plugins +%]
209             };
210             [% ELSE %]
211             use [% base_module %];
212             [% END %]
213             [% FOREACH line IN child_output %]
214             [% line %]
215             [% END %]
216            
217             [% END %]
218              
219             [% BLOCK all_locations %]
220            
221             [% FOREACH config IN configs %][% config %][% END %]
222             [% FOREACH literal IN literals %][% literal %][% END %]
223             [% IF base_handler %]
224              
225             SetHandler perl-script
226             PerlHandler [% base_handler +%]
227              
228             [% END %]
229            
230              
231             [% FOREACH child_piece IN child_output %][% child_piece %][% END %]
232             [% END %][%# all_locations %]
233              
234             [% BLOCK config %]
235             PerlSetVar [% var %] [% value %]
236              
237             [% END %]
238              
239             [% BLOCK sub_locations %]
240            
241             SetHandler perl-script
242             PerlHandler [% handler %]
243             [% FOREACH config IN loc_configs %]
244              
245             [% config %]
246             [% END %]
247             [% IF literal %]
248              
249             [% literal %]
250             [% END %]
251              
252            
253              
254             [% END %]
255             EO_TT_BLOCKS
256              
257             sub setup_template {
258 0     0 1   my $class = shift;
259 0   0       my $template_text = shift || $default_template_text;
260              
261 0 0         return if ( $template_is_setup );
262              
263 0           Inline->bind(
264             TT => $template_text,
265             POST_CHOMP => 1,
266             TRIM_LEADING_SPACE => 0,
267             TRIM_TRAILING_SPACE => 0,
268             );
269              
270 0           $template_is_setup = 1;
271             }
272              
273             package # application
274             application;
275 1     1   1323 use strict; use warnings;
  1     1   2  
  1         30  
  1         6  
  1         2  
  1         407  
276              
277             sub output_perl_block {
278 0     0     my $self = shift;
279 0           my $child_output = shift;
280 0           my $config = shift;
281              
282 0           my $base_module = $self->get_name();
283              
284 0           my @top_lines;
285             my @regular_lines;
286              
287 0           foreach my $child_hash ( @{ $child_output } ) {
  0            
288 0           my ( $key, $value ) = each %{ $child_hash };
  0            
289              
290 0 0         if ( $key eq 'PerlTop' ) { push @top_lines, $value; }
  0            
291 0           else { push @regular_lines, $value; }
292             }
293              
294 0           my $backend_config = $config->{HttpdConf};
295 0           my $full_base_use = 1;
296              
297 0 0 0       if ( defined $backend_config->{full_use}
298             and
299             not $backend_config->{full_use} )
300             {
301 0           $full_base_use = 0;
302             }
303              
304 0           my $perl_path = $^X;
305              
306 0           my $output = Bigtop::Backend::HttpdConf::Gantry::perl_block(
307             {
308             base_module => $base_module,
309             child_output => \@regular_lines,
310             top_lines => \@top_lines,
311             full_base_use => $full_base_use,
312             perl_path => $perl_path,
313 0           %{ $config }, # in case full use is true
314             }
315             );
316              
317 0           return [ $output ];
318             }
319              
320             sub output_httpd_conf_locations {
321 0     0     my $self = shift;
322 0           my $child_output = shift;
323 0           my $data = shift;
324 0           my $location = $data->{location};
325 0           my $skip_config = $data->{skip_config};
326 0           my $configs = $data->{configs};
327 0           my $config_type = $data->{config_type};
328              
329             # handle configs at root location
330 0           my $config_output;
331 0 0         if ( $skip_config ) {
332 0 0         if ( $data->{ instance } ) {
333             $config_output .= Bigtop::Backend::HttpdConf::Gantry::config(
334             {
335             var => 'GantryConfInstance',
336             value => $data->{ instance },
337             }
338 0           );
339 0 0         if ( $data->{ conffile } ) {
340             $config_output .= Bigtop::Backend::HttpdConf::Gantry::config(
341             {
342             var => 'GantryConfFile',
343             value => $data->{ conffile },
344             }
345 0           );
346             }
347             }
348             }
349             else {
350 0           $config_output = $self->walk_postorder(
351             'output_configs', {
352             configs => $configs,
353             config_type => $config_type,
354             }
355             );
356             }
357 0           my $literals = $self->walk_postorder( 'output_root_literal' );
358              
359 0   0       my $output = Bigtop::Backend::HttpdConf::Gantry::all_locations(
360             {
361             root_loc => $location || '/',
362             configs => $config_output,
363             literals => $literals,
364             child_output => $child_output,
365             base_handler => $data->{base_handler},
366             }
367             );
368              
369 0           return [ { locations => $output, }, { configs => $config_output } ];
370             }
371              
372             package # app_config_block
373             app_config_block;
374 1     1   5 use strict; use warnings;
  1     1   2  
  1         22  
  1         5  
  1         1  
  1         293  
375              
376             sub get_conf_names {
377 0     0     my $self = shift;
378              
379 0 0         return unless defined $self->{__TYPE__};
380              
381 0           return [ $self->{__TYPE__} ];
382             }
383              
384             sub output_configs {
385 0     0     my $self = shift;
386 0           my $child_output = shift;
387 0           my $data = shift;
388 0           my $configs = $data->{ configs };
389 0   0       my $desired_type = $data->{ config_type } || 'base';
390              
391 0 0         return unless $child_output;
392              
393             # you can stay if:
394             # A. desired config_type is base and self type is undef or base
395             # B. desired config_type is self type
396             #my $own_type = ( defined $self->{__TYPE__} ) ? $self->{__TYPE__} : 'base';
397 0   0       my $own_type = $self->{__TYPE__} || 'base';
398              
399 0 0         return unless ( $own_type eq $desired_type );
400              
401 0           my $output;
402              
403             my %configs_set;
404 0           foreach my $config ( @{ $child_output } ) {
  0            
405 0           $output .= Bigtop::Backend::HttpdConf::Gantry::config(
406             {
407             var => $config->{__KEYWORD__},
408             value => $config->{__ARGS__},
409             }
410             );
411 0           $configs_set{ $config->{__KEYWORD__} }++;
412             }
413              
414             # fill in missing values from base config
415 0           my $gen_root = 1;
416              
417             BASE_KEY:
418 0           foreach my $base_key ( keys %{ $configs->{ base } } ) {
  0            
419 0 0         next BASE_KEY if $configs_set{ $base_key };
420              
421             $output .= Bigtop::Backend::HttpdConf::Gantry::config(
422             {
423             var => $base_key,
424 0           value => $configs->{ base }{ $base_key },
425             }
426             );
427              
428 0 0         $gen_root = 0 if ( $base_key eq 'root' );
429             }
430              
431 0 0         if ( $gen_root ) {
432 0           $output .= Bigtop::Backend::HttpdConf::Gantry::config(
433             {
434             var => 'root',
435             value => 'html:html/templates',
436             }
437             );
438             }
439              
440 0           return [ $output ];
441             }
442              
443             package # app_config_statement
444             app_config_statement;
445 1     1   5 use strict; use warnings;
  1     1   2  
  1         28  
  1         6  
  1         2  
  1         78  
446              
447             sub output_configs {
448 0     0     my $self = shift;
449 0           shift; # no children => no child output
450 0           my $data = shift;
451 0           my $output_vals = $self->{__ARGS__}->get_args();
452              
453             return [ {
454 0           __KEYWORD__ => $self->{__KEYWORD__},
455             __ARGS__ => $output_vals
456             } ];
457             }
458              
459             package # literal_block
460             literal_block;
461 1     1   5 use strict; use warnings;
  1     1   2  
  1         23  
  1         4  
  1         3  
  1         109  
462              
463             sub output_perl_block {
464 0     0     my $self = shift;
465              
466 0           my $retval = $self->make_output( 'PerlBlock', 'I want a hash' );
467              
468 0 0         return $retval if $retval;
469              
470 0           return $self->make_output( 'PerlTop', 'I want a hash' );
471             }
472              
473             sub output_root_literal {
474 0     0     my $self = shift;
475              
476 0           return $self->make_output( 'Location' );
477             }
478              
479             sub output_httpd_conf_locations {
480 0     0     my $self = shift;
481              
482 0           return $self->make_output( 'HttpdConf' );
483             }
484              
485             package # controller_block
486             controller_block;
487 1     1   6 use strict; use warnings;
  1     1   3  
  1         22  
  1         4  
  1         2  
  1         511  
488              
489             sub base_handler_anyone {
490 0     0     my $self = shift;
491              
492 0 0         return unless $self->is_base_controller;
493              
494 0           return [ 1 ];
495             }
496              
497             sub output_perl_block {
498 0     0     my $self = shift;
499 0           my $app = $self->{__PARENT__}{__PARENT__}{__PARENT__};
500 0           my $full_name = $app->get_name() . '::' . $self->get_name();
501              
502 0 0         return if ( $self->is_base_controller );
503              
504 0           return [ { PerlBlock => ' ' x 4 . "use $full_name;\n" } ];
505             }
506              
507             sub output_httpd_conf_locations {
508 0     0     my $self = shift;
509 0           my $child_output = shift;
510 0           my $data = shift;
511 0           my $location = $data->{location};
512 0           my $skip_config = $data->{skip_config};
513 0           my $base_config = $data->{base_config};
514 0           my $config_type = $data->{config_type};
515              
516 0 0         return if ( $self->is_base_controller );
517              
518 0           my %child_loc = @{ $child_output };
  0            
519              
520 0 0         if ( keys %child_loc != 1 ) {
521 0           die "Error: controller '" . $self->get_name()
522             . "' must have one location or rel_location statement.\n";
523             }
524              
525 0           my $app = $self->{__PARENT__}{__PARENT__}{__PARENT__};
526 0           my $full_name = $app->get_name() . '::' . $self->get_name();
527              
528 0           my $loc_configs = $self->walk_postorder(
529             'output_controller_configs', $data
530             );
531              
532 0           my $literals = $self->walk_postorder( 'output_location_literal' );
533              
534 0           my $child_location;
535              
536 0 0         if ( defined $child_loc{rel_location} ) {
537 0           $child_location = "$location/$child_loc{rel_location}";
538             }
539             else { # must be location
540 0           $child_location = $child_loc{location};
541             }
542              
543 0           my $output = Bigtop::Backend::HttpdConf::Gantry::sub_locations(
544             {
545             loc => $child_location,
546 0           literal => join( "\n", @{ $literals } ),
547             handler => $full_name,
548             loc_configs => $loc_configs,
549             }
550             );
551              
552 0           return [ $output ];
553             }
554              
555             package # controller_statement
556             controller_statement;
557 1     1   7 use strict; use warnings;
  1     1   2  
  1         27  
  1         5  
  1         2  
  1         121  
558              
559             sub output_httpd_conf_locations {
560 0     0     my $self = shift;
561              
562 0 0         if ( $self->{__KEYWORD__} eq 'rel_location' ) {
    0          
563 0           return [ rel_location => $self->{__ARGS__}->get_first_arg() ];
564             }
565             elsif ( $self->{__KEYWORD__} eq 'location' ) {
566 0           return [ location => $self->{__ARGS__}->get_first_arg() ];
567             }
568             else {
569 0           return;
570             }
571             }
572              
573             package # controller_config_block
574             controller_config_block;
575 1     1   5 use strict; use warnings;
  1     1   2  
  1         27  
  1         4  
  1         3  
  1         312  
576              
577             sub output_controller_configs {
578 0     0     my $self = shift;
579 0           my $child_output = shift;
580 0           my $data = shift;
581              
582 0           my $controller = $self->get_controller_name();
583 0           my $skip_config = $data->{ skip_config };
584 0           my $config_type = $data->{ config_type };
585 0           my $configs = $data->{ controller_configs }{ $controller };
586 0   0       my $own_type = $self->{__TYPE__} || 'base';
587              
588 0 0         return unless $child_output;
589 0 0         return if $skip_config;
590 0 0         return unless $own_type eq $config_type;
591              
592 0           my $output;
593             my %config_set_for;
594              
595 0           foreach my $config ( @{ $child_output } ) {
  0            
596 0           $output .= Bigtop::Backend::HttpdConf::Gantry::config(
597             {
598             var => $config->{__KEYWORD__},
599             value => $config->{__ARGS__},
600             }
601             );
602 0           $config_set_for{ $config->{__KEYWORD__} }++;
603             }
604              
605             # fill in omitted keys from the base block
606             CONTROLLER_BASE_KEY:
607 0           foreach my $base_key ( keys %{ $configs->{ base } } ) {
  0            
608 0 0         next CONTROLLER_BASE_KEY if $config_set_for{ $base_key };
609              
610             $output .= Bigtop::Backend::HttpdConf::Gantry::config(
611             {
612             var => $base_key,
613 0           value => $configs->{ base }{ $base_key },
614             }
615             );
616             }
617              
618 0           return [ $output ];
619             }
620              
621             package # controller_config_statement
622             controller_config_statement;
623 1     1   6 use strict; use warnings;
  1     1   1  
  1         24  
  1         5  
  1         1  
  1         118  
624              
625             sub output_controller_configs {
626 0     0     my $self = shift;
627              
628 0           my $output_vals = $self->{__ARGS__}->get_args();
629              
630             return [ {
631 0           __KEYWORD__ => $self->{__KEYWORD__},
632             __ARGS__ => $output_vals
633             } ];
634             }
635              
636             package # controller_literal_block
637             controller_literal_block;
638 1     1   5 use strict; use warnings;
  1     1   3  
  1         25  
  1         6  
  1         2  
  1         88  
639              
640             sub output_location_literal {
641 0     0     my $self = shift;
642              
643 0           return $self->make_output( 'Location' );
644             }
645              
646             1;
647              
648             =head1 NAME
649              
650             Bigtop::Backend::HttpdConf::Gantry - httpd.conf generator for the Gantry framework
651              
652             =head1 SYNOPSIS
653              
654             If your bigtop file includes:
655              
656             config {
657             HttpdConf Gantry {}
658             }
659              
660             and there are controllers in your app section, this module will generate
661             docs/httpd.conf when you type:
662              
663             bigtop app.bigtop HttpdConf
664              
665             or
666              
667             bigtop app.bigtop all
668              
669             You can then directly Include this conf in your system httpd.conf or in one
670             of its virtual hosts.
671              
672             =head1 DESCRIPTION
673              
674             This is a Bigtop backend which generates httpd.conf files.
675              
676             By default, this module converts every statement in an app or controller
677             level config block into a PerlSetVar statement. If you have a different
678             conf scheme in mind (like Gantry::Conf with flat files), you may not want
679             to define those set vars. In that, case do this in the Bigtop config section:
680              
681             config {
682             HttpdConf Gantry { skip_config 1; }
683             }
684              
685             Any PerlSetVar statements you put in literal Location statements will
686             still appear (remember: literal means literal). But, no PerlSetVar statements
687             will be made by the module.
688              
689             =head1 KEYWORDS
690              
691             This module does not register any keywords. See Bigtop::HttpdConf
692             for a list of allowed keywords (think app and controller level 'location'
693             and controller level 'rel_location' statements).
694              
695             =head1 METHODS
696              
697             To keep podcoverage tests happy.
698              
699             =over 4
700              
701             =item backend_block_keywords
702              
703             Tells tentmaker that I understand these config section backend block keywords:
704              
705             no_gen
706             gen_root
707             full_use
708             gantry_conf
709             skip_config
710             template
711              
712             instance
713             conffile
714              
715             Note that instance and conffile are deprecated. You should use the single
716             gantry_conf instead. Then the instance and conffile will be drawn from the
717             Conf Gantry backend's config block. This save duplicating that data.
718              
719             =item what_do_you_make
720            
721             Tells tentmaker what this module makes. Summary: docs/httpd.conf.
722              
723             =item gen_HttpdConf
724              
725             Called by Bigtop::Parser to get me to do my thing.
726              
727             =item output_httpd_conf
728              
729             What I call on the AST packages to do my thing.
730              
731             =item setup_template
732              
733             Called by Bigtop::Parser so the user can substitute an alternate template
734             for the hard coded one here.
735              
736             =back
737              
738             =head1 AUTHOR
739              
740             Phil Crow
741              
742             =head1 COPYRIGHT and LICENSE
743              
744             Copyright (C) 2005 by Phil Crow
745              
746             This library is free software; you can redistribute it and/or modify
747             it under the same terms as Perl itself, either Perl version 5.8.6 or,
748             at your option, any later version of Perl 5 you may have available.
749              
750             =cut