line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package RapidApp::DBIC::Component::TableSpec; |
2
|
|
|
|
|
|
|
#use base 'DBIx::Class'; |
3
|
|
|
|
|
|
|
# this is for Attribute::Handlers: |
4
|
|
|
|
|
|
|
require base; base->import('DBIx::Class'); |
5
|
|
|
|
|
|
|
|
6
|
5
|
|
|
5
|
|
98284
|
use strict; |
|
5
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
173
|
|
7
|
5
|
|
|
5
|
|
31
|
use warnings; |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
169
|
|
8
|
|
|
|
|
|
|
|
9
|
5
|
|
|
5
|
|
501
|
use Sub::Name qw/subname/; |
|
5
|
|
|
|
|
644
|
|
|
5
|
|
|
|
|
292
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# DBIx::Class Component: ties a RapidApp::TableSpec object to |
12
|
|
|
|
|
|
|
# a Result class for use in configuring various modules that |
13
|
|
|
|
|
|
|
# consume/use a DBIC Source |
14
|
|
|
|
|
|
|
|
15
|
5
|
|
|
5
|
|
536
|
use RapidApp::Util qw(:all); |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
3048
|
|
16
|
|
|
|
|
|
|
|
17
|
5
|
|
|
5
|
|
2078
|
use RapidApp::TableSpec; |
|
5
|
|
|
|
|
18
|
|
|
5
|
|
|
|
|
249
|
|
18
|
5
|
|
|
5
|
|
7836
|
use RapidApp::Module::DbicCombo; |
|
5
|
|
|
|
|
22
|
|
|
5
|
|
|
|
|
362
|
|
19
|
5
|
|
|
5
|
|
39
|
use Module::Runtime; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
67
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
#__PACKAGE__->load_components(qw/IntrospectableM2M/); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
__PACKAGE__->load_components('+RapidApp::DBIC::Component::VirtualColumnsExt'); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
__PACKAGE__->mk_classdata( 'TableSpec' ); |
26
|
|
|
|
|
|
|
__PACKAGE__->mk_classdata( 'TableSpec_rel_columns' ); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
__PACKAGE__->mk_classdata( 'TableSpec_cnf' ); |
29
|
|
|
|
|
|
|
__PACKAGE__->mk_classdata( 'TableSpec_built_cnf' ); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# See default profile definitions in RapidApp::TableSpec::Column |
32
|
|
|
|
|
|
|
my $default_data_type_profiles = { |
33
|
|
|
|
|
|
|
text => [ 'bigtext' ], |
34
|
|
|
|
|
|
|
mediumtext => [ 'bigtext' ], |
35
|
|
|
|
|
|
|
longtext => [ 'bigtext' ], |
36
|
|
|
|
|
|
|
tinytext => [ 'text' ], |
37
|
|
|
|
|
|
|
smalltext => [ 'text' ], |
38
|
|
|
|
|
|
|
varchar => [ 'text' ], |
39
|
|
|
|
|
|
|
char => [ 'text' ], |
40
|
|
|
|
|
|
|
nvarchar => [ 'text' ], |
41
|
|
|
|
|
|
|
nchar => [ 'text' ], |
42
|
|
|
|
|
|
|
float => [ 'number' ], |
43
|
|
|
|
|
|
|
integer => [ 'number', 'int' ], |
44
|
|
|
|
|
|
|
tinyint => [ 'number', 'int' ], |
45
|
|
|
|
|
|
|
smallint => [ 'number', 'int' ], |
46
|
|
|
|
|
|
|
mediumint => [ 'number', 'int' ], |
47
|
|
|
|
|
|
|
bigint => [ 'number', 'int' ], |
48
|
|
|
|
|
|
|
decimal => [ 'number' ], |
49
|
|
|
|
|
|
|
numeric => [ 'number' ], |
50
|
|
|
|
|
|
|
double => [ 'number' ], |
51
|
|
|
|
|
|
|
'double precision' => [ 'number' ], |
52
|
|
|
|
|
|
|
datetime => [ 'datetime' ], |
53
|
|
|
|
|
|
|
timestamp => [ 'datetime' ], |
54
|
|
|
|
|
|
|
date => [ 'date' ], |
55
|
|
|
|
|
|
|
blob => [ 'blob' ], |
56
|
|
|
|
|
|
|
longblob => [ 'blob' ], |
57
|
|
|
|
|
|
|
mediumblob => [ 'blob' ], |
58
|
|
|
|
|
|
|
tinyblob => [ 'blob' ], |
59
|
|
|
|
|
|
|
smallblob => [ 'blob' ], |
60
|
|
|
|
|
|
|
binary => [ 'blob' ], |
61
|
|
|
|
|
|
|
varbinary => [ 'blob' ], |
62
|
|
|
|
|
|
|
year => [ 'otherdate' ], |
63
|
|
|
|
|
|
|
tsvector => [ 'bigtext','unsearchable','virtual_source' ], #<-- postgres-specific |
64
|
|
|
|
|
|
|
boolean => ['bool'], |
65
|
|
|
|
|
|
|
ipaddr => ['unsearchable'] #<-- postgres-specific |
66
|
|
|
|
|
|
|
}; |
67
|
|
|
|
|
|
|
__PACKAGE__->mk_classdata( 'TableSpec_data_type_profiles' ); |
68
|
|
|
|
|
|
|
__PACKAGE__->TableSpec_data_type_profiles({ %$default_data_type_profiles }); |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
## Sets up many_to_many along with TableSpec m2m multi-relationship column |
72
|
|
|
|
|
|
|
sub TableSpec_m2m { |
73
|
2
|
|
|
2
|
0
|
6
|
my $self = shift; |
74
|
2
|
|
|
|
|
7
|
my ($m2m,$local_rel,$remote_rel) = @_; |
75
|
|
|
|
|
|
|
|
76
|
2
|
50
|
|
|
|
13
|
$self->is_TableSpec_applied and |
77
|
|
|
|
|
|
|
die "TableSpec_m2m must be called before apply_TableSpec!"; |
78
|
|
|
|
|
|
|
|
79
|
2
|
50
|
|
|
|
300
|
$self->has_column($m2m) and die "'$m2m' is already defined as a column."; |
80
|
2
|
50
|
|
|
|
201
|
$self->has_relationship($m2m) and die "'$m2m' is already defined as a relationship."; |
81
|
|
|
|
|
|
|
|
82
|
2
|
50
|
|
|
|
539
|
my $rinfo = $self->relationship_info($local_rel) or die "'$local_rel' relationship not found"; |
83
|
2
|
|
|
|
|
214
|
eval('require ' . $rinfo->{class}); |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
die "m2m bridge relationship '$local_rel' is not a multi relationship" |
86
|
2
|
50
|
|
|
|
15
|
unless ($rinfo->{attrs}->{accessor} eq 'multi'); |
87
|
|
|
|
|
|
|
|
88
|
2
|
|
|
|
|
50
|
my $rrinfo = $rinfo->{class}->relationship_info($remote_rel); |
89
|
2
|
50
|
|
|
|
95
|
unless($rrinfo) { |
90
|
|
|
|
|
|
|
# Note: we're not dying here because this is known to happen when called from Schema::Loader |
91
|
|
|
|
|
|
|
# and we don't want that to fail. It is not known to fail during normal operation. TODO/FIXME |
92
|
0
|
|
|
|
|
0
|
warn "TableSpec_m2m(): unable to resolve remote rel '$remote_rel' -- falling back to many_to_many\n"; |
93
|
0
|
|
|
|
|
0
|
return $self->many_to_many($m2m,$local_rel,$remote_rel); |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
2
|
|
|
|
|
10
|
Module::Runtime::require_module($rrinfo->{class}); |
97
|
|
|
|
|
|
|
|
98
|
2
|
|
|
|
|
54
|
$rinfo->{table} = &_table_name_safe($rinfo->{class}->table); |
99
|
2
|
|
|
|
|
19
|
$rrinfo->{table} = &_table_name_safe($rrinfo->{class}->table); |
100
|
|
|
|
|
|
|
|
101
|
2
|
|
|
|
|
15
|
$rinfo->{cond_info} = $self->parse_relationship_cond($rinfo->{cond}); |
102
|
2
|
|
|
|
|
7
|
$rrinfo->{cond_info} = $self->parse_relationship_cond($rrinfo->{cond}); |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# |
105
|
|
|
|
|
|
|
#my $sql = '(' . |
106
|
|
|
|
|
|
|
# # SQLite Specific: |
107
|
|
|
|
|
|
|
# #'SELECT(GROUP_CONCAT(flags.flag,", "))' . |
108
|
|
|
|
|
|
|
# |
109
|
|
|
|
|
|
|
# # MySQL Sepcific: |
110
|
|
|
|
|
|
|
# #'SELECT(GROUP_CONCAT(flags.flag SEPARATOR ", "))' . |
111
|
|
|
|
|
|
|
# |
112
|
|
|
|
|
|
|
# # Generic (MySQL & SQLite): |
113
|
|
|
|
|
|
|
# 'SELECT(GROUP_CONCAT(`' . $rrinfo->{table} . '`.`' . $rrinfo->{cond_info}->{foreign} . '`))' . |
114
|
|
|
|
|
|
|
# |
115
|
|
|
|
|
|
|
# ' FROM `' . $rinfo->{table} . '`' . |
116
|
|
|
|
|
|
|
# ' JOIN `' . $rrinfo->{table} . '` `' . $rrinfo->{table} . '`' . |
117
|
|
|
|
|
|
|
# ' ON `' . $rinfo->{table} . '`.`' . $rrinfo->{cond_info}->{self} . '`' . |
118
|
|
|
|
|
|
|
# ' = `' . $rrinfo->{table} . '`.`' . $rrinfo->{cond_info}->{foreign} . '`' . |
119
|
|
|
|
|
|
|
# #' ON customers_to_flags.flag = flags.flag' . |
120
|
|
|
|
|
|
|
# ' WHERE `' . $rinfo->{cond_info}->{foreign} . '` = ' . $rel . '.' . $cond_data->{self} . |
121
|
|
|
|
|
|
|
#')'; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# Create a relationship exactly like the the local bridge relationship, adding |
124
|
|
|
|
|
|
|
# the 'm2m_attrs' attribute which will be used later on to setup the special, |
125
|
|
|
|
|
|
|
# m2m-specific multi-relationship column properties (renderer, editor, and to |
126
|
|
|
|
|
|
|
# trigger proxy m2m updates in DbicLink2): |
127
|
|
|
|
|
|
|
$self->add_relationship( |
128
|
|
|
|
|
|
|
$m2m, |
129
|
|
|
|
|
|
|
$rinfo->{class}, |
130
|
|
|
|
|
|
|
$rinfo->{cond}, |
131
|
2
|
|
|
|
|
7
|
{%{$rinfo->{attrs}}, m2m_attrs => { |
|
2
|
|
|
|
|
38
|
|
132
|
|
|
|
|
|
|
remote_rel => $remote_rel, |
133
|
|
|
|
|
|
|
rinfo => $rinfo, |
134
|
|
|
|
|
|
|
rrinfo => $rrinfo |
135
|
|
|
|
|
|
|
}} |
136
|
|
|
|
|
|
|
); |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# -- Add a normal many_to_many bridge so we have the many_to_many sugar later on: |
139
|
|
|
|
|
|
|
# (we use 'set_$rel' in update_records in DbicLink2) |
140
|
|
|
|
|
|
|
local $ENV{DBIC_OVERWRITE_HELPER_METHODS_OK} = 1 |
141
|
2
|
50
|
|
|
|
824
|
unless (exists $ENV{DBIC_OVERWRITE_HELPER_METHODS_OK}); |
142
|
2
|
|
|
|
|
26
|
$self->many_to_many(@_); |
143
|
|
|
|
|
|
|
#$self->apply_m2m_sugar(@_); |
144
|
|
|
|
|
|
|
# -- |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
## sugar copied from many_to_many (DBIx::Class::Relationship::ManyToMany), |
148
|
|
|
|
|
|
|
## but only sets up add_$rel and set_$rel and won't overwrite existing subs (safer) |
149
|
|
|
|
|
|
|
#sub apply_m2m_sugar { |
150
|
|
|
|
|
|
|
# my ($class, $meth, $rel, $f_rel, $rel_attrs) = @_; |
151
|
|
|
|
|
|
|
# |
152
|
|
|
|
|
|
|
# my $set_meth = "set_${meth}"; |
153
|
|
|
|
|
|
|
# my $add_meth = "add_${meth}"; |
154
|
|
|
|
|
|
|
# |
155
|
|
|
|
|
|
|
# $class->can($set_meth) and |
156
|
|
|
|
|
|
|
# die "m2m: set method '$set_meth' is already defined in (" . ref($class) . ")"; |
157
|
|
|
|
|
|
|
# |
158
|
|
|
|
|
|
|
# $class->can($add_meth) and |
159
|
|
|
|
|
|
|
# die "m2m: add method '$add_meth' is already defined in (" . ref($class) . ")"; |
160
|
|
|
|
|
|
|
# |
161
|
|
|
|
|
|
|
# my $add_meth_name = join '::', $class, $add_meth; |
162
|
|
|
|
|
|
|
# *$add_meth_name = subname $add_meth_name, sub { |
163
|
|
|
|
|
|
|
# my $self = shift; |
164
|
|
|
|
|
|
|
# @_ > 0 or $self->throw_exception( |
165
|
|
|
|
|
|
|
# "${add_meth} needs an object or hashref" |
166
|
|
|
|
|
|
|
# ); |
167
|
|
|
|
|
|
|
# my $source = $self->result_source; |
168
|
|
|
|
|
|
|
# my $schema = $source->schema; |
169
|
|
|
|
|
|
|
# my $rel_source_name = $source->relationship_info($rel)->{source}; |
170
|
|
|
|
|
|
|
# my $rel_source = $schema->resultset($rel_source_name)->result_source; |
171
|
|
|
|
|
|
|
# my $f_rel_source_name = $rel_source->relationship_info($f_rel)->{source}; |
172
|
|
|
|
|
|
|
# my $f_rel_rs = $schema->resultset($f_rel_source_name)->search({}, $rel_attrs||{}); |
173
|
|
|
|
|
|
|
# |
174
|
|
|
|
|
|
|
# my $obj; |
175
|
|
|
|
|
|
|
# if (ref $_[0]) { |
176
|
|
|
|
|
|
|
# if (ref $_[0] eq 'HASH') { |
177
|
|
|
|
|
|
|
# $obj = $f_rel_rs->find_or_create($_[0]); |
178
|
|
|
|
|
|
|
# } else { |
179
|
|
|
|
|
|
|
# $obj = $_[0]; |
180
|
|
|
|
|
|
|
# } |
181
|
|
|
|
|
|
|
# } else { |
182
|
|
|
|
|
|
|
# $obj = $f_rel_rs->find_or_create({@_}); |
183
|
|
|
|
|
|
|
# } |
184
|
|
|
|
|
|
|
# |
185
|
|
|
|
|
|
|
# my $link_vals = @_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {}; |
186
|
|
|
|
|
|
|
# my $link = $self->search_related($rel)->new_result($link_vals); |
187
|
|
|
|
|
|
|
# $link->set_from_related($f_rel, $obj); |
188
|
|
|
|
|
|
|
# $link->insert(); |
189
|
|
|
|
|
|
|
# return $obj; |
190
|
|
|
|
|
|
|
# }; |
191
|
|
|
|
|
|
|
# |
192
|
|
|
|
|
|
|
# my $set_meth_name = join '::', $class, $set_meth; |
193
|
|
|
|
|
|
|
# *$set_meth_name = subname $set_meth_name, sub { |
194
|
|
|
|
|
|
|
# my $self = shift; |
195
|
|
|
|
|
|
|
# @_ > 0 or $self->throw_exception( |
196
|
|
|
|
|
|
|
# "{$set_meth} needs a list of objects or hashrefs" |
197
|
|
|
|
|
|
|
# ); |
198
|
|
|
|
|
|
|
# my @to_set = (ref($_[0]) eq 'ARRAY' ? @{ $_[0] } : @_); |
199
|
|
|
|
|
|
|
# # if there is a where clause in the attributes, ensure we only delete |
200
|
|
|
|
|
|
|
# # rows that are within the where restriction |
201
|
|
|
|
|
|
|
# if ($rel_attrs && $rel_attrs->{where}) { |
202
|
|
|
|
|
|
|
# $self->search_related( $rel, $rel_attrs->{where},{join => $f_rel})->delete; |
203
|
|
|
|
|
|
|
# } else { |
204
|
|
|
|
|
|
|
# $self->search_related( $rel, {} )->delete; |
205
|
|
|
|
|
|
|
# } |
206
|
|
|
|
|
|
|
# # add in the set rel objects |
207
|
|
|
|
|
|
|
# $self->$add_meth($_, ref($_[1]) ? $_[1] : {}) for (@to_set); |
208
|
|
|
|
|
|
|
# }; |
209
|
|
|
|
|
|
|
#} |
210
|
|
|
|
|
|
|
## -- |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub is_TableSpec_applied { |
213
|
56
|
|
|
56
|
0
|
124
|
my $self = shift; |
214
|
|
|
|
|
|
|
return ( |
215
|
|
|
|
|
|
|
defined $self->TableSpec_cnf and |
216
|
|
|
|
|
|
|
defined $self->TableSpec_cnf->{apply_TableSpec_timestamp} |
217
|
56
|
|
33
|
|
|
1404
|
); |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub apply_TableSpec { |
221
|
54
|
|
|
54
|
0
|
155
|
my $self = shift; |
222
|
54
|
50
|
|
|
|
276
|
my %opt = (ref($_[0]) eq 'HASH') ? %{ $_[0] } : @_; # <-- arg as hash or hashref |
|
0
|
|
|
|
|
0
|
|
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
# ignore/return if apply_TableSpec has already been called: |
225
|
54
|
50
|
|
|
|
349
|
return if $self->is_TableSpec_applied; |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# make sure _virtual_columns and _virtual_columns_order get initialized |
228
|
54
|
|
|
|
|
9639
|
$self->add_virtual_columns(); |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
$self->TableSpec_data_type_profiles( |
232
|
0
|
0
|
|
|
|
0
|
%{ $self->TableSpec_data_type_profiles || {} }, |
233
|
0
|
|
|
|
|
0
|
%{ delete $opt{TableSpec_data_type_profiles} } |
234
|
54
|
50
|
|
|
|
186
|
) if ($opt{TableSpec_data_type_profiles}); |
235
|
|
|
|
|
|
|
|
236
|
54
|
|
|
|
|
379
|
$self->TableSpec($self->create_result_TableSpec($self,%opt)); |
237
|
|
|
|
|
|
|
|
238
|
54
|
|
|
|
|
2573
|
$self->TableSpec_rel_columns({}); |
239
|
54
|
|
|
|
|
1745
|
$self->TableSpec_cnf({}); |
240
|
54
|
|
|
|
|
1914
|
$self->TableSpec_built_cnf(undef); |
241
|
|
|
|
|
|
|
|
242
|
54
|
|
|
|
|
1253
|
$self->apply_row_methods(); |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
# Just doing this to ensure we're initialized: |
245
|
54
|
|
|
|
|
447
|
$self->TableSpec_set_conf( apply_TableSpec_timestamp => time ); |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
# --- Set some base defaults here: |
248
|
54
|
|
|
|
|
1206
|
my $table = &_table_name_safe($self->table); |
249
|
54
|
|
|
|
|
1833
|
my ($pri) = ($self->primary_columns,$self->columns); #<-- first primary col, or first col |
250
|
|
|
|
|
|
|
$self->TableSpec_set_conf( |
251
|
|
|
|
|
|
|
display_column => $pri, |
252
|
|
|
|
|
|
|
title => $table, |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# -- |
255
|
|
|
|
|
|
|
# New: initialize the columns cnf key early. It doesn't even need all |
256
|
|
|
|
|
|
|
# the columns (just at least one -- we're just doing the base columns |
257
|
|
|
|
|
|
|
# and not bothering with relationships + virtual columns). This is |
258
|
|
|
|
|
|
|
# just about getting the Hash defined so that later calls will update |
259
|
|
|
|
|
|
|
# this hash rather than create a new one, which can get lost in certain |
260
|
|
|
|
|
|
|
# situations (such as a Result Class that loads the TableSpec component |
261
|
|
|
|
|
|
|
# in-line but does not apply any column configs). |
262
|
|
|
|
|
|
|
# This was needed added after the recent prelim TableSpec_cnf refactor (in v0.99030) |
263
|
|
|
|
|
|
|
# which is a temp/in-between change that consolidates storage of column |
264
|
|
|
|
|
|
|
# configs internally while still preserving the original API for now. |
265
|
|
|
|
|
|
|
# Yes, this is ugly/hackish but will go away as soon as the full-blown, |
266
|
|
|
|
|
|
|
# long-planned TableSpec refactor is undertaken... |
267
|
54
|
|
|
|
|
917
|
columns => { map { $_ => {} } $self->columns } |
|
313
|
|
|
|
|
1504
|
|
268
|
|
|
|
|
|
|
# -- |
269
|
|
|
|
|
|
|
); |
270
|
|
|
|
|
|
|
# --- |
271
|
|
|
|
|
|
|
|
272
|
54
|
|
|
|
|
3225
|
return $self; |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
sub create_result_TableSpec { |
276
|
54
|
|
|
54
|
0
|
128
|
my $self = shift; |
277
|
54
|
|
|
|
|
97
|
my $ResultClass = shift; |
278
|
54
|
50
|
|
|
|
193
|
my %opt = (ref($_[0]) eq 'HASH') ? %{ $_[0] } : @_; # <-- arg as hash or hashref |
|
0
|
|
|
|
|
0
|
|
279
|
|
|
|
|
|
|
|
280
|
54
|
|
|
|
|
633
|
my $table = &_table_name_safe($ResultClass->table); |
281
|
|
|
|
|
|
|
|
282
|
54
|
|
|
|
|
1689
|
my $TableSpec = RapidApp::TableSpec->new( |
283
|
|
|
|
|
|
|
name => $table, |
284
|
|
|
|
|
|
|
%opt |
285
|
|
|
|
|
|
|
); |
286
|
|
|
|
|
|
|
|
287
|
54
|
|
|
|
|
1260
|
my $data_types = $self->TableSpec_data_type_profiles; |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
## WARNING! This logic overlaps with logic further down (in default_TableSpec_cnf_columns) |
290
|
54
|
|
|
|
|
2880
|
foreach my $col ($ResultClass->columns) { |
291
|
313
|
|
|
|
|
2100
|
my $info = $ResultClass->column_info($col); |
292
|
313
|
|
|
|
|
32437
|
my @profiles = (); |
293
|
|
|
|
|
|
|
|
294
|
313
|
100
|
|
|
|
1139
|
push @profiles, $info->{is_nullable} ? 'nullable' : 'notnull'; |
295
|
313
|
100
|
|
|
|
777
|
push @profiles, 'autoinc' if ($info->{is_auto_increment}); |
296
|
|
|
|
|
|
|
|
297
|
313
|
|
50
|
|
|
1303
|
my $type_profile = $data_types->{$info->{data_type}} || ['text']; |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# -- PostgreSQL override until array columns are supported (Github Issue #55): |
300
|
|
|
|
|
|
|
$type_profile = ['unsearchable','virtual_source'] if ( |
301
|
313
|
50
|
|
|
|
866
|
$info->{data_type} =~ /\[/ #<-- if the data_type contains a square backect, i.e. 'text[]' |
302
|
|
|
|
|
|
|
); |
303
|
|
|
|
|
|
|
# -- |
304
|
|
|
|
|
|
|
|
305
|
313
|
50
|
|
|
|
725
|
$type_profile = [ $type_profile ] unless (ref $type_profile); |
306
|
313
|
|
|
|
|
606
|
push @profiles, @$type_profile; |
307
|
|
|
|
|
|
|
|
308
|
313
|
|
|
|
|
1429
|
$TableSpec->add_columns( { name => $col, profiles => \@profiles } ); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
54
|
|
|
|
|
1627
|
return $TableSpec; |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
sub get_built_Cnf { |
316
|
1056
|
|
|
1056
|
0
|
2285
|
my $self = shift; |
317
|
|
|
|
|
|
|
|
318
|
1056
|
100
|
|
|
|
22127
|
$self->TableSpec_build_cnf unless ($self->TableSpec_built_cnf); |
319
|
1056
|
|
|
|
|
53084
|
return $self->TableSpec_built_cnf; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
sub TableSpec_build_cnf { |
323
|
66
|
|
|
66
|
0
|
15094
|
my $self = shift; |
324
|
66
|
50
|
|
|
|
199
|
my %set_cnf = %{ $self->TableSpec_cnf || {} }; |
|
66
|
|
|
|
|
1755
|
|
325
|
66
|
|
|
|
|
3978
|
$self->TableSpec_built_cnf($self->default_TableSpec_cnf(\%set_cnf)); |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub default_TableSpec_cnf { |
329
|
66
|
|
|
66
|
0
|
207
|
my $self = shift; |
330
|
66
|
|
50
|
|
|
211
|
my $set = shift || {}; |
331
|
|
|
|
|
|
|
|
332
|
66
|
|
|
|
|
143
|
my $data = $set; |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
|
335
|
66
|
|
|
|
|
653
|
my $table = &_table_name_safe($self->table); |
336
|
|
|
|
|
|
|
|
337
|
66
|
|
|
|
|
476
|
my $is_virtual = $self->_is_virtual_source; |
338
|
66
|
50
|
|
|
|
1634
|
my $defs_i = $is_virtual ? 'ra-icon-pg-red' : 'ra-icon-pg'; |
339
|
66
|
50
|
|
|
|
208
|
my $defm_i = $is_virtual ? 'ra-icon-pg-multi-red' : 'ra-icon-pg-multi'; |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# FIXME: These defaults cannot be seen via call from related tablespec, because of |
342
|
|
|
|
|
|
|
# a circular logic situation. For base-defaults, see apply_TableSpec above |
343
|
|
|
|
|
|
|
# This is one of the reasons the whole TableSpec design needs to be refactored |
344
|
66
|
|
|
|
|
159
|
my %defaults = (); |
345
|
66
|
50
|
33
|
|
|
283
|
$defaults{iconCls} = $data->{singleIconCls} if ($data->{singleIconCls} and ! $data->{iconCls}); |
346
|
66
|
|
66
|
|
|
521
|
$defaults{iconCls} = $defaults{iconCls} || $data->{iconCls} || $defs_i; |
347
|
66
|
|
66
|
|
|
269
|
$defaults{multiIconCls} = $data->{multiIconCls} || $defm_i; |
348
|
66
|
|
33
|
|
|
399
|
$defaults{singleIconCls} = $data->{singleIconCls} || $defaults{iconCls}; |
349
|
66
|
|
33
|
|
|
309
|
$defaults{title} = $data->{title} || $table; |
350
|
66
|
|
33
|
|
|
355
|
$defaults{title_multi} = $data->{title_multi} || $defaults{title}; |
351
|
66
|
|
|
|
|
2248
|
($defaults{display_column}) = $self->primary_columns; |
352
|
|
|
|
|
|
|
|
353
|
66
|
50
|
|
|
|
3591
|
my @display_columns = $data->{display_column} ? ( $data->{display_column} ) : $self->primary_columns; |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
# row_display coderef overrides display_column to provide finer grained display control |
356
|
|
|
|
|
|
|
my $orig_row_display = $data->{row_display} || sub { |
357
|
0
|
|
|
0
|
|
0
|
my $record = $_; |
358
|
0
|
|
|
|
|
0
|
my $title = join('/',map { $record->{$_} || '' } @display_columns); |
|
0
|
|
|
|
|
0
|
|
359
|
0
|
|
|
|
|
0
|
$title = sprintf('%.13s',$title) . '...' if (length $title > 13); |
360
|
0
|
|
|
|
|
0
|
return $title; |
361
|
66
|
|
50
|
|
|
634
|
}; |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
$defaults{row_display} = sub { |
364
|
0
|
|
|
0
|
|
0
|
my $display = $orig_row_display->(@_); |
365
|
0
|
0
|
|
|
|
0
|
return $display if (ref $display); |
366
|
|
|
|
|
|
|
return { |
367
|
|
|
|
|
|
|
title => $display, |
368
|
|
|
|
|
|
|
iconCls => $defaults{singleIconCls} |
369
|
0
|
|
|
|
|
0
|
}; |
370
|
66
|
|
|
|
|
452
|
}; |
371
|
|
|
|
|
|
|
|
372
|
66
|
|
|
|
|
191
|
my $rel_trans = {}; |
373
|
|
|
|
|
|
|
|
374
|
66
|
|
|
|
|
243
|
$defaults{related_column_property_transforms} = $rel_trans; |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
#my $defs = \%defaults; |
378
|
|
|
|
|
|
|
#my $col_cnf = $self->default_TableSpec_cnf_columns($set); |
379
|
|
|
|
|
|
|
#$defs = merge($defs,$col_cnf); |
380
|
|
|
|
|
|
|
#return merge($defs, $set); |
381
|
|
|
|
|
|
|
|
382
|
66
|
|
|
|
|
1287
|
%defaults = ( %defaults, %$set ); |
383
|
66
|
|
|
|
|
272
|
my $defs = \%defaults; |
384
|
66
|
|
|
|
|
561
|
my $col_cnf = $self->default_TableSpec_cnf_columns($defs); |
385
|
66
|
|
|
|
|
191
|
$defs->{columns} = $col_cnf->{columns}; |
386
|
|
|
|
|
|
|
|
387
|
66
|
|
|
|
|
1701
|
return $defs; |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
sub _is_virtual_source { |
391
|
176
|
|
|
176
|
|
418
|
my $self = shift; |
392
|
|
|
|
|
|
|
return ( |
393
|
176
|
|
33
|
|
|
3655
|
$self->result_source_instance->can('is_virtual') && |
394
|
|
|
|
|
|
|
$self->result_source_instance->is_virtual |
395
|
|
|
|
|
|
|
); |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub default_TableSpec_cnf_columns { |
399
|
66
|
|
|
66
|
0
|
186
|
my $self = shift; |
400
|
66
|
|
50
|
|
|
308
|
my $set = shift || {}; |
401
|
|
|
|
|
|
|
|
402
|
66
|
|
|
|
|
206
|
my $data = $set; |
403
|
|
|
|
|
|
|
|
404
|
66
|
|
|
|
|
483
|
my @col_order = $self->default_TableSpec_cnf_column_order($set); |
405
|
|
|
|
|
|
|
|
406
|
66
|
|
|
|
|
207
|
my $cols = { map { $_ => {} } @col_order }; |
|
443
|
|
|
|
|
1241
|
|
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
# lowest precidence: |
409
|
|
|
|
|
|
|
#$cols = merge($cols,$set->{column_properties_defaults} || {}); |
410
|
66
|
50
|
|
|
|
327
|
%$cols = ( %$cols, %{ $set->{column_properties_defaults} || {}} ); |
|
66
|
|
|
|
|
755
|
|
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
#$cols = merge($cols,$set->{column_properties_ordered} || {}); |
413
|
66
|
50
|
|
|
|
292
|
%$cols = ( %$cols, %{ $set->{column_properties_ordered} || {}} ); |
|
66
|
|
|
|
|
427
|
|
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# higher precidence: |
416
|
|
|
|
|
|
|
#$cols = merge($cols,$set->{column_properties} || {}); |
417
|
66
|
50
|
|
|
|
251
|
%$cols = ( %$cols, %{ $set->{column_properties} || {}} ); |
|
66
|
|
|
|
|
389
|
|
418
|
|
|
|
|
|
|
|
419
|
66
|
|
|
|
|
1931
|
my $data_types = $self->TableSpec_data_type_profiles; |
420
|
|
|
|
|
|
|
#scream(keys %$cols); |
421
|
|
|
|
|
|
|
|
422
|
66
|
|
|
|
|
3264
|
my $is_virtual = $self->_is_virtual_source; |
423
|
|
|
|
|
|
|
|
424
|
66
|
|
|
|
|
1432
|
foreach my $col (keys %$cols) { |
425
|
|
|
|
|
|
|
|
426
|
443
|
100
|
|
|
|
1918
|
my $is_phy = $self->has_column($col) ? 1 : 0; |
427
|
443
|
|
|
|
|
40239
|
$cols->{$col}{is_phy_colname} = $is_phy; #<-- track if this is also a physical column name |
428
|
|
|
|
|
|
|
|
429
|
443
|
|
|
|
|
804
|
my $is_local = $is_phy; |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
# If this is both a local column and a relationship, allow the rel to take over |
432
|
|
|
|
|
|
|
# if 'priority_rel_columns' is true: |
433
|
|
|
|
|
|
|
$is_local = 0 if ( |
434
|
|
|
|
|
|
|
$is_local and |
435
|
|
|
|
|
|
|
$self->has_relationship($col) and |
436
|
443
|
50
|
100
|
|
|
7541
|
$set->{'priority_rel_columns'} |
|
|
|
66
|
|
|
|
|
437
|
|
|
|
|
|
|
); |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
# -- If priority_rel_columns is on but we need to exclude a specific column: |
440
|
|
|
|
|
|
|
$is_local = 1 if ( |
441
|
|
|
|
|
|
|
! $is_local and |
442
|
|
|
|
|
|
|
$set->{no_priority_rel_column} and |
443
|
443
|
0
|
66
|
|
|
18382
|
$set->{no_priority_rel_column}->{$col} and |
|
|
|
33
|
|
|
|
|
|
|
|
0
|
|
|
|
|
444
|
|
|
|
|
|
|
$is_phy |
445
|
|
|
|
|
|
|
); |
446
|
|
|
|
|
|
|
# -- |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
# Never allow a rel col to take over a primary key: |
449
|
443
|
|
|
|
|
7439
|
my %pri_cols = map {$_=>1} $self->primary_columns; |
|
456
|
|
|
|
|
17822
|
|
450
|
443
|
100
|
|
|
|
1450
|
$is_local = 1 if ($pri_cols{$col}); |
451
|
|
|
|
|
|
|
|
452
|
443
|
100
|
|
|
|
1124
|
unless ($is_local) { |
453
|
|
|
|
|
|
|
# is it a rel col ? |
454
|
114
|
50
|
|
|
|
2247
|
if($self->has_relationship($col)) { |
455
|
114
|
|
|
|
|
6621
|
my $info = $self->relationship_info($col); |
456
|
|
|
|
|
|
|
|
457
|
114
|
|
|
|
|
4294
|
$cols->{$col}->{relationship_info} = $info; |
458
|
114
|
|
|
|
|
571
|
my $cond_data = $self->parse_relationship_cond($info->{cond}); |
459
|
114
|
|
|
|
|
1035
|
$cols->{$col}->{relationship_cond_data} = { %$cond_data, %$info }; |
460
|
|
|
|
|
|
|
|
461
|
114
|
100
|
100
|
|
|
994
|
if ($info->{attrs}->{accessor} eq 'single' || $info->{attrs}->{accessor} eq 'filter') { |
|
|
50
|
|
|
|
|
|
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
# -- NEW: Virtual Single Relationship - will be read-only |
464
|
49
|
50
|
33
|
|
|
277
|
unless($cond_data->{foreign} && $cond_data->{self}) { |
465
|
0
|
|
|
|
|
0
|
$cols->{$col}{virtualized_single_rel} = 1; |
466
|
0
|
|
|
|
|
0
|
$cols->{$col}{allow_add} = 0; |
467
|
0
|
|
|
|
|
0
|
$cols->{$col}{allow_edit} = 0; |
468
|
0
|
|
|
|
|
0
|
next; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
# -- |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
# New: pass the is_nullable flag in from the local FK column: |
473
|
49
|
50
|
|
|
|
228
|
if($self->has_column($cond_data->{self})) { |
474
|
|
|
|
|
|
|
$cols->{$col}{is_nullable} = $self->column_info($cond_data->{self}) |
475
|
49
|
100
|
|
|
|
4231
|
->{is_nullable} ? 1 : 0; |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
# Use TableSpec_related_get_set_conf instead of TableSpec_related_get_conf |
479
|
|
|
|
|
|
|
# to prevent possible deep recursion: |
480
|
|
|
|
|
|
|
|
481
|
49
|
|
|
|
|
5018
|
my $display_column = $self->TableSpec_related_get_set_conf($col,'display_column'); |
482
|
49
|
|
|
|
|
168
|
my $display_columns = $self->TableSpec_related_get_set_conf($col,'display_columns'); |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# -- auto_editor_params/auto_editor_type can be defined in either the local column |
485
|
|
|
|
|
|
|
# properties, or the remote TableSpec conf |
486
|
49
|
|
100
|
|
|
172
|
my $auto_editor_type = $self->TableSpec_related_get_set_conf($col,'auto_editor_type') || 'combo'; |
487
|
49
|
|
100
|
|
|
156
|
my $auto_editor_params = $self->TableSpec_related_get_set_conf($col,'auto_editor_params') || {}; |
488
|
49
|
|
50
|
|
|
173
|
my $auto_editor_win_params = $self->TableSpec_related_get_set_conf($col,'auto_editor_win_params') || {}; |
489
|
49
|
|
66
|
|
|
284
|
$cols->{$col}->{auto_editor_type} = $cols->{$col}->{auto_editor_type} || $auto_editor_type; |
490
|
49
|
|
100
|
|
|
253
|
$cols->{$col}->{auto_editor_params} = $cols->{$col}->{auto_editor_params} || {}; |
491
|
|
|
|
|
|
|
$cols->{$col}->{auto_editor_params} = { |
492
|
|
|
|
|
|
|
%$auto_editor_params, |
493
|
49
|
|
|
|
|
224
|
%{$cols->{$col}->{auto_editor_params}} |
|
49
|
|
|
|
|
249
|
|
494
|
|
|
|
|
|
|
}; |
495
|
|
|
|
|
|
|
# -- |
496
|
|
|
|
|
|
|
|
497
|
49
|
0
|
33
|
|
|
224
|
$display_column = $display_columns->[0] if ( |
|
|
|
33
|
|
|
|
|
498
|
|
|
|
|
|
|
! defined $display_column and |
499
|
|
|
|
|
|
|
ref($display_columns) eq 'ARRAY' and |
500
|
|
|
|
|
|
|
@$display_columns > 0 |
501
|
|
|
|
|
|
|
); |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
## fall-back set the display_column to the first key |
504
|
49
|
50
|
|
|
|
118
|
($display_column) = $self->primary_columns unless ($display_column); |
505
|
|
|
|
|
|
|
|
506
|
49
|
50
|
33
|
|
|
302
|
$display_columns = [ $display_column ] if ( |
507
|
|
|
|
|
|
|
! defined $display_columns and |
508
|
|
|
|
|
|
|
defined $display_column |
509
|
|
|
|
|
|
|
); |
510
|
|
|
|
|
|
|
|
511
|
49
|
50
|
|
|
|
137
|
die "$col doesn't have display_column or display_columns set!" unless ($display_column); |
512
|
|
|
|
|
|
|
|
513
|
49
|
|
|
|
|
152
|
$cols->{$col}->{displayField} = $display_column; |
514
|
49
|
|
|
|
|
153
|
$cols->{$col}->{display_columns} = $display_columns; #<-- in progress - used for grid instead of combo |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
#TODO: needs to be more generalized/abstracted |
517
|
|
|
|
|
|
|
#open_url, if defined, will add an autoLoad link to the renderer to |
518
|
|
|
|
|
|
|
#open/navigate to the related item |
519
|
49
|
|
|
|
|
147
|
$cols->{$col}->{open_url} = $self->TableSpec_related_get_set_conf($col,'open_url'); |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
$cols->{$col}->{valueField} = $cond_data->{foreign} |
522
|
49
|
50
|
|
|
|
189
|
or die "couldn't get foreign col condition data for $col relationship!"; |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
$cols->{$col}->{keyField} = $cond_data->{self} |
525
|
49
|
50
|
|
|
|
196
|
or die "couldn't get self col condition data for $col relationship!"; |
526
|
|
|
|
|
|
|
|
527
|
49
|
|
|
|
|
249
|
next; |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
elsif($info->{attrs}->{accessor} eq 'multi') { |
530
|
65
|
|
|
|
|
394
|
$cols->{$col}->{title_multi} = $self->TableSpec_related_get_set_conf($col,'title_multi'); |
531
|
65
|
|
|
|
|
245
|
$cols->{$col}->{multiIconCls} = $self->TableSpec_related_get_set_conf($col,'multiIconCls'); |
532
|
65
|
|
|
|
|
251
|
$cols->{$col}->{open_url_multi} = $self->TableSpec_related_get_set_conf($col,'open_url_multi'); |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
$cols->{$col}->{open_url_multi_rs_join_name} = |
535
|
65
|
|
50
|
|
|
272
|
$self->TableSpec_related_get_set_conf($col,'open_url_multi_rs_join_name') || 'me'; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
# New: add the 'relcol' profile to relationship columns: |
539
|
65
|
|
100
|
|
|
434
|
$cols->{$col}->{profiles} ||= []; |
540
|
65
|
|
|
|
|
163
|
push @{$cols->{$col}->{profiles}}, 'relcol'; |
|
65
|
|
|
|
|
283
|
|
541
|
65
|
50
|
|
|
|
190
|
push @{$cols->{$col}->{profiles}}, 'virtual_source' if ($is_virtual); |
|
0
|
|
|
|
|
0
|
|
542
|
65
|
50
|
|
|
|
283
|
push @{$cols->{$col}->{profiles}}, 'multirel' if ($info->{attrs}->{accessor} eq 'multi'); |
|
65
|
|
|
|
|
303
|
|
543
|
|
|
|
|
|
|
} |
544
|
65
|
|
|
|
|
231
|
next; |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
## WARNING! This logic overlaps with logic further up (in create_result_TableSpec) FIXME! |
548
|
329
|
|
|
|
|
1454
|
my $info = $self->column_info($col); |
549
|
329
|
|
|
|
|
32271
|
my @profiles = (); |
550
|
|
|
|
|
|
|
|
551
|
329
|
100
|
|
|
|
1222
|
push @profiles, $info->{is_nullable} ? 'nullable' : 'notnull'; |
552
|
329
|
100
|
|
|
|
927
|
push @profiles, 'autoinc' if ($info->{is_auto_increment}); |
553
|
|
|
|
|
|
|
|
554
|
329
|
|
50
|
|
|
1154
|
my $type_profile = $data_types->{$info->{data_type}} || ['text']; |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
# -- PostgreSQL override until array columns are supported (Github Issue #55): |
557
|
|
|
|
|
|
|
$type_profile = ['unsearchable','virtual_source'] if ( |
558
|
329
|
50
|
|
|
|
968
|
$info->{data_type} =~ /\[/ #<-- if the data_type contains a square backect, i.e. 'text[]' |
559
|
|
|
|
|
|
|
); |
560
|
|
|
|
|
|
|
# -- |
561
|
|
|
|
|
|
|
|
562
|
329
|
50
|
|
|
|
869
|
$type_profile = [ $type_profile ] unless (ref $type_profile); |
563
|
329
|
|
|
|
|
773
|
push @profiles, @$type_profile; |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
$cols->{$col}->{profiles} = [ $cols->{$col}->{profiles} ] if ( |
566
|
|
|
|
|
|
|
defined $cols->{$col}->{profiles} and |
567
|
|
|
|
|
|
|
not ref $cols->{$col}->{profiles} |
568
|
329
|
50
|
66
|
|
|
1237
|
); |
569
|
329
|
100
|
|
|
|
810
|
push @profiles, @{$cols->{$col}->{profiles}} if ($cols->{$col}->{profiles}); |
|
79
|
|
|
|
|
233
|
|
570
|
|
|
|
|
|
|
|
571
|
329
|
50
|
|
|
|
730
|
push @profiles, 'virtual_source' if ($is_virtual); |
572
|
|
|
|
|
|
|
|
573
|
329
|
|
|
|
|
745
|
$cols->{$col}->{profiles} = \@profiles; |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
## -- |
576
|
329
|
|
|
|
|
593
|
my $editor = {}; |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
## Set the 'default' field value to match the default from the db (if exists) for this column: |
579
|
329
|
100
|
|
|
|
774
|
$editor->{value} = $info->{default_value} if (exists $info->{default_value}); |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
# -- NEW: |
582
|
|
|
|
|
|
|
# ScalarRef values mean literal SQL which should be evaluated at the time. New feature in |
583
|
|
|
|
|
|
|
# RapidApp::JSON::MixedEncoder supports CodeRef values, which call them at encode time. This |
584
|
|
|
|
|
|
|
# lets us set the default editor value to what it should be at the time the form is loaded. |
585
|
329
|
50
|
50
|
|
|
1428
|
if((ref($info->{default_value})||'') eq 'SCALAR') { |
586
|
|
|
|
|
|
|
$editor->{value} = sub { |
587
|
0
|
|
|
0
|
|
0
|
my $value = $info->{default_value}; |
588
|
|
|
|
|
|
|
try { |
589
|
|
|
|
|
|
|
# Actually ask the database via calling a select on the literal SQL. We're in a try |
590
|
|
|
|
|
|
|
# block so if any of this fails, we fall back to the original ScalarRef which will |
591
|
|
|
|
|
|
|
# probably end up being undef |
592
|
|
|
|
|
|
|
$value = RapidApp->active_request_context |
593
|
0
|
|
|
|
|
0
|
->stash->{'RAPIDAPP_DISPATCH_MODULE'} # only way to get Module by the time we're called in the view |
594
|
|
|
|
|
|
|
->ResultSource->schema->storage->dbh |
595
|
|
|
|
|
|
|
->selectrow_arrayref( "SELECT $$value" )->[0]; |
596
|
0
|
|
|
|
|
0
|
}; |
597
|
0
|
|
|
|
|
0
|
return $value; |
598
|
|
|
|
|
|
|
} unless ( |
599
|
|
|
|
|
|
|
# just because this one is so common, don't waste resources asking the database |
600
|
0
|
0
|
|
|
|
0
|
${$info->{default_value}} eq 'null' |
|
0
|
|
|
|
|
0
|
|
601
|
|
|
|
|
|
|
); |
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
# -- |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
## This sets additional properties of the editor for numeric type columns according |
607
|
|
|
|
|
|
|
## to the DBIC schema (max-length, signed/unsigned, float vs int). The API with "profiles" |
608
|
|
|
|
|
|
|
## didn't anticipate this fine-grained need, so 'extra_properties' was added specifically |
609
|
|
|
|
|
|
|
## to accomidate this (see special logic in TableSpec::Column): |
610
|
|
|
|
|
|
|
## note: these properties only apply if the editor xtype is 'numberfield' which we assume, |
611
|
|
|
|
|
|
|
## and is already set from the profiles of 'decimal', 'float', etc |
612
|
329
|
100
|
66
|
|
|
1011
|
my $unsigned = ($info->{extra} && $info->{extra}->{unsigned}) ? 1 : 0; |
613
|
329
|
100
|
|
|
|
786
|
$editor->{allowNegative} = \0 if ($unsigned); |
614
|
|
|
|
|
|
|
|
615
|
329
|
100
|
|
|
|
767
|
if($info->{size}) { |
616
|
216
|
|
|
|
|
480
|
my $size = $info->{size}; |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# Special case for 'float'/'decimal' with a specified precision (where 0 is the same as int): |
619
|
216
|
100
|
|
|
|
535
|
if(ref $size eq 'ARRAY' ) { |
620
|
12
|
|
|
|
|
52
|
my ($s,$p) = @$size; |
621
|
12
|
|
|
|
|
35
|
$size = $s; |
622
|
12
|
|
|
|
|
58
|
$editor->{maxValue} = ('9' x $s); |
623
|
12
|
50
|
|
|
|
46
|
$size += 1 unless ($unsigned); #<-- room for a '-' |
624
|
12
|
50
|
33
|
|
|
76
|
if ($p && $p > 0) { |
625
|
12
|
|
|
|
|
61
|
$editor->{maxValue} .= '.' . ('9' x $p); |
626
|
12
|
|
|
|
|
32
|
$size += $p + 1 ; #<-- precision plus a spot for '.' in the max field length |
627
|
12
|
|
|
|
|
37
|
$editor->{decimalPrecision} = $p; |
628
|
|
|
|
|
|
|
} |
629
|
|
|
|
|
|
|
else { |
630
|
0
|
|
|
|
|
0
|
$editor->{allowDecimals} = \0; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
} |
633
|
216
|
|
|
|
|
530
|
$editor->{maxLength} = $size; |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
|
636
|
329
|
100
|
|
|
|
1010
|
if(keys %$editor > 0) { |
637
|
228
|
|
100
|
|
|
919
|
$cols->{$col}->{extra_properties} = $cols->{$col}->{extra_properties} || {}; |
638
|
|
|
|
|
|
|
$cols->{$col}->{extra_properties} = merge($cols->{$col}->{extra_properties},{ |
639
|
228
|
|
|
|
|
1148
|
editor => $editor |
640
|
|
|
|
|
|
|
}); |
641
|
|
|
|
|
|
|
} |
642
|
|
|
|
|
|
|
## -- |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
# --vv-- NEW: handling for 'enum' columns (Github Issue #30): |
645
|
329
|
0
|
33
|
|
|
1423
|
if($info->{data_type} eq 'enum' && $info->{extra} && $info->{extra}{list}) { |
|
|
|
0
|
|
|
|
|
646
|
0
|
|
|
|
|
0
|
my $list = $info->{extra}{list}; |
647
|
|
|
|
|
|
|
|
648
|
0
|
|
|
|
|
0
|
my $selections = []; |
649
|
|
|
|
|
|
|
# Null choice: |
650
|
|
|
|
|
|
|
push @$selections, { |
651
|
|
|
|
|
|
|
# #A9A9A9 = light grey |
652
|
|
|
|
|
|
|
text => '<span style="color:#A9A9A9;">(None)</span>', value => undef |
653
|
0
|
0
|
|
|
|
0
|
} if ($info->{is_nullable}); |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
push @$selections, map { |
656
|
0
|
|
|
|
|
0
|
{ text => $_, value => $_ } |
|
0
|
|
|
|
|
0
|
|
657
|
|
|
|
|
|
|
} @$list; |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
$cols->{$col}{menu_select_editor} = { |
660
|
|
|
|
|
|
|
#mode: 'combo', 'menu' or 'cycle': |
661
|
0
|
|
|
|
|
0
|
mode => 'menu', |
662
|
|
|
|
|
|
|
selections => $selections |
663
|
|
|
|
|
|
|
}; |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
# New: also save the list of possible values in a hashref... |
666
|
|
|
|
|
|
|
# This is being done so that they can be pre-validated in |
667
|
|
|
|
|
|
|
# quick search, needed for Postfix (Github Issue #56) |
668
|
|
|
|
|
|
|
# TODO: not happy about having to do this - revisit later |
669
|
0
|
|
|
|
|
0
|
$cols->{$col}{enum_value_hash} = { map {$_=>1} @$list } |
|
0
|
|
|
|
|
0
|
|
670
|
|
|
|
|
|
|
} |
671
|
|
|
|
|
|
|
# --^^-- |
672
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
} |
674
|
|
|
|
|
|
|
|
675
|
66
|
|
|
|
|
375
|
return { columns => $cols }; |
676
|
|
|
|
|
|
|
} |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
sub TableSpec_valid_db_columns { |
679
|
173
|
|
|
173
|
0
|
390
|
my $self = shift; |
680
|
|
|
|
|
|
|
|
681
|
173
|
|
|
|
|
368
|
my @single_rels = (); |
682
|
173
|
|
|
|
|
326
|
my @multi_rels = (); |
683
|
173
|
|
|
|
|
399
|
my @virtual_single_rels = (); |
684
|
|
|
|
|
|
|
|
685
|
173
|
|
|
|
|
334
|
my %fk_cols = (); |
686
|
173
|
|
|
|
|
3494
|
my %pri_cols = map {$_=>1} $self->primary_columns; |
|
190
|
|
|
|
|
7498
|
|
687
|
|
|
|
|
|
|
|
688
|
173
|
|
|
|
|
4656
|
foreach my $rel ($self->relationships) { |
689
|
343
|
|
|
|
|
16131
|
my $info = $self->relationship_info($rel); |
690
|
|
|
|
|
|
|
|
691
|
343
|
|
|
|
|
13701
|
my $accessor = $info->{attrs}->{accessor}; |
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
# 'filter' means single, but the name is also a local column |
694
|
|
|
|
|
|
|
$accessor = 'single' if ( |
695
|
|
|
|
|
|
|
$accessor eq 'filter' and |
696
|
|
|
|
|
|
|
$self->TableSpec_cnf->{'priority_rel_columns'} and |
697
|
|
|
|
|
|
|
!( |
698
|
|
|
|
|
|
|
$self->TableSpec_cnf->{'no_priority_rel_column'} and |
699
|
|
|
|
|
|
|
$self->TableSpec_cnf->{'no_priority_rel_column'}->{$rel} |
700
|
|
|
|
|
|
|
) and |
701
|
343
|
100
|
100
|
|
|
3625
|
! $pri_cols{$rel} #<-- exclude primary column names. TODO: this check is performed later, fix |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
702
|
|
|
|
|
|
|
); |
703
|
|
|
|
|
|
|
|
704
|
343
|
100
|
|
|
|
7244
|
if($accessor eq 'single') { |
|
|
100
|
|
|
|
|
|
705
|
99
|
|
|
|
|
570
|
my $cond_info = $self->parse_relationship_cond($info->{cond}); |
706
|
99
|
50
|
33
|
|
|
496
|
if($cond_info->{self} && $cond_info->{foreign}) { |
707
|
99
|
|
|
|
|
260
|
push @single_rels, $rel; |
708
|
99
|
|
|
|
|
195
|
my ($fk) = keys %{$info->{attrs}->{fk_columns}}; |
|
99
|
|
|
|
|
407
|
|
709
|
99
|
100
|
|
|
|
385
|
$fk_cols{$fk} = $rel if($fk); |
710
|
|
|
|
|
|
|
} |
711
|
|
|
|
|
|
|
else { |
712
|
|
|
|
|
|
|
# (Github Issue #40) |
713
|
|
|
|
|
|
|
# New: "virtual" single rels are relationships for which we |
714
|
|
|
|
|
|
|
# cannot introspect in both directions (i.e. not physical |
715
|
|
|
|
|
|
|
# foreign keys). These are still "single" in that they map to |
716
|
|
|
|
|
|
|
# one related row, but will not be editable and not have a |
717
|
|
|
|
|
|
|
# open link (yet) |
718
|
0
|
|
|
|
|
0
|
push @virtual_single_rels, $rel; |
719
|
|
|
|
|
|
|
} |
720
|
|
|
|
|
|
|
} |
721
|
|
|
|
|
|
|
elsif($accessor eq 'multi') { |
722
|
175
|
|
|
|
|
517
|
push @multi_rels, $rel; |
723
|
|
|
|
|
|
|
} |
724
|
|
|
|
|
|
|
} |
725
|
|
|
|
|
|
|
|
726
|
173
|
|
|
|
|
1125
|
$self->TableSpec_set_conf('relationship_column_names',\@single_rels); |
727
|
173
|
|
|
|
|
3806
|
$self->TableSpec_set_conf('multi_relationship_column_names',\@multi_rels); |
728
|
173
|
|
|
|
|
3425
|
$self->TableSpec_set_conf('relationship_column_fks_map',\%fk_cols); |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
# New: move single rels up to immediately follow their FK column: |
731
|
173
|
100
|
|
|
|
3709
|
my @cols = map { $_, ( $fk_cols{$_} ? $fk_cols{$_} : () ) } $self->columns; |
|
996
|
|
|
|
|
4919
|
|
732
|
|
|
|
|
|
|
|
733
|
173
|
|
|
|
|
839
|
return uniq(@cols,@single_rels,@multi_rels,@virtual_single_rels); |
734
|
|
|
|
|
|
|
} |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
# There is no longer extra logic at this stage because we're |
737
|
|
|
|
|
|
|
# backing off of the entire original "ordering" design: |
738
|
66
|
|
|
66
|
0
|
476
|
sub default_TableSpec_cnf_column_order { (shift)->TableSpec_valid_db_columns } |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
# Tmp code: these are all key names that may be used to set column |
741
|
|
|
|
|
|
|
# properties (column TableSpecs). We are keeping track of them to |
742
|
|
|
|
|
|
|
# use to for remapping while the TableSpec_cnf refactor/consolidation |
743
|
|
|
|
|
|
|
# is underway... |
744
|
|
|
|
|
|
|
my @col_prop_names = qw( |
745
|
|
|
|
|
|
|
columns |
746
|
|
|
|
|
|
|
column_properties |
747
|
|
|
|
|
|
|
column_properties_ordered |
748
|
|
|
|
|
|
|
column_properties_defaults |
749
|
|
|
|
|
|
|
); |
750
|
|
|
|
|
|
|
my %col_prop_names = map {$_=>1} @col_prop_names; |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
# The TableSpec_set_conf method is overly complex to allow |
753
|
|
|
|
|
|
|
# flexible arguments as either hash or hashref, and because of |
754
|
|
|
|
|
|
|
# the special case of setting the nested 'column_properties' |
755
|
|
|
|
|
|
|
# param, if specified as the first argument, and then be able to |
756
|
|
|
|
|
|
|
# accept its sub params as either a hash or a hashref. In hindsight, |
757
|
|
|
|
|
|
|
# allowing this was probably not worth the extra maintenace/code and |
758
|
|
|
|
|
|
|
# was too fancy for its own good (since this case may or may not |
759
|
|
|
|
|
|
|
# shift the key/value positions in the arg list) but it is a part |
760
|
|
|
|
|
|
|
# of the API for now... |
761
|
|
|
|
|
|
|
sub TableSpec_set_conf { |
762
|
824
|
|
|
824
|
0
|
1393
|
my $self = shift; |
763
|
824
|
50
|
|
|
|
1967
|
die "TableSpec_set_conf(): bad arguments" unless (scalar(@_) > 0); |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
# First arg can be a hashref - deref and call again: |
766
|
824
|
50
|
|
|
|
1702
|
if(ref($_[0])) { |
767
|
0
|
0
|
0
|
|
|
0
|
die "TableSpec_set_conf(): bad arguments" unless ( |
768
|
|
|
|
|
|
|
ref($_[0]) eq 'HASH' and |
769
|
|
|
|
|
|
|
scalar(@_) == 1 |
770
|
|
|
|
|
|
|
); |
771
|
0
|
|
|
|
|
0
|
return $self->TableSpec_set_conf(%{$_[0]}) |
|
0
|
|
|
|
|
0
|
|
772
|
|
|
|
|
|
|
} |
773
|
|
|
|
|
|
|
|
774
|
824
|
|
|
|
|
15871
|
$self->TableSpec_built_cnf(undef); #<-- FIXME!! |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
# Special handling for setting 'column_properties': |
777
|
824
|
100
|
|
|
|
12205
|
if ($col_prop_names{$_[0]}) { |
778
|
50
|
|
|
|
|
102
|
shift @_; #<-- pull out the 'column_properties' first arg |
779
|
50
|
|
|
|
|
171
|
return $self->_TableSpec_set_column_properties(@_); |
780
|
|
|
|
|
|
|
}; |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
# Enforce even number of args for good measure: |
783
|
774
|
50
|
|
|
|
1859
|
die join(' ', |
784
|
|
|
|
|
|
|
'TableSpec_set_conf( %cnf ):', |
785
|
|
|
|
|
|
|
"odd number of args in key/value list:", Dumper(\@_) |
786
|
|
|
|
|
|
|
) if (scalar(@_) & 1); |
787
|
|
|
|
|
|
|
|
788
|
774
|
|
|
|
|
2155
|
my %cnf = @_; |
789
|
|
|
|
|
|
|
|
790
|
774
|
|
|
|
|
2036
|
for my $param (keys %cnf) { |
791
|
|
|
|
|
|
|
# Also make sure all the keys (even positions) are simple scalars: |
792
|
1186
|
50
|
|
|
|
10157
|
die join(' ', |
793
|
|
|
|
|
|
|
'TableSpec_set_conf( %cnf ):', |
794
|
|
|
|
|
|
|
'found ref in key position:', Dumper($_) |
795
|
|
|
|
|
|
|
) if (ref($param)); |
796
|
|
|
|
|
|
|
|
797
|
1186
|
100
|
|
|
|
2396
|
if($col_prop_names{$param}) { |
798
|
|
|
|
|
|
|
# Also handle column_properties specified with other params: |
799
|
|
|
|
|
|
|
die join(' ', |
800
|
|
|
|
|
|
|
'TableSpec_set_conf( %cnf ): Expected', |
801
|
|
|
|
|
|
|
"HashRef value for config key '$param':", Dumper($cnf{$param}) |
802
|
57
|
50
|
|
|
|
205
|
) unless (ref($cnf{$param}) eq 'HASH'); |
803
|
57
|
|
|
|
|
374
|
$self->_TableSpec_set_column_properties($cnf{$param}); |
804
|
|
|
|
|
|
|
} |
805
|
|
|
|
|
|
|
else { |
806
|
1129
|
|
|
|
|
19610
|
$self->TableSpec_cnf->{$param} = $cnf{$param} |
807
|
|
|
|
|
|
|
} |
808
|
|
|
|
|
|
|
} |
809
|
|
|
|
|
|
|
} |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
# Special new internal method for setting column properties and |
812
|
|
|
|
|
|
|
# properly handle backward compatability. Simultaneously sets/updates |
813
|
|
|
|
|
|
|
# the cnf key names for all the 'column_properties' names that are |
814
|
|
|
|
|
|
|
# currently supported by the API (as references pointing to the same |
815
|
|
|
|
|
|
|
# single config HashRef). This is only temporary and is a throwback |
816
|
|
|
|
|
|
|
# caused by the older/original API design for the TableSpec_cnf and |
817
|
|
|
|
|
|
|
# will be removed later on once the other config names can be depricated |
818
|
|
|
|
|
|
|
# along with other planned refactored. This is just a stop-gap to |
819
|
|
|
|
|
|
|
# allow this refactor to be done in stages... |
820
|
|
|
|
|
|
|
sub _TableSpec_set_column_properties { |
821
|
165
|
|
|
165
|
|
293
|
my $self = shift; |
822
|
165
|
50
|
|
|
|
387
|
die "TableSpec_set_conf( column_properties => %cnf ): bad args" |
823
|
|
|
|
|
|
|
unless (scalar(@_) > 0); |
824
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
# First arg can be a hashref - deref and call again: |
826
|
165
|
100
|
|
|
|
368
|
if(ref($_[0])) { |
827
|
58
|
50
|
33
|
|
|
336
|
die "TableSpec_set_conf( column_properties => %cnf ): bad args" unless ( |
828
|
|
|
|
|
|
|
ref($_[0]) eq 'HASH' and |
829
|
|
|
|
|
|
|
scalar(@_) == 1 |
830
|
|
|
|
|
|
|
); |
831
|
58
|
|
|
|
|
116
|
return $self->_TableSpec_set_column_properties(%{$_[0]}) |
|
58
|
|
|
|
|
306
|
|
832
|
|
|
|
|
|
|
} |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
# Enforce even number of args for good measure: |
835
|
107
|
50
|
|
|
|
244
|
die join(' ', |
836
|
|
|
|
|
|
|
'TableSpec_set_conf( column_properties => %cnf ):', |
837
|
|
|
|
|
|
|
"odd number of args in key/value list:", Dumper(\@_) |
838
|
|
|
|
|
|
|
) if (scalar(@_) & 1); |
839
|
|
|
|
|
|
|
|
840
|
107
|
|
|
|
|
389
|
my %cnf = @_; |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
# Also make sure all the keys (even positions) are simple scalars: |
843
|
|
|
|
|
|
|
ref($_) and die join(' ', |
844
|
|
|
|
|
|
|
'TableSpec_set_conf( column_properties => %cnf ):', |
845
|
|
|
|
|
|
|
'found ref in key position:', Dumper($_) |
846
|
107
|
|
50
|
|
|
787
|
) for (keys %cnf); |
847
|
|
|
|
|
|
|
|
848
|
107
|
|
|
|
|
495
|
my %valid_colnames = map {$_=>1} ($self->TableSpec_valid_db_columns); |
|
744
|
|
|
|
|
1391
|
|
849
|
|
|
|
|
|
|
|
850
|
107
|
|
|
|
|
243
|
my $col_props; |
851
|
107
|
|
100
|
|
|
2355
|
$col_props ||= $self->TableSpec_cnf->{$_} for (@col_prop_names); |
852
|
107
|
|
100
|
|
|
6713
|
$col_props ||= {}; |
853
|
|
|
|
|
|
|
|
854
|
107
|
|
|
|
|
320
|
for my $col (keys %cnf) { |
855
|
|
|
|
|
|
|
warn join(' ', |
856
|
|
|
|
|
|
|
"Ignoring config for unknown column name '$col'", |
857
|
|
|
|
|
|
|
"in $self TableSpec config\n" |
858
|
681
|
50
|
0
|
|
|
1485
|
) and next unless ($valid_colnames{$col}); |
859
|
681
|
|
|
|
|
1106
|
$col_props->{$col} = $cnf{$col}; |
860
|
|
|
|
|
|
|
} |
861
|
|
|
|
|
|
|
|
862
|
107
|
|
|
|
|
1954
|
$self->TableSpec_cnf->{$_} = $col_props for (@col_prop_names); |
863
|
|
|
|
|
|
|
} |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
# New function for updating/merging in column configs. This allows |
867
|
|
|
|
|
|
|
# setting certain column configs without overwriting existing config |
868
|
|
|
|
|
|
|
# keys that are not being specified: |
869
|
|
|
|
|
|
|
sub TableSpec_merge_columns_conf { |
870
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
871
|
0
|
|
|
|
|
0
|
my $conf = shift; |
872
|
|
|
|
|
|
|
|
873
|
0
|
0
|
|
|
|
0
|
die "TableSpec_merge_columns_conf( \%columns ): bad args" |
874
|
|
|
|
|
|
|
unless (ref($conf) eq 'HASH'); |
875
|
|
|
|
|
|
|
|
876
|
0
|
|
0
|
|
|
0
|
my $existing = $self->TableSpec_get_conf('columns') || {}; |
877
|
|
|
|
|
|
|
|
878
|
0
|
|
|
|
|
0
|
my @cols = uniq( keys %$conf, keys %$existing ); |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
my %new = ( map { |
881
|
0
|
|
|
|
|
0
|
$_ => { |
882
|
0
|
0
|
|
|
|
0
|
%{ $existing->{$_} || {} }, |
883
|
0
|
0
|
|
|
|
0
|
%{ $conf->{$_} || {} }, |
|
0
|
|
|
|
|
0
|
|
884
|
|
|
|
|
|
|
} |
885
|
|
|
|
|
|
|
} @cols ); |
886
|
|
|
|
|
|
|
|
887
|
0
|
|
|
|
|
0
|
return $self->TableSpec_set_conf( columns => \%new ); |
888
|
|
|
|
|
|
|
} |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
sub TableSpec_get_conf { |
893
|
1654
|
|
|
1654
|
0
|
16742
|
my $self = shift; |
894
|
1654
|
|
50
|
|
|
4145
|
my $param = shift || return undef; |
895
|
1654
|
|
66
|
|
|
5413
|
my $storage = shift || $self->get_built_Cnf; |
896
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
# Special: map all column prop names into 'column_properties' |
898
|
1654
|
100
|
|
|
|
23239
|
$param = 'column_properties' if ($col_prop_names{$param}); |
899
|
|
|
|
|
|
|
|
900
|
1654
|
|
|
|
|
4106
|
my $value = $storage->{$param}; |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
# --- FIXME FIXME FIXME |
903
|
|
|
|
|
|
|
# In the original design of the TableSpec_cnf internals, which |
904
|
|
|
|
|
|
|
# was too fancy for its own good, meta/type information was |
905
|
|
|
|
|
|
|
# transparently stored to be able to do things like remember |
906
|
|
|
|
|
|
|
# the order of keys in hashes, auto dereference, etc. This has |
907
|
|
|
|
|
|
|
# been unfactored and converted to simple key/values since, however, |
908
|
|
|
|
|
|
|
# places that might still call TableSpec_get_conf still expect |
909
|
|
|
|
|
|
|
# to get back lists instead of ArrayRefs/HashRefs in certain |
910
|
|
|
|
|
|
|
# places. These places should be very limited (part of the reason |
911
|
|
|
|
|
|
|
# it was decided this whole thing wasn't worth it, because it just |
912
|
|
|
|
|
|
|
# wasn't used enough), but for now, to honor the original API (mostly) |
913
|
|
|
|
|
|
|
# we're dereferencing according to wantarray, since all the places |
914
|
|
|
|
|
|
|
# that expect to get lists back obviously call TableSpec_get_conf |
915
|
|
|
|
|
|
|
# in LIST context. This should not be kept this way for too long, |
916
|
|
|
|
|
|
|
# however! It is just temporary until those outside places |
917
|
|
|
|
|
|
|
# can be confirmed and eliminated, or a proper deprecation plan |
918
|
|
|
|
|
|
|
# can be made, should that even be needed... |
919
|
|
|
|
|
|
|
|
920
|
1654
|
50
|
66
|
|
|
4554
|
if(wantarray && ref($value)) { |
921
|
0
|
0
|
0
|
|
|
0
|
cluck join("\n",'', |
922
|
|
|
|
|
|
|
" WARNING: calling TableSpec_get_conf() in LIST context", |
923
|
|
|
|
|
|
|
" is deprecated, please update your code.", |
924
|
|
|
|
|
|
|
" --> Auto-dereferencing param '$param' $value",'', |
925
|
|
|
|
|
|
|
'') if (ref($value) eq 'ARRAY' || ref($value) eq 'HASH'); |
926
|
0
|
0
|
|
|
|
0
|
return @$value if (ref($value) eq 'ARRAY'); |
927
|
0
|
0
|
|
|
|
0
|
return %$value if (ref($value) eq 'HASH'); |
928
|
|
|
|
|
|
|
} |
929
|
|
|
|
|
|
|
|
930
|
|
|
|
|
|
|
# When trying to get a param that does not exist, return an |
931
|
|
|
|
|
|
|
# empty list if called in LIST context, otherwise undef |
932
|
1654
|
50
|
|
|
|
6488
|
return wantarray ? () : undef unless (exists $storage->{$param}); |
|
|
100
|
|
|
|
|
|
933
|
|
|
|
|
|
|
# --- |
934
|
|
|
|
|
|
|
|
935
|
996
|
|
|
|
|
5880
|
return $value; |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
sub TableSpec_has_conf { |
940
|
84
|
|
|
84
|
0
|
219
|
my $self = shift; |
941
|
84
|
|
|
|
|
211
|
my $param = shift; |
942
|
84
|
|
33
|
|
|
444
|
my $storage = shift || $self->get_built_Cnf; |
943
|
84
|
50
|
|
|
|
2883
|
return 1 if (exists $storage->{$param}); |
944
|
0
|
|
|
|
|
0
|
return 0; |
945
|
|
|
|
|
|
|
} |
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
sub TableSpec_related_class { |
949
|
554
|
|
|
554
|
0
|
934
|
my $self = shift; |
950
|
554
|
|
50
|
|
|
1135
|
my $rel = shift || return undef; |
951
|
554
|
|
50
|
|
|
10105
|
my $info = $self->relationship_info($rel) || return undef; |
952
|
554
|
|
|
|
|
21992
|
my $relclass = $info->{class}; |
953
|
|
|
|
|
|
|
|
954
|
554
|
|
|
|
|
28172
|
eval "require $relclass;"; |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
#my $relclass = $self->related_class($rel) || return undef; |
957
|
554
|
50
|
|
|
|
5175
|
$relclass->can('TableSpec_get_conf') || return undef; |
958
|
554
|
|
|
|
|
1813
|
return $relclass; |
959
|
|
|
|
|
|
|
} |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
# Gets a TableSpec conf param, if exists, from a related Result Class |
962
|
|
|
|
|
|
|
sub TableSpec_related_get_conf { |
963
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
964
|
0
|
|
0
|
|
|
0
|
my $rel = shift || return undef; |
965
|
0
|
|
0
|
|
|
0
|
my $param = shift || return undef; |
966
|
|
|
|
|
|
|
|
967
|
0
|
|
0
|
|
|
0
|
my $relclass = $self->TableSpec_related_class($rel) || return undef; |
968
|
|
|
|
|
|
|
|
969
|
0
|
|
|
|
|
0
|
return $relclass->TableSpec_get_conf($param); |
970
|
|
|
|
|
|
|
} |
971
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
# Gets a TableSpec conf param, if exists, from a related Result Class, |
973
|
|
|
|
|
|
|
# but uses the already 'set' params in TableSpec_cnf as storage, so that |
974
|
|
|
|
|
|
|
# get_built_cnf doesn't get called. |
975
|
|
|
|
|
|
|
sub TableSpec_related_get_set_conf { |
976
|
554
|
|
|
554
|
0
|
993
|
my $self = shift; |
977
|
554
|
|
50
|
|
|
1192
|
my $rel = shift || return undef; |
978
|
554
|
|
50
|
|
|
1268
|
my $param = shift || return undef; |
979
|
|
|
|
|
|
|
|
980
|
554
|
|
50
|
|
|
1432
|
my $relclass = $self->TableSpec_related_class($rel) || return undef; |
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
#return $relclass->TableSpec_get_conf($param,$relclass->TableSpec_cnf); |
983
|
554
|
|
|
|
|
1568
|
return $relclass->TableSpec_get_set_conf($param); |
984
|
|
|
|
|
|
|
} |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
# The "set conf" is different from the "built conf" in that it is passive, and only |
987
|
|
|
|
|
|
|
# returns the values which have been expressly "set" on the Result class with a |
988
|
|
|
|
|
|
|
# "TableSpec_set_conf" call. The built conf reaches out to code to build a configuration, |
989
|
|
|
|
|
|
|
# which causes recursive limitations in that code that reaches out to other TableSpec |
990
|
|
|
|
|
|
|
# classes. |
991
|
|
|
|
|
|
|
sub TableSpec_get_set_conf { |
992
|
858
|
|
|
858
|
0
|
1484
|
my $self = shift; |
993
|
858
|
|
50
|
|
|
1839
|
my $param = shift || return undef; |
994
|
858
|
|
|
|
|
16731
|
return $self->TableSpec_get_conf($param,$self->TableSpec_cnf); |
995
|
|
|
|
|
|
|
} |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
# TODO: Find a better way to handle this. Is there a real API |
999
|
|
|
|
|
|
|
# in DBIC to find this information? |
1000
|
|
|
|
|
|
|
sub get_foreign_column_from_cond { |
1001
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
1002
|
0
|
|
|
|
|
0
|
my $cond = shift; |
1003
|
|
|
|
|
|
|
|
1004
|
0
|
0
|
0
|
|
|
0
|
die "currently only single-key hashref conditions are supported" unless ( |
1005
|
|
|
|
|
|
|
ref($cond) eq 'HASH' and |
1006
|
|
|
|
|
|
|
scalar keys %$cond == 1 |
1007
|
|
|
|
|
|
|
); |
1008
|
|
|
|
|
|
|
|
1009
|
0
|
|
|
|
|
0
|
foreach my $i (%$cond) { |
1010
|
0
|
|
|
|
|
0
|
my ($side,$col) = split(/\./,$i); |
1011
|
0
|
0
|
0
|
|
|
0
|
return $col if (defined $col and $side eq 'foreign'); |
1012
|
|
|
|
|
|
|
} |
1013
|
|
|
|
|
|
|
|
1014
|
0
|
|
|
|
|
0
|
die "Failed to find forein column from condition: " . Dumper($cond); |
1015
|
|
|
|
|
|
|
} |
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
# This function parses 'foreign' and 'self' column names from the |
1018
|
|
|
|
|
|
|
# 'cond' of a defined in a DBIC relationship into a hashref. It is |
1019
|
|
|
|
|
|
|
# only able to do this for simple, single-key foreign key rels |
1020
|
|
|
|
|
|
|
# of the form: { "foreign.id_col" => "self.fk_col" } |
1021
|
|
|
|
|
|
|
# All other forms, such as multi-keys and CodeRefs, will return |
1022
|
|
|
|
|
|
|
# and empty HashRef. The only reason we really need this information |
1023
|
|
|
|
|
|
|
# outside of DBIC is for editable single rels (FKs) to be able |
1024
|
|
|
|
|
|
|
# to present selection dialogs (i.e. dropdowns) and currently |
1025
|
|
|
|
|
|
|
# the "open" magnify links, but the open links are planned to be |
1026
|
|
|
|
|
|
|
# changed to reference URLs based on the relationship name, which |
1027
|
|
|
|
|
|
|
# will remove this dependency and allow open links for any relationship |
1028
|
|
|
|
|
|
|
# column, including even those with CodeRef conditions... |
1029
|
|
|
|
|
|
|
sub parse_relationship_cond { |
1030
|
507
|
|
|
507
|
0
|
1550
|
my ($self,$cond,$info) = @_; |
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
return {} unless ( |
1033
|
507
|
50
|
33
|
|
|
3246
|
ref($cond) eq 'HASH' and |
1034
|
|
|
|
|
|
|
scalar keys %$cond == 1 |
1035
|
|
|
|
|
|
|
); |
1036
|
|
|
|
|
|
|
|
1037
|
507
|
|
|
|
|
1202
|
my $data = {}; |
1038
|
507
|
|
|
|
|
1571
|
foreach my $i (%$cond) { |
1039
|
1014
|
|
|
|
|
3403
|
my ($side,$col) = split(/\./,$i); |
1040
|
1014
|
|
|
|
|
3020
|
$data->{$side} = $col; |
1041
|
|
|
|
|
|
|
} |
1042
|
507
|
|
|
|
|
1490
|
return $data; |
1043
|
|
|
|
|
|
|
} |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
# Works like an around method modifier, but $self is expected as first arg and |
1046
|
|
|
|
|
|
|
# $orig (method) is expected as second arg (reversed from a normal around modifier). |
1047
|
|
|
|
|
|
|
# Calls the supplied method and returns what changed in the record from before to |
1048
|
|
|
|
|
|
|
# after the call. e.g.: |
1049
|
|
|
|
|
|
|
# |
1050
|
|
|
|
|
|
|
# my ($changes) = $self->proxy_method_get_changed('update',{ foo => 'sdfds'}); |
1051
|
|
|
|
|
|
|
# |
1052
|
|
|
|
|
|
|
# This is typically used for update, but could be any other method, too. |
1053
|
|
|
|
|
|
|
# |
1054
|
|
|
|
|
|
|
# Detects/propogates wantarray context. Call like this to chain from another modifier: |
1055
|
|
|
|
|
|
|
#my ($changes,@ret) = wantarray ? |
1056
|
|
|
|
|
|
|
# $self->proxy_method_get_changed($orig,@_) : |
1057
|
|
|
|
|
|
|
# @{$self->proxy_method_get_changed($orig,@_)}; |
1058
|
|
|
|
|
|
|
# |
1059
|
|
|
|
|
|
|
sub proxy_method_get_changed { |
1060
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
1061
|
0
|
|
|
|
|
0
|
my $method = shift; |
1062
|
|
|
|
|
|
|
|
1063
|
5
|
|
|
5
|
|
22746
|
no warnings 'uninitialized'; # because we might compare undef values |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
4691
|
|
1064
|
|
|
|
|
|
|
|
1065
|
0
|
|
|
|
|
0
|
my $origRow = $self; |
1066
|
0
|
|
|
|
|
0
|
my %old = (); |
1067
|
0
|
0
|
|
|
|
0
|
if($self->in_storage) { |
1068
|
0
|
|
0
|
|
|
0
|
$origRow = $self->get_from_storage || $self; |
1069
|
0
|
|
|
|
|
0
|
%old = $origRow->get_columns; |
1070
|
|
|
|
|
|
|
} |
1071
|
|
|
|
|
|
|
|
1072
|
0
|
|
|
|
|
0
|
my @ret = (); |
1073
|
|
|
|
|
|
|
wantarray ? |
1074
|
0
|
0
|
|
|
|
0
|
@ret = $self->$method(@_) : |
1075
|
|
|
|
|
|
|
$ret[0] = $self->$method(@_); |
1076
|
|
|
|
|
|
|
|
1077
|
0
|
|
|
|
|
0
|
my %new = (); |
1078
|
0
|
0
|
|
|
|
0
|
if($self->in_storage) { |
1079
|
0
|
|
|
|
|
0
|
%new = $self->get_columns; |
1080
|
|
|
|
|
|
|
} |
1081
|
|
|
|
|
|
|
|
1082
|
|
|
|
|
|
|
# This logic is duplicated in DbicLink2. Not sure how to avoid it, though, |
1083
|
|
|
|
|
|
|
# and keep a clean API |
1084
|
0
|
|
|
|
|
0
|
my @changed = (); |
1085
|
0
|
|
|
|
|
0
|
foreach my $col (uniq(keys %new,keys %old)) { |
1086
|
0
|
0
|
0
|
|
|
0
|
next if (! defined $new{$col} and ! defined $old{$col}); |
1087
|
0
|
0
|
|
|
|
0
|
next if ($new{$col} eq $old{$col}); |
1088
|
0
|
|
|
|
|
0
|
push @changed, $col; |
1089
|
|
|
|
|
|
|
} |
1090
|
|
|
|
|
|
|
|
1091
|
0
|
|
|
|
|
0
|
my @new_changed = (); |
1092
|
0
|
|
|
|
|
0
|
my $fk_map = $self->TableSpec_get_conf('relationship_column_fks_map'); |
1093
|
0
|
|
|
|
|
0
|
foreach my $col (@changed) { |
1094
|
0
|
0
|
|
|
|
0
|
unless($fk_map->{$col}) { |
1095
|
0
|
|
|
|
|
0
|
push @new_changed, $col; |
1096
|
0
|
|
|
|
|
0
|
next; |
1097
|
|
|
|
|
|
|
} |
1098
|
|
|
|
|
|
|
|
1099
|
0
|
|
|
|
|
0
|
my $rel = $fk_map->{$col}; |
1100
|
0
|
|
|
|
|
0
|
my $display_col = $self->TableSpec_related_get_set_conf($rel,'display_column'); |
1101
|
|
|
|
|
|
|
|
1102
|
0
|
|
|
|
|
0
|
my $relOld = $origRow->$rel; |
1103
|
0
|
|
|
|
|
0
|
my $relNew = $self->$rel; |
1104
|
|
|
|
|
|
|
|
1105
|
0
|
0
|
0
|
|
|
0
|
unless($display_col and ($relOld or $relNew)) { |
|
|
|
0
|
|
|
|
|
1106
|
0
|
|
|
|
|
0
|
push @new_changed, $col; |
1107
|
0
|
|
|
|
|
0
|
next; |
1108
|
|
|
|
|
|
|
} |
1109
|
|
|
|
|
|
|
|
1110
|
0
|
|
|
|
|
0
|
push @new_changed, $rel; |
1111
|
|
|
|
|
|
|
|
1112
|
0
|
0
|
0
|
|
|
0
|
$old{$rel} = $relOld->get_column($display_col) if (exists $old{$col} and $relOld); |
1113
|
0
|
0
|
0
|
|
|
0
|
$new{$rel} = $relNew->get_column($display_col) if (exists $new{$col} and $relNew); |
1114
|
|
|
|
|
|
|
} |
1115
|
|
|
|
|
|
|
|
1116
|
0
|
|
|
|
|
0
|
@changed = @new_changed; |
1117
|
|
|
|
|
|
|
|
1118
|
0
|
|
|
|
|
0
|
my $col_props = $self->TableSpec_get_conf('columns'); |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
my %diff = map { |
1121
|
0
|
|
|
|
|
0
|
$_ => { |
1122
|
|
|
|
|
|
|
old => $old{$_}, |
1123
|
|
|
|
|
|
|
new => $new{$_}, |
1124
|
|
|
|
|
|
|
header => ($col_props->{$_} && $col_props->{$_}->{header}) ? |
1125
|
0
|
0
|
0
|
|
|
0
|
$col_props->{$_}->{header} : $_ |
1126
|
|
|
|
|
|
|
} |
1127
|
|
|
|
|
|
|
} @changed; |
1128
|
|
|
|
|
|
|
|
1129
|
0
|
0
|
|
|
|
0
|
return wantarray ? (\%diff,@ret) : [\%diff,@ret]; |
1130
|
|
|
|
|
|
|
} |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
sub getOpenUrl { |
1134
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
1135
|
0
|
|
|
|
|
0
|
return $self->TableSpec_get_conf('open_url'); |
1136
|
|
|
|
|
|
|
} |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
sub getRestKey { |
1139
|
183
|
|
|
183
|
0
|
11295
|
my $self = shift; |
1140
|
183
|
|
|
|
|
782
|
my $rest_key_col = $self->TableSpec_get_conf('rest_key_column'); |
1141
|
183
|
50
|
33
|
|
|
803
|
return $rest_key_col if ($rest_key_col && $rest_key_col ne ''); |
1142
|
183
|
|
|
|
|
3968
|
my @pri = $self->primary_columns; |
1143
|
183
|
50
|
33
|
|
|
10252
|
return $pri[0] if ($pri[0] && scalar @pri == 1); |
1144
|
0
|
|
|
|
|
0
|
return undef; |
1145
|
|
|
|
|
|
|
} |
1146
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
### Util functions: to be called in Row-object context |
1148
|
|
|
|
|
|
|
sub apply_row_methods { |
1149
|
54
|
|
|
54
|
0
|
148
|
my $class = shift; |
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
my %RowMethods = ( |
1152
|
|
|
|
|
|
|
|
1153
|
0
|
|
|
0
|
|
0
|
getOpenUrl => sub { $class->TableSpec_get_conf('open_url') }, |
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
1154
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
getRecordPkValue => sub { |
1156
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
1157
|
0
|
|
|
|
|
0
|
my @pk_vals = map { $self->get_column($_) } $self->primary_columns; |
|
0
|
|
|
|
|
0
|
|
1158
|
0
|
|
|
|
|
0
|
return join('~$~',@pk_vals); |
1159
|
|
|
|
|
|
|
}, |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
getRestKeyVal => sub { |
1162
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
1163
|
0
|
0
|
|
|
|
0
|
my $col = $class->getRestKey or return $self->getRecordPkValue; |
1164
|
0
|
|
|
0
|
|
0
|
return try{$self->get_column($col)}; |
|
0
|
|
|
|
|
0
|
|
1165
|
|
|
|
|
|
|
}, |
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
getRestPath => sub { |
1168
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
1169
|
0
|
0
|
|
|
|
0
|
my $url = $class->getOpenUrl or return undef; |
1170
|
0
|
0
|
|
|
|
0
|
my $val = $self->getRestKeyVal or return undef; |
1171
|
0
|
|
|
|
|
0
|
return "$url/$val"; |
1172
|
|
|
|
|
|
|
}, |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
getDisplayValue => sub { |
1175
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
1176
|
0
|
|
|
|
|
0
|
my $display_column = $class->TableSpec_get_conf('display_column'); |
1177
|
0
|
0
|
|
|
|
0
|
return $self->get_column($display_column) if ($self->has_column($display_column)); |
1178
|
0
|
|
|
|
|
0
|
return $self->getRecordPkValue; |
1179
|
|
|
|
|
|
|
}, |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
inlineNavLink => sub { |
1182
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
1183
|
0
|
|
0
|
|
|
0
|
my $text = shift || '<span>open</span>'; |
1184
|
0
|
|
|
|
|
0
|
my %attrs = ( class => "ra-nav-link ra-icon-magnify-tiny", @_ ); |
1185
|
|
|
|
|
|
|
|
1186
|
0
|
0
|
|
|
|
0
|
my $title = $self->getDisplayValue or return undef; |
1187
|
0
|
0
|
|
|
|
0
|
my $url = $self->getRestPath or return undef; |
1188
|
|
|
|
|
|
|
|
1189
|
0
|
|
|
|
|
0
|
%attrs = ( |
1190
|
|
|
|
|
|
|
href => '#!' . $url, |
1191
|
|
|
|
|
|
|
title => $title, |
1192
|
|
|
|
|
|
|
%attrs |
1193
|
|
|
|
|
|
|
); |
1194
|
|
|
|
|
|
|
|
1195
|
0
|
|
|
|
|
0
|
my $attr_str = join(' ',map { $_ . '="' . $attrs{$_} . '"' } keys %attrs); |
|
0
|
|
|
|
|
0
|
|
1196
|
0
|
|
|
|
|
0
|
return '<a ' . $attr_str . '>' . $text . '</a>'; |
1197
|
|
|
|
|
|
|
}, |
1198
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
displayWithLink => sub { |
1200
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
1201
|
0
|
|
|
|
|
0
|
return $self->getDisplayValue . ' ' . $self->inlineNavLink; |
1202
|
|
|
|
|
|
|
} |
1203
|
54
|
|
|
|
|
1437
|
); |
1204
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
# --- Actualize/load methods into the Row object namespace: |
1206
|
54
|
|
|
|
|
261
|
foreach my $meth (keys %RowMethods) { |
1207
|
5
|
|
|
5
|
|
45
|
no strict 'refs'; |
|
5
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
1264
|
|
1208
|
378
|
|
|
|
|
844
|
my $meth_name = join '::', $class, $meth; |
1209
|
378
|
|
|
|
|
2717
|
*$meth_name = subname $meth_name => $RowMethods{$meth}; |
1210
|
|
|
|
|
|
|
} |
1211
|
|
|
|
|
|
|
# --- |
1212
|
|
|
|
|
|
|
} |
1213
|
|
|
|
|
|
|
|
1214
|
|
|
|
|
|
|
|
1215
|
|
|
|
|
|
|
sub _table_name_safe { |
1216
|
447
|
|
|
447
|
|
24139
|
my $arg = shift; |
1217
|
|
|
|
|
|
|
|
1218
|
447
|
50
|
33
|
|
|
5465
|
my $table = !(ref $arg) && $arg->can('table') ? $arg->table : $arg; # class method or straight function |
1219
|
|
|
|
|
|
|
|
1220
|
447
|
50
|
50
|
|
|
2524
|
$table = $$table if ((ref($table)||'') eq 'SCALAR'); # Handle ScalarRef values |
1221
|
447
|
|
|
|
|
2232
|
$table = (reverse split(/\./,$table))[0]; # Handle 'db.table' and 'schema.db.table' formats |
1222
|
|
|
|
|
|
|
|
1223
|
447
|
|
|
|
|
1791
|
$table =~ s/[\'\"]//g; # Strip quotes |
1224
|
447
|
|
|
|
|
1056
|
$table =~ s/\W/_/g; # Convert any non-word characters to underscore |
1225
|
|
|
|
|
|
|
|
1226
|
447
|
|
|
|
|
1464
|
$table |
1227
|
|
|
|
|
|
|
} |
1228
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
|
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
### -- old, pre-rest inlineNavLink: |
1232
|
|
|
|
|
|
|
## This function creates links just like the JavaScript function Ext.ux.RapidApp.inlineLink |
1233
|
|
|
|
|
|
|
#use URI::Escape; |
1234
|
|
|
|
|
|
|
#sub inlineNavLink { |
1235
|
|
|
|
|
|
|
# my $self = shift; |
1236
|
|
|
|
|
|
|
# my $text = shift || '<span>open</span>'; |
1237
|
|
|
|
|
|
|
# my %attrs = ( class => "magnify-link-tiny", @_ ); |
1238
|
|
|
|
|
|
|
# my $loadCfg = delete $attrs{loadCfg} || {}; |
1239
|
|
|
|
|
|
|
# |
1240
|
|
|
|
|
|
|
# my $title = $self->getDisplayValue || return undef; |
1241
|
|
|
|
|
|
|
# my $url = $self->getOpenUrl || return undef; |
1242
|
|
|
|
|
|
|
# my $pk_val = $self->getRecordPkValue || return undef; |
1243
|
|
|
|
|
|
|
# |
1244
|
|
|
|
|
|
|
# $loadCfg = merge({ |
1245
|
|
|
|
|
|
|
# title => $title, |
1246
|
|
|
|
|
|
|
# autoLoad => { |
1247
|
|
|
|
|
|
|
# url => $url, |
1248
|
|
|
|
|
|
|
# params => { '___record_pk' => $pk_val } |
1249
|
|
|
|
|
|
|
# } |
1250
|
|
|
|
|
|
|
# },$loadCfg); |
1251
|
|
|
|
|
|
|
# |
1252
|
|
|
|
|
|
|
# my $href = '#loadcfg:data=' . uri_escape(encode_json($loadCfg)); |
1253
|
|
|
|
|
|
|
# my $onclick = 'return Ext.ux.RapidApp.InlineLinkHandler.apply(this,arguments);'; |
1254
|
|
|
|
|
|
|
# |
1255
|
|
|
|
|
|
|
# %attrs = ( |
1256
|
|
|
|
|
|
|
# href => $href, |
1257
|
|
|
|
|
|
|
# onclick => $onclick, |
1258
|
|
|
|
|
|
|
# ondblclick => $onclick, |
1259
|
|
|
|
|
|
|
# title => $title, |
1260
|
|
|
|
|
|
|
# %attrs |
1261
|
|
|
|
|
|
|
# ); |
1262
|
|
|
|
|
|
|
# |
1263
|
|
|
|
|
|
|
# my $attr_str = join(' ',map { $_ . '="' . $attrs{$_} . '"' } keys %attrs); |
1264
|
|
|
|
|
|
|
# |
1265
|
|
|
|
|
|
|
# return '<a ' . $attr_str . '>' . $text . '</a>'; |
1266
|
|
|
|
|
|
|
# |
1267
|
|
|
|
|
|
|
#} |
1268
|
|
|
|
|
|
|
# |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
|
1271
|
|
|
|
|
|
|
1; |