File Coverage

lib/Mojolicious/Plugin/Fondation/Manager.pm
Criterion Covered Total %
statement 99 102 97.0
branch 19 24 79.1
condition 5 10 50.0
subroutine 10 13 76.9
pod 0 3 0.0
total 133 152 87.5


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Fondation::Manager;
2             $Mojolicious::Plugin::Fondation::Manager::VERSION = '0.03';
3             # ABSTRACT: Plugin registry, post-load actions, and finalyze initialization
4              
5 13     13   108 use Mojo::Base -base, -signatures;
  13         23  
  13         86  
6 13     13   3792 use Mojolicious::Plugin::Fondation::Utils qw(find_share_dir share_relative);
  13         25  
  13         23870  
7              
8             has 'app';
9             has 'config';
10             has 'api';
11              
12             has registry => sub { {} };
13             has load_order => sub { [] };
14             has fixture_sets => sub { [] };
15             has log => undef;
16              
17             has action_classes => sub ($self) {
18             my $short_list = $self->config->{actions} // ['Templates', 'Controllers', 'Static'];
19             my %seen = map { $_ => 1 } @$short_list;
20             my @all = @$short_list;
21              
22             for my $long (@{$self->load_order}) {
23             my $meta = $self->registry->{$long}{fondation_meta} // {};
24             for my $short (@{ $meta->{provides_actions} // [] }) {
25             next if $seen{$short}++;
26             push @all, $short;
27             }
28             }
29              
30             return [ map { $self->_resolve_action_class($_) } @all ];
31             };
32              
33             # ---------------------------------------------------------------------------
34             # load_all -- instantiate plugins from a pre-sorted list (from Resolver)
35             # ---------------------------------------------------------------------------
36 66     66 0 105 sub load_all ($self, $sorted_specs) {
  66         106  
  66         89  
  66         79  
37 66   33     383 $self->{log} //= $self->app->log->context('[Fondation]');
38              
39 66         1584 for my $spec (@$sorted_specs) {
40 161         597 my $long = $spec->{long};
41 161         228 my $short = $spec->{short};
42 161         247 my $merged = $spec->{config};
43 161         208 my $meta = $spec->{meta};
44              
45 161 100       275 next if $self->registry->{$long};
46              
47             # Fondation itself is registered by the caller
48 95 50       454 next if $long eq 'Mojolicious::Plugin::Fondation';
49              
50 95         236 $self->log->debug("Loading plugin $short");
51              
52 95         1546 my $instance = $self->_prepare_and_register($long, $short, $merged);
53              
54 95         368 my $share_dir = find_share_dir($long, $merged->{share_dir});
55              
56 95         2559 $self->registry->{$long} = {
57             instance => $instance,
58             short_name => $short,
59             share_dir => $share_dir,
60             config => $merged,
61             loaded_at => time,
62             metadata => { has_templates => 0, has_assets => 0 },
63             fondation_meta => $meta,
64             };
65              
66 95         434 push @{$self->load_order}, $long;
  95         206  
67             }
68             }
69              
70 95     95   128 sub _prepare_and_register ($self, $long, $short, $merged) {
  95         134  
  95         122  
  95         121  
  95         128  
  95         120  
71 95         173 my $app = $self->app;
72              
73             # 1. Loading the Instance (without Register)
74 95         350 my $instance = $app->plugins->load_plugin($long);
75              
76             # 2. Injection of the contextual logger before register
77 95         28796 $instance->{log} = $app->log->context("[$short]");
78              
79             # 3. Inject the ->log method if it doesn't exist
80 95 100       3053 unless ($instance->can('log')) {
81 35     2   186 Mojo::Util::monkey_patch(ref($instance), log => sub { shift->{log} });
  2     2   24  
        0      
        0      
        0      
82             }
83              
84             # 4. Calling the register (the logger is now available)disponible)
85 95         821 $instance->register($app, $merged);
86              
87 95         16029 return $instance;
88             }
89              
90 198     198   288 sub _resolve_action_class ($self, $short) {
  198         334  
  198         272  
  198         226  
91 198 50       348 return $short if $short =~ /^Mojolicious::/;
92              
93 198         283 for my $long (@{$self->load_order}) {
  198         312  
94 485   50     1041 my $meta = $self->registry->{$long}{fondation_meta} // {};
95 485   100     1824 my $provides = $meta->{provides_actions} // [];
96             return "${long}::Action::${short}"
97 485 100       906 if grep { $_ eq $short } @$provides;
  18         63  
98             }
99 193         650 return "Mojolicious::Plugin::Fondation::Action::${short}";
100             }
101              
102 161     161   222 sub _run_post_load_actions_for ($self, $long, $conf = {}) {
  161         228  
  161         201  
  161         228  
  161         217  
103 161         351 my $plugin = $self->registry->{$long}{instance};
104 161 50 33     1168 return unless $plugin && ref $plugin;
105 161         279 my $share_dir = $self->registry->{$long}{share_dir};
106              
107 161         516 for my $action_class (@{$self->action_classes}) {
  161         322  
108 486 100       46239 eval "require $action_class; 1" or do {
109 4         18 $self->log->warn("Action $action_class not loaded: $@");
110 4         69 next;
111             };
112              
113 482         4032 my ($action_short) = $action_class =~ /::Action::(.+)$/;
114 482         1448 my $action_log = $self->app->log->context("[$action_short >]");
115              
116 482         15739 my $action = $action_class->new(
117             manager => $self,
118             log => $action_log,
119             );
120 482         3102 $action->after_load($long, $conf, $share_dir);
121             }
122             }
123              
124 66     66 0 98 sub run_post_load_actions ($self) {
  66         91  
  66         121  
125 66         110 my $count = scalar @{$self->action_classes};
  66         163  
126 66         170 $self->log->debug("Running post-load actions for all plugins ($count configured)");
127              
128 66         870 for my $long (@{$self->load_order}) {
  66         134  
129 161         2112 $self->_run_post_load_actions_for($long);
130             }
131              
132             # Add local 'share/templates'
133 66         1046 my $app_templates = $self->app->home->child('share', 'templates');
134 66 100       1508 if (-d $app_templates) {
135 1         22 unshift @{$self->app->renderer->paths}, $app_templates->to_string;
  1         3  
136 1         15 $self->log->debug("App templates priority: " . share_relative($app_templates));
137             }
138              
139             # Add local 'public'
140 66         2828 my $app_public = $self->app->home->child('public');
141 66 100       1344 if (-d $app_public) {
142 1         17 unshift @{$self->app->static->paths}, $app_public->to_string;
  1         5  
143 1         17 $self->log->debug("App public priority: " . share_relative($app_public));
144             }
145             }
146              
147 66     66 0 115 sub run_finalyze ($self) {
  66         105  
  66         92  
148 66         178 $self->log->debug("Running fondation_finalyze in loading order");
149              
150 66         780 for my $long (@{$self->load_order}) {
  66         154  
151 161         516 my $entry = $self->registry->{$long};
152 161         591 my $plugin = $entry->{instance};
153              
154 161 50       330 if (! defined $plugin) {
155 0         0 $self->log->info("Skipped finalyze for $long");
156 0         0 next;
157             }
158              
159 161 100       756 if ($plugin->can('fondation_finalyze')) {
160             eval {
161 27         61 $plugin->fondation_finalyze($self->app, $long);
162 27         586 1;
163 27 50       42 } or do {
164 0           die "Error in fondation_finalyze for $long: $@";
165             };
166             }
167             }
168             }
169              
170             1;
171              
172             __END__