]> git.decadent.org.uk Git - maypole.git/blob - lib/Apache/MVC.pm
Added doc stubs for Aaron's new methods.
[maypole.git] / lib / Apache / MVC.pm
1 package Apache::MVC;
2
3 our $VERSION = '2.10';
4
5 use strict;
6 use warnings;
7
8 use base 'Maypole';
9 use Maypole::Headers;
10 use Maypole::Constants;
11
12 __PACKAGE__->mk_accessors( qw( ar ) );
13
14 BEGIN {
15     my $version;
16     eval 'use mod_perl2; $version = $mod_perl2::VERSION; ';
17     if ($@) {
18         use mod_perl;
19         $version = 0;
20         require Apache;
21         require Apache::Request;
22     } else {
23         require Apache2::RequestIO;
24         require Apache2::RequestRec;
25         require Apache2::RequestUtil;
26         require APR::URI;
27         require Apache2::Request;
28     }
29
30     use constant APACHE2 => $version;
31 }
32
33 sub get_request {
34     my ( $self, $r ) = @_;
35     $self->{ar} = (APACHE2) ? Apache2::Request->new($r) : Apache::Request->new($r);
36 }
37
38 sub get_protocol {
39   my $self = shift;
40   my $protocol = ( $self->{ar}->protocol =~ m/https/i ) ? 'https' : 'http' ;
41   return $protocol;
42 }
43
44 sub parse_location {
45     my $self = shift;
46
47     # Reconstruct the request headers
48     $self->headers_in(Maypole::Headers->new);
49     my %headers;
50     if (APACHE2) { %headers = %{$self->{ar}->headers_in};
51     } else { %headers = $self->{ar}->headers_in; }
52     for (keys %headers) {
53         $self->headers_in->set($_, $headers{$_});
54     }
55
56     $self->{path} = $self->{ar}->uri;
57     my $loc = $self->{ar}->location;
58     no warnings 'uninitialized';
59     $self->{path} .= '/' if $self->{path} eq $loc;
60     $self->{path} =~ s/^($loc)?\///;
61     $self->parse_path;
62     $self->parse_args;
63 }
64
65 sub parse_args {
66     my $self = shift;
67     $self->{params} = { $self->_mod_perl_args( $self->{ar} ) };
68     $self->{query}  = { $self->_mod_perl_args( $self->{ar} ) };
69 }
70
71 # FIXME: use headers_in to gather host and other information?
72 sub redirect_request {
73   my $self = shift;
74   my $redirect_url = $_[0];
75   my $status = "302";
76   if ($_[1]) {
77     my %args = @_;
78     if ($args{url}) {
79       $redirect_url = $args{url};
80     } else {
81       my $path = $args{path} || $self->{path};
82       my $host = $args{domain} || $self->{ar}->hostname;
83       my $protocol = $args{protocol} || ( $self->{ar}->protocol =~ m/https/i ) ? 'https' : 'http' ;;
84       $redirect_url = "${protocol}://${host}/${path}";
85     }
86     $status = $args{status} if ($args{status});
87   }
88
89   $self->headers_out->set('Status' => $status);
90   $self->headers_out->set('Location' => $redirect_url);
91   return OK;
92 }
93
94 sub send_output {
95     my $r = shift;
96     $r->{ar}->content_type(
97           $r->{content_type} =~ m/^text/
98         ? $r->{content_type} . "; charset=" . $r->{document_encoding}
99         : $r->{content_type}
100     );
101     $r->{ar}->headers_out->set(
102         "Content-Length" => do { use bytes; length $r->{output} }
103     );
104
105     foreach ($r->headers_out->field_names) {
106         next if /^Content-(Type|Length)/;
107         $r->{ar}->headers_out->set($_ => $r->headers_out->get($_));
108     }
109
110     APACHE2 || $r->{ar}->send_http_header;
111     $r->{ar}->print( $r->{output} );
112 }
113
114 sub get_template_root {
115     my $r = shift;
116     $r->{ar}->document_root . "/" . $r->{ar}->location;
117 }
118
119 sub _mod_perl_args {
120     my ( $self, $apr ) = @_;
121     my %args;
122     foreach my $key ( $apr->param ) {
123         my @values = $apr->param($key);
124         $args{$key} = @values == 1 ? $values[0] : \@values;
125     }
126     return %args;
127 }
128
129 1;
130
131 =head1 NAME
132
133 Apache::MVC - Apache front-end to Maypole
134
135 =head1 SYNOPSIS
136
137     package BeerDB;
138     use base 'Apache::MVC';
139     BeerDB->setup("dbi:mysql:beerdb");
140     BeerDB->config->uri_base("http://your.site/");
141     BeerDB->config->display_tables([qw[beer brewery pub style]]);
142     # Now set up your database:
143     # has-a relationships
144     # untaint columns
145
146     1;
147
148 =head1 DESCRIPTION
149
150 A mod_perl platform driver for Maypole. Your application can inherit from
151 Apache::MVC directly, but it is recommended that you use
152 L<Maypole::Application>.
153
154 =head1 INSTALLATION
155
156 Create a driver module like the one above.
157
158 Put the following in your Apache config:
159
160     <Location /beer>
161         SetHandler perl-script
162         PerlHandler BeerDB
163     </Location>
164
165 Copy the templates found in F<templates/factory> into the
166 F<beer/factory> directory off the web root. When the designers get
167 back to you with custom templates, they are to go in
168 F<beer/custom>. If you need to do override templates on a
169 database-table-by-table basis, put the new template in
170 F<beer/I<table>>. 
171
172 This will automatically give you C<add>, C<edit>, C<list>, C<view> and
173 C<delete> commands; for instance, a list of breweries, go to 
174
175     http://your.site/beer/brewery/list
176
177 For more information about how the system works and how to extend it,
178 see L<Maypole>.
179
180 =head1 Implementation
181
182 This class overrides a set of methods in the base Maypole class to provide it's
183 functionality. See L<Maypole> for these:
184
185 =over
186
187 =item get_request
188
189 =item get_template_root
190
191 =item get_protocol
192
193 =item parse_args
194
195 =item parse_location
196
197 =item send_output
198
199 =item redirect_request
200
201 =back
202
203 =head1 AUTHOR
204
205 Simon Cozens, C<simon@cpan.org>
206 Marcus Ramberg, C<marcus@thefeed.no>
207 Screwed up by Sebastian Riedel, C<sri@oook.de>
208
209 =head1 LICENSE
210
211 You may distribute this code under the same terms as Perl itself.
212
213 =cut