File Coverage

blib/lib/Mojolicious/Plugin/Facets.pm
Criterion Covered Total %
statement 81 81 100.0
branch 17 20 85.0
condition 2 3 66.6
subroutine 9 9 100.0
pod 1 1 100.0
total 110 114 96.4


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Facets;
2              
3 6     6   106133 use Mojo::Base 'Mojolicious::Plugin';
  6         23  
  6         55  
4 6     6   1344 use Mojolicious::Routes;
  6         40  
  6         95  
5 6     6   274 use Mojolicious::Static;
  6         19  
  6         65  
6 6     6   235 use Mojolicious::Sessions;
  6         18  
  6         62  
7 6     6   271 use Mojo::Cache;
  6         20  
  6         62  
8 6     6   230 use Mojo::Path;
  6         18  
  6         80  
9              
10             our $VERSION = "0.05";
11              
12             my @facets;
13              
14             sub register {
15 6     6 1 364 my ($self, $app, $config) = @_;
16              
17 6         48 $app->hook(around_dispatch => \&_detect_facet);
18 6         158 $app->helper(facet_do => \&_facet_do);
19              
20 6         164 my @default_static_paths = @{ $app->static->paths };
  6         31  
21 6         83 my @default_renderer_paths = @{ $app->renderer->paths };
  6         23  
22 6         64 my @default_routes_namespaces = @{ $app->routes->namespaces };
  6         30  
23              
24 6         90 foreach my $facet_name (keys %$config) {
25              
26 6         22 my $facet_config = $config->{$facet_name};
27 6 50       41 die "Missing 'setup' key on facet '$facet_name' config." unless $facet_config->{setup};
28             die "Missing 'host' or 'path' key on facet '$facet_name' config."
29 6 50 66     42 unless $facet_config->{host} || $facet_config->{path};
30              
31             my $facet = {
32             name => $facet_name,
33             host => $facet_config->{host},
34             routes => Mojolicious::Routes->new(namespaces => [@default_routes_namespaces]),
35             static => Mojolicious::Static->new,
36             sessions => Mojolicious::Sessions->new,
37             renderer_paths => [@default_renderer_paths],
38             renderer_cache => Mojo::Cache->new,
39 6 100       44 $facet_config->{path} ? ( path => Mojo::Path->new($facet_config->{path})->leading_slash(1)->trailing_slash(0) ) : (),
40             };
41              
42             # localize
43 6         588 local $app->{routes} = $facet->{routes};
44 6         21 local $app->{static} = $facet->{static};
45 6         92 local $app->{sessions} = $facet->{sessions};
46 6         32 local $app->renderer->{paths} = $facet->{renderer_paths};
47 6         48 local $app->renderer->{cache} = $facet->{renderer_cache};
48              
49             # setup
50 6         64 $facet_config->{setup}->($app);
51              
52             # store
53 6         3432 push @facets, $facet;
54             }
55              
56             }
57              
58             sub _detect_facet {
59 22     22   528125 my ($next, $c) = @_;
60              
61             # detect facet
62 22         68 my $active_facet;
63 22         170 my $req_host = $c->req->headers->host;
64 22         915 $req_host =~ s/:\d+$//;
65              
66 22         121 foreach my $facet (@facets) {
67              
68 22         75 my $match = 0;
69              
70 22 100       139 if ($facet->{host}) {
71 17 100       113 $match = 1 if $req_host eq $facet->{host};
72             }
73              
74 22 100       119 if ($facet->{path}) {
75              
76 5 100       50 if ($c->req->url->path->contains($facet->{path})) {
77 2         709 $match = 1;
78              
79             # rebase
80 2         8 my $path_length = scalar @{$facet->{path}};
  2         10  
81 2         51 my $base_path = $c->req->url->base->path->trailing_slash(1);
82 2         187 my $req_path = $c->req->url->path->leading_slash(0);
83              
84 2         161 while ($path_length--) {
85 2         8 push @$base_path, shift @$req_path;
86             }
87             }
88             else {
89 3         1552 $match = 0;
90             }
91             }
92              
93 22 100       155 if ($match) {
94 9         30 $active_facet = $facet;
95             last
96 9         62 }
97             }
98              
99             # localize relevant data and continue dispatch chain
100 22 100       104 if ($active_facet) {
101 9         72 $c->app->log->debug(qq/Dispatching facet "$active_facet->{name}"/);
102              
103 9         791 $c->stash->{'mojox.facet'} = $active_facet->{name};
104              
105 9         155 local $c->app->{routes} = $active_facet->{routes};
106 9         88 local $c->app->{static} = $active_facet->{static};
107 9         86 local $c->app->{sessions} = $active_facet->{sessions};
108 9         79 local $c->app->renderer->{paths} = $active_facet->{renderer_paths};
109 9         131 local $c->app->renderer->{cache} = $active_facet->{renderer_cache};
110 9         159 $next->();
111             }
112             else {
113             # no facet, continue dispatch
114 13         61 $next->();
115             }
116             }
117              
118              
119             sub _facet_do {
120 1     1   2159 my ($c, $facet_name, $code) = @_;
121              
122 1         3 my ($facet) = grep { $_->{name} eq $facet_name } @facets;
  1         4  
123 1 50       5 die "Facet '$facet_name' do not exist." unless $facet;
124              
125 1         4 local $c->app->{routes} = $facet->{routes};
126 1         6 local $c->app->{static} = $facet->{static};
127 1         6 local $c->app->{sessions} = $facet->{sessions};
128 1         5 local $c->app->renderer->{paths} = $facet->{renderer_paths};
129 1         8 local $c->app->renderer->{cache} = $facet->{renderer_cache};
130 1         6 local $c->{stash} = {};
131 1         3 $code->($c);
132             }
133              
134              
135              
136              
137              
138             1;
139             __END__