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