File Coverage

blib/lib/Mojolicious/Plugin/Facets.pm
Criterion Covered Total %
statement 90 90 100.0
branch 20 24 83.3
condition 2 3 66.6
subroutine 13 13 100.0
pod 1 1 100.0
total 126 131 96.1


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Facets;
2              
3 6     6   83402 use Mojo::Base 'Mojolicious::Plugin';
  6         16  
  6         35  
4 6     6   929 use Mojolicious::Routes;
  6         23  
  6         58  
5 6     6   182 use Mojolicious::Static;
  6         11  
  6         45  
6 6     6   172 use Mojolicious::Sessions;
  6         13  
  6         44  
7 6     6   156 use Mojo::Cache;
  6         13  
  6         40  
8 6     6   172 use Mojo::Path;
  6         13  
  6         44  
9 6     6   298 use constant DEBUG => $ENV{DEBUG_FACETS};
  6         12  
  6         7537  
10              
11             our $VERSION = "0.07";
12              
13              
14             my @facets;
15              
16             sub register {
17 6     6 1 222 my ($self, $app, $config) = @_;
18              
19 6         46 $app->hook(around_dispatch => \&_detect_facet);
20              
21 6         91 $app->helper(facet_do => \&_facet_do);
22              
23             $app->helper(has_facet => sub {
24 3     3   8573 my ($c, $name) = @_;
25 3 50       11 return unless $name;
26 3         6 for (@facets) {
27 5 100       20 return 1 if $_->{name} eq $name;
28             }
29 1         4 return;
30 6         139 });
31              
32             $app->helper(add_facet => sub {
33 1     1   10894 shift;
34 1         6 $self->_add_facet($app, @_);
35 6         106 });
36              
37 6         96 foreach my $facet_name (keys %$config) {
38 6         21 $self->_add_facet($app, $facet_name, $config->{$facet_name});
39             }
40             }
41              
42             sub _add_facet {
43 7     7   21 my ($self, $app, $facet_name, $facet_config) = @_;
44              
45 7 50       30 die "Missing 'setup' key on facet '$facet_name' config." unless $facet_config->{setup};
46             die "Missing 'host' or 'path' key on facet '$facet_name' config."
47 7 50 66     34 unless $facet_config->{host} || $facet_config->{path};
48              
49             my $facet = {
50             name => $facet_name,
51             host => $facet_config->{host},
52 7         23 routes => Mojolicious::Routes->new(namespaces => [@{ $app->routes->namespaces }]),
53             static => Mojolicious::Static->new,
54             sessions => Mojolicious::Sessions->new,
55 7         185 renderer_paths => [@{ $app->renderer->paths }],
56             renderer_cache => Mojo::Cache->new,
57 7 100       17 $facet_config->{path} ? ( path => Mojo::Path->new($facet_config->{path})->leading_slash(1)->trailing_slash(0) ) : (),
58             };
59              
60             # localize
61 7         513 local $app->{routes} = $facet->{routes};
62 7         21 local $app->{static} = $facet->{static};
63 7         18 local $app->{sessions} = $facet->{sessions};
64 7         21 local $app->renderer->{paths} = $facet->{renderer_paths};
65 7         44 local $app->renderer->{cache} = $facet->{renderer_cache};
66              
67             # setup
68 7         51 $facet_config->{setup}->($app);
69              
70             # store
71 7         2891 push @facets, $facet;
72             }
73              
74              
75             sub _detect_facet {
76 23     23   348486 my ($next, $c) = @_;
77              
78             # detect facet
79 23         50 my $active_facet;
80 23         121 my $req_host = $c->req->headers->host;
81 23         868 $req_host =~ s/:\d+$//;
82              
83 23         79 foreach my $facet (@facets) {
84              
85 24         45 my $match = 0;
86              
87 24 100       106 if ($facet->{host}) {
88 17 100       62 $match = 1 if $req_host eq $facet->{host};
89             }
90              
91 24 100       81 if ($facet->{path}) {
92              
93 7 100       50 if ($c->req->url->path->contains($facet->{path})) {
94 3         708 $match = 1;
95              
96             # rebase
97 3         6 my $path_length = scalar @{$facet->{path}};
  3         13  
98 3         33 my $base_path = $c->req->url->base->path->trailing_slash(1);
99 3         180 my $req_path = $c->req->url->path->leading_slash(0);
100              
101 3         174 while ($path_length--) {
102 3         9 push @$base_path, shift @$req_path;
103             }
104             }
105             else {
106 4         1515 $match = 0;
107             }
108             }
109              
110 24 100       129 if ($match) {
111 10         35 $active_facet = $facet;
112             last
113 10         23 }
114             }
115              
116             # localize relevant data and continue dispatch chain
117 23 100       68 if ($active_facet) {
118 10         16 DEBUG and $c->app->log->debug(qq/Dispatching facet "$active_facet->{name}"/);
119              
120 10         42 $c->stash->{'mojox.facet'} = $active_facet->{name};
121              
122 10         115 local $c->app->{routes} = $active_facet->{routes};
123 10         66 local $c->app->{static} = $active_facet->{static};
124 10         50 local $c->app->{sessions} = $active_facet->{sessions};
125 10         61 local $c->app->renderer->{paths} = $active_facet->{renderer_paths};
126 10         104 local $c->app->renderer->{cache} = $active_facet->{renderer_cache};
127 10         73 $next->();
128             }
129             else {
130             # no facet, continue dispatch
131 13         43 $next->();
132             }
133             }
134              
135              
136             sub _facet_do {
137 1     1   1623 my ($c, $facet_name, $code) = @_;
138              
139 1         3 my ($facet) = grep { $_->{name} eq $facet_name } @facets;
  1         5  
140 1 50       4 die "Facet '$facet_name' do not exist." unless $facet;
141              
142 1         3 local $c->app->{routes} = $facet->{routes};
143 1         6 local $c->app->{static} = $facet->{static};
144 1         15 local $c->app->{sessions} = $facet->{sessions};
145 1         7 local $c->app->renderer->{paths} = $facet->{renderer_paths};
146 1         7 local $c->app->renderer->{cache} = $facet->{renderer_cache};
147 1         7 local $c->{stash} = {};
148 1         13 $code->($c);
149             }
150              
151              
152              
153              
154              
155             1;
156             __END__