File Coverage

blib/lib/Mojolicious/Plugin/FormFieldsFromJSON.pm
Criterion Covered Total %
statement 451 467 96.5
branch 201 244 82.3
condition 152 253 60.0
subroutine 33 33 100.0
pod 1 1 100.0
total 838 998 83.9


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::FormFieldsFromJSON;
2 85     85   82362 use Mojo::Base 'Mojolicious::Plugin';
  85         226  
  85         678  
3              
4             # ABSTRACT: create form fields based on a definition in a JSON file
5              
6             our $VERSION = '1.01';
7              
8 85     85   19699 use Carp;
  85         229  
  85         5715  
9 85     85   597 use File::Basename;
  85         183  
  85         5545  
10 85     85   547 use File::Spec;
  85         199  
  85         2365  
11 85     85   43247 use IO::Dir;
  85         140712  
  85         4745  
12 85     85   701 use List::Util qw(first);
  85         207  
  85         5690  
13              
14 85     85   554 use Mojo::Asset::File;
  85         190  
  85         1265  
15 85     85   2481 use Mojo::Collection;
  85         197  
  85         4303  
16 85     85   474 use Mojo::ByteStream;
  85         188  
  85         2631  
17 85     85   454 use Mojo::File;
  85         181  
  85         2892  
18 85     85   542 use Mojo::JSON qw(decode_json);
  85         215  
  85         3889  
19              
20 85     85   557 use Mojolicious ();
  85         186  
  85         511619  
21              
22             has dir => sub {["."]} ;
23              
24             my $selected_value = Mojolicious->VERSION < 6.16 ? 'selected' : undef;
25             my $checked_value = Mojolicious->VERSION < 6.16 ? 'checked' : undef;
26              
27             sub register {
28 85     85 1 4244 my ($self, $app, $config) = @_;
29              
30 85   50     386 $config //= {};
31              
32 85 100       363 if ( $config->{template_file} ) {
33 1         7 $config->{template} = Mojo::File->new( $app->home, 'templates', $config->{template_file} )->slurp;
34 1   33     236 $config->{template} //= $app->renderer->get_data_template( $config->{template_file} );
35             }
36            
37 85         222 my %configs;
38 85 100       326 if(ref $config->{dir} eq "ARRAY"){
39 1         2 @{$self->dir} = @{$config->{dir}};
  1         3  
  1         3  
40             }
41             else{
42 84         204 @{$self->dir} = ($config->{dir});
  84         306  
43             }
44            
45             my %valid_types = (
46 85 100       233 %{ $config->{types} || {} },
  85         1206  
47             text => 1,
48             checkbox => 1,
49             select => 1,
50             radio => 1,
51             hidden => 1,
52             textarea => 1,
53             password => 1,
54             );
55              
56 85         253 my %configfiles;
57             $app->helper(
58             forms => sub {
59 1 50   1   11269 if( %configfiles ) {
60 0         0 return sort keys %configfiles;
61             }
62              
63 1         2 for my $dir (@{$self->dir}){
  1         5  
64 1         12 my $dir = IO::Dir->new( $dir );
65              
66             FILE:
67 1         94 while ( my $file = $dir->read ) {
68 5 100       94 next FILE if $file !~ m{\.json\z};
69              
70 3         81 my $filename = basename $file;
71 3         10 $filename =~ s{\.json\z}{};
72              
73 3         12 $configfiles{$filename} = 1;
74             }
75             }
76              
77 1         59 return sort keys %configfiles;
78             }
79 85         1107 );
80              
81             $app->helper(
82 1     1   4636 "form_fields_from_json_dir" => sub {return $self->dir}
83 85         13285 );
84              
85             $app->helper(
86             fields => sub {
87 2     2   20026 my ($c, $file, $params) = @_;
88              
89 2 100       9 if ( !$configs{$file} ) {
90 1         4 $self->_load_config_from_file($c, \%configs, $file);
91             }
92              
93 2         5 my @fields;
94             my @fields_long;
95 2         4 for my $field ( @{ $configs{$file} } ) {
  2         5  
96 4   33     17 my $name = $field->{label} // $field->{name} // '';
      0        
97 4         6 push @fields, $name;
98 4   50     65 push @fields_long, +{ label => $name, name => $field->{name} // '' };
99             }
100              
101 2 100 66     12 if ( $params and $params->{hash} ) {
102 1         5 return @fields_long;
103             }
104              
105 1         8 return @fields;
106             }
107 85         8043 );
108              
109             $app->helper(
110             'validate_form_fields' => sub {
111 23     23   239385 my ($c, $file) = @_;
112            
113 23 50       116 return '' if !$file;
114            
115 23 100       114 if ( !$configs{$file} ) {
116 10         71 $self->_load_config_from_file($c, \%configs, $file);
117             }
118            
119 23 50       82 return '' if !$configs{$file};
120            
121 23         54 my $config = $configs{$file};
122              
123 23         173 my $validation = $c->validation;
124              
125 23         14686 my $params_hash = $c->req->params->to_hash;
126 23 50       795 my @param_names = keys %{ $params_hash || {} };
  23         119  
127              
128 23         67 my %params = map{ $_ => $c->every_param( $_ ) }@param_names;
  20         86  
129 23         1670 $validation->input( \%params );
130              
131 23         150 my %errors;
132            
133             FIELD:
134 23         50 for my $field ( @{ $config } ) {
  23         58  
135 23 50       101 if ( 'HASH' ne ref $field ) {
136 0         0 $app->log->error( 'Field definition must be a HASH - skipping field' );
137 0         0 next FIELD;
138             }
139              
140 23 50       96 if ( !$field->{validation} ) {
141 0         0 next FIELD;
142             }
143              
144 23 50       84 if ( 'HASH' ne ref $field->{validation} ) {
145 0         0 $app->log->warn( 'Validation settings must be a HASH - skipping field' );
146 0         0 next FIELD;
147             }
148              
149 23   33     74 my $name = $field->{name} // $field->{label} // '';
      0        
150 23         49 my $global_error = 1;
151              
152 23 100       78 if ( $field->{validation}->{required} ) {
153 7         42 $validation->required( $name );
154              
155 7         415 my $value = $field->{validation}->{required};
156 7 100 66     35 if ( ref $value && 'HASH' eq ref $value ) {
157 2   50     10 $global_error = $value->{msg} // 1;
158             }
159             }
160             else {
161 16         64 $validation->optional( $name );
162             }
163              
164             RULE:
165 23         561 for my $rule ( sort keys %{ $field->{validation} } ) {
  23         131  
166 27 100       146 last RULE if !defined $params{$name};
167              
168 22 100       86 next RULE if $rule eq 'required';
169              
170 19         44 my $value = $field->{validation}->{$rule};
171 19         44 my $ref = ref $value;
172 19         41 my $method = $rule;
173 19         31 my $error = 1;
174              
175 19         37 my @params;
176              
177 19 100       102 if ( !$ref ) {
    100          
    50          
178 3         10 @params = $value;
179             }
180             elsif ( $ref eq 'ARRAY' ) {
181 6         10 @params = @{ $value };
  6         21  
182             }
183             elsif ( $ref eq 'HASH' ) {
184 10 50       31 @params = ref $value->{args} ? @{ $value->{args} } : $value->{args};
  10         27  
185 10   50     28 $error = $value->{msg} // 1;
186             }
187              
188             eval{
189 19         89 $validation->check( $method, @params );
190 19         999 1;
191 19 50       38 } or do {
192 0         0 $app->log->error( "Validating $name with rule $method failed: $@" );
193             };
194              
195 19 100       58 if ( $validation->has_error( $name ) ) {
196 8         46 $errors{$name} = $error;
197 8         24 last RULE;
198             }
199             }
200              
201 23 100 100     118 if ( $validation->has_error( $name ) && !defined $errors{$name} ) {
202 4         47 $errors{$name} = $global_error;
203             }
204             }
205              
206 23         275 return %errors;
207             }
208 85         7566 );
209              
210             $app->helper(
211             'form_fields' => sub {
212 107     107   1261467 my ($c, $file, %params) = @_;
213              
214             # get form config
215 107 100       576 return '' if !$self->_load_config_from_file($c, \%configs, $file);
216 106 50 66     485 return '' if !$configs{$file} && !ref $file;
217 106   66     799 my $field_config = $configs{$file} || $file;
218              
219 106         250 my @fields;
220              
221 106 100       248 my %fields_to_show = map { $_ => 1 } @{ $params{fields} || [] };
  2         10  
  106         797  
222              
223             FIELD:
224 106         282 for my $field ( @{$field_config} ) {
  106         336  
225 145 100 100     651 next FIELD if %fields_to_show && !$fields_to_show{ $field->{name} };
226              
227 143         661 my $field_content = $self->_build_form_field($c, $field, \%params, $config, \%valid_types);
228              
229 143 50       494 if (length $field_content) {
230 143         1355 push @fields, $field_content;
231             }
232             }
233              
234 106         369 return Mojo::ByteStream->new( join "\n\n", @fields );
235             }
236 85         7432 );
237              
238             $app->helper(
239             'form_field_by_name' => sub {
240 4     4   47032 my ($c, $file, $field_name, %params) = @_;
241              
242             # get form config
243 4 50       20 return '' if !$self->_load_config_from_file($c, \%configs, $file);
244 4 0 33     16 return '' if !$configs{$file} && !ref $file;
245 4   33     24 my $field_config = $configs{$file} || $file;
246              
247             # find field config
248             my @fields_filtered = grep {
249 8         28 $_->{name} eq $field_name
250 4         9 } @{ $field_config };
  4         12  
251              
252 4 50       25 return '' if !(scalar @fields_filtered);
253              
254 4         31 return $self->_build_form_field($c, $fields_filtered[0], \%params, $config, \%valid_types);
255             }
256 85         7262 );
257             }
258              
259             sub _load_config_from_file {
260 122     122   556 my ($self, $c, $configs, $file) = @_;
261              
262 122 50       617 return 0 if !$file;
263              
264 122 100 100     1037 if ( !$configs->{$file} && !ref $file ) {
265 85         262 my $path;
266              
267             # search until first match
268 85         236 my $i=0;
269             do {
270 89         573 my $_path= File::Spec->catfile( $self->dir->[$i], $file . '.json' );
271 89 100       5295 $path = $_path if -r $_path;
272 85   100     232 } while ( not defined $path and ++$i <= $#{$self->dir} );
  5         27  
273              
274 85 100       470 if( not defined $path){
275 1         6 $c->app->log->error( "FORMFIELDS $file: not found in directories" );
276 1         21 $c->app->log->error( " $_") for @{$self->dir};
  1         5  
277 1         36 return 0;
278             }
279              
280             eval {
281 84         960 my $content = Mojo::Asset::File->new( path => $path )->slurp;
282 84         26697 $configs->{$file} = decode_json $content;
283 84 50       265 } or do {
284 0         0 $c->app->log->error( "FORMFIELDS $file: $@" );
285 0         0 return 0;
286             };
287              
288 84 50       33292 if ( 'ARRAY' ne ref $configs->{$file} ) {
289 0         0 $c->app->log->error( 'Definition JSON must be an ARRAY' );
290 0         0 return 0;
291             }
292             }
293              
294 121         490 return 1;
295             }
296              
297             sub _build_form_field {
298 147     147   495 my ($self, $c, $field, $params, $plugin_config, $valid_types) = @_;
299              
300              
301 147 50       582 if ( 'HASH' ne ref $field ) {
302 0         0 $c->app->log->error( 'Field definition must be an HASH - skipping field' );
303 0         0 return '';
304             }
305              
306 147         652 my $type = lc $field->{type};
307 147         345 my $orig_type = $type;
308              
309 147 100 100     613 if ( $plugin_config->{alias} && $plugin_config->{alias}->{$type} ) {
310 3         10 $type = $plugin_config->{alias}->{$type};
311             }
312              
313 147 50       683 if ( !$valid_types->{$type} ) {
314 0         0 $c->app->log->warn( "Invalid field type $type - falling back to 'text'" );
315 0         0 $type = 'text';
316             }
317              
318 147 100 100     965 if ( $plugin_config->{global_attributes} && $type ne 'hidden' && 'HASH' eq ref $plugin_config->{global_attributes} ) {
      66        
319              
320             ATTRIBUTE:
321 24         41 for my $attribute ( keys %{ $plugin_config->{global_attributes} } ) {
  24         81  
322 24   100     109 $field->{attributes}->{$attribute} //= '';
323              
324 24         50 my $field_attr = $field->{attributes}->{$attribute};
325 24         52 my $global_attr = $plugin_config->{global_attributes}->{$attribute};
326              
327 24 100       141 next ATTRIBUTE if $field_attr =~ m{\Q$global_attr};
328              
329 18 100       53 my $space = length $field_attr ? ' ' : '';
330              
331 18         74 $field->{attributes}->{$attribute} .= $space . $global_attr;
332             }
333             }
334              
335 147 50 66     543 if ( $field->{translate_sublabels} && $plugin_config->{translation_method} && !$field->{translation_method} ) {
      33        
336 2         19 $field->{translation_method} = $plugin_config->{translation_method};
337             }
338              
339 147         1695 my $sub = $self->can( '_' . $type );
340 147         548 my $form_field = $self->$sub( $c, $field, %{ $params } );
  147         690  
341              
342 147         115026 $form_field = Mojo::ByteStream->new( $form_field );
343              
344 147   100     3761 my $template = $field->{template} // $plugin_config->{templates}->{$orig_type} // $plugin_config->{template};
      100        
345              
346 147 100 66     816 if ( $template && $type ne 'hidden' ) {
347 23   50     138 my $label = $field->{label} // '';
348 23         59 my $loc = $plugin_config->{translation_method};
349              
350 23 50 66     131 if ( $plugin_config->{translate_labels} && $loc && 'CODE' eq ref $loc ) {
      66        
351 1         13 $label = $loc->($c, $label);
352             }
353              
354             $form_field = Mojo::ByteStream->new(
355             $c->render_to_string(
356             inline => $template,
357             id => $field->{id} // $field->{name} // $field->{label} // '',
358             label => $label,
359             field => $form_field,
360             message => $field->{msg} // '',
361 23   33     564 info => $field->{info} // '',
      33        
      0        
      100        
      100        
362             )
363             );
364             # $c->app->log->debug("rendered formfield: ".$form_field);
365             }
366              
367 147         58565 return $form_field;
368             }
369              
370             sub _hidden {
371 8     8   33 my ($self, $c, $field, %params) = @_;
372              
373 8   33     37 my $name = $field->{name} // $field->{label} // '';
      0        
374              
375 8         18 my $from_stash_key = $params{from_stash};
376             my $from_stash = $from_stash_key ?
377 8 50       43 $c->stash( $from_stash_key )->{$name} :
378             undef;
379              
380             my $value = $params{$name}->{data} // $from_stash //
381             $c->stash( $name ) // $c->param( $name ) //
382 8   66     144 $field->{data} // '';
      66        
      66        
      66        
      50        
383              
384 8   33     975 my $id = $field->{id} // $name;
385 8 50       18 my %attrs = %{ $field->{attributes} || {} };
  8         50  
386              
387 8         73 return $c->hidden_field( $name, $value, id => $id, %attrs );
388             }
389              
390             sub _text {
391 33     33   118 my ($self, $c, $field, %params) = @_;
392              
393 33   33     204 my $name = $field->{name} // $field->{label} // '';
      0        
394              
395 33         87 my $from_stash_key = $params{from_stash};
396             my $from_stash = $from_stash_key ?
397 33 100       183 $c->stash( $from_stash_key )->{$name} :
398             undef;
399              
400             my $value = $params{$name}->{data} // $from_stash //
401             $c->stash( $name ) // $c->param( $name ) //
402 33   100     455 $field->{data} // '';
      100        
      100        
      100        
      100        
403              
404 33   33     6991 my $id = $field->{id} // $name;
405 33 100       164 my %attrs = %{ $field->{attributes} || {} };
  33         262  
406              
407 33         408 return $c->text_field( $name, $value, id => $id, %attrs );
408             }
409              
410             sub _select {
411 38     38   145 my ($self, $c, $field, %params) = @_;
412              
413 38   33     171 my $name = $field->{name} // $field->{label} // '';
      0        
414              
415 38         104 my $from_stash_key = $params{from_stash};
416             my $from_stash = $from_stash_key ?
417 38 100       156 $c->stash( $from_stash_key )->{$name} :
418             undef;
419              
420 38   100     329 my $field_params = $params{$name} || {},
421              
422             my %select_params = (
423             disabled => $self->_get_highlighted_values( $field, 'disabled' ),
424             selected => $self->_get_highlighted_values( $field, 'selected' ),
425             );
426              
427 38         219 my $stash_values = $c->every_param( $name );
428 38 50 100     9188 if (scalar(@{ $stash_values || [] }) == 0 && defined( $c->stash( $name ))){
  38 100       372  
429 3         47 my $local_stash = $c->stash( $name );
430 3 100       41 $stash_values = ref $local_stash ? $local_stash : [ $local_stash ];
431             }
432              
433 38 100       549 if ( $from_stash ) {
434 1 50       7 $stash_values = ref $from_stash ? $from_stash : [ $from_stash ];
435             }
436              
437 38         82 my $reset;
438 38 50       78 if ( @{ $stash_values || [] } ) {
  38 100       207  
439 13         54 $select_params{selected} = $self->_get_highlighted_values(
440             +{ selected => $stash_values },
441             'selected',
442             );
443              
444 13         53 $reset = 1;
445             }
446              
447 38         139 for my $key ( qw/disabled selected/ ) {
448 76         203 my $hashref = $self->_get_highlighted_values( $field_params, $key );
449 76 100       204 if ( keys %{ $hashref } ) {
  76         312  
450 7         27 $select_params{$key} = $hashref;
451             }
452             }
453              
454 38 100       207 if ( $field_params->{data} ) {
455 5         10 $select_params{data} = $field_params->{data};
456             }
457              
458 38         202 my @values = $self->_get_select_values( $c, $field, %select_params );
459 38   33     279 my $id = $field->{id} // $name;
460 38 100       94 my %attrs = %{ $field->{attributes} || {} };
  38         266  
461              
462 38 100       169 if ( $field->{multiple} ) {
463 4         13 $attrs{multiple} = 'multiple';
464 4   50     22 $attrs{size} = $field->{size} || 5;
465             }
466              
467 38         101 my @selected = keys %{ $select_params{selected} };
  38         131  
468 38 100       132 if ( @selected ) {
469 18         35 my $single = scalar @selected;
470 18 100       71 my $param = $single == 1 ? $selected[0] : \@selected;
471 18         90 $c->param( $name, $param );
472             }
473              
474 38         721 my $select_field = $c->select_field( $name, [ @values ], id => $id, %attrs );
475              
476             # reset parameters
477 38 100       94500 if ( $reset ) {
478 13         144 my $single = scalar @{ $stash_values };
  13         42  
479 13 100       53 my $param = $single == 1 ? $stash_values->[0] : $stash_values;
480 13         52 $c->param( $name, $param );
481             }
482              
483 38         424 return $select_field;
484             }
485              
486             sub _get_highlighted_values {
487 386     386   912 my ($self, $field, $key) = @_;
488              
489 386 100       1466 return +{} if !$field->{$key};
490              
491 69         141 my %highlighted;
492              
493 69 100       311 if ( !ref $field->{$key} ) {
    50          
494 25         62 my $value = $field->{$key};
495 25         82 $highlighted{$value} = 1;
496             }
497             elsif ( 'ARRAY' eq ref $field->{$key} ) {
498 44         90 for my $value ( @{ $field->{$key} } ) {
  44         121  
499 52         164 $highlighted{$value} = 1;
500             }
501             }
502              
503 69         240 return \%highlighted;
504             }
505              
506             sub _get_select_values {
507 39     39   255 my ($self, $c, $field, %params) = @_;
508              
509 39   100     271 my $data = $params{data} || $field->{data} || [];
510 39 100       229 if ( $field->{data_cb} ) {
511 1         8 my @parts = split /::/, $field->{data_cb};
512 1         3 my $subname = pop @parts;
513 1         4 my $class = join '::', @parts;
514 1         13 my $sub = $class->can( $subname );
515 1 50       12 $data = $sub->() if $sub;
516             }
517              
518 39         168 my @values;
519 39 100       172 if ( 'ARRAY' eq ref $data ) {
    50          
520 35         170 @values = $self->_transform_array_values( $data, %params );
521             }
522             elsif( 'HASH' eq ref $data ) {
523 4         29 @values = $self->_transform_hash_values( $c, $data, %params );
524             }
525              
526 39         140 return @values;
527             }
528              
529             sub _transform_hash_values {
530 4     4   14 my ($self, $c, $data, %params) = @_;
531              
532 4         9 my @values;
533 4         47 my $numeric = 1;
534 4         9 my $counter = 0;
535 4         8 my %mapping;
536              
537             KEY:
538 4         7 for my $key ( keys %{ $data } ) {
  4         19  
539 7 100       24 if ( ref $data->{$key} ) {
540 1         6 my @group_values = $self->_get_select_values( $c, +{ data => $data->{$key} }, %params );
541 1         9 $values[$counter] = Mojo::Collection->new( $key => \@group_values );
542 1         10 $mapping{$key} = $counter;
543             }
544             else {
545 6         10 my %opts;
546              
547 6 50       17 $opts{disabled} = 'disabled' if $params{disabled}->{$key};
548 6 50       15 $opts{selected} = $selected_value if $params{selected}->{$key};
549             #$opts{selected} = undef if $params{selected}->{$key};
550              
551 6         29 $values[$counter] = [ $data->{$key} => $key, %opts ];
552 6         17 $mapping{$key} = $counter;
553             }
554              
555 7         23 $counter++;
556             }
557              
558 4 100   5   30 if ( first{ $_ =~ m{[^0-9]} }keys %mapping ) {
  5         25  
559 3         6 $numeric = 0;
560             }
561              
562             my @sorted_keys = $numeric ?
563 1         6 sort { $a <=> $b }keys %mapping :
564 4 100       41 sort { $a cmp $b }keys %mapping;
  2         12  
565              
566 4         14 my @indexes = @mapping{ @sorted_keys };
567              
568 4         10 my @sorted_values = @values[ @indexes ];
569              
570 4         15 return @sorted_values;
571             }
572              
573             sub _transform_array_values {
574 35     35   138 my ($self, $data, %params) = @_;
575              
576 35         92 my @values;
577 35         210 my $numeric = 1;
578              
579 35         68 for my $value ( @{ $data } ) {
  35         99  
580 93 100 66     465 if ( $numeric && $value =~ m{[^0-9]} ) {
581 35         83 $numeric = 0;
582             }
583              
584 93         154 my %opts;
585              
586 93 100       277 $opts{disabled} = 'disabled' if $params{disabled}->{$value};
587 93 100       316 $opts{selected} = $selected_value if $params{selected}->{$value};
588             #$opts{selected} = undef if $params{selected}->{$value};
589              
590 93         353 push @values, [ $value => $value, %opts ];
591             }
592              
593             @values = $numeric ?
594 0         0 sort{ $a->[0] <=> $b->[0] }@values :
595 35 50       275 sort{ $a->[0] cmp $b->[0] }@values;
  80         308  
596              
597 35         139 return @values;
598             }
599              
600             sub _radio {
601 25     25   85 my ($self, $c, $field, %params) = @_;
602              
603 25   33     128 my $name = $field->{name} // $field->{label} // '';
      0        
604 25   33     145 my $id = $field->{id} // $name;
605 25 100       77 my %attrs = %{ $field->{attributes} || {} };
  25         175  
606              
607 25   66     221 my $data = $params{$name}->{data} // $field->{data} // [];
      50        
608 25 100       122 my @values = ref $data ? @{ $data } : ($data);
  17         68  
609              
610 25   50     179 my $field_params = $params{$name} || {},
611              
612             my %select_params = (
613             disabled => $self->_get_highlighted_values( $field, 'disabled' ),
614             selected => $self->_get_highlighted_values( $field, 'selected' ),
615             );
616              
617 25         150 my $stash_values = $c->every_param( $name );
618 25 50 100     5048 if (scalar(@{ $stash_values || [] }) == 0 && defined( $c->stash( $name ))){
  25 100       289  
619 1         18 my $local_stash = $c->stash( $name );
620 1 50       19 $stash_values = ref $local_stash ? $local_stash : [ $local_stash ];
621             }
622 25         339 my $reset;
623 25 50       61 if ( @{ $stash_values || [] } ) {
  25 100       150  
624 4         16 $select_params{selected} = $self->_get_highlighted_values(
625             +{ selected => $stash_values },
626             'selected',
627             );
628 4         10 $reset = 1;
629             }
630              
631 25         86 for my $key ( qw/disabled selected/ ) {
632 50         170 my $hashref = $self->_get_highlighted_values( $field_params, $key );
633 50 100       123 if ( keys %{ $hashref } ) {
  50         212  
634 5         15 $select_params{$key} = $hashref;
635             }
636             }
637              
638 25         77 my @selected = keys %{ $select_params{selected} };
  25         158  
639 25 100       92 if ( @selected ) {
640 6         12 my $single = scalar @selected;
641 6 50       15 my $param = $single == 1 ? $selected[0] : \@selected;
642 6         24 $c->param( $name, $param );
643             }
644              
645 25         153 my $radiobuttons = '';
646 25         67 for my $radio_value ( @values ) {
647 42         101 my %value_attributes;
648              
649 42 100       152 if ( $select_params{disabled}->{$radio_value} ) {
650 3         7 $value_attributes{disabled} = 'disabled';
651             }
652              
653 42 100       279 if ( $select_params{selected}->{$radio_value} ) {
654 6         14 $value_attributes{checked} = $checked_value;
655             }
656              
657 42         163 my $local_label = '';
658 42 100       116 if ( $field->{show_value} ) {
659 4         8 $local_label = $radio_value;
660             }
661              
662 42         93 my $loc = $field->{translation_method};
663 42 50 100     171 if ( length $local_label && $field->{translate_sublabels} && $loc && 'CODE' eq ref $loc ) {
      66        
      66        
664 2         8 $local_label = $loc->($c, $local_label);
665             }
666              
667 42 100       134 $local_label = " " . $local_label if length $local_label;
668              
669 42         333 $radiobuttons .= $c->radio_button(
670             $name => $radio_value,
671             id => $id,
672             %attrs,
673             %value_attributes,
674             ) . "$local_label\n";
675              
676 42 100       68712 if ( defined $field->{after_element} ) {
677 2         8 $radiobuttons .= $field->{after_element};
678             }
679             }
680              
681 25 100       107 if ( $reset ) {
682 4         8 my $single = scalar @{ $stash_values };
  4         11  
683 4 50       16 my $param = $single == 1 ? $stash_values->[0] : $stash_values;
684 4         17 $c->param( $name, $param );
685             }
686              
687 25         192 return $radiobuttons;
688             }
689              
690             sub _checkbox {
691 28     28   117 my ($self, $c, $field, %params) = @_;
692              
693 28   33     136 my $name = $field->{name} // $field->{label} // '';
      0        
694 28   33     192 my $id = $field->{id} // $name;
695 28 100       73 my %attrs = %{ $field->{attributes} || {} };
  28         220  
696              
697 28   66     249 my $data = $params{$name}->{data} // $field->{data} // [];
      50        
698 28 100       124 my @values = ref $data ? @{ $data } : ($data);
  15         48  
699              
700 28   50     164 my $field_params = $params{$name} || {},
701              
702             my %select_params = (
703             disabled => $self->_get_highlighted_values( $field, 'disabled' ),
704             selected => $self->_get_highlighted_values( $field, 'selected' ),
705             );
706              
707 28         186 my $stash_values = $c->every_param( $name );
708 28 50 100     7106 if (scalar(@{ $stash_values || [] }) == 0 && defined( $c->stash( $name ))){
  28 100       287  
709 2         27 my $local_stash = $c->stash( $name );
710 2 100       21 $stash_values = ref $local_stash ? $local_stash : [ $local_stash ];
711             }
712 28         395 my $reset;
713 28 50       52 if ( @{ $stash_values || [] } ) {
  28 100       136  
714 5         20 $select_params{selected} = $self->_get_highlighted_values(
715             +{ selected => $stash_values },
716             'selected',
717             );
718 5         23 $c->param( $name, '' );
719 5         77 $reset = 1;
720             }
721              
722 28         112 for my $key ( qw/disabled selected/ ) {
723 56         175 my $hashref = $self->_get_highlighted_values( $field_params, $key );
724 56 100       98 if ( keys %{ $hashref } ) {
  56         248  
725 6         18 $select_params{$key} = $hashref;
726             }
727             }
728              
729 28         99 my @selected = keys %{ $select_params{selected} };
  28         192  
730 28 100       92 if ( @selected ) {
731 8         23 my $single = scalar @selected;
732 8 100       33 my $param = $single == 1 ? $selected[0] : \@selected;
733 8         28 $c->param( $name, $param );
734             }
735              
736 28         175 my $checkboxes = '';
737 28         71 for my $checkbox_value ( @values ) {
738 44         87 my %value_attributes;
739              
740 44 100       177 if ( $select_params{disabled}->{$checkbox_value} ) {
741 3         8 $value_attributes{disabled} = 'disabled';
742             }
743              
744 44 100       323 if ( $select_params{selected}->{$checkbox_value} ) {
745 9         29 $value_attributes{checked} = $checked_value;
746             }
747              
748 44         170 my $local_label = '';
749 44 100       143 if ( $field->{show_value} ) {
750 4         7 $local_label = $checkbox_value;
751             }
752              
753 44         90 my $loc = $field->{translation_method};
754 44 50 100     168 if ( length $local_label && $field->{translate_sublabels} && $loc && 'CODE' eq ref $loc ) {
      66        
      66        
755 2         11 $local_label = $loc->($c, $local_label);
756             }
757              
758 44 100       160 $local_label = " " . $local_label if length $local_label;
759              
760 44         410 $checkboxes .= $c->check_box(
761             $name => $checkbox_value,
762             id => $id,
763             %attrs,
764             %value_attributes,
765             ) . "$local_label\n";
766              
767 44 100       74728 if ( defined $field->{after_element} ) {
768 3         10 $checkboxes .= $field->{after_element};
769             }
770             }
771              
772 28 100       122 if ( $reset ) {
773 5         21 my $single = scalar @{ $stash_values };
  5         11  
774 5 100       19 my $param = $single == 1 ? $stash_values->[0] : $stash_values;
775 5         20 $c->param( $name, $param );
776             }
777              
778 28         215 return $checkboxes;
779             }
780              
781             sub _textarea {
782 8     8   38 my ($self, $c, $field, %params) = @_;
783              
784 8   33     78 my $name = $field->{name} // $field->{label} // '';
      0        
785 8   66     84 my $value = $params{$name}->{data} // $c->stash( $name ) // $c->param( $name ) // $field->{data} // '';
      100        
      100        
      100        
786 8   33     1311 my $id = $field->{id} // $name;
787 8 100       28 my %attrs = %{ $field->{attributes} || {} };
  8         73  
788              
789 8         86 return $c->text_area( $name, $value, id => $id, %attrs );
790             }
791              
792             sub _password {
793 6     6   30 my ($self, $c, $field, %params) = @_;
794              
795 6   33     49 my $name = $field->{name} // $field->{label} // '';
      0        
796 6   33     48 my $value = $params{$name}->{data} // $c->stash( $name ) // $c->param( $name ) // $field->{data} // '';
      66        
      66        
      50        
797 6   33     1031 my $id = $field->{id} // $name;
798 6 100       14 my %attrs = %{ $field->{attributes} || {} };
  6         55  
799              
800 6         59 return $c->password_field( $name, value => $value, id => $id, %attrs );
801             }
802              
803             1;
804              
805             __END__