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