1=pod
2
3=head1 NAME
4
5HTML::Mason::Subclassing - Documentation on Subclassing Internal Mason classes
6
7=head1 DESCRIPTION
8
9This is the deep voodoo guide, for folks who want to create their own
10custom subclasses for parts of Mason, such as the Request or Interp
11objects.
12
13=head1 Class::Container
14
15A number of modules in Mason are subclasses of C<Class::Container>.
16This module was originally part of the Mason core as
17C<HTML::Mason::Container>, but Ken Williams decided to release it separately on CPAN.
18
19It was created to encapsulate some common behaviors for Mason objects
20such as parameter validation and the creation of "contained" objects.
21
22Basically, any Mason object which takes parameters to its constructor
23B<must> inherit from this module.  Of course, since all of the classes
24that you might consider subclassing already inherit from
25C<Class::Container>, you won't need to inherit from it directly.
26However, you may need to use some of its methods.
27
28So before you go further we highly recommend familiarizing yourself
29with C<Class::Container> and its methods.  Also feel free to look at
30some of the Mason core modules to see how C<Class::Container> is used
31within Mason itself.
32
33=head1 SUBCLASSABLE CLASSES
34
35The following classes have been designed with subclassing in mind:
36
37=over 4
38
39=item * HTML::Mason::Request
40
41This object is your old friend C<$m>.  The request contains
42information about the current request context, and provides methods
43for calling other components.
44
45=item * HTML::Mason::Resolver
46
47The resolver's job is to translate a component paths into an actual
48component.  Mason comes with a single Resolver subclass,
49C<HTML::Mason::Resolver::File>, which is used to translate component
50paths into filesystem paths.
51
52=item * HTML::Mason::ComponentSource
53
54An object of this class represents a component's source.  These
55objects are instantiated by the resolver when it finds a component
56matching a given path.
57
58=item * HTML::Mason::Lexer
59
60The lexer is responsible for parsing a component.  Creating a new
61lexer would allow you to change Mason's component syntax.
62
63=item * HTML::Mason::Compiler
64
65The compiler takes the parsed chunks from the lexer and gives them
66meaning.  The default compiler, C<HTML::Mason::Compiler::ToObject>,
67turns a Mason component into a Mason "object file", which contains
68actual Perl code.
69
70=item * HTML::Mason::ApacheHandler
71
72The ApacheHandler class is the bridge between the mod_perl world and
73Mason, primarily Mason's Interp class.
74
75It also provides its own C<HTML::Mason::Request> and
76C<HTML::Resolver::File> subclasses which implement some mod_perl
77specific behaviors and features.
78
79=item * HTML::Mason::Interp
80
81The Interp is the core of Mason, and is primarily responsible for
82making all the other objects do their jobs.
83
84=back
85
86=head1 CONSTRUCTORS
87
88If you choose to override the constructor, which is always C<new> with
89Mason objects, that you make sure to call the superclass's constructor
90and that you use the object returned by it.  A good boilerplate for an
91overridden constructor looks something like this:
92
93  sub new
94  {
95      my $class = shift;
96
97      my $self = $class->SUPER::new(@_);
98
99      $self->_do_some_init;
100
101      return $self;
102  }
103
104=head1 Request
105
106=head2 What to Subclass?
107
108One important thing to know about this class is that it is actually
109several classes.  The first, C<HTML::Mason::Request>, is used when
110ApacheHandler is not loaded.  The other,
111C<HTML::Mason::Request::ApacheHandler>, is loaded by ApacheHandler and
112used to provide some mod_perl specific features.  Similar, the
113CGIHandler class provides its own request subclass,
114C<HTML::Mason::Request::CGIHandler>.
115
116It is impossible to know which one of these to subclass at compile
117time, since it is possible that your subclass will be loaded before
118either ApacheHandler or CGIHandler.
119
120To handle this, simply call the C<alter_superclass()> method in your
121constructor, like this:
122
123  sub new
124  {
125      my $class = shift;
126
127      $class->alter_superclass( $HTML::Mason::ApacheHandler::VERSION ?
128                                'HTML::Mason::Request::ApacheHandler' :
129                                $HTML::Mason::CGIHandler::VERSION ?
130                                'HTML::Mason::Request::CGI' :
131                                'HTML::Mason::Request' );
132
133      my $self = $class->SUPER::new(@_);
134
135      ...
136
137      return $self;
138  }
139
140It is quite important that you do this as these handler-specific
141subclasses provide important functionality.  The C<alter_superclass()>
142method is implemented in the
143L<C<HTML::Mason::Request>|HTML::Mason::Request> base class, and will
144do the right thing even in cases of multiple inheritance.  It also
145cooperates with C<Class::Container> to make sure that it sees changes
146to the inheritance hierarchy.
147
148=head2 The exec() method
149
150The C<exec> method is called in order to execute a request, and is the
151method that you are most likely to want to override.
152
153However, if you do override it we suggest that you make sure to call
154the parent class's C<exec> method to implement the actual component
155execution and there is no need for you to re-implement them.
156
157Since the C<exec()> method is scalar/list context-sensitive, your
158C<exec> method will need to preserve that.  Here is a boilerplate:
159
160  sub exec
161  {
162      my $self = shift;
163
164      ... # do something cool
165
166      my @r;
167      if (wantarray)
168      {
169          @r = $self->SUPER::exec(@_);
170      }
171      else
172      {
173          $r[0] = $self->SUPER::exec(@_);
174      }
175
176      ... # maybe do some cleanup
177
178      return wantarray ? @r : $r[0];
179  }
180
181=head2 Subrequests
182
183Your custom request class will also be used to implement subrequests,
184which are implemented by calling C<exec> just like any other method.
185If you only want to do certain things in C<exec> for the first
186request, you can simply check the value of C<< $self->is_subrequest >>.
187
188=head2 Examples
189
190See the C<MasonX::Request::WithApacheSession> module on CPAN.
191
192=head1 Resolver and ComponentSource
193
194The resolver takes a component path and figures out what component
195that path corresponds to.
196
197All resolver classes must implement two methods, C<get_info> and
198C<glob_path>.  The first takes a component path and returns a new
199C<HTML::Mason::ComponentSource> object.  This object contains
200information about the component, such as its last modified time and
201its source.  See the
202L<C<HTML::Mason::ComponentSource>|HTML::Mason::ComponentSource>
203documentation for more details.
204
205You may choose to provide your own ComponentSource subclass as well,
206if your resolver implementation can take advantage of it.
207
208The C<glob_path> method is responsible for translating a component
209path like F</foo/*/bar> into a list of component paths that match that
210glob pattern.
211
212=head1 Lexer
213
214The rationale for providing your own lexer would be to extend or
215replace Mason's syntax.
216
217The lexer is called by the compiler via its C<lex> method.  The
218arguments it receives are the component name, source, and the compiler
219object.  See the L<Compiler class|HTML::Mason::Compiler> documentation
220for details on what methods the lexer can call.
221
222=head1 Compiler
223
224See the L<Compiler class|HTML::Mason::Compiler> documentation for
225details on what methods a subclass of this class needs to provide.
226
227If you simply want to tweak Mason's existing behavior, you will
228probably want to subclass C<HTML::Mason::Compiler::ToObject>, which is
229the default Compiler class.  For example, if you wanted to do
230something like make attributes dynamic, you could override the
231C<_flags_or_attr()> method in ToObject.
232
233If you want to drastically change the behavior, you can subclass
234C<HTML::Mason::Compiler> instead.  An example of this would be
235creating a compiler that generates C<EmbPerl> or C<Apache::ASP> as
236output.
237
238=head1 ApacheHandler
239
240The methods that you are most likely to want to subclass are
241documented in the L<C<ApacheHandler class>|HTML::Mason::ApacheHandler>
242documentation.
243
244Providing an ApacheHandler subclass gives you a chance to do your own
245client parameter parsing, as well as the capability of providing a
246different way of handling requests.
247
248=head1 CGIHandler
249
250Like the ApacheHandler, you could subclass this module in order to
251provide your own argument processing or to step in and provide a
252different way to handle requests.
253
254=head1 USING SUBCLASSES
255
256When using your custom subclasses, we recommend that you take
257advantage of Mason's ability to construct subclassed object on the
258fly.
259
260For example, if you're subclassed the Interp object, you can still let
261the ApacheHandler object create the Interp object for you, as long as
262you give it the appropriate L<interp_class|HTML::Mason::Params/interp_class> parameter.  This is
263important because Mason may internally set up certain defaults for
264contained objects.  For example, the ApacheHandler, by default, will
265tell the Interp object to use the
266C<HTML::Mason::Request::ApacheHandler> Request subclass.  If you
267create an Interp object manually and you want to use that Interp
268object with ApacheHandler, you'll have to specify the same Request
269class.
270
271For example:
272
273  my $interp =
274      My::Interp->new
275          ( request_class  => 'HTML::Mason::Request::ApacheHandler',
276            my_new_interp_param => 42,
277          );
278
279  my $ah = HTML::Mason::ApacheHandler->new( interp => $interp );
280
281It is far easier to simply do this:
282
283  my $ah =
284      HTML::Mason::ApacheHandler->new
285          ( interp_class => 'My::Interp',
286            my_new_interp_param => 42,
287          );
288
289Your new parameter, C<my_new_interp_param>, will still be passed to
290the C<My::Interp> constructor, but this also gives ApacheHandler a
291chance to set various parameters for the Interp object.  Of course,
292you can still override these defaults explicitly:
293
294  my $ah =
295      HTML::Mason::ApacheHandler->new
296          ( interp_class => 'My::Interp',
297            resolver_class => 'My::Resolver'.
298            my_new_interp_param => 42,
299          );
300
301If you need access to the interp object's methods directly, it will be
302always be available via C<< $ah->interp >>.
303
304=cut
305