Evented-API-Engine
view release on metacpan or search on metacpan
lib/Evented/API/Module.pm view on Meta::CPAN
# Copyright (c) 2017, Mitchell Cooper
# Module represents an API module and provides an interface for managing one.
package Evented::API::Module;
use warnings;
use strict;
use 5.010;
use Evented::Object;
use parent 'Evented::Object';
use Scalar::Util qw(blessed weaken);
use List::Util qw(first);
our $VERSION = '4.13';
=head1 NAME
B<Evented::API::Module> - represents a module for use with
L<Evented::API::Engine>.
=head1 SYNOPSIS
# Module metadata
#
# @name: 'My::Module'
# @package: 'M::My::Module'
# @description:
#
# @depends.modules+ 'Some::Other'
# @depends.modules+ 'Another::Yet'
#
# @author.name: 'Mitchell Cooper'
# @author.website: 'https://github.com/cooper'
#
package M::My::Module;
use warnings;
use strict;
use 5.010;
# Auto-exported variables
our ($api, $mod);
# Default initializer
sub init {
say 'Loading ', $mod->name;
# indicates load success
return 1;
}
# Default deinitializer
sub void {
say 'Bye!';
# indicates unload success
return 1;
}
# Package must return module object
$mod;
=head1 DESCRIPTION
=head2 Module directory structure
Modules must be placed within one of the search directories specified in the
L<Evented:API::Engine> C<mod_inc> consturctor option or the C<dirs> option
of C<< ->load_module >> and similar Engine methods.
A module in its simplest form is a directory with the C<.module> extension
lib/Evented/API/Module.pm view on Meta::CPAN
$mod->Log("void stopped: ".$void_fire->stop);
$mod->Log("Can't unload: canceled by '$stopper'");
return;
}
# if this is a submodule, it isn't allowed to refuse to unload.
elsif ($stopper) {
$mod->Log(
"Warning! This submodule has requested to remain ".
'loaded, but submodules MUST be unloaded with their parent'
);
}
# void was successful
return 1;
}
##################
### SUBMODULES ###
##################
=head2 $mod->load_submodule($submod_name)
Loads a submodule.
This is generally used within the module initializer.
B<Parameters>
=over
=item *
B<$submod_name> - name of the submodule, without the parent module name prefix.
for instance if the full submodule name is C<My::Module::Sub>, this is simply
C<Sub>.
=back
B<Returns>
Submodule object on success, false otherwise.
=cut
sub load_submodule {
my ($mod, $mod_name) = @_;
$mod->Log("Loading submodule $mod_name");
# call ->load_module with the search dir set to the
# parent module's main directory.
$mod->api->{indent}++;
my $ret = $mod->api->load_module($mod_name, [ $mod->{dir} ], 1);
$mod->api->{indent}--;
# add weakly to submodules list. hold weak reference to parent module.
if ($ret) {
my $a = $mod->{submodules} ||= [];
push @$a, $ret;
weaken($a->[$#$a]);
weaken($ret->{parent} = $mod);
}
return $ret;
}
=head2 $mod->unload_submodule($submod)
Unloads a submodule.
You do not have to call this in the parent module deinitializer. Only use this
method if you want to dynamically unload a submodule for some reason without
unloading the parent module.
B<Parameters>
=over
=item *
B<$submod> - submodule object or name, without the parent module name prefix.
for instance if the full submodule name is C<My::Module::Sub>, this is simply
C<Sub>.
=back
=cut
sub unload_submodule {
my ($mod, $submod, $reloading) = @_;
my $submod_name = $submod->name;
$mod->Log("Unloading submodule $submod_name");
# unload
$mod->api->{indent}++;
# ($mod, $unload_dependents, $force, $unloading_submodule, $reloading)
#
# do not force, as that might unload the parent
# but do say we are unloading a submodule so it can be unloaded
# independently (which usually wouldn't be allowed)
#
$mod->api->unload_module($submod, undef, undef, 1, $reloading);
$mod->api->{indent}--;
# remove from submodules
if (my $submods = $mod->{submodules}) {
@$submods = grep { $_ != $submod } @$submods;
}
delete $submod->{parent};
return 1;
}
=head2 $mod->add_companion_submodule($mod_name, $submod_name)
Registers a submodule (provided by this module) as a companion of another
top-level module.
Companion submodules are submodules which are automatically loaded and unloaded
( run in 1.704 second using v1.01-cache-2.11-cpan-39bf76dae61 )