File Coverage

inc/Plack/Builder.pm
Criterion Covered Total %
statement 49 78 62.8
branch 5 22 22.7
condition 3 9 33.3
subroutine 14 22 63.6
pod 0 9 0.0
total 71 140 50.7


line stmt bran cond sub pod time code
1             #line 1
2 4     4   1789 package Plack::Builder;
  4         8  
  4         140  
3 4     4   1647 use strict;
  4         930  
  4         16  
4             use parent qw( Exporter );
5             our @EXPORT = qw( builder add enable enable_if mount );
6 4     4   214  
  4         6  
  4         47  
7 4     4   1800 use Carp ();
  4         38792  
  4         101  
8 4     4   1881 use Plack::App::URLMap;
  4         5789  
  4         93  
9 4     4   20 use Plack::Middleware::Conditional; # TODO delayed load?
  4         5  
  4         2568  
10             use Scalar::Util ();
11              
12 4     4 0 7 sub new {
13 4         18 my $class = shift;
14             bless { middlewares => [ ] }, $class;
15             }
16              
17 4     4 0 10 sub add_middleware {
18             my($self, $mw, @args) = @_;
19 4 50       21  
20 4         20 if (ref $mw ne 'CODE') {
21 4     4   34 my $mw_class = Plack::Util::load_class($mw, 'Plack::Middleware');
  4         38  
22             $mw = sub { $mw_class->wrap($_[0], @args) };
23             }
24 4         10  
  4         33  
25             push @{$self->{middlewares}}, $mw;
26             }
27              
28 0     0 0 0 sub add_middleware_if {
29             my($self, $cond, $mw, @args) = @_;
30 0 0       0  
31 0         0 if (ref $mw ne 'CODE') {
32 0     0   0 my $mw_class = Plack::Util::load_class($mw, 'Plack::Middleware');
  0         0  
33             $mw = sub { $mw_class->wrap($_[0], @args) };
34             }
35 0         0  
36 0     0   0 push @{$self->{middlewares}}, sub {
37 0         0 Plack::Middleware::Conditional->wrap($_[0], condition => $cond, builder => $mw);
38             };
39             }
40              
41             # do you want remove_middleware() etc.?
42              
43 0     0   0 sub _mount {
44             my ($self, $location, $app) = @_;
45 0 0       0  
46 0         0 if (!$self->{_urlmap}) {
47             $self->{_urlmap} = Plack::App::URLMap->new;
48             }
49 0         0  
50 0         0 $self->{_urlmap}->map($location => $app);
51             $self->{_urlmap}; # for backward compat.
52             }
53              
54 4     4 0 8 sub to_app {
55             my($self, $app) = @_;
56 4 50       11  
    0          
57 4         14 if ($app) {
58             $self->wrap($app);
59 0 0       0 } elsif ($self->{_urlmap}) {
60             $self->{_urlmap} = $self->{_urlmap}->to_app
61 0         0 if Scalar::Util::blessed($self->{_urlmap});
62             $self->wrap($self->{_urlmap});
63 0         0 } else {
64             Carp::croak("to_app() is called without mount(). No application to build.");
65             }
66             }
67              
68 4     4 0 7 sub wrap {
69             my($self, $app) = @_;
70 4 50 33     17  
71 0         0 if ($self->{_urlmap} && $app ne $self->{_urlmap}) {
72             Carp::carp("WARNING: wrap() and mount() can't be used altogether in Plack::Builder.\n" .
73             "WARNING: This causes all previous mount() mappings to be ignored.");
74             }
75 4         13  
  4         12  
76 4         9 for my $mw (reverse @{$self->{middlewares}}) {
77             $app = $mw->($app);
78             }
79 4         111  
80             $app;
81             }
82              
83             # DSL goes here
84             our $_add = our $_add_if = our $_mount = sub {
85             Carp::croak("enable/mount should be called inside builder {} block");
86             };
87 4     4 0 25  
88 0     0 0 0 sub enable { $_add->(@_) }
89             sub enable_if(&$@) { $_add_if->(@_) }
90              
91 0     0 0 0 sub mount {
92 0 0       0 my $self = shift;
93 0         0 if (Scalar::Util::blessed($self)) {
94             $self->_mount(@_);
95 0         0 }else{
96             $_mount->($self, @_);
97             }
98             }
99              
100 4     4 0 54 sub builder(&) {
101             my $block = shift;
102 4         29  
103             my $self = __PACKAGE__->new;
104 4         5  
105 4         45 my $mount_is_called;
106             my $urlmap = Plack::App::URLMap->new;
107 0     0   0 local $_mount = sub {
108 0         0 $mount_is_called++;
109 0         0 $urlmap->map(@_);
110 4         56 $urlmap;
111             };
112 4     4   15 local $_add = sub {
113 4         12 $self->add_middleware(@_);
114             };
115 0     0   0 local $_add_if = sub {
116 4         12 $self->add_middleware_if(@_);
117             };
118 4         25  
119             my $app = $block->();
120 4 50       24  
121 0 0       0 if ($mount_is_called) {
122 0         0 if ($app ne $urlmap) {
123             Carp::carp("WARNING: You used mount() in a builder block, but the last line (app) isn't using mount().\n" .
124             "WARNING: This causes all mount() mappings to be ignored.\n");
125 0         0 } else {
126             $app = $app->to_app;
127             }
128             }
129 4 50 33     39  
      33        
130             $app = $app->to_app if $app and Scalar::Util::blessed($app) and $app->can('to_app');
131 4         15  
132             $self->to_app($app);
133             }
134              
135             1;
136              
137             __END__