File Coverage

blib/lib/Rose/HTML/Form/Field/Set.pm
Criterion Covered Total %
statement 47 50 94.0
branch 20 24 83.3
condition n/a
subroutine 7 7 100.0
pod 3 3 100.0
total 77 84 91.6


line stmt bran cond sub pod time code
1             package Rose::HTML::Form::Field::Set;
2              
3 2     2   103341 use strict;
  2         15  
  2         79  
4              
5 2     2   432 use Rose::HTML::Object::Errors qw(:set);
  2         6  
  2         15  
6              
7 2     2   13 use base 'Rose::HTML::Form::Field::TextArea';
  2         13  
  2         1156  
8              
9             our $VERSION = '0.606';
10              
11             sub deflate_value
12             {
13 16     16 1 48 my($self, $list) = @_;
14              
15 16 100       51 my @list = $list ? @$list : (); # shallow copy
16              
17 16 100       47 return $self->input_value_filtered unless(ref $list eq 'ARRAY');
18              
19             return join(', ', map
20             {
21 15 100       32 if(/["\\\s,]/) # needs escaping
  60         155  
22             {
23 24         42 s/\\/\\\\/g; # escape backslashes
24 24         58 s/"/\\"/g; # escape double quotes
25 24         87 qq("$_") # double quote the whole thing
26             }
27 36         90 else { $_ }
28             }
29             @list);
30             }
31              
32             sub inflate_value
33             {
34 17     17 1 32 my($self, $value) = @_;
35              
36 17 100       45 return $value if(ref $value eq 'ARRAY');
37 12 100       24 return undef unless(defined $value);
38              
39 11         34 my @strings;
40              
41             # Extract comma- or whitespace-separated, possibly double-quoted strings
42 11         27 while(length $value)
43             {
44 41         144 $value =~ s/^(?:(?:\s*,\s*)+|\s+)//;
45              
46 41 100       84 last unless(length($value));
47              
48 37 100       166 if($value =~ s/^"((?:[^"\\]+|\\.)*)"//s)
    100          
49             {
50 17         42 my $string = $1;
51             # Interpolate backslash escapes
52 17         24 my $interpolated = $string;
53              
54 17         26 my $error;
55              
56             TRY:
57             {
58 17         21 local $@;
  17         28  
59 17         43 $interpolated =~ s/\\(.)/eval qq("\\$1")/ge;
  12         603  
60 17         37 $error = $@;
61             }
62              
63 17 50       37 if($error)
64             {
65 0         0 $self->add_error_id(SET_INVALID_QUOTED_STRING, { string => $string });
66 0         0 next;
67             }
68              
69 17         54 push(@strings, $interpolated);
70             }
71             elsif($value =~ s/^([^,"\s]+)//)
72             {
73 18         55 push(@strings, $1);
74             }
75             else
76             {
77 2 50       18 $self->error(SET_PARSE_ERROR, { context => (length($value) < 5) ? "...$value" :
78             '...' . substr($value, 0, 5) });
79 2         6 last;
80             }
81             }
82              
83 11         32 return \@strings;
84             }
85              
86             sub validate
87             {
88 1     1 1 3 my($self) = shift;
89              
90 1         6 my $ok = $self->SUPER::validate(@_);
91 1 50       5 return $ok unless($ok);
92              
93 1 50       8 return 0 if($self->has_errors);
94 0           return 1;
95             }
96              
97             if(__PACKAGE__->localizer->auto_load_messages)
98             {
99             __PACKAGE__->localizer->load_all_messages;
100             }
101              
102 2     2   17 use utf8; # The __DATA__ section contains UTF-8 text
  2         11  
  2         14  
103              
104             1;
105              
106             __DATA__
107              
108             [% LOCALE en %]
109              
110             SET_INVALID_QUOTED_STRING = "Invalid quoted string: \"[string]\"" # Testing parser "
111             SET_PARSE_ERROR = "Could not parse input: parse error at \[[context]\]"
112              
113             [% LOCALE de %]
114              
115             SET_INVALID_QUOTED_STRING = "Ungültig gequoteter String: \"[string]\""
116             SET_PARSE_ERROR = "Konnte Eingabe nicht parsen: Fehler bei \[[context]\]"
117              
118             [% LOCALE fr %]
119              
120             SET_INVALID_QUOTED_STRING = "Texte entre guillemets invalide: \"[string]\""
121             SET_PARSE_ERROR = "Impossible d'évaluer la saisie : erreur à \[[context]\]"
122              
123             [% LOCALE bg %]
124              
125             SET_INVALID_QUOTED_STRING = "Нeвалиден низ в кавички: \"[string]\""
126             SET_PARSE_ERROR = "Невъзможна обработка на въведените данни: грешка при \[[context]\]"
127              
128             __END__
129              
130             =head1 NAME
131              
132             Rose::HTML::Form::Field::Set - Text area that accepts whitespace- or comma-separated strings.
133              
134             =head1 SYNOPSIS
135              
136             $field =
137             Rose::HTML::Form::Field::Set->new(
138             label => 'States',
139             name => 'states',
140             default => 'NY NJ NM');
141              
142             $vals = $field->internal_value;
143              
144             print $vals->[1]; # "NJ"
145              
146             $field->input_value('NY, NJ, "New Mexico"');
147              
148             $vals = $field->internal_value;
149              
150             print $vals->[3]; # "New Mexico"
151              
152             $field->input_value([ 'New York', 'New Jersey' ]);
153              
154             print $field->internal_value->[0]; # "New York"
155              
156             ...
157              
158             =head1 DESCRIPTION
159              
160             L<Rose::HTML::Form::Field::Set> is a subclass of L<Rose::HTML::Form::Field::TextArea> that accepts whitespace- or comma-separated strings. Its internal value is a reference to an array of strings, or undef if the input value could not be parsed.
161              
162             Strings with spaces, double quotes, backslashes, or commas must be double-quoted. Use a backslash character "\" to escape double-quotes within double-quoted strings. Backslashed escapes in double-quoted strings are interpolated according to Perl's rules.
163              
164             =head1 AUTHOR
165              
166             John C. Siracusa (siracusa@gmail.com)
167              
168             =head1 LICENSE
169              
170             Copyright (c) 2010 by John C. Siracusa. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.