File Coverage

blib/lib/CGI/Application/Plugin/RunmodeDeclare.pm
Criterion Covered Total %
statement 89 89 100.0
branch 16 20 80.0
condition 4 5 80.0
subroutine 21 21 100.0
pod 3 3 100.0
total 133 138 96.3


line stmt bran cond sub pod time code
1             package CGI::Application::Plugin::RunmodeDeclare;
2             {
3             $CGI::Application::Plugin::RunmodeDeclare::VERSION = '0.10';
4             }
5              
6 5     5   75255 use warnings;
  5         11  
  5         177  
7 5     5   29 use strict;
  5         9  
  5         175  
8              
9             =head1 NAME
10              
11             CGI::Application::Plugin::RunmodeDeclare - Declare runmodes with keywords
12              
13             =head1 VERSION
14              
15             version 0.10
16              
17             =cut
18              
19 5     5   27 use base 'Devel::Declare::MethodInstaller::Simple';
  5         13  
  5         5989  
20 5     5   181006 use Carp qw(croak);
  5         16  
  5         1876  
21              
22             sub import {
23 9     9   14010 my $class = shift;
24 9         25 my $caller = caller;
25              
26 9         54 my %remap = (
27             runmode => runmode =>
28             startmode => startmode =>
29             errormode => errormode =>
30             invocant => '$self' =>
31             into => $caller,
32             @_ );
33              
34 9         86 $class->install_methodhandler(
35             into => $remap{into},
36             name => $remap{runmode},
37             pre_install => \&_setup_runmode,
38             invocant => $remap{invocant},
39             );
40 9         2140 $class->install_methodhandler(
41             into => $remap{into},
42             name => $remap{startmode},
43             pre_install => \&_setup_startmode,
44             invocant => $remap{invocant},
45             );
46 9         1574 $class->install_methodhandler(
47             into => $remap{into},
48             name => $remap{errormode},
49             pre_install => \&_setup_errormode,
50             invocant => $remap{invocant},
51             );
52             }
53              
54              
55             my %REGISTRY;
56             # per-macro setup
57             sub _split {
58 21     21   2954 my $n = shift; my ($p,$l) = $n =~ /^(.*?)(?:::(\w*))?$/; return ($p, $l);
  21         164  
  21         60  
59             }
60             sub _setup_runmode {
61 7     7   43 my ($fullname, $code) = @_;
62 7         26 my ($pkg, $name) = _split($fullname);
63 7     23   47 $pkg->add_callback( init => sub { $_[0]->run_modes([ $name ]) } );
  23         5228  
64             }
65             sub _setup_startmode {
66 6     6   37 my ($fullname, $code) = @_;
67 5     5   40 no strict 'refs'; no warnings 'uninitialized';
  5     5   9  
  5         169  
  5         27  
  5         10  
  5         1190  
68 6         18 my ($pkg, $name) = _split($fullname);
69             # compile time check
70 6 50       35 croak "start mode redefined (from $REGISTRY{$pkg}{start_mode_installed})" if $REGISTRY{$pkg}{start_mode_installed};
71             $pkg->add_callback(
72             init => sub {
73             # run time check
74 22 100   22   37494 return if exists $_[0]->{__START_MODE_SET_BY_RUNMODEDECLARE};
75 12         69 $_[0]->run_modes( [$name] );
76 12         311 $_[0]->start_mode($name);
77 12         110 $_[0]->{__START_MODE_SET_BY_RUNMODEDECLARE} = 1;
78             }
79 6         58 );
80 6         77 $REGISTRY{$pkg}{start_mode_installed} = $fullname;
81             }
82             sub _setup_errormode {
83 5     5   33 my ($fullname, $code) = @_;
84 5     5   32 no strict 'refs'; no warnings 'uninitialized';
  5     5   9  
  5         149  
  5         32  
  5         14  
  5         4339  
85 5         13 my ($pkg, $name) = _split($fullname);
86 5 50       28 croak "error mode redefined (from $REGISTRY{$pkg}{error_mode_installed})" if $REGISTRY{$pkg}{error_mode_installed};
87             $pkg->add_callback(
88             init => sub {
89 16 100   16   1647 return if exists $_[0]->{__ERROR_MODE_SET_BY_RUNMODEDECLARE};
90 12         58 $_[0]->error_mode($name);
91 12         124 $_[0]->{__ERROR_MODE_SET_BY_RUNMODEDECLARE} = 1;
92             }
93 5         64 );
94 5         71 $REGISTRY{$pkg}{error_mode_installed} = $fullname;
95             }
96              
97             =begin pod-coverage
98              
99             =over 4
100              
101             =item strip_name - we hook into this to install cgiapp callbacks
102              
103             =item parse_proto - proto parser
104              
105             =item inject_parsed_proto - turn it into code
106              
107             =back
108              
109             =end pod-coverage
110              
111             =cut
112              
113             sub strip_name {
114 18     18 1 5450 my $ctx = shift;
115              
116 18         78 my $name = $ctx->SUPER::strip_name;
117 18         591 $ctx->{pre_install}->($ctx->get_curstash_name . '::' . $name);
118              
119 18         144 return $name;
120             }
121              
122             sub parse_proto {
123 18     18 1 968 my $self = shift;
124 18         28 my ($proto) = @_;
125 18   100     83 $proto ||= '';
126 18         37 $proto =~ s/[\r\n]/ /sg;
127 18         35 $proto =~ s/^\s+//; $proto =~ s/\s+$//;
  18         35  
128              
129 18         33 my $invocant = $self->{invocant};
130 18 50       54 $invocant = $1 if $proto =~ s{^(\$\w+):\s*}{};
131              
132 22 50       159 my @args =
133 18         69 map { m{^ ([\$@%])(\w+) }x ? [$1, $2] : () }
134             split /\s*,\s*/,
135             $proto
136             ;
137              
138             return (
139 18         80 $invocant,
140             $proto,
141             @args,
142             );
143             }
144              
145             # Turn the parsed signature into Perl code
146             sub inject_parsed_proto {
147 18     18 1 68 my $self = shift;
148 18         101 my ($invocant, $proto, @args) = @_;
149              
150 18         24 my @code;
151 18         43 push @code, "my $invocant = shift;";
152 18 100 66     115 push @code, "my ($proto) = \@_;" if defined $proto and length $proto;
153              
154 18         31 for my $sig (@args) {
155 22         40 my ($sigil, $name) = @$sig;
156 22 100       67 push @code, _default_for($sigil,$name,$invocant) if $sigil eq '$'; # CA->param only handles scalars
157 22         52 push @code, _default_for($sigil,$name,"${invocant}->query");
158 22 100       86 push @code, _php_style_default_for($sigil,"${name}","${invocant}->query") if $sigil eq '@'; # support PHP-style foo[] params
159             }
160              
161 18         112 return join ' ', @code;
162             }
163              
164             sub _default_for {
165 38     38   50 my $sigil = shift;
166 38         50 my $name = shift;
167 38         43 my $invocant = shift;
168              
169             return
170 38 100       193 "${sigil}${name} = ${invocant}->param('${name}') unless "
171             . ( $sigil eq '$' ? 'defined' : '' )
172             . " ${sigil}${name}; ";
173              
174             }
175              
176             sub _php_style_default_for {
177 6     6   10 my $sigil = shift;
178 6         17 my $name = shift;
179 6         10 my $invocant = shift;
180              
181 6         14 my $varname = $name . '[]';
182             return
183 6         32 "${sigil}${name} = ${invocant}->param('${name}[]') unless "
184             . " ${sigil}${name}; ";
185              
186             }
187              
188              
189             1; # End of CGI::Application::Plugin::RunmodeDeclare
190              
191             __END__