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