File Coverage

blib/lib/Dancer/Plugin/Dispatcher.pm
Criterion Covered Total %
statement 65 65 100.0
branch 20 26 76.9
condition 7 14 50.0
subroutine 10 10 100.0
pod 0 3 0.0
total 102 118 86.4


line stmt bran cond sub pod time code
1             # ABSTRACT: Simple yet Powerful Controller Class dispatcher for Dancer
2              
3             package Dancer::Plugin::Dispatcher;
4             {
5             $Dancer::Plugin::Dispatcher::VERSION = '0.12';
6             }
7              
8             our $VERSION = '0.12'; # VERSION
9              
10              
11 3     3   1435023 use strict;
  3         9  
  3         136  
12 3     3   21 use warnings;
  3         6  
  3         110  
13 3     3   19 use Dancer qw/:syntax/;
  3         11  
  3         22  
14 3     3   4520 use Dancer::Plugin;
  3         4900  
  3         3250  
15              
16             our $CONTROLLERS;
17              
18             # automation ... sorta
19              
20             sub dispatcher {
21 15 50   15 0 43 return unless config->{plugins};
22              
23 15         118 our $cfg = config->{plugins}->{Dispatcher};
24 15         93 our $base = $cfg->{base};
25              
26             # check for a base class in the configuration
27 15 100       36 if ($base) {
28 14 100       31 unless ($CONTROLLERS) {
29 3         6 my $base_file = $base;
30 3         5 $base_file =~ s/::/\//gi;
31 3         6 $base_file .= '.pm';
32              
33 3 100       86 eval "require $base" unless $INC{$base_file};
34 3         13 $CONTROLLERS->{$base}++;
35             }
36             }
37             else {
38 1         10 ($base) = caller(1);
39 1   50     5 $base ||= 'main';
40             }
41              
42             sub BUILDCODE {
43              
44 21     21 0 20 my $code;
45              
46             # define the input
47 21         32 my $shortcut = shift;
48              
49             # format the shortcut
50 21         60 my ($class, $action) = split /#/, $shortcut;
51 21 100       43 if ($class) {
52              
53             # run through the filters
54 9         19 $class = ucfirst $class;
55 9         13 $class =~ s/([a-z])\-([a-z])/$1::\u$2/gpi;
56 9         11 $class =~ s/([a-z])\_([a-z])/$1\u$2/gpi;
57              
58             # prepend base to class if applicable
59 9 50       31 $class = join "::", $base, $class if $base;
60             }
61             else {
62              
63 12 50       31 $class = $base if $base;
64             }
65              
66             # build the return code (+chain if specified)
67             $code = sub {
68              
69 13     13   46 my $class_file = $class;
70 13         34 $class_file =~ s/::/\//gi;
71 13         18 $class_file .= '.pm';
72              
73 13 100       608 eval "require $class" unless $INC{$class_file};
74 13         44 $CONTROLLERS->{$class_file}++;
75              
76 13         78 debug lc "dispatching $class -> $action";
77 13 50 33     655 $class->$action(@_) if $class && $action;
78 21         104 };
79              
80 21         69 return $code;
81              
82             }
83              
84 15         25 my @codes = map { BUILDCODE($_) } @_;
  21         40  
85             my $code = sub {
86 11     11   24153 my @args = @_;
87 11         18 my $data;
88 11         32 foreach my $code (@codes) {
89              
90             # HOW I WISH IT COULD WORK
91             #-- break if content is set
92             #-- last if Dancer::SharedData->response->content;
93              
94             # HOW IT MUST WORK
95             # execute code
96             # break if content is returned or
97             # if redirect was issued
98 13         55 $data = $code->(@args);
99 13 100 100     24855 last if $data || Dancer::SharedData->response->status =~ /^3\d\d$/;
100             }
101 11         82 return $data;
102 15         109 };
103              
104 15         47 return $code;
105             }
106              
107             sub auto_dispatcher {
108 3 50   3 0 16 return unless config->{plugins};
109              
110 3         44 our $cfg = config->{plugins}->{Dispatcher};
111 3         18 foreach my $route (@{$cfg->{routes}}) {
  3         11  
112 5         1812 my $re = qr/([a-z,]+) *([^\s>]+) *> *(.*)/;
113 5         59 my ($m, $r, $s) = $route =~ $re;
114 5         18 foreach my $i (split /,/, $m) {
115 6 50 33     445 if ($i && $r && $s) {
      33        
116 6         43 my $c = dispatcher(split(/[\s,]/, $s));
117 6 100       17 if ($i eq 'get') {
118             Dancer::App->current->registry->universal_add($_, $r, $c)
119 5         24 for ('get', 'head');
120             }
121             else {
122 1         5 Dancer::App->current->registry->universal_add($i, $r, $c);
123             }
124             }
125             }
126             }
127             }
128              
129 9     9   1896 register dispatch => sub { dispatcher @_ };
130              
131             register_plugin;
132             auto_dispatcher;
133              
134             1;
135              
136             __END__