| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package DBIx::Objects; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
74159
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
52
|
|
|
4
|
1
|
|
|
1
|
|
6
|
use warnings qw(all); |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
502
|
|
|
5
|
1
|
|
|
1
|
|
6
|
use vars qw($VERSION); |
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
75
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
BEGIN { |
|
8
|
1
|
|
|
1
|
|
193
|
$VERSION=0.04; |
|
9
|
|
|
|
|
|
|
} |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
### |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
package DBIx::Object; |
|
14
|
|
|
|
|
|
|
|
|
15
|
1
|
|
|
1
|
|
6
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
50
|
|
|
16
|
1
|
|
|
1
|
|
148
|
use warnings qw(all); |
|
|
1
|
|
|
|
|
10
|
|
|
|
1
|
|
|
|
|
4027
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Back-end methods |
|
19
|
|
|
|
|
|
|
sub _blank { # Default back-end for constructor |
|
20
|
|
|
|
|
|
|
# ARGS: $self, [$namespace,] @arglist |
|
21
|
|
|
|
|
|
|
# $namespace - Scalar (string) - Namespace of managing package for variables |
|
22
|
|
|
|
|
|
|
# @arglist - Array (string) - List of variables to be registered as methods |
|
23
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
24
|
0
|
|
0
|
|
|
|
my $package= |
|
25
|
|
|
|
|
|
|
(UNIVERSAL::isa($_[0],__PACKAGE__) && # Looks like a descendant |
|
26
|
|
|
|
|
|
|
shift) || caller; # Shift or autodetect namespace to register |
|
27
|
0
|
0
|
|
|
|
|
warn "Package $package not listed in registry" |
|
28
|
|
|
|
|
|
|
unless defined($self->{_REGISTRY}{$package}); |
|
29
|
0
|
|
|
|
|
|
while (@_) { |
|
30
|
0
|
|
|
|
|
|
local $_=uc(shift); |
|
31
|
0
|
|
|
|
|
|
$self->{$_}=undef; |
|
32
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$_}{source}=$package; |
|
33
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$_}{access}=1; # default to rw |
|
34
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$_}{type}="basic"; |
|
35
|
|
|
|
|
|
|
} |
|
36
|
|
|
|
|
|
|
} |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub _register { # Default back-end for package registration |
|
39
|
|
|
|
|
|
|
# Call immediately after being bless()ed |
|
40
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
41
|
0
|
|
|
|
|
|
my $package=caller; |
|
42
|
0
|
0
|
|
|
|
|
$self->{_REGISTRY}{$package}{prep}=0 unless (defined($self->{_REGISTRY}{$package})); |
|
43
|
0
|
|
|
|
|
|
return defined($self->{_REGISTRY}{$package}); |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub _unregister{# Default back-end for package de-registration |
|
47
|
|
|
|
|
|
|
# If you wish to partially destruct an object, make sure to call this |
|
48
|
|
|
|
|
|
|
# from each namespace being removed from the object |
|
49
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
50
|
0
|
|
|
|
|
|
my $package=caller; |
|
51
|
0
|
|
|
|
|
|
$self->_taint($package); |
|
52
|
0
|
|
|
|
|
|
undef $self->{_REGISTRY}{$package}; |
|
53
|
0
|
|
|
|
|
|
return (!(defined($self->{_REGISTRY}{$package}))); |
|
54
|
|
|
|
|
|
|
} |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub _primary { # Sets/detects whether a namespace contains the primary key |
|
57
|
|
|
|
|
|
|
# Used internally to assure that the primary key's namespace is always |
|
58
|
|
|
|
|
|
|
# in sync with the rest of the object |
|
59
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
60
|
0
|
|
0
|
|
|
|
my $package=(UNIVERSAL::isa($_[0],__PACKAGE__) && shift) || caller; |
|
61
|
0
|
0
|
|
|
|
|
if ($_[0]) {$self->{_REGISTRY}{_PRIMARY}=$package;$self->_taint;} |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
62
|
0
|
|
0
|
|
|
|
return ($self->{_REGISTRY}{_PRIMARY} || 0); |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub _readonly { # Sets/detects whether a data mehod is tagged read-only |
|
66
|
|
|
|
|
|
|
# Used by AUTOLOAD to detect read-only method calls |
|
67
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
68
|
0
|
|
0
|
|
|
|
my $package=(UNIVERSAL::isa($_[0],__PACKAGE__) && shift) || caller; |
|
69
|
0
|
|
|
|
|
|
my $var=uc(shift); |
|
70
|
0
|
0
|
|
|
|
|
if (@_) {local $_=shift;$self->{_REGISTRY}{_DATA}{$var}{access}=(!($_)?1:0) if (/[01]/);} #Set to "0" to catch in this check next time |
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
71
|
0
|
|
0
|
|
|
|
return (!($self->{_REGISTRY}{_DATA}{$var}{access}) || |
|
72
|
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{source} eq $self->_primary); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub _validate { # Marks a namespace as tied to the back-end database |
|
76
|
|
|
|
|
|
|
# Intended to be called on first refresh - Paired with _taint |
|
77
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
78
|
0
|
|
0
|
|
|
|
my $package=shift || caller; |
|
79
|
0
|
0
|
|
|
|
|
(my @vars=$self->_vars($package)) || return $self; |
|
80
|
0
|
|
|
|
|
|
foreach my $var (@vars) { |
|
81
|
0
|
0
|
|
|
|
|
if ($self->_isobject($var)) { # Reset embedded object information (only if needed) |
|
82
|
0
|
0
|
0
|
|
|
|
unless ($self->{var} && ($self->{_REGISTRY}{_DATA}{$var}{data} eq $self->{$var})) { |
|
83
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{data}=$self->{$var}; |
|
84
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{prep}=0; |
|
85
|
0
|
|
|
|
|
|
$self->{$var}=undef; |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
} |
|
89
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{$package}{prep}=1; |
|
90
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{ref($self)}{prep}=1; |
|
91
|
0
|
|
|
|
|
|
$self->_clean($package); |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub _taint { # Marks a namespace as untied from the back-end database |
|
95
|
|
|
|
|
|
|
# Intended to be called on destruction only |
|
96
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
97
|
0
|
|
0
|
|
|
|
my $package=shift || caller; |
|
98
|
0
|
|
|
|
|
|
$self->_dirty($package); |
|
99
|
0
|
0
|
|
|
|
|
(my @vars=$self->_vars($package)) || return $self; |
|
100
|
0
|
|
|
|
|
|
foreach my $var (@vars) { |
|
101
|
0
|
0
|
|
|
|
|
if ($self->_isobject($var)) { # Reset embedded object information (only if needed) |
|
102
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{prep}=0; |
|
103
|
0
|
|
|
|
|
|
$self->{$var}=undef; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
|
|
|
|
|
|
} |
|
106
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{$package}{prep}=0; |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub _clean { # Marks a namespace as in-sync with the back-end database |
|
110
|
|
|
|
|
|
|
# Intended to be called on all calls to add(), refresh() and update() |
|
111
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
112
|
0
|
|
0
|
|
|
|
my $package=shift || caller; |
|
113
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{$package}{dirty}=0; |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub _dirty { # Marks a namespace as out-of-sync with the back-end databse |
|
117
|
|
|
|
|
|
|
# Intended to be called upon a write-access call to a class-method |
|
118
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
119
|
0
|
|
0
|
|
|
|
my $package=shift || caller; |
|
120
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{$package}{dirty}=1; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub _vars { # Returns a list of variables registered to a specific namespace |
|
124
|
|
|
|
|
|
|
# Used internally by default _refresh() and update() methods |
|
125
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
126
|
0
|
|
0
|
|
|
|
my $package=shift || caller; |
|
127
|
0
|
|
|
|
|
|
my @vars = (); |
|
128
|
0
|
|
|
|
|
|
my @keys = keys(%{$self->{_REGISTRY}{_DATA}}); |
|
|
0
|
|
|
|
|
|
|
|
129
|
0
|
|
|
|
|
|
foreach my $var(@keys) { |
|
130
|
0
|
0
|
|
|
|
|
push @vars,$var if ($self->{_REGISTRY}{_DATA}{$var}{source} eq $package); |
|
131
|
|
|
|
|
|
|
} |
|
132
|
0
|
|
|
|
|
|
return @vars; |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub _refresh { # Default back-end for refresh |
|
136
|
|
|
|
|
|
|
# Inherited classes should implement a custom _refresh() |
|
137
|
|
|
|
|
|
|
# Alternatively, the default _refresh may be used if a valid DBI connection |
|
138
|
|
|
|
|
|
|
# is set using $__PACKAGE__::dbh and the table is set to $__PACKAGE__::table |
|
139
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
140
|
0
|
|
0
|
|
|
|
my $package=(UNIVERSAL::isa($_[0],__PACKAGE__) && shift) || ref($self); |
|
141
|
0
|
|
0
|
|
|
|
my @vars=$self->_vars($package) || return $self; |
|
142
|
0
|
|
|
|
|
|
my $sth; |
|
143
|
|
|
|
|
|
|
{ |
|
144
|
1
|
|
|
1
|
|
10
|
no strict 'vars'; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
183
|
|
|
|
0
|
|
|
|
|
|
|
|
145
|
0
|
|
|
|
|
|
eval "\$sth=\$dbh->prepare_cached('SELECT \@vars FROM \$table WHERE (ID=?)');"; |
|
146
|
|
|
|
|
|
|
} |
|
147
|
0
|
0
|
|
|
|
|
$sth->execute(@_) or return $self->blank; |
|
148
|
0
|
0
|
|
|
|
|
if ($sth->rows!=1) { |
|
149
|
0
|
|
|
|
|
|
$self->blank; |
|
150
|
|
|
|
|
|
|
} else { |
|
151
|
0
|
|
|
|
|
|
my $res=$sth->fetchrow_hashref; |
|
152
|
0
|
|
|
|
|
|
foreach my $var (@vars) { |
|
153
|
0
|
|
|
|
|
|
$self->{$var}=$res->{$var}; |
|
154
|
|
|
|
|
|
|
} |
|
155
|
0
|
|
|
|
|
|
$self->_validate; |
|
156
|
|
|
|
|
|
|
} |
|
157
|
0
|
|
|
|
|
|
$sth->finish; |
|
158
|
0
|
|
|
|
|
|
return $self; |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub AUTOLOAD { # Default method call handler |
|
162
|
|
|
|
|
|
|
# Current support: |
|
163
|
|
|
|
|
|
|
# * Read/Write registered methods from internal hash |
|
164
|
0
|
|
|
0
|
|
|
my $param; |
|
165
|
|
|
|
|
|
|
my $package; |
|
166
|
|
|
|
|
|
|
{ |
|
167
|
1
|
|
|
1
|
|
7
|
no strict 'vars'; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
5509
|
|
|
|
0
|
|
|
|
|
|
|
|
168
|
0
|
|
|
|
|
|
$AUTOLOAD=~s/(.*):://; |
|
169
|
0
|
|
|
|
|
|
$package=$1; |
|
170
|
0
|
|
|
|
|
|
$param=$AUTOLOAD; |
|
171
|
|
|
|
|
|
|
} |
|
172
|
0
|
0
|
|
|
|
|
if (UNIVERSAL::isa($_[0],__PACKAGE__)) { # Method call of a sub-class |
|
173
|
0
|
|
|
|
|
|
my $self=shift; |
|
174
|
0
|
0
|
|
|
|
|
if ($self->{_REGISTRY}{_DATA}{uc($param)}) { # Acceptable function call |
|
175
|
0
|
|
|
|
|
|
my $source=$self->{_REGISTRY}{_DATA}{uc($param)}{source}; |
|
176
|
0
|
0
|
|
|
|
|
if (!($self->valid($source))) { |
|
177
|
0
|
|
|
|
|
|
$self->refresh($source); |
|
178
|
|
|
|
|
|
|
} |
|
179
|
|
|
|
|
|
|
# SET access |
|
180
|
0
|
0
|
0
|
|
|
|
if ((@_) && !($self->_readonly($source,$param))) { # Update rewriteable request |
|
181
|
0
|
0
|
|
|
|
|
if ($self->_isbasic($param)) { |
|
|
|
0
|
|
|
|
|
|
|
182
|
0
|
|
|
|
|
|
$self->{uc($param)}=@_; |
|
183
|
0
|
|
|
|
|
|
$self->_taint; |
|
184
|
|
|
|
|
|
|
} elsif ($self->_isobject($param)) { # Object SET |
|
185
|
0
|
0
|
|
|
|
|
unless ($self->_isobjarray($param)) { # No SET allowed on arrays |
|
186
|
0
|
|
|
|
|
|
my ($temp,$pid)=@_; |
|
187
|
0
|
0
|
|
|
|
|
if (ref($temp) eq $self->{_REGISTRY}{_DATA}{uc($param)}{class}) { |
|
188
|
|
|
|
|
|
|
# TODO: see if temp->isa($self->{_REGISTRY}{_DATA}{uc($param)}{class}) |
|
189
|
0
|
|
|
|
|
|
$pid=$temp->id; #Retrieve ID from internal object |
|
190
|
|
|
|
|
|
|
} else { |
|
191
|
0
|
|
|
|
|
|
$pid=$temp; #Assume ID is specified if not compatible object |
|
192
|
|
|
|
|
|
|
} |
|
193
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{uc($param)}{data}=$pid; |
|
194
|
0
|
|
|
|
|
|
$self->_taint; |
|
195
|
|
|
|
|
|
|
} |
|
196
|
|
|
|
|
|
|
} |
|
197
|
|
|
|
|
|
|
} # GET access |
|
198
|
0
|
0
|
|
|
|
|
if ($self->_isobject($param)) { # Prepare object |
|
199
|
0
|
0
|
|
|
|
|
return (wantarray?undef:0) unless $self->_o_prep($param); |
|
|
|
0
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
} |
|
201
|
0
|
0
|
|
|
|
|
if ($self->_isobjarray($param)) { # Object array returns special values |
|
202
|
0
|
0
|
|
|
|
|
return (wantarray?@{$self->{uc($param)}}:$self->{_REGISTRY}{_DATA}{uc($param)}{prep}); |
|
|
0
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
} else { |
|
204
|
0
|
|
|
|
|
|
return $self->{uc($param)}; |
|
205
|
|
|
|
|
|
|
} |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
} |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub new { # Default constructor |
|
211
|
|
|
|
|
|
|
# Do not overload this unless you're SURE you know what you're doing |
|
212
|
0
|
|
|
0
|
|
|
my $self={ }; |
|
213
|
0
|
|
|
|
|
|
my $proto=shift; |
|
214
|
0
|
|
0
|
|
|
|
my $class=ref($proto) || $proto; |
|
215
|
0
|
|
|
|
|
|
bless $self,$class; |
|
216
|
0
|
|
|
|
|
|
eval "foreach \$_ (\@".$class."::ISA) {eval \$_.\"::blank(\\\$self);\";}"; |
|
217
|
0
|
|
|
|
|
|
$self->_register; |
|
218
|
0
|
|
|
|
|
|
$self->blank(@_); |
|
219
|
0
|
0
|
|
|
|
|
if (@_) { |
|
220
|
0
|
0
|
|
|
|
|
eval ($self->_primary."::_refresh(\$self,'".$self->_primary."',@_);") if ($self->_primary); |
|
221
|
0
|
|
|
|
|
|
$self->_refresh(@_); |
|
222
|
|
|
|
|
|
|
} |
|
223
|
0
|
|
|
|
|
|
return $self; |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub clean { # Returns true if namepace is in-sync with back-end database |
|
227
|
|
|
|
|
|
|
# Be sure to check for valid()ity BEFORE using this |
|
228
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
229
|
0
|
|
0
|
|
|
|
my $package=shift || caller; |
|
230
|
0
|
|
|
|
|
|
return !($self->{_REGISTRY}{$package}{dirty}); |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
sub valid { # Returns true if namespace is tied and in-sync with back-end database |
|
234
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
235
|
0
|
|
0
|
|
|
|
my $package=shift || ref($self); |
|
236
|
0
|
0
|
0
|
|
|
|
if ($self->_primary) |
|
|
0
|
|
|
|
|
|
|
|
237
|
0
|
|
0
|
|
|
|
{return ($self->{_REGISTRY}{$self->_primary}{prep} && |
|
238
|
|
|
|
|
|
|
$self->clean($self->_primary) && |
|
239
|
|
|
|
|
|
|
$self->{_REGISTRY}{$package}{prep} && |
|
240
|
|
|
|
|
|
|
$self->clean($package))} |
|
241
|
|
|
|
|
|
|
else {return $self->{_REGISTRY}{$package}{prep} && |
|
242
|
|
|
|
|
|
|
$self->clean($package)}; |
|
243
|
|
|
|
|
|
|
} |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
sub blank { # Default (abstract) blank method - used by the default constructor |
|
246
|
|
|
|
|
|
|
# This should be overridden by any inherited class that's meant to be useful |
|
247
|
|
|
|
|
|
|
# A typical blank() method should look like: |
|
248
|
|
|
|
|
|
|
# sub blank { |
|
249
|
|
|
|
|
|
|
# my $self=shift; |
|
250
|
|
|
|
|
|
|
# $self->_register; |
|
251
|
|
|
|
|
|
|
# $self->_blank("FOO", "BAR", ... , "LAST"); |
|
252
|
|
|
|
|
|
|
# } |
|
253
|
0
|
|
|
0
|
|
|
$_[0]->_register; |
|
254
|
|
|
|
|
|
|
} |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
sub refresh { # Default front-end for refresh |
|
257
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
258
|
0
|
|
0
|
|
|
|
my $package=shift || ref($self); |
|
259
|
0
|
|
|
|
|
|
$self->_taint($package); |
|
260
|
0
|
|
|
|
|
|
eval $package."::_refresh(\$self,".$self->id.");"; |
|
261
|
0
|
|
|
|
|
|
return $self->valid; |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub id { # Default id method - must be explicitly so that it can be overloaded |
|
265
|
|
|
|
|
|
|
# when needed for refresh, but not be dependant on the object being valid |
|
266
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
267
|
|
|
|
|
|
|
# Set access |
|
268
|
0
|
0
|
0
|
|
|
|
if ((@_) && !($self->_readonly("id"))) { # Update rewriteable request |
|
269
|
0
|
|
|
|
|
|
$self->{ID}=@_; |
|
270
|
0
|
|
|
|
|
|
$self->_taint; |
|
271
|
|
|
|
|
|
|
} |
|
272
|
0
|
|
|
|
|
|
return $self->{ID}; |
|
273
|
|
|
|
|
|
|
} |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
sub _isbasic { # Returns true if access method marked as basic (default) |
|
276
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
277
|
0
|
|
|
|
|
|
my $var=uc(shift); |
|
278
|
0
|
|
|
|
|
|
return ($self->{_REGISTRY}{_DATA}{$var}{type} eq "basic"); |
|
279
|
|
|
|
|
|
|
} |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub _isobject { # Returns true if access method marked as embedded object |
|
282
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
283
|
0
|
|
|
|
|
|
my $var=uc(shift); |
|
284
|
0
|
|
|
|
|
|
return ($self->{_REGISTRY}{_DATA}{$var}{type} eq "object"); |
|
285
|
|
|
|
|
|
|
} |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
sub _isobjarray { |
|
288
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
289
|
0
|
|
|
|
|
|
my $var=uc(shift); |
|
290
|
0
|
|
0
|
|
|
|
return ($self->_isobject($var) && $self->{_REGISTRY}{_DATA}{$var}{array}); |
|
291
|
|
|
|
|
|
|
} |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub _object { # Marks an access member as an object (call in blank) |
|
294
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
295
|
0
|
|
|
|
|
|
my $var=uc(shift); |
|
296
|
0
|
|
0
|
|
|
|
my $package=(UNIVERSAL::isa($_[0],__PACKAGE__) && shift) || ref($self); |
|
297
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{prep}=0; |
|
298
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{class}=$package; |
|
299
|
0
|
|
0
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{data}=$self->{$var} || undef; |
|
300
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{array}=0; |
|
301
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{type}="object"; |
|
302
|
0
|
|
|
|
|
|
$self->{$var}=undef; |
|
303
|
|
|
|
|
|
|
} |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub _objarray { # Marks an access member as an array of objects (call in blank) |
|
306
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
307
|
0
|
|
|
|
|
|
my $var=uc(shift); |
|
308
|
0
|
|
0
|
|
|
|
my $package=(UNIVERSAL::isa($_[0],__PACKAGE__) && shift) || ref($self); |
|
309
|
0
|
|
|
|
|
|
$self->_object($var,$package); |
|
310
|
0
|
|
|
|
|
|
$self->_readonly($var,1); |
|
311
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{array}=1; |
|
312
|
|
|
|
|
|
|
} |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# This (objarray) won't be fully implemented until I can figure out how the heck |
|
315
|
|
|
|
|
|
|
# to set the data source as an array - it probably has to be dealt with by |
|
316
|
|
|
|
|
|
|
# end-module's refresh ($self->{$var}=@arrayofdata;) [UPDATE VALIDATE TO DEAL WITH THIS]... |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub _o_prep { |
|
319
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
320
|
0
|
|
|
|
|
|
my $var=uc(shift); |
|
321
|
0
|
|
|
|
|
|
my $class=$self->{_REGISTRY}{_DATA}{$var}{class}; |
|
322
|
0
|
|
|
|
|
|
my $source=$self->{_REGISTRY}{_DATA}{$var}{source}; |
|
323
|
0
|
0
|
|
|
|
|
return 0 unless $self->valid($source); |
|
324
|
0
|
0
|
|
|
|
|
return $self->{_REGISTRY}{_DATA}{$var}{prep} if |
|
325
|
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{prep}; |
|
326
|
0
|
0
|
|
|
|
|
if ($self->_isobjarray($var)) { |
|
327
|
0
|
|
|
|
|
|
for (my $i=0;$i<=$#{$self->{_REGISTRY}{_DATA}{$var}{data}};$i++) { |
|
|
0
|
|
|
|
|
|
|
|
328
|
0
|
|
|
|
|
|
$self->{$var}[$i]=$class->new($self->{_REGISTRY}{_DATA}{$var}{data}[$i]); |
|
329
|
|
|
|
|
|
|
} |
|
330
|
0
|
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{prep}=$#{$self->{_REGISTRY}{_DATA}{$var}{data}}+1; |
|
|
0
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
} else { |
|
332
|
0
|
0
|
|
|
|
|
$self->{_REGISTRY}{_DATA}{$var}{prep}=(($self->{$var}=$class->new($self->{_REGISTRY}{_DATA}{$var}{data}))?1:0); |
|
333
|
|
|
|
|
|
|
} |
|
334
|
0
|
|
|
|
|
|
return $self->{_REGISTRY}{_DATA}{$var}{prep}; |
|
335
|
|
|
|
|
|
|
} |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
# TODO: Update updates recursively (into embedded objects) |
|
338
|
|
|
|
|
|
|
# UpdateNR updates non-0recursively (data ghets lost) |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
# DOCUMENT: _validate also initializes objects by setting internal DATA value and clearing external value |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
package DBIx::Object::DBI; #Shortcut functions for DBI-based backend |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
our @ISA=qw(DBIx::Object); |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
sub blank { |
|
348
|
0
|
|
|
0
|
|
|
$_[0]->_register; |
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
sub _dbidbh { # Sets/returns the DBI connection to use |
|
352
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
353
|
0
|
|
0
|
|
|
|
my $package=(UNIVERSAL::isa($_[0],__PACKAGE__) && shift) || caller; |
|
354
|
0
|
0
|
|
|
|
|
if($_[0]) {$self->{_REGISTRY}{$package}{DBI}{dbh}=$_[0];} |
|
|
0
|
|
|
|
|
|
|
|
355
|
0
|
|
|
|
|
|
return $self->{_REGISTRY}{$package}{DBI}{dbh}; |
|
356
|
|
|
|
|
|
|
} |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
sub _dbirefresh { # Sets/returns the SQL statement to run on refresh calls |
|
359
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
360
|
0
|
|
0
|
|
|
|
my $package=(UNIVERSAL::isa($_[0],__PACKAGE__) && shift) || caller; |
|
361
|
0
|
0
|
|
|
|
|
if($_[0]) {$self->{_REGISTRY}{$package}{DBI}{refresh}=$_[0];} |
|
|
0
|
|
|
|
|
|
|
|
362
|
0
|
|
|
|
|
|
return $self->{_REGISTRY}{$package}{DBI}{refresh}; |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub _refresh { # Default back-end for DBI refresh |
|
366
|
|
|
|
|
|
|
# Inherited classes may implement a custom _refresh() |
|
367
|
0
|
|
|
0
|
|
|
my $self=shift; |
|
368
|
0
|
|
0
|
|
|
|
my $package=(UNIVERSAL::isa($_[0],__PACKAGE__) && shift) || ref($self); |
|
369
|
0
|
|
|
|
|
|
my $sth=$self->{_REGISTRY}{$package}{DBI}{dbh}->prepare_cached($self->{_REGISTRY}{$package}{DBI}{refresh}); |
|
370
|
0
|
0
|
|
|
|
|
$sth->execute(@_) or return $self->blank; |
|
371
|
0
|
0
|
|
|
|
|
if ($sth->rows!=1) { |
|
372
|
0
|
|
|
|
|
|
$self->blank; |
|
373
|
|
|
|
|
|
|
} else { |
|
374
|
0
|
|
|
|
|
|
my $res=$sth->fetchrow_hashref; |
|
375
|
0
|
|
|
|
|
|
foreach my $key (keys %{$res}) { |
|
|
0
|
|
|
|
|
|
|
|
376
|
0
|
|
|
|
|
|
$self->{uc($key)}=$res->{$key}; |
|
377
|
|
|
|
|
|
|
} |
|
378
|
0
|
|
|
|
|
|
$self->_validate($package); |
|
379
|
|
|
|
|
|
|
} |
|
380
|
0
|
|
|
|
|
|
$sth->finish; |
|
381
|
0
|
|
|
|
|
|
return $self; |
|
382
|
|
|
|
|
|
|
} |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
1; |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
__END__ |