File Coverage

blib/lib/Catalyst/Action/Wizard.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Catalyst::Action::Wizard
4              
5             =head1 DESCRIPTION
6              
7             Actions like realization of wizards. You need this
8             if you have some multi-actions data gathering which unlikely
9             to be saved in session and to big to pass them
10             as POST or GET parameters.
11              
12             =head1 AUTHORS
13              
14             Pavel Boldin (), <davinchi@cpan.ru>
15              
16             =cut
17              
18             package Catalyst::Action::Wizard;
19              
20 1     1   770 use strict;
  1         3  
  1         38  
21 1     1   5 use warnings;
  1         2  
  1         33  
22              
23 1     1   1967 use Catalyst::Action;
  0            
  0            
24             use Catalyst::Wizard;
25             use Catalyst::Utils;
26             use MRO::Compat;
27              
28             use Scalar::Util;
29              
30             use base 'Catalyst::Action';
31              
32             our $VERSION = '0.008';
33              
34             sub refaddr($) {
35             sprintf "%x", Scalar::Util::refaddr(shift);
36             }
37              
38             sub _current_wizard {
39             return Catalyst::Wizard::_current_wizard(@_);
40             }
41              
42             sub _new_wizard {
43             my $c = shift;
44             my $wizard_id = shift || 'new';
45              
46             my $class = $c->config->{wizard}{class} || 'Catalyst::Wizard';
47              
48             Catalyst::Utils::ensure_class_loaded( $class );
49              
50             Catalyst::Wizard::DEBUG &&
51             Catalyst::Wizard->info( 'calling _new_wizard: '.$wizard_id );
52              
53             _current_wizard($c, $class->new( $c, $wizard_id ) );
54             }
55              
56             sub _dont_create_if_empty {
57             my $c = shift;
58             my $caller_pkg = shift;
59              
60             # check if not creating wizard in this caller package
61             if ( my $re = $c->config->{wizard}{_ignore_empty_wizard_call_pkg_re} ) {
62             return 1 if $caller_pkg =~ $re;
63             return;
64             }
65              
66             return unless exists $c->config->{wizard}{ignore_empty_wizard_call_pkg};
67              
68             my $config = $c->config->{wizard}{ignore_empty_wizard_call_pkg};
69              
70             return unless ref $config eq 'ARRAY';
71              
72             my @prefixes = grep { m/::$/o } @$config;
73             my @packages = grep { m/\w$/o } @$config;
74              
75             my @regexp;
76              
77             if ( @packages ) {
78             push @regexp, '^(?:'.join ('|', @packages).')$';
79             }
80              
81             if ( @prefixes ) {
82             push @regexp, '^(?:'.join ('|', @prefixes).')';
83             }
84              
85             my $regexp = join '|', @regexp;
86              
87             $regexp = qr/$regexp/o;
88              
89             $c->config->{wizard}{_ignore_empty_wizard_call_pkg_re} = $regexp;
90              
91             # pass thru
92             return _dont_create_if_empty( $c, $caller_pkg );
93             }
94              
95             sub wizard {
96             my $self = shift;
97             my $c = shift;
98              
99             if ( @_ ) {
100              
101             if ( ! _current_wizard( $c )
102             && $_[0] eq '-last'
103             && (
104             @_ == 3
105             || @_ == 2
106             )
107             ) {
108             shift;
109              
110             my $step_type = 'redirect';
111              
112             if ( @_ == 2 ) {
113             $step_type = shift;
114             $step_type =~ s/^-//g;
115              
116             if ( $step_type !~ m/redirect|detach|forward/ ) {
117             die "Unknown step type: $step_type";
118             }
119             }
120              
121             my $path = shift;
122              
123             my $fake_wizard = [ $c, $step_type, $path ];
124              
125             bless $fake_wizard, 'Catalyst::FakeWizard';
126              
127             return $fake_wizard;
128             }
129              
130             if ( !_current_wizard( $c ) ) {
131             _new_wizard( $c );
132             }
133              
134             _current_wizard($c)->add_steps(caller => [ caller ], @_);
135             } elsif( ! _current_wizard( $c )
136             && _dont_create_if_empty( $c, caller() )
137             ) {
138             return bless \(my $a = ''), 'Catalyst::FakeWizard';
139             }
140              
141             return _current_wizard($c);
142             }
143              
144             sub execute {
145             my $self = shift;
146             my ($controller, $c) = @_;
147              
148             #warn "executing: $self";
149              
150             if ( $self->name eq '_BEGIN' ) {
151             my $wizard_id = $c->can('wizard_id') ? $c->wizard_id
152             : exists $c->req->params->{wid} ? $c->req->params->{wid}
153             : ''
154             ;
155              
156             my $wizard_id_without_step;
157              
158             if ( $wizard_id ) {
159             ($wizard_id_without_step) = $wizard_id =~ /([0-9a-zA-Z]{32})/;
160             }
161              
162             if ( $wizard_id && $wizard_id_without_step ) {
163             _new_wizard( $c, $wizard_id );
164             }
165              
166             } elsif ( $self->name eq '_END' ) {
167             # $self->next::method(@_);
168             if ( _current_wizard( $c ) ) {
169             _current_wizard( $c )->save( $c );
170             }
171             # return;
172             } elsif ( $self->name !~ /^_(?:ACTION|DISPATCH|AUTO)/ ) {
173              
174             my @ret = eval { $self->next::method(@_) };
175              
176             # can be created in action
177             my $wizard = _current_wizard( $c );
178              
179             if ($wizard
180             &&
181             (
182             (
183             $@
184             && $@ eq $Catalyst::Wizard::GOTO_NEXT
185             )
186             || $wizard->{goto}
187             )
188             ) {
189             undef $@;
190             $wizard->perform_step( $c );
191             }
192             elsif ( $@ ) {
193             die $@;
194             }
195              
196             return wantarray ? @ret : $ret[0];
197             }
198              
199             $self->next::method(@_);
200             }
201              
202             1;