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   878 use strict;
  6         15  
  6         175  
6 6     6   42 use warnings;
  6         11  
  6         178  
7              
8 6     6   35 use RapidApp::Util qw(:all);
  6         12  
  6         17201  
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 65 }') for @attrs;
  10 100   1698 0 27  
  1698 50   167 0 5825  
  1698 100   1836 0 3343  
  167 100   996 0 783  
  167 50   781 0 386  
  1836 0   0 0 5935  
  1836 0   0 0 4308  
  996 0   0 0 3428  
  996 0   0 0 2342  
  781 50   781 0 2855  
  781 50   1 0 1543  
  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 2692  
  781 100   768 0 1900  
  1 50   147 0 17  
  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 57  
  10 0   0 0 29  
  768 50   781 0 2620  
  768 100   237 0 1559  
  147 0   0 0 627  
  147 50   4 0 377  
  0 50   781 0 0  
  0 50   781 0 0  
  781 0   0 0 2774  
  781 50   1070 0 1600  
  0 50   511 0 0  
  0 50   791 0 0  
  0         0  
  0         0  
  1         6  
  1         4  
  1         3  
  1         7  
  1         4  
  439         1793  
  439         890  
  781         3162  
  781         1576  
  4215         11869  
  4215         25054  
  2         19  
  2         5  
  160         739  
  160         388  
  295         1242  
  295         662  
  1         9  
  1         4  
  82         433  
  82         193  
  82         411  
  82         205  
  0         0  
  0         0  
  1238         3562  
  1238         8700  
  63         307  
  63         141  
  82         403  
  82         219  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  781         2517  
  781         1593  
  781         1755  
  781         2510  
  781         2440  
  237         965  
  237         763  
  0         0  
  0         0  
  4         30  
  4         11  
  781         2753  
  781         1705  
  781         2707  
  781         1724  
  0         0  
  0         0  
  1070         3069  
  1070         3431  
  511         1788  
  511         1022  
  791         5015  
  791         1673  
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 2047 '.join(';', map { 'exists $self->{'.$_.'} or $self->{'.$_.'}= '.$defaults{$_} } keys %defaults).'
  909 100       2735  
  909 50       2511  
  909 50       2607  
  909 100       2289  
  909 50       2527  
  909 50       2378  
  909 50       3158  
  909 50       2428  
  909 50       2337  
  909 50       2319  
  909 100       2457  
  909         3183  
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   1802 my ($self,$new,$old) = @_;
76 781 50       2259 return unless ($new);
77            
78 781         15816 $self->xtype(undef);
79 781         15679 $self->tpl(undef);
80            
81 781 100 66     7367 return unless (defined $new and not blessed $new);
82 597         2175 $self->{renderer}= jsfunc($new);
83             }
84              
85             sub _set_menu_select_editor {
86 1     1   4 my ($self,$new,$old) = @_;
87 1 50       6 return unless ($new);
88            
89 1         32 my %val_to_disp = ();
90 1         6 my @value_list = ();
91            
92 1         3 foreach my $sel (uniq(@{$new->{selections}})) {
  1         10  
93 2         10 push @value_list, [$sel->{value},$sel->{text},$sel->{iconCls}];
94 2 50 33     20 if(defined $sel->{value} and defined $sel->{text}) {
95 2         7 $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       10 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     11 if($sel->{iconCls} and jstrue($new->{render_icon_only}));
102             };
103             }
104            
105 1         2 my $first_val;
106 1 50       22 $first_val = $value_list[0]->[0] if (defined $value_list[0]);
107            
108 1         8 my $mapjs = encode_json(\%val_to_disp);
109            
110 1         155 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         8 $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       35 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     7 my $mode = $new->{mode} || 'combo';
124            
125 1 50       6 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         8 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     48 $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       7 $self->{editor}->{value} = $orig_value if (defined $orig_value);
168            
169 1 50       30 $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 2325 my $class= shift;
178 909 100       3817 my $self= bless { (ref($_[0]) eq 'HASH')? %{$_[0]} : @_ }, $class;
  11         52  
179 909 50 33     2953 $self->{renderer} = jsfunc($self->{renderer}) if (defined $self->{renderer} and not blessed $self->{renderer});
180 909         3064 for (keys %$self) {
181 935 50       2456 $attrKeySet{$_} || die("No such attribute: $class\::$_");
182 935         1651 my $t= $triggers{$_};
183 935 50       2277 $t and $self->$t($self->{$_});
184             }
185 909         19827 $self->apply_defaults;
186 909         25337 return $self;
187             }
188              
189             sub apply_attributes {
190 1081     1081 0 1889 my $self = shift;
191 1081 50       7397 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         3966 delete $new{$_} for (grep { $_ =~ /^\_/ } keys %new);
  9496         17169  
196            
197 1081         2777 foreach my $attr (@attrs) {
198 56212 100       98798 next unless (exists $new{$attr});
199 9496         196364 $self->$attr($new{$attr});
200 9496         17828 delete $new{$attr};
201             }
202            
203             #There should be nothing left over in %new:
204 1081 50       2717 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         2731 }
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   1768 my $self = shift;
245            
246 1081 100       2820 $self->no_column(${$self->{no_column}}) if (ref $self->{no_column}); # consistent 0/1
  948         19555  
247 1081 100       20574 $self->no_column(0) unless ($self->no_column);
248            
249 1081         3152 $self->_normalize_allow_edit;
250 1081 100       2830 $self->allow_edit(${$self->{allow_edit}}) if (ref $self->{allow_edit});
  654         13549  
251              
252 1081         2842 $self->_normalize_allow_add;
253 1081 100       2655 $self->allow_add(${$self->{allow_add}}) if (ref $self->{allow_add});
  715         14932  
254            
255 1081         2739 $self->_normalize_allow_view;
256 1081 100       3946 $self->allow_view(${$self->{allow_view}}) if (ref $self->{allow_view});
  2         48  
257            
258             }
259              
260             sub _normalize_allow_edit {
261 1081     1081   1757 my $self = shift;
262            
263             # if its already set - and turned off - we're done:
264 1081 100 100     4862 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       833 $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     3409 );
275            
276 258 100       5320 $self->allow_edit( $no_edit ? 0 : 1 )
277             }
278              
279             sub _normalize_allow_add {
280 1081     1081   1888 my $self = shift;
281            
282             # if its already set - and turned off - we're done:
283 1081 100 100     3519 return if (exists $self->{allow_add} && !jstrue($self->{allow_add}));
284              
285 194 100       889 $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     2895 );
      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     2069 );
300            
301 192 100       3933 $self->allow_add( $no_add ? 0 : 1 )
302             }
303              
304             sub _normalize_allow_view {
305 1081     1081   1873 my $self = shift;
306            
307             # if its already set - and turned off - we're done:
308 1081 100 100     3091 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       2587 $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     19137 );
321            
322 983 100       19416 $self->allow_view( $no_view ? 0 : 1 )
323             }
324             ##
325             ## -----
326              
327              
328             sub get_grid_config {
329 5199     5199 0 8444 my $self = shift;
330 5199 100       9306 return { map { defined($self->{$_})? ($_ => $self->{$_}) : () } @gridColParams };
  207960         416780  
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;