File Coverage

blib/lib/Labyrinth/Request.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Labyrinth::Request;
2              
3 2     2   5103 use warnings;
  2         3  
  2         56  
4 2     2   8 use strict;
  2         4  
  2         61  
5              
6 2     2   8 use vars qw($VERSION $AUTOLOAD);
  2         11  
  2         138  
7             $VERSION = '5.30';
8              
9             =head1 NAME
10              
11             Labyrinth::Request - Request Manager for Labyrinth
12              
13             =head1 SYNOPSIS
14              
15             use Labyrinth::Request;
16              
17             # database object creation
18             my ($content,@actions) = Request($realm);
19              
20             =head1 DESCRIPTION
21              
22             The Request package, given a request string (or defaults), will retrieve
23             the appropriate actions, template file and continuations for that request.
24              
25             The configuration of request settings can either be held within INI files
26             within a designated path or in request table within a database.
27              
28             If using INI files, each file represents a collection of commands within a
29             single section. There is one special section, 'realm', which describes the
30             overall layout files, actions and continuations for the type of account.
31             Typically there are at least two realms, 'public' and 'admin'. To describe
32             the path to these request files, the following should exist within your global
33             settings file:
34              
35             requests=/path/to/request/files
36              
37             Alternative if you wish to use the request settings from a database table, in
38             your globale settings file, you will need the following setting:
39              
40             requests=dbi
41              
42             For more information for the database method, please see the
43             L distribution.
44              
45             =cut
46              
47             # -------------------------------------
48             # Library Modules
49              
50 2     2   364 use Config::IniFiles;
  0            
  0            
51              
52             use Labyrinth::Audit;
53             use Labyrinth::Globals;
54             use Labyrinth::Variables;
55             use Labyrinth::Writer;
56              
57             # -------------------------------------
58             # Variables
59              
60             my @configkeys = qw(layout actions content onsuccess onfailure onerror secure rewrite);
61             my %resetkeys = (onsuccess => 1, onfailure => 1, onerror => 1);
62             my %stored;
63              
64             my @autosubs = qw(
65             layout
66             content
67             onsuccess
68             onerror
69             onfailure
70             );
71             my %autosubs = map {$_ => 1} @autosubs;
72              
73             # -------------------------------------
74             # The Subs
75              
76             =head1 FUNCTIONS
77              
78             =head2 Constructor
79              
80             =over 4
81              
82             =item new()
83              
84             Create a new request object.
85              
86             =back
87              
88             =cut
89              
90             sub new {
91             my $self = shift;
92             my $realm = shift;
93             my $request = shift || 'home-'.$realm;
94             my @actions;
95              
96             ## split the reset request into it's component parts
97             my ($section,$command) = split("-",$request);
98             $tvars{request} = $request;
99             $tvars{section} = $section;
100             $tvars{command} = $command;
101              
102             # sort the realm out
103             my ($layout,$actions,$content,$onsuccess,$onfailure,$onerror)
104             = $self->_read_config('realm',$realm,@configkeys);
105              
106             $onsuccess = $request;
107             @actions = split(",",$actions) if($actions);
108              
109             # create an attributes hash
110             my $atts = {
111             'actions' => \@actions,
112             'layout' => $layout,
113             'content' => $content,
114             'onsuccess' => $onsuccess,
115             'onfailure' => $onfailure,
116             'onerror' => $onerror,
117             };
118              
119             LogDebug("--new:actions=[@actions]");
120             # LogDebug("--new:layout=[$layout]");
121             # LogDebug("--new:content=[$content]");
122              
123             # create the object
124             bless $atts, $self;
125             return $atts;
126             }
127              
128             =head2 Methods
129              
130             =head3 Handling Actions
131              
132             =over 4
133              
134             =item next_action()
135              
136             For the current command request, return the next action within its action list.
137              
138             =item add_actions(@actions)
139              
140             Add actions to the action list for the current command request.
141              
142             =back
143              
144             =cut
145              
146             sub next_action { my $self = shift; shift @{$self->{actions}} }
147             sub add_actions { my $self = shift; push @{$self->{actions}}, @_ }
148              
149             =head3 Handling Command Resets
150              
151             =over 4
152              
153             =item reset_realm($realm)
154              
155             Reloads settings for a new realm setting.
156              
157             =item reset_request($request)
158              
159             Reloads settings for a new command request.
160              
161             =item redirect
162              
163             Instead of a local template file or a continuation, a redirect may be used.
164             This method reformats the URL within a redirect request.
165              
166             =back
167              
168             =cut
169              
170             sub reset_realm {
171             my $self = shift;
172             my $realm = shift;
173             my %hash;
174              
175             @hash{@configkeys} = $self->_read_config('realm',$realm,@configkeys);
176              
177             $self->{section} = 'realm';
178             $self->{command} = $realm; # needed to check onsuccess, etc.
179              
180             for(@configkeys) {
181             next unless($hash{$_});
182             if($_ eq 'actions') {
183             my @actions = split(",",$hash{$_});
184             $self->add_actions(@actions);
185             LogDebug("--reset_realm:actions=@actions");
186             } else {
187             $self->{$_} = $hash{$_};
188             #LogDebug("--reset_realm:$_=$self->{$_}");
189             }
190             }
191             }
192              
193             sub reset_request {
194             my $self = shift;
195             my $request = shift;
196             my %hash;
197              
198             ## split the reset request into it's component parts
199             my ($section,$command) = split("-",$request);
200             $tvars{request} = $request;
201             $tvars{section} = $section;
202             $tvars{command} = $command;
203             return unless($section && $command);
204              
205             # remove any remaining actiona
206             while($self->next_action){};
207              
208             @hash{@configkeys} = $self->_read_config($section,$command,@configkeys);
209              
210             #if($settings{$protocol} eq 'https' && !$hash{secure} || $hash{secure} !~ /^(on|either|both)$/) {
211             # # redirect to HTTP string
212             # $self->redirect('http',$hash{rewrite},$request);
213             # return;
214             #} elsif($settings{$protocol} eq 'http' && $hash{secure} && $hash{secure} =~ /^(on|either|both)$/) {
215             # # redirect to HTTPS string
216             # $self->redirect('https',$hash{rewrite});
217             # return;
218             #}
219              
220             for(@configkeys) {
221             next unless($hash{$_} || $resetkeys{$_});
222             if($_ eq 'actions') {
223             my @actions = split(",",$hash{$_});
224             $self->add_actions(@actions);
225             LogDebug("--reset_request:actions=@actions");
226             } else {
227             $self->{$_} = $hash{$_};
228             LogDebug("--reset_request:$_=" . (defined $self->{$_} ? $self->{$_} : ''));
229             }
230             }
231             }
232              
233             sub redirect {
234             my ($self,$protocol,$rewrite,$request) = @_;
235              
236             return $tvars{redirect} if(!$protocol);
237              
238             # set to existing query string, with new protocol
239             $tvars{redirect} = "$protocol://$ENV{HTTP_HOST}";
240              
241             if(defined $rewrite) {
242             $tvars{redirect} .= $rewrite;
243             } else {
244             $tvars{redirect} .= $ENV{REQUEST_URI} if($ENV{REQUEST_URI});
245              
246             # rewrite query string
247             if(defined $request) {
248             $tvars{redirect} =~ s/\?.*//;
249             $tvars{redirect} .= "?act=$request" if($request);
250             }
251             }
252             }
253              
254             # private method to read config data
255              
256             sub _read_config {
257             my ($self,$section,$command,@keys) = @_;
258             my @values;
259              
260             LogDebug("--read_config:section=$section,command=$command,request=$settings{requests}");
261              
262             if($settings{requests} eq 'dbi') {
263             my @rows = $dbi->GetQuery('hash','GetRequest',$section,$command);
264             if(@rows) {
265             push @values, map {$rows[0]->{$_}} @keys;
266             } else {
267             push @values, map {''} @keys;
268             }
269             } else {
270             my $file = "$settings{requests}/$section.ini";
271             Croak("Cannot read configuration file [$file]\n") unless(-r $file);
272             my $cfg = Config::IniFiles->new( -file => $file );
273             Croak("Cannot access configuration file [$file]: @Config::IniFiles::errors\n") unless($cfg);
274              
275             for my $key (@keys) {
276             my $value = $cfg->val( $command, $key );
277             #LogDebug("--_read_config:[$command-$key]=[$value], file=[$file]");
278             push @values, ($value ? $value : undef);
279             }
280             }
281             return @values;
282             }
283              
284             =head2 Accessor Methods
285              
286             =over 4
287              
288             =item layout
289              
290             Layout template to be used
291              
292             =item content
293              
294             Content template to be used
295              
296             =item onsuccess
297              
298             Command to execute if this command succeeds.
299              
300             =item onerror
301              
302             Command to execute if this command fails.
303              
304             =item onfailure
305              
306             Command to execute if this command fails with an unrecoverable error.
307              
308             =back
309              
310             =cut
311              
312             sub AUTOLOAD {
313             no strict 'refs';
314             my $name = $AUTOLOAD;
315             $name =~ s/^.*:://;
316             die "Unknown sub $AUTOLOAD\n" unless($autosubs{$name});
317              
318             *$name = sub {
319             my $self = shift;
320             my $value = $self->{$name};
321             if($name =~ /^on/) { $self->{$name} = undef } # once seen, forget it
322             return $value;
323             };
324             goto &$name;
325             }
326              
327             sub DESTROY {}
328              
329             1;
330              
331             __END__