File Coverage

blib/lib/HTML/Mason/MethodMaker.pm
Criterion Covered Total %
statement 70 77 90.9
branch 16 22 72.7
condition n/a
subroutine 13 14 92.8
pod n/a
total 99 113 87.6


line stmt bran cond sub pod time code
1             # Copyright (c) 1998-2005 by Jonathan Swartz. All rights reserved.
2             # This program is free software; you can redistribute it and/or modify it
3             # under the same terms as Perl itself.
4              
5             package HTML::Mason::MethodMaker;
6             $HTML::Mason::MethodMaker::VERSION = '1.58';
7 34     34   209 use strict;
  34         72  
  34         947  
8 34     34   174 use warnings;
  34         59  
  34         1060  
9              
10 34     34   10725 use Params::Validate qw(validate_pos);
  34         230514  
  34         3653  
11              
12             sub import
13             {
14 287     287   4057 my $caller = caller;
15 287         496 shift; # don't need class name
16 287         934 my %p = @_;
17              
18 287 100       941 if ($p{read_only})
19             {
20 249 50       851 foreach my $ro ( ref $p{read_only} ? @{ $p{read_only} } : $p{read_only} )
  249         763  
21             {
22 34     34   249 no strict 'refs';
  34         70  
  34         5179  
23 1990     55947   5704 *{"$caller\::$ro"} = sub { return $_[0]->{$ro} };
  1990         8207  
  55947         186044  
24             }
25             }
26              
27             #
28             # The slight weirdness to avoid calling shift in these rw subs is
29             # _intentional_. These subs get called a lot simply to read the
30             # value, and optimizing this common case actually does achieve
31             # something.
32             #
33 287 100       922 if ($p{read_write})
34             {
35 134 50       499 foreach my $rw ( ref $p{read_write} ? @{ $p{read_write} } : $p{read_write} )
  134         361  
36             {
37 450 100       905 if (ref $rw)
38             {
39 410         762 my ($name, $spec) = @$rw;
40             my $sub =
41 5137 100   5137   10422 sub { if (@_ > 1)
42             {
43 58         120 my $s = shift;
44 58         892 validate_pos(@_, $spec);
45 57         233 $s->{$name} = shift;
46 57         198 return $s->{$name};
47             }
48 5079         16955 return $_[0]->{$name};
49 410         1488 };
50 34     34   213 no strict 'refs';
  34         70  
  34         3126  
51 410         608 *{"$caller\::$name"} = $sub
  410         1732  
52             }
53             else
54             {
55             my $sub =
56 289 100   289   741 sub { if (@_ > 1)
57             {
58 217         559 $_[0]->{$rw} = $_[1];
59             }
60 289         682 return $_[0]->{$rw};
61 40         155 };
62 34     34   199 no strict 'refs';
  34         92  
  34         5164  
63 40         75 *{"$caller\::$rw"} = $sub;
  40         812  
64             }
65             }
66             }
67              
68 287 100       310916 if ($p{read_write_contained})
69             {
70 32         146 foreach my $object (keys %{ $p{read_write_contained} })
  32         166  
71             {
72 32         79 foreach my $rwc (@{ $p{read_write_contained}{$object} })
  32         123  
73             {
74 288 50       595 if (ref $rwc)
75             {
76 288         491 my ($name, $spec) = @$rwc;
77             my $sub =
78 391     391   723 sub { my $s = shift;
79 391         640 my %new;
80 391 50       1036 if (@_)
81             {
82 391         4679 validate_pos(@_, $spec);
83 390         1509 %new = ( $name => $_[0] );
84             }
85 390         2052 my %args = $s->delayed_object_params( $object,
86             %new );
87 390         9503 return $args{$rwc};
88 288         1033 };
89 34     34   199 no strict 'refs';
  34         73  
  34         3595  
90 288         430 *{"$caller\::$name"} = $sub;
  288         70648  
91             }
92             else
93             {
94             my $sub =
95 0     0     sub { my $s = shift;
96 0 0         my %new = @_ ? ( $rwc => $_[0] ) : ();
97 0           my %args = $s->delayed_object_params( $object,
98             %new );
99 0           return $args{$rwc};
100 0           };
101 34     34   217 no strict 'refs';
  34         63  
  34         3279  
102 0           *{"$caller\::$rwc"} = $sub;
  0            
103             }
104             }
105             }
106             }
107             }
108              
109             1;
110              
111             =pod
112              
113             =head1 NAME
114              
115             HTML::Mason::MethodMaker - Used to create simple get & get/set methods in other classes
116              
117             =head1 SYNOPSIS
118              
119             use HTML::Mason::MethodMaker
120             ( read_only => 'foo',
121             read_write => [
122             [ bar => { type => SCALAR } ],
123             [ baz => { isa => 'HTML::Mason::Baz' } ],
124             'quux', # no validation
125             ],
126             read_write_contained => { other_object =>
127             [
128             [ 'thing1' => { isa => 'Thing1' } ],
129             'thing2', # no validation
130             ]
131             },
132             );
133              
134             =head1 DESCRIPTION
135              
136             This automates the creation of simple accessor methods.
137              
138             =head1 USAGE
139              
140             This module creates methods when it is C'd by another module.
141             There are three types of methods: 'read_only', 'read_write',
142             'read_write_contained'.
143              
144             Attributes specified as 'read_only' get an accessor that only returns
145             the value of the attribute. Presumably, these attributes are set via
146             more complicated methods in the class or as a side effect of one of
147             its methods.
148              
149             Attributes specified as 'read_write' will take a single optional
150             parameter. If given, this parameter will become the new value of the
151             attribute. This value is then returned from the method. If no
152             parameter is given, then the current value is returned.
153              
154             If you want the accessor to use C to validate any
155             values passed to the accessor (and you _do_), then the the accessor
156             specification should be an array reference containing two elements.
157             The first element is the accessor name and the second is the
158             validation spec.
159              
160             The 'read_write_contained' parameter is used to create accessor for
161             delayed contained objects. A I contained object is one that
162             is B created in the containing object's accessor, but rather at
163             some point after the containing object is constructed. For example,
164             the Interpreter object creates Request objects after the Interpreter
165             itself has been created.
166              
167             The value of the 'read_write_contained' parameter should be a hash
168             reference. The keys are the internal name of the contained object,
169             such as "request" or "compiler". The values for the keys are the same
170             as the parameters given for 'read_write' accessors.
171              
172             =cut