1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
|
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Bradley Baetz <bbaetz@student.usyd.edu.au>
#
package Bugzilla;
use strict;
use Bugzilla::CGI;
use Bugzilla::Config;
use Bugzilla::DB;
use Bugzilla::Template;
sub create {
my $class = shift;
my $B = $class->instance;
# And set up the vars for this request
$B->_init_transient;
return $B;
}
# We don't use Class::Singleton, because theres no need. However, I'm keeping
# the same interface in case we do change in the future
my $_instance;
sub instance {
my $class = shift;
$_instance = $class->_new_instance unless ($_instance);
return $_instance;
}
sub template { return $_[0]->{_template}; }
sub cgi { return $_[0]->{_cgi}; }
sub dbh { return $_[0]->{_dbh}; }
sub switch_to_shadow_db {
my $self = shift;
if (!$self->{_dbh_shadow}) {
if (Param('shadowdb')) {
$self->{_dbh_shadow} = Bugzilla::DB::connect_shadow();
} else {
$self->{_dbh_shadow} = $self->{_dbh_main};
}
}
$self->{_dbh} = $self->{_dbh_shadow};
}
sub switch_to_main_db {
my $self = shift;
$self->{_dbh} = $self->{_dbh_main};
}
# PRIVATE methods below here
# Called from instance
sub _new_instance {
my $class = shift;
my $self = { };
bless($self, $class);
$self->_init_persistent;
return $self;
}
# Initialise persistent items
sub _init_persistent {
my $self = shift;
# We're always going to use the main db, so connect now
$self->{_dbh} = $self->{_dbh_main} = Bugzilla::DB::connect_main();
# Set up the template
$self->{_template} = Bugzilla::Template->create();
}
# Initialise transient (per-request) items
sub _init_transient {
my $self = shift;
$self->{_cgi} = new Bugzilla::CGI if exists $::ENV{'GATEWAY_INTERFACE'};
}
# Clean up transient items such as database handles
sub _cleanup {
my $self = shift;
delete $self->{_cgi};
}
sub DESTROY {
my $self = shift;
# Clean up transient items. We can't just let perl handle removing
# stuff from the $self hash because some stuff (eg database handles)
# may need special casing
# under a persistent environment (ie mod_perl)
$self->_cleanup;
# Now clean up the persistent items
$self->{_dbh_main}->disconnect if $self->{_dbh_main};
$self->{_dbh_shadow}->disconnect if
$self->{_dbh_shadow} and Param("shadowdb")
}
1;
__END__
=head1 NAME
Bugzilla - Semi-persistent collection of various objects used by scripts
and modules
=head1 SYNOPSIS
use Bugzilla;
Bugzilla->create;
sub someModulesSub {
my $B = Bugzilla->instance;
$B->template->process(...);
}
=head1 DESCRIPTION
Several Bugzilla 'things' are used by a variety of modules and scripts. This
includes database handles, template objects, and so on.
This module is a singleton intended as a central place to store these objects.
This approach has several advantages:
=over 4
=item *
They're not global variables, so we don't have issues with them staying arround
with mod_perl
=item *
Everything is in one central place, so its easy to access, modify, and maintain
=item *
Code in modules can get access to these objects without having to have them
all passed from the caller, and the caller's caller, and....
=item *
We can reuse objects across requests using mod_perl where appropriate (eg
templates), whilst destroying those which are only valid for a single request
(such as the current user)
=back
Note that items accessible via this object may be loaded when the Bugzilla
object is created, or may be demand-loaded when requested.
For something to be added to this object, it should either be able to benefit
from persistence when run under mod_perl (such as the a C<template> object),
or should be something which is globally required by a large ammount of code
(such as the current C<user> object).
=head1 CREATION
=over 4
=item C<create>
Creates the C<Bugzilla> object, and initialises any per-request data
=item C<instance>
Returns the current C<Bugzilla> instance. If one doesn't exist, then it will
be created, but no per-request data will be set. The only use this method has
for creating the object is from a mod_perl init script. (Its also what
L<Class::Singleton> does, and I'm trying to keep that interface for this)
=back
=head1 FUNCTIONS
=over 4
=item C<template>
The current C<Template> object, to be used for output
=item C<cgi>
The current C<cgi> object. Note that modules should B<not> be using this in
general. Not all Bugzilla actions are cgi requests. Its useful as a convenience
method for those scripts/templates which are only use via CGI, though.
=item C<dbh>
The current database handle. See L<DBI>.
=item C<switch_to_shadow_db>
Switch from using the main database to using the shadow database.
=item C<switch_to_main_db>
Change the database object to refer to the main database.
=back
|