File Coverage

lib/Mojolicious/Plugin/Route.pm
Criterion Covered Total %
statement 93 94 98.9
branch 32 42 76.1
condition 10 15 66.6
subroutine 16 16 100.0
pod 1 1 100.0
total 152 168 90.4


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Route;
2              
3 3     3   2243 use Mojo::Base 'Mojolicious::Plugin';
  3         160293  
  3         21  
4 3     3   1315 use Mojo::Util 'camelize';
  3         12  
  3         154  
5 3     3   357 use Mojo::Loader 'load_class';
  3         27936  
  3         116  
6 3     3   18 use Carp;
  3         6  
  3         201  
7              
8 3         4171 use constant BASE => {
9             files => [],
10             references => {}
11 3     3   17 };
  3         6  
12              
13             our $VERSION = '0.09';
14              
15             sub register {
16 2     2 1 87 my ($self, $app, $conf) = @_;
17              
18 2         6 my ($moniker, $moniker_path) = $self->_get_moniker($app, $conf);
19 2   50     14 my $namespace = $conf->{namespace} // 'Route';
20 2   100     7 my $inverse = $conf->{inverse} // undef;
21 2         6 my $path_routes = $app->home . '/lib/' . $moniker_path;
22              
23 2 50       42 croak "Routes path ($path_routes) does not exist!" unless -d $path_routes;
24              
25 2         7 $path_routes =~ s/\/$//;
26 2         4 $path_routes .= '/' . $namespace;
27              
28 2 50       26 croak "Namespace ($namespace) does not exist!" unless -d $path_routes;
29              
30 2         7 $self->_find_files($path_routes);
31              
32 2         7 $self->_load_routes($app, $moniker, $namespace, $inverse);
33            
34 2         1112 $self->_clean_base;
35             }
36              
37             sub _find_files {
38 5     5   10 my ($self, $path, $find) = @_;
39              
40 5         6 my $more;
41 5   100     19 $find ||= '';
42              
43             # find files and folders
44 5         671 for my $file ( glob($path . '/*' . $find) ) {
45 15 100       166 if (-d $file) {
46 4         9 $more = '/*';
47              
48 4         6 next;
49             }
50              
51 11 50       108 push(@{BASE->{files}}, $1) if $file =~ /\/lib\/([\w\/]+)\.pm$/;
  11         44  
52             }
53              
54 5 100       15 if ($more) {
55 3         4 $find .= $more;
56 3         21 $self->_find_files($path, $find);
57             }
58             }
59              
60             sub _load_routes {
61 2     2   5 my ($self, $app, $moniker, $namespace, $inverse) = @_;
62              
63 2         5 my $base = $moniker . '::' . $namespace;
64            
65 2         12 my $routes = $app->routes;
66              
67 2         11 for my $file (@{BASE->{files}}) {
  2         4  
68 11         1327 $file =~ s/\//::/g;
69              
70 11         23 my $class = $self->_load_class($file);
71              
72 11 50 33     108 if ($class && $class->isa('MojoX::Route')) {
73 11         46 my $ref = $class->new(app => $app);
74              
75 11 100       78 $self->_any($routes, $ref, $file, $base, $inverse) if $class->can('any');
76 11 100       60 $self->_under($routes, $ref, $file, $base, $inverse) if $class->can('under');
77 11 100       109 $self->_route($routes, $ref, $file, $base, $inverse) if $class->can('route');
78             }
79             }
80             }
81              
82             sub _clean_base {
83 2     2   4 @{BASE->{files}} = ();
  2         6  
84 2         3 %{BASE->{references}} = ();
  2         12  
85             }
86              
87             sub _any {
88 2     2   4 my ($self, $routes, $ref, $file, $base, $inverse) = @_;
89              
90 2         4 my ($name, $ref_name) = $self->_ref_name($file, $base);
91            
92 2         3 my @params;
93 2 100       3 push(@params, BASE->{references}->{$ref_name}) if $self->_valid_reference($ref_name);
94 2         4 push(@params, $routes);
95              
96 2 50       6 my $any = $ref->any($inverse ? reverse(@params) : @params);
97              
98 2 50       467 BASE->{references}->{$name} = $any if $any;
99             }
100              
101             sub _under {
102 7     7   15 my ($self, $routes, $ref, $file, $base, $inverse) = @_;
103              
104 7         14 my ($name, $ref_name) = $self->_ref_name($file, $base);
105            
106 7         10 my @params;
107 7 100       14 push(@params, BASE->{references}->{$ref_name}) if $self->_valid_reference($ref_name);
108 7         12 push(@params, $routes);
109              
110 7 100       22 my $under = $ref->under($inverse ? reverse(@params) : @params);
111              
112 7 50       1979 BASE->{references}->{$name} = $under if $under;
113             }
114              
115             sub _route {
116 6     6   14 my ($self, $routes, $ref, $file, $base, $inverse) = @_;
117              
118 6         12 my ($name, $ref_name) = $self->_ref_name($file, $base);
119            
120 6         8 my @params;
121 6 100       10 push(@params, BASE->{references}->{$name}) if $self->_valid_reference($name);
122 6 100       12 push(@params, BASE->{references}->{$ref_name}) if $self->_valid_reference($ref_name);
123 6         8 push(@params, $routes);
124              
125 6 100       18 $ref->route($inverse ? reverse(@params) : @params);
126             }
127              
128             sub _ref_name {
129 15     15   23 my ($self, $name, $base) = @_;
130              
131 15         78 $name =~ s/${base}:://;
132 15         41 my ($ref_name) = $name =~ /^([\w:]+)::\w+$/;
133              
134 15         36 return ($name, $ref_name);
135             }
136              
137             sub _load_class {
138 11     11   16 my ($self, $class) = @_;
139              
140             # load class
141 11         26 my $e = load_class $class;
142              
143 11 50       5877 return $class unless $e;
144              
145 0         0 return;
146             }
147              
148             sub _get_moniker {
149 2     2   4 my ($self, $app, $conf) = @_;
150              
151             # set path lib
152 2         13 my $path = $app->home . '/lib/';
153              
154             # check if moniker is defined
155 2 50 33     109 return ($conf->{moniker}, $conf->{moniker}) if $conf->{moniker} && -d $path . $conf->{moniker};
156              
157             # check if need camelize moniker
158 2         12 my $moniker = camelize($app->moniker);
159            
160             # generate moniker path
161 2         50 my $moniker_path = $moniker;
162 2         3 $moniker_path =~ s/::/\//g;
163            
164 2 50       45 return ($app->moniker, $app->moniker) unless -d $path . $moniker_path;
165              
166 2         8 return ($moniker, $moniker_path);
167             }
168              
169             sub _valid_reference {
170 21     21   28 my ($self, $name) = @_;
171            
172 21   100     74 return $name && defined BASE->{references}->{$name};
173             }
174              
175             1;
176              
177             __END__