File Coverage

blib/lib/RapidApp/Module/DatStor/Column.pm
Criterion Covered Total %
statement 176 276 63.7
branch 110 222 49.5
condition 32 44 72.7
subroutine 46 78 58.9
pod 0 68 0.0
total 364 688 52.9


line stmt bran cond sub pod time code
1             package RapidApp::Module::DatStor::Column;
2              
3             # ** This class used to be RapidApp::Column **
4              
5 6     6   674 use strict;
  6         11  
  6         184  
6 6     6   29 use warnings;
  6         11  
  6         144  
7              
8 6     6   4089 use RapidApp::Util qw(:all);
  6         15  
  6         14194  
9              
10             our @gridColParams= qw(
11             name sortable hidden header dataIndex width editor menuDisabled tpl xtype
12             id no_column no_multifilter no_quick_search extra_meta_data css listeners
13             filter field_cnf rel_combo_field_cnf field_cmp_config render_fn renderer
14             allow_add allow_edit allow_view query_id_use_column query_search_use_column
15             trueText falseText menu_select_editor render_column multifilter_type summary_functions
16             no_summary allow_batchedit format align is_nullable documentation
17             );
18             our @attrs= ( @gridColParams, qw(
19             data_type required_fetch_columns read_raw_munger update_munger
20             field_readonly field_readonly_config field_config no_fetch broad_data_type
21             quick_search_exact_only enum_value_hash search_operator_strf
22             ) );
23             our %triggers= (
24             render_fn => '_set_render_fn',
25             renderer => '_set_renderer',
26             menu_select_editor => '_set_menu_select_editor',
27             );
28              
29              
30             eval('sub '.$_.' {'
31             .(exists($triggers{$_})
32             ? 'if (scalar @_ > 1) { my $old= $_[0]->{'.$_.'}; $_[0]->{'.$_.'} = $_[1]; $_[0]->'.$triggers{$_}.'($_[0]->{'.$_.'}, $old); }'
33             : '$_[0]->{'.$_.'} = $_[1] if scalar @_ > 1;'
34             ).'$_[0]->{'.$_.'}
35 10 50   10 0 67 }') for @attrs;
  10 100   1698 0 25  
  1698 50   167 0 4954  
  1698 100   1836 0 2861  
  167 100   996 0 603  
  167 50   781 0 286  
  1836 0   0 0 5082  
  1836 0   0 0 3839  
  996 0   0 0 2797  
  996 0   0 0 2136  
  781 50   781 0 2332  
  781 50   1 0 1324  
  0 0   0 0 0  
  0 0   0 0 0  
  0 0   0 0 0  
  0 0   0 0 0  
  0 0   0 0 0  
  0 0   0 0 0  
  0 0   0 0 0  
  0 0   0 0 0  
  781 50   10 0 2422  
  781 100   768 0 1434  
  1 50   147 0 6  
  1 0   0 0 3  
  0 50   781 0 0  
  0 0   0 0 0  
  0 0   0 0 0  
  0 50   1 0 0  
  0 50   439 0 0  
  0 50   781 0 0  
  0 100   4215 0 0  
  0 50   2 0 0  
  0 50   160 0 0  
  0 50   295 0 0  
  0 50   1 0 0  
  0 50   82 0 0  
  0 50   82 0 0  
  0 0   0 0 0  
  0 100   1238 0 0  
  0 50   63 0 0  
  10 50   82 0 45  
  10 0   0 0 21  
  768 50   781 0 2253  
  768 100   237 0 1403  
  147 0   0 0 627  
  147 50   4 0 292  
  0 50   781 0 0  
  0 50   781 0 0  
  781 0   0 0 2346  
  781 50   1070 0 1381  
  0 50   511 0 0  
  0 50   791 0 0  
  0         0  
  0         0  
  1         5  
  1         3  
  1         3  
  1         5  
  1         4  
  439         1347  
  439         776  
  781         2519  
  781         1462  
  4215         9679  
  4215         21140  
  2         12  
  2         5  
  160         595  
  160         328  
  295         1017  
  295         548  
  1         5  
  1         3  
  82         307  
  82         181  
  82         353  
  82         212  
  0         0  
  0         0  
  1238         3055  
  1238         7402  
  63         266  
  63         148  
  82         344  
  82         171  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  781         2016  
  781         1287  
  781         1370  
  781         2086  
  781         2020  
  237         823  
  237         552  
  0         0  
  0         0  
  4         24  
  4         14  
  781         2321  
  781         1308  
  781         2333  
  781         1283  
  0         0  
  0         0  
  1070         2468  
  1070         3011  
  511         1639  
  511         884  
  791         3386  
  791         1518  
36              
37             our %defaults= (
38             sortable => '\1',
39             hidden => '\0',
40             header => '$self->{name}',
41             dataIndex => '$self->{name}',
42             width => '70',
43             no_column => '\0',
44             no_multifilter => '\0',
45             no_quick_search => '\0',
46             field_readonly => '0',
47             required_fetch_columns => '[]',
48             field_readonly_config => '{}',
49             field_config => '{}',
50             );
51              
52             eval 'sub apply_defaults {
53             my $self= shift;
54 909 50   909 0 1805 '.join(';', map { 'exists $self->{'.$_.'} or $self->{'.$_.'}= '.$defaults{$_} } keys %defaults).'
  909 50       2627  
  909 50       2241  
  909 50       2136  
  909 100       2007  
  909 100       1980  
  909 50       2016  
  909 50       2677  
  909 50       2589  
  909 100       2275  
  909 50       2002  
  909 50       2197  
  909         2420  
55             }';
56              
57              
58              
59              
60             sub _set_render_fn {
61 0     0   0 my ($self,$new,$old) = @_;
62            
63 0         0 die 'render_fn is depricated, please use renderer instead.';
64            
65 0 0       0 return unless ($new);
66            
67             # renderer takes priority over render_fn
68 0 0       0 return if (defined $self->renderer);
69            
70 0         0 $self->xtype('templatecolumn');
71 0         0 $self->tpl('{[' . $new . '(values.' . $self->name . ',values)]}');
72             }
73              
74             sub _set_renderer {
75 781     781   1453 my ($self,$new,$old) = @_;
76 781 50       1815 return unless ($new);
77            
78 781         13487 $self->xtype(undef);
79 781         13240 $self->tpl(undef);
80            
81 781 100 66     6173 return unless (defined $new and not blessed $new);
82 597         1778 $self->{renderer}= jsfunc($new);
83             }
84              
85             sub _set_menu_select_editor {
86 1     1   3 my ($self,$new,$old) = @_;
87 1 50       5 return unless ($new);
88            
89 1         2 my %val_to_disp = ();
90 1         5 my @value_list = ();
91            
92 1         1 foreach my $sel (uniq(@{$new->{selections}})) {
  1         17  
93 2         9 push @value_list, [$sel->{value},$sel->{text},$sel->{iconCls}];
94 2 50 33     18 if(defined $sel->{value} and defined $sel->{text}) {
95 2         8 $val_to_disp{$sel->{value}} = $sel->{text};
96              
97             $val_to_disp{$sel->{value}} = '<div class="with-icon ' . $sel->{iconCls} . '">' . $sel->{text} . '</div>'
98 2 50       9 if($sel->{iconCls});
99            
100             $val_to_disp{$sel->{value}} = '<img src="_ra-rel-mnt_/assets/rapidapp/misc/static/s.gif" class="ra-icon-centered-16x16 ' . $sel->{iconCls} . '">'
101 2 50 33     8 if($sel->{iconCls} and jstrue($new->{render_icon_only}));
102             };
103             }
104            
105 1         3 my $first_val;
106 1 50       12 $first_val = $value_list[0]->[0] if (defined $value_list[0]);
107            
108 1         10 my $mapjs = encode_json(\%val_to_disp);
109            
110 1         64 my $js = 'function(v){' .
111             'var val_map = ' . $mapjs . ';' .
112             'if(typeof val_map[v] !== "undefined") { return val_map[v]; }' .
113             'return v;' .
114             '}';
115            
116 1         5 $self->{renderer} = jsfunc($js,$self->{renderer});
117            
118             # If there is already a 'value' property set in editor save it to preserve it (see below):
119 1 50       26 my $orig_value = ref($self->{editor}) eq 'HASH' ? $self->{editor}->{value} : undef;
120            
121             # Update: removed extra, not-needed check of 'allow_edit' param (fixes Github Issue #35)
122              
123 1   50     6 my $mode = $new->{mode} || 'combo';
124            
125 1 50       7 if($mode eq 'combo') {
    50          
    0          
126             $self->{editor} = {
127 0         0 xtype => 'ra-icon-combo',
128             allowBlank => \0,
129             value_list => \@value_list,
130             };
131             }
132             elsif($mode eq 'menu') {
133            
134             $self->{editor} = {
135 1         11 xtype => 'menu-field',
136             menuOnShow => \1,
137             value_list => \@value_list,
138             value => $first_val,
139             minHeight => 10,
140             minWidth => 10
141             };
142            
143 1   33     28 $self->{editor}->{header} = $new->{header} || $self->header;
144             delete $self->{editor}->{header} unless (
145             defined $self->{editor}->{header} and
146 1 50 33     15 $self->{editor}->{header} ne ''
147             );
148            
149             }
150             elsif($mode eq 'cycle') {
151            
152             $self->{editor} = {
153 0         0 xtype => 'cycle-field',
154             cycleOnShow => \1,
155             value_list => \@value_list,
156             value => $first_val,
157             minHeight => 10,
158             minWidth => 10
159             };
160            
161             }
162             else {
163 0         0 die "menu_select_editor: Invalid mode '$mode' - must be 'combo', 'menu' or 'cycle'"
164             }
165            
166             # restore the original 'value' if it was already defined (see above)
167 1 50       5 $self->{editor}->{value} = $orig_value if (defined $orig_value);
168            
169 1 50       24 $self->{editor}->{width} = $new->{width} if ($new->{width});
170             }
171              
172              
173             our %attrKeySet= map { $_ => 1 } @attrs;
174             our %gridColParamKeySet= map { $_ => 1 } @gridColParams;
175              
176             sub new {
177 909     909 0 1927 my $class= shift;
178 909 100       3064 my $self= bless { (ref($_[0]) eq 'HASH')? %{$_[0]} : @_ }, $class;
  11         42  
179 909 50 33     2376 $self->{renderer} = jsfunc($self->{renderer}) if (defined $self->{renderer} and not blessed $self->{renderer});
180 909         2600 for (keys %$self) {
181 935 50       2272 $attrKeySet{$_} || die("No such attribute: $class\::$_");
182 935         1525 my $t= $triggers{$_};
183 935 50       2190 $t and $self->$t($self->{$_});
184             }
185 909         17228 $self->apply_defaults;
186 909         21523 return $self;
187             }
188              
189             sub apply_attributes {
190 1081     1081 0 1688 my $self = shift;
191 1081 50       6391 my %new = (ref($_[0]) eq 'HASH') ? %{ $_[0] } : @_; # <-- arg as hash or hashref
  0         0  
192            
193             # Ignore attribute names which start with underscore (_) -- backcompat fix for special
194             # flag/keys added in 1.1000 for the "allow_*" refactor
195 1081         3747 delete $new{$_} for (grep { $_ =~ /^\_/ } keys %new);
  9496         15291  
196            
197 1081         2396 foreach my $attr (@attrs) {
198 56212 100       84430 next unless (exists $new{$attr});
199 9496         168018 $self->$attr($new{$attr});
200 9496         16204 delete $new{$attr};
201             }
202            
203             #There should be nothing left over in %new:
204 1081 50       2324 if (scalar(keys %new) > 0) {
205             #die "invalid attributes (" . join(',',keys %new) . ") passed to apply_attributes";
206             #use Data::Dumper;
207 0         0 die "invalid attributes (" . join(',',keys %new) . ") passed to apply_attributes :\n" . Dumper(\%new);
208             }
209            
210             $self->_normalize_allow_add_edit
211 1081         2526 }
212              
213             sub applyIf_attributes {
214 0     0 0 0 my $self = shift;
215 0 0       0 my %new = (ref($_[0]) eq 'HASH') ? %{ $_[0] } : @_; # <-- arg as hash or hashref
  0         0  
216            
217             # Ignore attribute names which start with underscore (_) -- backcompat fix for special
218             # flag/keys added in 1.1000 for the "allow_*" refactor
219 0         0 delete $new{$_} for (grep { $_ =~ /^\_/ } keys %new);
  0         0  
220            
221 0         0 foreach my $attr (@attrs) {
222 0 0       0 next unless (exists $new{$attr});
223 0 0       0 $self->$attr($new{$attr}) unless defined $self->{$attr}; # <-- only set attrs that aren't already set
224 0         0 delete $new{$attr};
225             }
226            
227             #There should be nothing left over in %new:
228 0 0       0 if (scalar(keys %new) > 0) {
229             #die "invalid attributes (" . join(',',keys %new) . ") passed to apply_attributes";
230             #use Data::Dumper;
231 0         0 die "invalid attributes (" . join(',',keys %new) . ") passed to apply_attributes :\n" . Dumper(\%new);
232             }
233            
234             $self->_normalize_allow_add_edit
235 0         0 }
236              
237             ## -----
238             ##
239             ## This just ensures allow_add/allow_edit/allow_view/no_column are always populated, with
240             ## values which are already implied by the existing rules. This just makes it easier to
241             ## check later, avoiding all the defined or not checks, etc
242             ##
243             sub _normalize_allow_add_edit {
244 1081     1081   1628 my $self = shift;
245            
246 1081 100       2474 $self->no_column(${$self->{no_column}}) if (ref $self->{no_column}); # consistent 0/1
  948         17123  
247 1081 100       17397 $self->no_column(0) unless ($self->no_column);
248            
249 1081         2635 $self->_normalize_allow_edit;
250 1081 100       2310 $self->allow_edit(${$self->{allow_edit}}) if (ref $self->{allow_edit});
  654         11550  
251              
252 1081         2664 $self->_normalize_allow_add;
253 1081 100       2420 $self->allow_add(${$self->{allow_add}}) if (ref $self->{allow_add});
  715         12946  
254            
255 1081         2663 $self->_normalize_allow_view;
256 1081 100       3491 $self->allow_view(${$self->{allow_view}}) if (ref $self->{allow_view});
  2         42  
257            
258             }
259              
260             sub _normalize_allow_edit {
261 1081     1081   1561 my $self = shift;
262            
263             # if its already set - and turned off - we're done:
264 1081 100 100     4156 return if (exists $self->{allow_edit} && !jstrue($self->{allow_edit}));
265            
266             # remember if allow_edit was *not* already set, because this effects the default for allow_add
267 258 100       776 $self->{_allow_edit_init_unset} = 1 unless (exists $self->{allow_edit});
268            
269             # if its true (or not yet set, which implies true) test for any
270             # conditions which prevent it from being true
271             my $no_edit = (
272             ! $self->{editor}
273             || ( $self->no_column && $self->{_allow_edit_init_unset} )
274 258   100     2971 );
275            
276 258 100       4917 $self->allow_edit( $no_edit ? 0 : 1 )
277             }
278              
279             sub _normalize_allow_add {
280 1081     1081   1537 my $self = shift;
281            
282             # if its already set - and turned off - we're done:
283 1081 100 100     3067 return if (exists $self->{allow_add} && !jstrue($self->{allow_add}));
284              
285 194 100       980 $self->{_allow_add_init_unset} = 1 unless (exists $self->{allow_add});
286              
287             # Go with allow_edit when it's explicitly false and we weren't set
288             return $self->allow_add(0) if(
289             ! exists $self->{allow_add}
290             && ! $self->allow_edit
291             && ! $self->{_allow_edit_init_unset}
292 194 100 100     2514 );
      100        
293            
294             # if its true (or not yet set, which implies true) test for any
295             # conditions which prevent it from being true
296             my $no_add = (
297             ! $self->{editor}
298             || ( $self->no_column && ! $self->allow_edit && $self->{_allow_add_init_unset} )
299 192   100     1675 );
300            
301 192 100       3416 $self->allow_add( $no_add ? 0 : 1 )
302             }
303              
304             sub _normalize_allow_view {
305 1081     1081   1663 my $self = shift;
306            
307             # if its already set - and turned off - we're done:
308 1081 100 100     2701 return if (exists $self->{allow_view} && !jstrue($self->{allow_view}));
309            
310             # remember if allow_edit was *not* already set, because this effects the default for allow_add
311 983 100       2217 $self->{_allow_view_init_unset} = 1 unless (exists $self->{allow_view});
312            
313             # If allow_edit was expressly set to false:
314             #my $deny_edit = (! $self->allow_edit && ! $self->{_allow_edit_init_unset});
315            
316             # if its true (or not yet set, which implies true) test for any
317             # conditions which prevent it from being true
318             my $no_view = (
319             $self->no_column && $self->{_allow_view_init_unset}
320 983   100     16343 );
321            
322 983 100       17172 $self->allow_view( $no_view ? 0 : 1 )
323             }
324             ##
325             ## -----
326              
327              
328             sub get_grid_config {
329 5199     5199 0 7397 my $self = shift;
330 5199 100       7648 return { map { defined($self->{$_})? ($_ => $self->{$_}) : () } @gridColParams };
  207960         350708  
331             }
332              
333             sub apply_field_readonly_config {
334 0     0 0   my $self= shift;
335 0 0         %{ $self->{field_readonly_config} }= %{ $self->{field_readonly_config} }, (ref($_[0]) eq 'HASH') ? %{ $_[0] } : @_; # <-- arg as hash or hashref
  0            
  0            
  0            
336             }
337              
338             sub get_field_config_readonly_param {
339 0     0 0   my $self= shift;
340 0           return $self->{field_readonly_config}{$_[0]};
341             }
342              
343             sub has_field_config_readonly_param {
344 0     0 0   my $self= shift;
345 0           return exists $self->{field_readonly_config}{$_[0]};
346             }
347              
348             sub has_no_field_readonly_config {
349 0     0 0   my $self= shift;
350 0           return 0 == (keys %{ $self->{field_readonly_config} });
  0            
351             }
352              
353             sub delete_field_readonly_config_param {
354 0     0 0   my $self= shift;
355 0           delete $self->{field_readonly_config}{$_[0]};
356             }
357              
358             sub apply_field_config {
359 0     0 0   my $self= shift;
360 0 0         %{ $self->{field_config} }= %{ $self->{field_config} }, (ref($_[0]) eq 'HASH') ? %{ $_[0] } : @_; # <-- arg as hash or hashref
  0            
  0            
  0            
361             }
362             sub get_field_config_param {
363 0     0 0   my $self= shift;
364 0           return $self->{field_config}{$_[0]};
365             }
366              
367             sub has_field_config_param {
368 0     0 0   my $self= shift;
369 0           return exists $self->{field_config}{$_[0]};
370             }
371             sub has_no_field_config {
372 0     0 0   my $self= shift;
373 0           return 0 == (keys %{ $self->{field_config} });
  0            
374             }
375              
376             sub delete_field_config_param {
377 0     0 0   my $self= shift;
378 0           delete $self->{field_config}{$_[0]};
379             }
380              
381             sub get_field_config {
382 0     0 0   my $self = shift;
383            
384 0           my $config = $self->field_config;
385 0 0         $config = $self->editor if ($self->editor);
386            
387 0           my $cnf = {
388             name => $self->name,
389             %$config
390             };
391            
392 0 0         $cnf = { %$cnf, %{$self->field_readonly_config} } if ($self->field_readonly);
  0            
393            
394 0           $self->field_cmp_config($cnf);
395            
396 0           return $cnf;
397             }
398              
399             1;