Mojolicious-Plugin-Fondation
view release on metacpan or search on metacpan
lib/Mojolicious/Plugin/Fondation.pm view on Meta::CPAN
Mojolicious::Plugin::Fondation - Hierarchical plugin loader with configuration priority and resource sharing
=head1 VERSION
version 0.03
=head1 SYNOPSIS
# In your Mojolicious application (myapp.pl or startup)
plugin 'Fondation' => {
dependencies => [
{ 'Fondation::User' => { title => 'Custom User' } },
'Fondation::Authorization',
],
};
# In a plugin (e.g. lib/Mojolicious/Plugin/Fondation/User.pm)
package Mojolicious::Plugin::Fondation::User;
use Mojo::Base 'Mojolicious::Plugin', -signatures;
sub fondation_meta {
return {
dependencies => [],
defaults => {
title => 'User Management',
items_per_page => 20,
},
};
}
sub register ($self, $app, $conf) {
$app->routes->get('/users' => sub ($c) { $c->render(text => "Users!") });
return $self; # Important for finalyze actions
}
sub fondation_finalyze ($self, $app, $long_name) {
# Optional: code to run after all plugins are loaded
$self->log->debug("User plugin fully loaded");
}
1;
=head1 DESCRIPTION
Fondation attempts to provide a foundation for building websites from
pre-built bricks. It is a plugin loader for Mojolicious that enables
hierarchical, recursive plugin loading with automatic configuration
merging, resource sharing (controllers, templates), and post-load actions.
It is designed for modular applications where multiple plugins contribute
routes, templates, and behavior, while avoiding duplicate loads and
respecting configuration priorities.
Key features:
=over 4
=item * Recursive plugin loading via C<dependencies>
=item * Configuration cascade: direct > app config > plugin defaults
=item * Automatic discovery and registration of C<share/templates>
=item * Application-level C<share/templates> have priority
=item * Extensible post-load actions (Templates, Controllers, custom)
=item * Deferred initialization via C<fondation_finalyze>
=item * Contextual logging via C<< $self->log >> (Mojo::Log context)
=back
=head1 LOADING ORDER
1. load_plugin_recursive
ââ Fondation -> dependencies recursively
2. run_post_load_actions
ââ For every plugin (load order), execute all actions
(Templates, Controllers, custom)
ââ App-level share/templates added with highest priority
3. run_finalyze
ââ For every plugin (load order), call fondation_finalyze()
=head1 QUICK START
# myapp.pl
use Mojolicious::Lite;
plugin 'Fondation' => {
dependencies => [
'Fondation::User',
'Fondation::Authorization',
],
};
# Fondation loads Authorization, which depends on Role + Permission.
# Result: Role -> Permission -> Authorization -> User
# All share/templates and controllers are auto-discovered.
=head2 With a config file
# myapp.conf
{
'Fondation' => {
dependencies => ['Fondation::User', 'Fondation::Authorization'],
},
'Fondation::User' => {
title => 'User Management',
},
}
# myapp.pl
plugin 'Config';
plugin 'Fondation'; # reads dependencies from config
=head1 CONFIGURATION PRIORITIES
Each plugin receives a merged configuration built from three sources,
combined with L<Hash::Merge>. The cascade priority is:
=head3 1. Direct configuration (passed in C<dependencies> array)
plugin 'Fondation' => {
dependencies => [
{ 'Fondation::User' => { title => 'Direct override' } },
],
};
=head3 2. Application configuration file (e.g. myapp.conf)
{
'Fondation::User' => {
title => 'From config file',
}
}
=head3 3. Plugin defaults (returned by C<fondation_meta>)
sub fondation_meta {
return {
defaults => { title => 'Default value' },
};
}
The merge rules are:
=over 4
=item * Scalars -- overwrite. The highest-priority non-empty value wins.
=item * Hashes -- merged recursively. Keys present at multiple levels are resolved
by priority; keys present at only one level survive untouched.
=item * Arrays -- concatenated. All values from all levels are kept, ordered
by priority: direct elements first, then app config, then defaults.
=back
Example: a plugin declares C<allowed_roles =E<gt> ['user']> in its defaults,
the app config adds C<allowed_roles =E<gt> ['editor']>, and a direct dependency
passes C<allowed_roles =E<gt> ['admin']>. The merged result is
C<['admin', 'editor', 'user']> -- all three roles are available, with the
highest-priority one first.
The C<dependencies> key is not special -- it follows the same array
concatenation rules. This means an app config can add extra dependencies
without repeating those already declared.
=head1 RESOURCE DIRECTORIES (share/)
Fondation automatically handles shared resources from plugins:
=over 4
=item * C<share/templates> -> pushed to C<$app->renderer->paths>
=item * C<share/public> -> pushed to C<$app->static->paths>
=back
( run in 2.114 seconds using v1.01-cache-2.11-cpan-9581c071862 )