13 use Maypole::Constants;
15 __PACKAGE__->mk_accessors( qw( ar ) );
21 $MODPERL2 = ( exists $ENV{MOD_PERL_API_VERSION} and
22 $ENV{MOD_PERL_API_VERSION} >= 2 );
24 eval 'use mod_perl2; $modperl_version = $mod_perl2::VERSION;';
26 $modperl_version = $Apache2::RequestRec::VERSION;
28 require Apache2::RequestIO;
29 require Apache2::RequestRec;
30 require Apache2::RequestUtil;
31 eval 'use Apache2::Const -compile => qw/REDIRECT/;'; # -compile 4 no import
35 eval ' use mod_perl; ';
37 require Apache::Request;
38 eval 'use Apache::Constants -compile => qw/REDIRECT/;';
46 Apache::MVC - Apache front-end to Maypole
51 use Maypole::Application;
55 A mod_perl platform driver for Maypole. Your application can inherit from
56 Apache::MVC directly, but it is recommended that you use
57 L<Maypole::Application>.
61 Create a driver module like the one illustrated in L<Maypole::Application>.
63 Put the following in your Apache config:
66 SetHandler perl-script
70 Copy the templates found in F<templates/factory> into the F<beer/factory>
71 directory off the web root. When the designers get back to you with custom
72 templates, they are to go in F<beer/custom>. If you need to override templates
73 on a database-table-by-table basis, put the new template in F<beer/I<table>>.
75 This will automatically give you C<add>, C<edit>, C<list>, C<view> and C<delete>
76 commands; for instance, to see a list of breweries, go to
78 http://your.site/beer/brewery/list
80 For more information about how the system works and how to extend it,
85 This class overrides a set of methods in the base Maypole class to provide its
86 functionality. See L<Maypole> for these:
98 $ar = eval {require Apache2::Request} ? Apache2::Request->new($r) : $r;
100 else { $ar = Apache::Request->instance($r); }
109 my ($self,@args) = @_;
110 my ($package, $line) = (caller)[0,2];
111 if ( $args[0] and ref $self ) {
112 $self->{ar}->warn("[$package line $line] ", @args) ;
114 print "warn called by ", caller, " with ", @_, "\n";
127 # Reconstruct the request headers
128 $self->headers_in(Maypole::Headers->new);
130 if ($MODPERL2) { %headers = %{$self->ar->headers_in};
131 } else { %headers = $self->ar->headers_in; }
132 for (keys %headers) {
133 $self->headers_in->set($_, $headers{$_});
136 my $path = $self->ar->uri;
137 my $base = URI->new($self->config->uri_base);
138 my $loc = $base->path;
141 no warnings 'uninitialized';
142 $path .= '/' if $path eq $loc;
144 $path =~ s/^($loc)?//;
146 $path =~ s/^($loc)?\///;
161 $self->params( { $self->_mod_perl_args( $self->ar ) } );
162 $self->query( $self->params );
165 =item redirect_request
167 Sets output headers to redirect based on the arguments provided
169 Accepts either a single argument of the full url to redirect to, or a hash of
172 $r->redirect_request('http://www.example.com/path');
176 $r->redirect_request(protocol=>'https', domain=>'www.example.com', path=>'/path/file?arguments', status=>'302', url=>'..');
178 The named parameters are protocol, domain, path, status and url
180 Only 1 named parameter is required but other than url, they can be combined as
181 required and current values (from the request) will be used in place of any
182 missing arguments. The url argument must be a full url including protocol and
183 can only be combined with status.
190 my $redirect_url = $_[0];
191 my $status = $MODPERL2 ? eval 'Apache2::Const::REDIRECT;' :
192 eval 'Apache::Constants::REDIRECT;'; # why have to eval this?
196 $redirect_url = $args{url};
198 my $path = $args{path} || $r->path;
199 my $host = $args{domain} || $r->ar->hostname;
200 my $protocol = $args{protocol} || $r->get_protocol;
201 $redirect_url = "${protocol}://${host}/${path}";
203 $status = $args{status} if ($args{status});
206 $r->ar->status($status);
207 $r->ar->headers_out->set('Location' => $redirect_url);
217 my $protocol = ( $self->ar->protocol =~ m/https/i ) ? 'https' : 'http' ;
227 $r->ar->content_type(
228 $r->content_type =~ m/^text/
229 ? $r->content_type . "; charset=" . $r->document_encoding
232 $r->ar->headers_out->set(
233 "Content-Length" => do { use bytes; length $r->output }
236 foreach ($r->headers_out->field_names) {
237 next if /^Content-(Type|Length)/;
238 $r->ar->headers_out->set($_ => $r->headers_out->get($_));
241 $MODPERL2 || $r->ar->send_http_header;
242 $r->ar->print( $r->output );
245 =item get_template_root
249 sub get_template_root {
251 $r->ar->document_root . "/" . $r->ar->location;
258 #########################################################
259 # private / internal methods and subs
263 my ( $self, $apr ) = @_;
265 if ($apr->isa('Apache::Request')) {
266 foreach my $key ( $apr->param ) {
267 my @values = $apr->param($key);
268 $args{$key} = @values == 1 ? $values[0] : \@values;
271 my $body = $self->_prepare_body($apr);
272 %args = %{$body->param};
273 my $uri = URI->new($self->ar->unparsed_uri);
274 foreach my $key ($uri->query_param) {
275 if (ref $args{$key}) {
276 push (@{$args{$key}}, $uri->query_param($key));
279 $args{$key} = [ $args{$key}, $uri->query_param($key) ];
281 my @args = $uri->query_param($key);
282 if (scalar @args > 1) {
283 $args{$key} = [ $uri->query_param($key) ];
285 $args{$key} = $uri->query_param($key);
295 my ( $self, $r ) = @_;
297 unless ($self->{__http_body}) {
298 my $content_type = $r->headers_in->get('Content-Type');
299 my $content_length = $r->headers_in->get('Content-Length');
300 my $body = HTTP::Body->new( $content_type, $content_length );
301 my $length = $content_length;
303 $r->read( my $buffer, ( $length < 8192 ) ? $length : 8192 );
304 $length -= length($buffer);
307 $self->{__http_body} = $body;
309 return $self->{__http_body};
316 Simon Cozens, C<simon@cpan.org>
321 Marcus Ramberg, C<marcus@thefeed.no>
322 Sebastian Riedel, C<sri@oook.de>
326 You may distribute this code under the same terms as Perl itself.