File Coverage

blib/lib/Class/Handler.pm
Criterion Covered Total %
statement 12 47 25.5
branch 0 22 0.0
condition n/a
subroutine 4 7 57.1
pod 0 2 0.0
total 16 78 20.5


line stmt bran cond sub pod time code
1              
2             # $Id: Handler.pm,v 1.3 2000/09/12 19:43:02 nwiger Exp $
3             #################################################################
4             #
5             # Copyright (c) 2000, Nathan Wiger
6             #
7             # Class::Handler - Create Apache-like pseudoclass event handlers
8             #
9             #################################################################
10              
11             require 5.003;
12             package Class::Handler;
13              
14 1     1   588 use strict;
  1         2  
  1         37  
15 1     1   6 no strict 'refs';
  1         1  
  1         32  
16 1     1   5 use vars qw(@EXPORT @ISA $VERSION $AUTOLOAD);
  1         13  
  1         91  
17              
18 1     1   5 use Exporter;
  1         2  
  1         606  
19             @ISA = qw(Exporter);
20             @EXPORT = qw(handler nohandler);
21              
22             # Internal recordkeeping
23             my %HANDLERS;
24              
25             # Both of these functions are exported, and basically just work by
26             # pushing stuff in and out of arrays and hashes. The AUTOLOAD
27             # routine is then used for the meat of everything.
28              
29             sub handler ($@) {
30              
31 0     0 0   my($handler, @classes) = @_;
32              
33             # If no package name, we simply prefix the caller's
34             # package name to it.
35              
36 0           my $pkg = caller;
37 0 0         $handler = "$pkg\::$handler" unless $handler =~ /^\w+::\w+/;
38              
39             # If the handler is new, all we have to do is add Class::Handler
40             # to @ISA for the handler name, since we want our own AUTOLOAD
41             # to handle method dispatch.
42              
43 0 0         @{"${handler}::ISA"} = ('Class::Handler') unless exists $HANDLERS{$handler};
  0            
44              
45             # We push the new classes onto the end of the handler list.
46             # We do not allow multiple instances of the same class because
47             # this is most likely an error caused by duplicate or overlapping
48             # importing of modules.
49              
50 0           for my $c (@classes) {
51 0 0         next if grep /^$c$/, @{$HANDLERS{$handler}};
  0            
52 0 0         push @{$HANDLERS{$handler}}, $c or return undef;
  0            
53             }
54 0           return 1;
55             }
56              
57              
58             sub nohandler ($@) {
59              
60 0     0 0   my($handler, @classes) = @_;
61              
62             # First, remove the selected classes from the handler list
63             # Again, first check to make sure we have a full pkg name
64              
65 0           my $pkg = caller;
66 0 0         $handler = "$pkg\::$handler" unless $handler =~ /^\w+::\w+/;
67              
68 0           my @tmp_classes;
69 0           for my $c (@classes) {
70 0           for my $ec (@{$HANDLERS{$handler}}) {
  0            
71 0 0         next if $c eq $ec;
72 0           push @tmp_classes, $ec;
73             }
74 0           $HANDLERS{$handler} = \@tmp_classes;
75             }
76              
77             # Check to see if we have anything left; if not, remove the
78             # @ISA array and delete the %HANDLERS hash entry. Testing
79             # @tmp_classes instead of the handlers list will implicitly
80             # catch the single-arg syntax used for removing handlers.
81              
82 0 0         unless (@tmp_classes) {
83 0           undef @{"${handler}::ISA"};
  0            
84 0           delete $HANDLERS{$handler};
85             }
86              
87 0           return 1;
88             }
89              
90             sub AUTOLOAD {
91              
92             # This does all the real work, attempting to use each of the
93             # methods from a given handler's classes in turn.
94 0     0     my($ret, @ret);
95              
96             # Chop our $AUTOLOAD down
97 0           my($handler, $method) = $AUTOLOAD =~ m/^(.*)::(\w+)$/g;
98              
99             # For each class listed in the %HANDLERS list, we try to use
100             # its method in turn. If it doesn't exist or returns undef,
101             # we go to the next one in line.
102              
103 0           for my $c (@{$HANDLERS{$handler}}) {
  0            
104 0 0         next unless ${c}->can($method);
105              
106             # This is the only way we can catch different return contexts
107 0 0         if (wantarray()) {
108 0 0         (@ret = ${c}->$method(@_)) ? return(@ret) : next;
109             } else {
110 0 0         ($ret = ${c}->$method(@_)) ? return($ret) : next;
111             }
112             }
113 0           return undef;
114             }
115              
116             1;
117              
118             __END__