Ado

 view release on metacpan or  search on metacpan

lib/Ado/Plugin.pm  view on Meta::CPAN

package Ado::Plugin;
use Mojo::Base 'Mojolicious::Plugin';
use Mojo::Util qw(decamelize class_to_path decode);

File::Spec::Functions->import(qw(catfile catdir));

has app => sub { Mojo::Server->new->build_app('Ado') };
has name => sub {

    # Only the last word of the plugin's package name
    (ref $_[0] || $_[0]) =~ /(\w+)$/ && return $1;
};

#has config_dir => sub { $_[0]->app->home->rel_dir('etc/plugins') };
has config_dir => sub {
    catdir($_[0]->home_dir, 'etc', 'plugins');
};

has home_dir => sub {
    my $p = $INC{class_to_path(ref($_[0]))};

    # /home/you/dev/Ado-Plugin-Foo/lib/Ado/Plugin/Foo.pm
    # /home/you/dev/Ado-Plugin-Foo
    $p =~ s|[\\/]lib.+||x
      || return $_[0]->app->home;
    return $p;
};
has ext => 'conf';

has config_classes => sub {
    {   conf => 'Mojolicious::Plugin::Config',
        json => 'Mojolicious::Plugin::JSONConfig',
        pl   => 'Mojolicious::Plugin::Config'
    };
};

sub _get_plugin_config {
    my ($self) = @_;
    state $app              = $self->app;
    state $mode             = $app->mode;
    state $home             = $app->home;
    state $local_config_dir = catdir($home, 'etc', 'plugins');
    my $config_dir   = $self->config_dir;
    my $ext          = $self->ext;
    my $name         = decamelize($self->name);
    my $config       = {};
    my $config_class = $self->config_classes->{$ext};
    if (my $e = Mojo::Loader::load_class($config_class)) {
        Carp::croak ref $e ? "Exception: $e" : $config_class . ' - Not found!';
    }
    my @config_paths = ("$config_dir/$name.$ext", "$config_dir/$name.$mode.$ext");
    push @config_paths, "$local_config_dir/$name.$ext", "$local_config_dir/$name.$mode.$ext"
      if $local_config_dir ne $config_dir;

    #Try global, global.mode, local, local.mode
    foreach my $f (@config_paths) {
        if (-f $f) {
            my $specific =
              eval { $config_class->new->load($f, {}, $app) } || Carp::croak($@);
            $config = {%$config, %$specific};
        }
    }
    return $config;
}

#plugin configuration getter
sub config {
    my ($self, $key, $value) = @_;
    $self->{config} //= $self->_get_plugin_config();
    if (defined $value) {
        $self->{config}->{$key} = $value;
        return $self->{config};
    }
    return $key
      ? $self->{config}->{$key}
      : $self->{config};
}

# one place for initializing plugins in register()
sub initialise {
    my ($self, $app, $conf) = @_;

    $self->app($app);    #!Needed in $self->config!
    state $mode = $app->mode;

    #Merge passed configuration with configuration
    #from  etc/ado.conf and etc/plugins/$name.conf
    for my $k (keys %$conf) { $self->config($k => $conf->{$k}); }
    $conf = $self->config;

    # Add namespaces if defined.
    push @{$app->routes->namespaces}, @{$conf->{namespaces}}
      if @{$conf->{namespaces} || []};

    # Load routes if defined.
    $app->load_routes($conf->{routes}) if (@{$conf->{routes} || []});

    # Add templates folder if the plugin is not in the same folder
    my $templates_dir = catdir($self->home_dir, 'templates');
    if ((!List::Util::first { $templates_dir eq $_ // '' } @{$app->renderer->paths})
        && -d $templates_dir)
    {
        push @{$app->renderer->paths}, $templates_dir;
    }

    # Add plugin specific public folder if differs from app public
    my $public_dir = catdir($self->home_dir, 'public');
    if ((!List::Util::first { $public_dir eq $_ // '' } @{$app->static->paths})
        && -d $public_dir)
    {
        push @{$app->static->paths}, $public_dir;
    }

    return ($self, $app, $conf);
}



( run in 0.781 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )