Plaggerのソースコード読む(4)

Plaggerのソースコード読む(2)の続き。


今回はPluginのロードについて。


まずload_pluginsメソッド(Plagger.pmです)。

    $self->load_plugins(@{ $config->{plugins} || [] });

$config->{plugins}の中身は、(2)の変数をDumpしたのを見たらわかると思う。
一応書くと、

'plugins' => [
               {
                'config' => {
                             'feed' => [
                                         {
                                          'url' => 'http://d.hatena.ne.jp/tayaya/rss'
                                         }
                                       ]
                             },
                'module' => 'Subscription::Config'
               },
            ・
            ・
            ・
             [

こんな感じで、各Pluginの設定が入ってる。
ちなみにGlobalな設定は$self->conf (Plugin側からは$context->conf) でアクセスできます。


load_pluginsの中を見てみると、

    my $plugin_path = $self->conf->{plugin_path} || [];
       $plugin_path = [ $plugin_path ] unless ref $plugin_path;

Globalのplugin_path(外部Pluginのパス)をとってくる。
配列になってるとこからわかるように、plugin_pathは複数設定できるということですね。


次。

    for my $path (@$plugin_path) {
    ・
    ・
    ・

このforループでは、plugin_pathで設定したディレクトリ内に
PlaggerのPluginファイルがあるかどうかを調べ、
Pluginファイルがあれば$self->plugins_pathに($self->conf->plugin_pathじゃないですよ)
そのパスを設定、ということをやっています。


ここでは
File::SpecやFile::Find::Ruleモジュール、ファイルテスト演算子など、
パスやファイルの扱い方に関して結構勉強になると思うので、
興味のある方はみてみると良いかもしれません。


外部Pluginのパスを設定し終わったら、いよいよconfig.yamlに書いたPluginをロードしていきます。

    for my $plugin (@plugins) {
        $self->load_plugin($plugin) unless $plugin->{disable};
    }

@pluginsはload_pluginsを呼ぶときに渡された @{$config->plugins} です。


ではload_pluginの中身。

    my $module = delete $config->{module};
    $module =~ s/^Plagger::Plugin:://;
    $module = "Plagger::Plugin::$module";

$moduleに「Plagger::Plugin::*」と、正式名称(?)を代入しています。
$module =~ s/^Plagger::Plugin:://; がなぜ書いてあるかよくわからないのですが、
昔はconfig.yamlには

  - module: Plagger::Plugin::Subscription::Config

みたいに書くようにしてたのかな?(古いconfig.yamlと互換性もたせるため?)


とりあえず続き。

    if ($module->isa('Plagger::Plugin')) {
        $self->log(debug => "$module is loaded elsewhere ... maybe .t script?");
    } elsif (my $path = $self->plugins_path->{$module}) {
        eval { require $path } or die $@;
    } else {
        $module->require or die $@;
    }

ここがPluginをロードしてる所です。
まず、

    if ($module->isa('Plagger::Plugin')) {

Pluginがすでにロードされているかどうかを調べ、
ロードされていなければ

    } elsif (my $path = $self->plugins_path->{$module}) {
        eval { require $path } or die $@;

外部Pluginのpathをrequire。
どちらでもなければ

$module->require or die $@;

普通にrequireします。


とまあさらっと書いたんですが、
2番目のrequire $pathの部分。
$pathには 'C:\plugin\Sample.pm' みたいにパスが入ってます。
ということは下のようになるわけで、

require 'C:\plugin\Sample.pm';

こんな風にパスでもrequireできるんですね。
初めて知りました。へえー。


最後です。

    my $plugin = $module->new($config);
    $plugin->cache( Plagger::CacheProxy->new($plugin, $self->cache) );
    $plugin->register($self);

    push @{$self->{plugins}}, $plugin;

Pluginをnewし、
cache、registerを呼び出します。


そして
@{$self->{plugins}}にpushして終了です。


registerは重要なので、次回にでも書いていきたいと思います。