]> git.uio.no Git - usit-rt.git/blame - lib/RT/Interface/Web/Request.pm
Upgrade to 4.0.10.
[usit-rt.git] / lib / RT / Interface / Web / Request.pm
CommitLineData
84fb5b46
MKG
1# BEGIN BPS TAGGED BLOCK {{{
2#
3# COPYRIGHT:
4#
403d7b0b 5# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
84fb5b46
MKG
6# <sales@bestpractical.com>
7#
8# (Except where explicitly superseded by other copyright notices)
9#
10#
11# LICENSE:
12#
13# This work is made available to you under the terms of Version 2 of
14# the GNU General Public License. A copy of that license should have
15# been provided with this software, but in any event can be snarfed
16# from www.gnu.org.
17#
18# This work is distributed in the hope that it will be useful, but
19# WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21# General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26# 02110-1301 or visit their web page on the internet at
27# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28#
29#
30# CONTRIBUTION SUBMISSION POLICY:
31#
32# (The following paragraph is not intended to limit the rights granted
33# to you to modify and distribute this software under the terms of
34# the GNU General Public License and is only of importance to you if
35# you choose to contribute your changes and enhancements to the
36# community by submitting them to Best Practical Solutions, LLC.)
37#
38# By intentionally submitting any modifications, corrections or
39# derivatives to this work, or any other work intended for use with
40# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41# you are the copyright holder for those contributions and you grant
42# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43# royalty-free, perpetual, license to use, copy, create derivative
44# works based on those contributions, and sublicense and distribute
45# those contributions and any derivatives thereof.
46#
47# END BPS TAGGED BLOCK }}}
48
49package RT::Interface::Web::Request;
50
51use strict;
52use warnings;
53
54our $VERSION = '0.30';
55use HTML::Mason::PSGIHandler;
56use base qw(HTML::Mason::Request::PSGI);
57use Params::Validate qw(:all);
58
59sub new {
60 my $class = shift;
61 $class->valid_params( %{ $class->valid_params },cgi_request => { type => OBJECT, optional => 1 } );
62 return $class->SUPER::new(@_);
63}
64
65
66=head2 callback
67
68Method replaces deprecated component C<Element/Callback>.
69
70Takes hash with optional C<CallbackPage>, C<CallbackName>
71and C<CallbackOnce> arguments, other arguments are passed
72throught to callback components.
73
74=over 4
75
76=item CallbackPage
77
78Page path relative to the root, leading slash is mandatory.
79By default is equal to path of the caller component.
80
81=item CallbackName
82
83Name of the callback. C<Default> is used unless specified.
84
85=item CallbackOnce
86
87By default is false, otherwise runs callbacks only once per
88process of the server. Such callbacks can be used to fill
89structures.
90
91=back
92
93Searches for callback components in
94F<< /Callbacks/<any dir>/CallbackPage/CallbackName >>, for
95example F</Callbacks/MyExtension/autohandler/Default> would
96be called as default callback for F</autohandler>.
97
98=cut
99
100{
101my %cache = ();
102my %called = ();
103sub callback {
104 my ($self, %args) = @_;
105
106 my $name = delete $args{'CallbackName'} || 'Default';
107 my $page = delete $args{'CallbackPage'} || $self->callers(0)->path;
108 unless ( $page ) {
109 $RT::Logger->error("Couldn't get a page name for callbacks");
110 return;
111 }
112
113 my $CacheKey = "$page--$name";
114 return 1 if delete $args{'CallbackOnce'} && $called{ $CacheKey };
115 $called{ $CacheKey } = 1;
116
117 my $callbacks = $cache{ $CacheKey };
118 unless ( $callbacks ) {
119 $callbacks = [];
120 my $path = "/Callbacks/*$page/$name";
121 my @roots = RT::Interface::Web->ComponentRoots;
122 my %seen;
123 @$callbacks = (
124 grep defined && length,
125 # Skip backup files, files without a leading package name,
126 # and files we've already seen
127 grep !$seen{$_}++ && !m{/\.} && !m{~$} && m{^/Callbacks/[^/]+\Q$page/$name\E$},
128 map { sort $self->interp->resolver->glob_path($path, $_) }
129 @roots
130 );
131 foreach my $comp (keys %seen) {
132 next unless $seen{$comp} > 1;
133 $RT::Logger->error("Found more than one occurrence of the $comp callback. This may cause only one of the callbacks to run. Look for the duplicate Callback in your @roots");
134 }
135
136 $cache{ $CacheKey } = $callbacks unless RT->Config->Get('DevelMode');
137 }
138
139 my @rv;
140 foreach my $cb ( @$callbacks ) {
141 push @rv, scalar $self->comp( $cb, %args );
142 }
143 return @rv;
144}
403d7b0b
MKG
145
146sub clear_callback_cache {
147 %cache = %called = ();
148}
84fb5b46
MKG
149}
150
151=head2 request_path
152
153Returns path of the request.
154
155Very close to C<< $m->request_comp->path >>, but if called in a dhandler returns
156path of the request without dhandler name, but with dhandler arguments instead.
157
158=cut
159
160sub request_path {
161 my $self = shift;
162
163 my $path = $self->request_comp->path;
164 # disabled dhandlers, not RT case, but anyway
165 return $path unless my $dh_name = $self->dhandler_name;
166 # not a dhandler
167 return $path unless substr($path, -length("/$dh_name")) eq "/$dh_name";
168 substr($path, -length $dh_name) = $self->dhandler_arg;
169 return $path;
170}
171
403d7b0b
MKG
172=head2 abort
173
174Logs any recorded SQL statements for this request before calling the standard
175abort.
176
177=cut
178
179sub abort {
180 my $self = shift;
181 RT::Interface::Web::LogRecordedSQLStatements(
182 RequestData => {
183 Path => $self->request_path,
184 },
185 );
186 return $self->SUPER::abort(@_);
187}
188
84fb5b46 1891;