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   110353 use strict;
  2         16  
  2         69  
4              
5 2     2   524 use Rose::HTML::Object::Errors qw(:set);
  2         4  
  2         14  
6              
7 2     2   14 use base 'Rose::HTML::Form::Field::TextArea';
  2         21  
  2         1103  
8              
9             our $VERSION = '0.606';
10              
11             sub deflate_value
12             {
13 16     16 1 35 my($self, $list) = @_;
14              
15 16 100       54 my @list = $list ? @$list : (); # shallow copy
16              
17 16 100       53 return $self->input_value_filtered unless(ref $list eq 'ARRAY');
18              
19             return join(', ', map
20             {
21 15 100       34 if(/["\\\s,]/) # needs escaping
  60         149  
22             {
23 24         54 s/\\/\\\\/g; # escape backslashes
24 24         53 s/"/\\"/g; # escape double quotes
25 24         102 qq("$_") # double quote the whole thing
26             }
27 36         97 else { $_ }
28             }
29             @list);
30             }
31              
32             sub inflate_value
33             {
34 17     17 1 37 my($self, $value) = @_;
35              
36 17 100       47 return $value if(ref $value eq 'ARRAY');
37 12 100       30 return undef unless(defined $value);
38              
39 11         22 my @strings;
40              
41             # Extract comma- or whitespace-separated, possibly double-quoted strings
42 11         25 while(length $value)
43             {
44 41         142 $value =~ s/^(?:(?:\s*,\s*)+|\s+)//;
45              
46 41 100       94 last unless(length($value));
47              
48 37 100       162 if($value =~ s/^"((?:[^"\\]+|\\.)*)"//s)
    100          
49             {
50 17         44 my $string = $1;
51             # Interpolate backslash escapes
52 17         29 my $interpolated = $string;
53              
54 17         24 my $error;
55              
56             TRY:
57             {
58 17         24 local $@;
  17         25  
59 17         44 $interpolated =~ s/\\(.)/eval qq("\\$1")/ge;
  12         595  
60 17         35 $error = $@;
61             }
62              
63 17 50       40 if($error)
64             {
65 0         0 $self->add_error_id(SET_INVALID_QUOTED_STRING, { string => $string });
66 0         0 next;
67             }
68              
69 17         55 push(@strings, $interpolated);
70             }
71             elsif($value =~ s/^([^,"\s]+)//)
72             {
73 18         56 push(@strings, $1);
74             }
75             else
76             {
77 2 50       19 $self->error(SET_PARSE_ERROR, { context => (length($value) < 5) ? "...$value" :
78             '...' . substr($value, 0, 5) });
79 2         6 last;
80             }
81             }
82              
83 11         34 return \@strings;
84             }
85              
86             sub validate
87             {
88 1     1 1 2 my($self) = shift;
89              
90 1         7 my $ok = $self->SUPER::validate(@_);
91 1 50       4 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         4  
  2         11  
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.