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.02';
3             # ABSTRACT: Plugin registry, post-load actions, and finalyze initialization
4              
5 13     13   74 use Mojo::Base -base, -signatures;
  13         21  
  13         85  
6 13     13   3806 use Mojolicious::Plugin::Fondation::Utils qw(find_share_dir share_relative);
  13         24  
  13         24508  
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 106 sub load_all ($self, $sorted_specs) {
  66         108  
  66         94  
  66         92  
37 66   33     377 $self->{log} //= $self->app->log->context('[Fondation]');
38              
39 66         1540 for my $spec (@$sorted_specs) {
40 161         627 my $long = $spec->{long};
41 161         243 my $short = $spec->{short};
42 161         241 my $merged = $spec->{config};
43 161         220 my $meta = $spec->{meta};
44              
45 161 100       378 next if $self->registry->{$long};
46              
47             # Fondation itself is registered by the caller
48 95 50       468 next if $long eq 'Mojolicious::Plugin::Fondation';
49              
50 95         215 $self->log->debug("Loading plugin $short");
51              
52 95         1540 my $instance = $self->_prepare_and_register($long, $short, $merged);
53              
54 95         410 my $share_dir = find_share_dir($long, $merged->{share_dir});
55              
56 95         2506 $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         445 push @{$self->load_order}, $long;
  95         212  
67             }
68             }
69              
70 95     95   119 sub _prepare_and_register ($self, $long, $short, $merged) {
  95         153  
  95         127  
  95         115  
  95         112  
  95         122  
71 95         171 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         29239 $instance->{log} = $app->log->context("[$short]");
78              
79             # 3. Inject the ->log method if it doesn't exist
80 95 100       2992 unless ($instance->can('log')) {
81 35     2   191 Mojo::Util::monkey_patch(ref($instance), log => sub { shift->{log} });
  2     2   56  
        0      
        0      
        0      
82             }
83              
84             # 4. Calling the register (the logger is now available)disponible)
85 95         863 $instance->register($app, $merged);
86              
87 95         15692 return $instance;
88             }
89              
90 198     198   249 sub _resolve_action_class ($self, $short) {
  198         452  
  198         266  
  198         209  
91 198 50       381 return $short if $short =~ /^Mojolicious::/;
92              
93 198         259 for my $long (@{$self->load_order}) {
  198         332  
94 485   50     1157 my $meta = $self->registry->{$long}{fondation_meta} // {};
95 485   100     1903 my $provides = $meta->{provides_actions} // [];
96             return "${long}::Action::${short}"
97 485 100       892 if grep { $_ eq $short } @$provides;
  18         75  
98             }
99 193         687 return "Mojolicious::Plugin::Fondation::Action::${short}";
100             }
101              
102 161     161   236 sub _run_post_load_actions_for ($self, $long, $conf = {}) {
  161         209  
  161         217  
  161         250  
  161         232  
103 161         378 my $plugin = $self->registry->{$long}{instance};
104 161 50 33     1152 return unless $plugin && ref $plugin;
105 161         298 my $share_dir = $self->registry->{$long}{share_dir};
106              
107 161         507 for my $action_class (@{$self->action_classes}) {
  161         300  
108 486 100       46913 eval "require $action_class; 1" or do {
109 4         14 $self->log->warn("Action $action_class not loaded: $@");
110 4         65 next;
111             };
112              
113 482         3943 my ($action_short) = $action_class =~ /::Action::(.+)$/;
114 482         1561 my $action_log = $self->app->log->context("[$action_short Action]");
115              
116 482         15848 my $action = $action_class->new(
117             manager => $self,
118             log => $action_log,
119             );
120 482         3254 $action->after_load($long, $conf, $share_dir);
121             }
122             }
123              
124 66     66 0 101 sub run_post_load_actions ($self) {
  66         100  
  66         96  
125 66         129 my $count = scalar @{$self->action_classes};
  66         201  
126 66         234 $self->log->debug("Running post-load actions for all plugins ($count configured)");
127              
128 66         916 for my $long (@{$self->load_order}) {
  66         153  
129 161         2132 $self->_run_post_load_actions_for($long);
130             }
131              
132             # Add local 'share/templates'
133 66         1152 my $app_templates = $self->app->home->child('share', 'templates');
134 66 100       1707 if (-d $app_templates) {
135 1         15 unshift @{$self->app->renderer->paths}, $app_templates->to_string;
  1         17  
136 1         15 $self->log->debug("App templates priority: " . share_relative($app_templates));
137             }
138              
139             # Add local 'public'
140 66         3014 my $app_public = $self->app->home->child('public');
141 66 100       1339 if (-d $app_public) {
142 1         14 unshift @{$self->app->static->paths}, $app_public->to_string;
  1         4  
143 1         13 $self->log->debug("App public priority: " . share_relative($app_public));
144             }
145             }
146              
147 66     66 0 112 sub run_finalyze ($self) {
  66         101  
  66         93  
148 66         182 $self->log->debug("Running fondation_finalyze in loading order");
149              
150 66         835 for my $long (@{$self->load_order}) {
  66         169  
151 161         512 my $entry = $self->registry->{$long};
152 161         679 my $plugin = $entry->{instance};
153              
154 161 50       303 if (! defined $plugin) {
155 0         0 $self->log->info("Skipped finalyze for $long");
156 0         0 next;
157             }
158              
159 161 100       738 if ($plugin->can('fondation_finalyze')) {
160             eval {
161 27         57 $plugin->fondation_finalyze($self->app, $long);
162 27         548 1;
163 27 50       46 } or do {
164 0           die "Error in fondation_finalyze for $long: $@";
165             };
166             }
167             }
168             }
169              
170             1;
171              
172             __END__