[Catalyst] MyApp::C::PageHooks - thoughts ?

Matthew Pitts mpitts at a3its.com
Mon Oct 29 20:24:10 GMT 2007


I wanted to get some thoughts on something a little different that I'm
doing...

What I want to to have is Controllers that are temporary (i.e. date
sensitive) that represent a particular "promotion" that's running on a
site. This promotion may need to affect different areas of the site, but
I don't want to have $c->forward calls like the following everywhere
that I need the Promo's code to inject stash data.

$c->forward('Controller::Promos::Foo', 'some_action') 

So, I decided to do a form of "hooks" within my app so that any given
controller can affect the stash for a defined set of hooks.

Below is the first run of my code to implement this. Basically, I
override Controller->register_actions and run through all the
controllers looking for C->config->{pagehooks} and build a local hashref
containing the hook definitions.

Then, in all the places throughout the app that are defined as
"hookable" I just do a:

$c->forward('Controller::PageHooks', 'run_hook', 'hook_name', [ 'arg1',
'arg2' ]);

and it "just works".

The main advantage with is that I can remove the promo's controller and
don't need to change any other controllers. I can even get my design
guys to code their templates in such a way that when the promo expires,
every place on the site affected by the promo magically goes back to
pre-promo look-and-feel.

Any thoughts on my level of sanity here?

package MyApp::Controller::PageHooks;
use base 'Catalyst::Controller';

use strict;
use warnings;

my $HOOKS = {};

sub register_actions {
    my $self = shift;
    my ( $c ) = @_;
    
    $self->register_hooks($c);
    
    return $self->SUPER::register_actions(@_);
}

sub register_hooks {
    my ( $self, $c ) = @_;
    
    my @ctrls = $c->controllers;
    
    foreach my $ctrl (@ctrls) {
        my $ctrl_ref = $c->controller($ctrl);
        
        if ( $ctrl_ref->config->{pagehooks} ) {
            my $hook = $ctrl_ref->config->{pagehooks};
            while ( my ($hook, $action) = each(%{$hook}) ) {
                $HOOKS->{$hook} ||= ();
                push @{$HOOKS->{$hook}}, [ $ctrl, $action ];    
            }
        }
    }
}

sub run_hook : Private {
    my ( $self, $c, $hook, @args ) = @_;
    
    if ( $hook && $HOOKS->{$hook} ) {
        foreach my $action_ref (@{$HOOKS->{$hook}}) {
            my $ctrl = $c->controller($action_ref->[0]);
            my $act  = $ctrl->action_for($action_ref->[1]);
            
            if ( $ctrl && $act ) {
                $c->forward($action_ref->[0], $action_ref->[1], \@args);
            }
        }
    }    
}

1;

-- 
Matthew W. Pitts
Software Engineer
mpitts at a3its.com
336.202.3913 (mobile)

A3 IT Solutions, LLC
www.a3its.com





More information about the Catalyst mailing list