catlxom の プラグイン機構を plagger ライクに #0 (catlxom メモ #5)

前回のエントリの続き。実際に plagger の hook 機構をパクってみた。

これに合わせて、Entry::Blosxom と Template::TT も修正してますが、他のプラグインはまだ対応させてないので、動かないです。また、plugin 機構以外の、今までのエントリで挙げた修正もこの中に含まれてます。

あと、filter 部分はまだ着手してないです。ここだけ他の hook と扱いが違うので、どうすればキレイに実装できるかなぁ、と思案中。

Index: plugins/Entry/Blosxom.pm
===================================================================
--- plugins/Entry/Blosxom.pm    (revision 23)
+++ plugins/Entry/Blosxom.pm    (working copy)
@@ -9,6 +9,15 @@
 
 __PACKAGE__->classdata->{entries} = [];
 
+sub register {
+    my ($class, $c) = @_;
+    $c->catlxom->register_hook(
+        $class,
+        'setup'  => 'setup',
+        'update' => 'update',
+    );
+}
+
 sub setup {
     my ( $self, $c ) = @_;
 
@@ -44,20 +53,15 @@
                     )
                 }
             );
-
             push @{ $self->classdata->{entries} }, $entry;
         }
     );
 
-    $self->entries->add( __PACKAGE__ );
-
-    $self->NEXT::setup($c);
+    $c->catlxom->entries->add( __PACKAGE__ );
 }
 
 sub update {
     my ( $self, $c ) = @_;
-
-    $self->NEXT::update($c);
 }
 
 1;
Index: plugins/Template/TT.pm
===================================================================
--- plugins/Template/TT.pm  (revision 23)
+++ plugins/Template/TT.pm  (working copy)
@@ -10,15 +10,24 @@
 
 our $VERSION = '0.01';
 
+my $template_dir = Catlxom::Util::load_dir('template');
+my $path_root    = join '/', $template_dir->dir_list;
+
 __PACKAGE__->classdata->{templates} = {};
-__PACKAGE__->classdata->{tt}        = Template->new;
+__PACKAGE__->classdata->{tt}        = Template->new( INCLUDE_PATH => $path_root );
 
+sub register {
+    my ($class, $c) = @_;
+    $c->catlxom->register_hook(
+        $class,
+        'setup'       => 'setup',
+        'interpolate' => 'interpolate',
+    );
+}
+
 sub setup {
     my ( $self, $c ) = @_;
 
-    my $template_dir = Catlxom::Util::load_dir('template');
-    my $path_root    = join '/', $template_dir->dir_list;
-
     $template_dir->recurse(
         callback => sub {
             my $file = shift;
@@ -48,8 +57,6 @@
             };
         }
     );
-
-    $self->NEXT::setup($c);
 }
 
 sub interpolate {
@@ -78,16 +85,14 @@
             \$template->{template},
             {
                 name => $c->config->{name},
-                %{ $self->stashall },
-                entries => $self->entries->filtered,
+                %{ $c->catlxom->stashall },
+                entries => $c->catlxom->entries->filtered,
 
                 c => $c,
             },
             \$c->res->{body},
-        );
+        ) or $c->error( $self->classdata->{tt}->error );
     }
-
-    $self->NEXT::interpolate($c);
 }
 
 1;
Index: lib/Catlxom/Context/Base.pm
===================================================================
--- lib/Catlxom/Context/Base.pm (revision 23)
+++ lib/Catlxom/Context/Base.pm (working copy)
@@ -14,14 +14,8 @@
 
 sub setup {
     my ($self, $c) = @_;
-
     $self->plugin->load($c);
-    {
-        # plugin setup
-        no warnings 'redefine';
-        local *setup = sub { };
-        $self->setup($c);
-    }
+    $self->run_hook($c, 'setup');
 }
 
 sub initialize {
@@ -30,34 +24,48 @@
     $self->_stash( {} );
 }
 
-sub start       { }
-sub update      { }
-sub sort        { }
-sub paginate    { }
-sub fixedup     { }
-sub interpolate { }
-sub end         { }
+sub register_hook {
+    my ($self, $plugin, @hooks) = @_;
+    while (my($hook, $callback) = splice @hooks, 0, 2) {
+        push @{ $self->{hooks}->{$hook} }, {
+            callback  => $callback,
+            plugin    => $plugin,
+        };
+    }
+}
 
+sub run_hook {
+    my($self, $c, $hook) = @_;
+    for my $action (@{ $self->{hooks}->{$hook} }) {
+        my $plugin   = $action->{plugin};
+        my $callback = $action->{callback};
+        no strict 'refs';
+        $plugin->$callback($c);
+    }
+}
+
 sub dispatch {
     my ( $self, $c ) = @_;
 
-    $self->initialize($c);
+    $self->run_hook($c, 'initialize');
 
-    $self->start($c);
-    $self->update($c);
+    $self->run_hook($c, 'start');
+    $self->run_hook($c, 'update');
 
     $self->entries->filter($c);
-    $self->sort($c);
-    $self->paginate($c);
+    $self->run_hook($c, 'filter');
+    $self->run_hook($c, 'sort');
+    $self->run_hook($c, 'paginate');
 
-    $self->fixedup($c);
-    $self->interpolate($c);
-    $self->end($c);
+    $self->run_hook($c, 'fixedup');
+    $self->run_hook($c, 'interpolate');
+    $self->run_hook($c, 'end');
 }
 
 sub stash {
     my $self   = shift;
-    my $caller = caller(0);
+    ( my $caller = lc caller(0) ) =~ s/Catlxom::Plugin:://i;
+    $caller =~ s/::/_/g;
 
     if (@_) {
         my $stash = @_ > 1 ? {@_} : $_[0];
Index: lib/Catlxom/Plugins.pm
===================================================================
--- lib/Catlxom/Plugins.pm  (revision 23)
+++ lib/Catlxom/Plugins.pm  (working copy)
@@ -51,7 +51,7 @@
         ( my $plugin = 'Catlxom::Plugin::' . join( '::', @path ) . $file->basename )
             =~ s/\.pm$//;
 
-        unshift @Catlxom::Context::ISA, $plugin;
+        $plugin->register($c);
     }
 
     if ( $c->debug ) {