File Coverage

blib/lib/Yukki/Web/Context.pm
Criterion Covered Total %
statement 32 53 60.3
branch 0 6 0.0
condition n/a
subroutine 11 22 50.0
pod 10 10 100.0
total 53 91 58.2


line stmt bran cond sub pod time code
1             package Yukki::Web::Context;
2             $Yukki::Web::Context::VERSION = '0.991_002'; # TRIAL
3              
4 1     1   227152 $Yukki::Web::Context::VERSION = '0.991002';use v5.24;
  1         4  
5 1     1   7 use utf8;
  1         2  
  1         9  
6 1     1   411 use Moo;
  1         10754  
  1         6  
7              
8 1     1   1784 use Sub::Name qw( subname );
  1         592  
  1         62  
9 1     1   355 use Type::Utils;
  1         24048  
  1         9  
10 1     1   1870 use Types::Standard qw( ArrayRef HashRef Str );
  1         41280  
  1         14  
11 1     1   1321 use Types::URI qw( Uri );
  1         97344  
  1         17  
12 1     1   839 use Yukki::Web::Request;
  1         4  
  1         37  
13 1     1   419 use Yukki::Web::Response;
  1         4  
  1         45  
14              
15 1     1   8 use namespace::clean;
  1         2  
  1         6  
16              
17             # ABSTRACT: request-response context descriptor
18              
19              
20             has env => (
21             is => 'ro',
22             isa => HashRef,
23             required => 1,
24             );
25              
26              
27             has request => (
28             is => 'ro',
29             isa => class_type('Yukki::Web::Request'),
30             required => 1,
31             lazy => 1,
32             default => sub { Yukki::Web::Request->new(env => shift->env) },
33             handles => [ qw( session session_options ) ],
34             );
35              
36              
37             has response => (
38             is => 'ro',
39             isa => class_type('Yukki::Web::Response'),
40             required => 1,
41             lazy => 1,
42             default => sub { Yukki::Web::Response->new },
43             );
44              
45              
46             has stash => (
47             is => 'ro',
48             isa => HashRef,
49             required => 1,
50             default => sub { +{} },
51             );
52              
53              
54             has base_url => (
55             is => 'rw',
56             isa => Uri,
57             required => 1,
58             coerce => 1,
59             lazy => 1,
60             builder => '_build_base_url',
61             );
62              
63             sub _build_base_url {
64 0     0     my $self = shift;
65              
66 0           my $base_url = $self->env->{'yukki.settings'}->base_url;
67 0 0         if ($base_url eq 'SCRIPT_NAME') {
    0          
68 0           return $self->request->base;
69             }
70              
71             elsif ($base_url eq 'REWRITE') {
72 0           my $path_info = $self->env->{PATH_INFO};
73 0           my $request_uri = $self->env->{REQUEST_URI};
74              
75 0 0         if ($request_uri =~ s/$path_info$//) {
76 0           my $base_url = $self->request->uri;
77 0           $base_url->path($request_uri);
78 0           return $base_url->canonical;
79             }
80              
81 0           return $self->request->base;
82             }
83              
84             else {
85 0           return $_;
86             }
87             }
88              
89              
90             # TODO Store these in a flash stash
91             for my $message_type (qw( errors warnings info )) {
92             has $message_type => (
93             is => 'ro',
94             isa => ArrayRef[Str],
95             required => 1,
96             default => sub { [] },
97             );
98              
99 1     1   782 no strict 'refs';
  1         3  
  1         249  
100              
101             *{__PACKAGE__ . "::list_$message_type"} = subname "list_$message_type", sub {
102 0     0 1   my $self = shift;
        0 1    
        0 1    
103 0           map { ucfirst "$_." } $self->$message_type->@*
  0            
104             };
105              
106             *{__PACKAGE__ . "::add_$message_type"} = subname "add_$message_type", sub {
107 0     0 1   my $self = shift;
        0 1    
        0 1    
108 0           push $self->$message_type->@*, @_;
109             };
110              
111             *{__PACKAGE__ . "::has_$message_type"} = subname "add_$message_type", sub {
112 0     0 1   my $self = shift;
        0 1    
        0 1    
113 0           scalar $self->$message_type->@*;
114             };
115             }
116              
117              
118              
119             sub rebase_url {
120 0     0 1   my ($self, $url) = @_;
121 0           return URI->new($url)->abs($self->base_url);
122             }
123              
124              
125             1;
126              
127             __END__
128              
129             =pod
130              
131             =encoding UTF-8
132              
133             =head1 NAME
134              
135             Yukki::Web::Context - request-response context descriptor
136              
137             =head1 VERSION
138              
139             version 0.991_002
140              
141             =head1 SYNOPSIS
142              
143             # Many components are handed a Context in $ctx...
144              
145             my $request = $ctx->request;
146             my $session = $ctx->session;
147             my $session_options = $ctx->session_options;
148             my $response = $ctx->response;
149             my $stash = $ctx->stash;
150              
151             $ctx->add_errors('bad stuff');
152             $ctx->add_warnings('not so good stuff');
153             $ctx->add_info('some stuff');
154              
155             =head1 DESCRIPTION
156              
157             This describes information about a single request-repsonse to be handled by the server.
158              
159             =head1 ATTRIBUTES
160              
161             =head2 env
162              
163             This is the L<PSGI> environment. Do not use directly. This will probably be
164             renamed to make it more difficult to use directly in the future.
165              
166             =head2 request
167              
168             This is the L<Yukki::Web::Request> object representing the incoming request.
169              
170             =head2 response
171              
172             This is the L<Yukki::Web::Response> object representing the response to send
173             back to the client.
174              
175             =head2 stash
176              
177             This is a temporary stash of information. Use of this should be avoided when
178             possible. Global state like this (even if it only lasts for one request) should
179             only be used as a last resort.
180              
181             =head2 base_url
182              
183             This is a L<URI> describing the base path to get to this Yukki wiki site. It is configured from the L<Yukki::Web::Settings/base_url> setting. The value of the setting will determine how this value is calculated or may set it explicitly.
184              
185             =over
186              
187             =item *
188              
189             C<SCRIPT_NAME>. When C<base_url> is set to C<SCRIPT_NAME>, then the full path to the script name will be used as the base URL. This is the default and, generally, the safest option.
190              
191             =item *
192              
193             C<REWRITE>. The C<REWRITE> option takes a slightly different approach to building the base URL. It looks at the C<REQUEST_URI> and compares that to the C<PATH_INFO> and finds the common components. For example:
194              
195             PATH_INFO=/page/view/main
196             REQUEST_URI=/yukki-site/page/view/main
197              
198             this leads to a base URL of:
199              
200             /yukki-site
201              
202             If C<PATH_INFO> is not a sub-path of C<REQUEST_URI>, this will fall back to the same solution as C<SCRIPT_NAME> above.
203              
204             =item *
205              
206             Anything else will be considered an absolute URL and used as the base URL.
207              
208             =back
209              
210             This may be used to construct redirects or URLs for links and form actions.
211              
212             =head2 errors
213              
214             =head2 warnings
215              
216             =head2 info
217              
218             These each contain an array of errors.
219              
220             The C<list_errors>, C<list_warnings>, and C<list_info> methods are provided to
221             return the values as a list.
222              
223             The C<add_errors>, C<add_warnings>, and C<add_info> methods are provided to
224             append new messages.
225              
226             The C<has_errors>, C<has_warnings>, and C<has_info> methods are provided to tell
227             you if there are any messages.
228              
229             =head1 METHODS
230              
231             =head2 rebase_url
232              
233             my $url = $ctx->rebase_url($path);
234              
235             Given a relative URL, this returns an absolute URL using the L</base_url>.
236              
237             =head2 list_errors
238              
239             =head2 list_warnings
240              
241             =head2 list_info
242              
243             These methods return the list of errors, warnings, and info messages associated with the current flow.
244              
245             =head2 add_errors
246              
247             =head2 add_warnings
248              
249             =head2 add_info
250              
251             These methods add zero or more errors, warnings, and info messages to be associated with the current flow.
252              
253             =head2 has_errors
254              
255             =head2 has_warnings
256              
257             =head2 has_info
258              
259             These methods return a true value if there are any errors, warnings, or info messages associated with the current flow.
260              
261             =head1 AUTHOR
262              
263             Andrew Sterling Hanenkamp <hanenkamp@cpan.org>
264              
265             =head1 COPYRIGHT AND LICENSE
266              
267             This software is copyright (c) 2017 by Qubling Software LLC.
268              
269             This is free software; you can redistribute it and/or modify it under
270             the same terms as the Perl 5 programming language system itself.
271              
272             =cut