]> git.decadent.org.uk Git - maypole.git/blob - lib/Maypole/CLI.pm
added preprocess_location method
[maypole.git] / lib / Maypole / CLI.pm
1 package Maypole::CLI;
2 use UNIVERSAL::require;
3 use URI;
4 use URI::QueryParam;
5 use Maypole::Constants;
6
7 use strict;
8 use warnings;
9 my $package;
10 our $buffer;
11
12 # Command line action
13 CHECK {
14     if ( ( caller(0) )[1] eq "-e" ) {
15         $package->handler() == OK and print $buffer;
16     }
17 }
18
19 sub import {
20     $package = $_[1];
21     $package->require;
22     die "Couldn't require $package - $@" if $@;
23     no strict 'refs';
24     unshift @{ $package . "::ISA" }, "Maypole::CLI";
25 }
26
27 sub get_template_root { $ENV{MAYPOLE_TEMPLATES} || "." }
28
29 sub warn {
30     my ($self,@args) = @_;
31     my ($package, $line) = (caller)[0,2];
32     warn "[$package line $line] ", @args ;
33     return;
34 }
35
36 sub parse_location {
37     my $self = shift;
38     my $url  = URI->new( shift @ARGV );
39
40     $self->preprocess_location();
41
42     (my $uri_base = $self->config->uri_base) =~ s:/$::;
43     my $root = URI->new( $uri_base )->path;
44     $self->{path} = $url->path;
45     $self->{path} =~ s:^$root/?::i if $root;
46     $self->parse_path;
47     $self->parse_args($url);
48 }
49
50 sub parse_args {
51     my ( $self, $url ) = @_;
52     $self->{params} = $url->query_form_hash;
53     $self->{query}  = $url->query_form_hash;
54 }
55
56 sub send_output { $buffer = shift->{output} }
57
58 sub call_url {
59     my $self = shift;
60     local @ARGV = @_;
61     $package->handler() == OK and return $buffer;
62 }
63
64
65 1;
66
67 =head1 NAME
68
69 Maypole::CLI - Command line interface to Maypole for testing and debugging
70
71 =head1 SYNOPSIS
72
73   % setenv MAYPOLE_TEMPLATES /var/www/beerdb/
74   % perl -MMaypole::CLI=BeerDB -e1 http://localhost/beerdb/brewery/frontpage
75
76 =head1 DESCRIPTION
77
78 This module is used to test Maypole sites without going through a web
79 server or modifying them to use a CGI frontend. To use it, you should
80 first either be in the template root for your Maypole site or set the
81 environment variable C<MAYPOLE_TEMPLATES> to the right value.
82
83 Next, you import the C<Maypole::CLI> module specifying your base Maypole
84 subclass. The usual way to do this is with the C<-M> flag: 
85 C<perl -MMaypole::CLI=MyApp>. This is equivalent to:
86
87     use Maypole::CLI qw(MyApp);
88
89 Now Maypole will automatically call your application's handler with the
90 URL specified as the first command line parameter. This should be the
91 full URL, starting from whatever you have defined as the C<uri_base> in
92 your application's configuration, and may include query parameters.
93
94 The Maypole HTML output should then end up on standard output.
95
96 =head1 Support for testing
97
98 The module can also be used as part of a test script. 
99
100 When used programmatically, rather than from the command line, its
101 behaviour is slightly different. 
102
103 Although the URL is taken from C<@ARGV> as normal, your application's
104 C<handler> method is not called automatically, as it is when used on the
105 command line; you need to call it manually. Additionally, when
106 C<handler> is called, the output is not printed to standard output but
107 stored in C<$Maypole::CLI::buffer>, to allow you to check the contents
108 more easily.
109
110 For instance, a test script could look like this:
111
112     use Test::More tests => 3;
113     use Maypole::CLI qw(BeerDB);
114     use Maypole::Constants;
115     $ENV{MAYPOLE_TEMPLATES} = "t/templates";
116
117     # Hack because isa_ok only supports object isa not class isa
118     isa_ok( (bless {},"BeerDB") , "Maypole");
119
120     like(BeerDB->call_url("http://localhost/beerdb/"), qr/frontpage/, "Got the front page");
121
122     like(BeerDB->call_url("http://localhost/beerdb/beer/list"), qr/Organic Best/, "Found a beer in the list");
123
124 =head1 METHODS 
125
126 =over 
127
128 =item call_url
129
130 for use in scripts. takes an url as argument, and returns the buffer. 
131
132 =back
133
134
135 =head1 Implementation
136
137 This class overrides a set of methods in the base Maypole class to provide it's 
138 functionality. See L<Maypole> for these:
139
140 =over
141
142 =item get_template_root
143
144 =item parse_args
145
146 =item parse_location
147
148 =item send_output
149
150 =item warn
151
152 =back
153
154 =cut