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