File Coverage

blib/lib/Rose/HTML/Form/Field/Time.pm
Criterion Covered Total %
statement 44 50 88.0
branch 12 20 60.0
condition 14 24 58.3
subroutine 7 7 100.0
pod 2 2 100.0
total 79 103 76.7


line stmt bran cond sub pod time code
1             package Rose::HTML::Form::Field::Time;
2              
3 7     7   108056 use strict;
  7         28  
  7         243  
4              
5 7     7   542 use Rose::HTML::Object::Errors qw(:time);
  7         17  
  7         55  
6              
7 7     7   68 use base 'Rose::HTML::Form::Field::Text';
  7         31  
  7         1522  
8              
9             our $VERSION = '0.621';
10              
11             __PACKAGE__->add_required_html_attr(
12             {
13             size => 13,
14             });
15              
16             sub inflate_value
17             {
18 197     197 1 398 my($self, $time) = @_;
19              
20 7     7   63 no warnings; # undef time okay
  7         17  
  7         3838  
21 197 100       809 if($time =~ /^\s*(\d\d?)(?::(\d\d)(?::(\d\d))?)?\s*([ap]\.?m\.?)?\s*$/i)
22             {
23 43         132 my $hour = $1;
24 43   100     133 my $min = $2 || 0;
25 43   100     132 my $sec = $3 || 0;
26 43   50     145 my $ampm = $4 || '';
27              
28 43 50       93 if($ampm)
29             {
30 43         82 $ampm = uc($ampm);
31 43         108 $ampm =~ s/[^APM]//g;
32             }
33              
34 43 50       99 unless($ampm)
35             {
36 0 0       0 if($hour >= 12)
37             {
38 0 0       0 $hour -= 12 if($hour > 12);
39 0         0 $ampm = 'PM';
40             }
41 0         0 else { $ampm = 'AM' }
42             }
43              
44 43         305 return sprintf("%02d:%02d:%02d $ampm", $hour, $min, $sec);
45             }
46              
47 154         321 return $time;
48             }
49              
50             sub validate
51             {
52 7     7 1 20 my($self) = shift;
53              
54 7         32 my $ok = $self->SUPER::validate(@_);
55 7 50       21 return $ok unless($ok);
56              
57 7         22 my $time = $self->internal_value;
58              
59 7 100 66     53 return 1 unless ($time && $time =~ /\S/);
60              
61 5 100       23 unless($time =~ /^(\d\d):(\d\d):(\d\d) ([AP]M)$/)
62             {
63 2         22 $self->add_error_id(TIME_INVALID);
64 2         14 return 0;
65             }
66              
67 3         8 my $hour = $1;
68 3   50     10 my $min = $2 || 0;
69 3   50     22 my $sec = $3 || 0;
70 3   50     11 my $ampm = $4 || '';
71              
72 3 100 66     16 if($hour > 12 && $ampm)
73             {
74 1         6 $self->add_error_id(TIME_INVALID_AMPM);
75 1         6 return 0;
76             }
77              
78 2 50 33     14 if($hour > 12 || $min > 59 || $sec > 59)
      33        
79             {
80 0         0 $self->add_error_id(TIME_INVALID);
81 0         0 return 0;
82             }
83              
84 2         11 return 1;
85             }
86              
87             if(__PACKAGE__->localizer->auto_load_messages)
88             {
89             __PACKAGE__->localizer->load_all_messages;
90             }
91              
92 7     7   71 use utf8; # The __DATA__ section contains UTF-8 text
  7         16  
  7         48  
93              
94             1;
95              
96             __DATA__
97              
98             [% LOCALE en %]
99              
100             TIME_INVALID = "Invalid time."
101             TIME_INVALID_AMPM = "AM/PM only valid with hours less than 12."
102              
103             [% LOCALE de %]
104              
105             TIME_INVALID = "Ungültige Zeit."
106             TIME_INVALID_AMPM = "AM und PM nur gültig mit Stunden kleiner 12."
107              
108             [% LOCALE fr %]
109              
110             TIME_INVALID = "Heure invalide."
111             TIME_INVALID_AMPM = "AM/PM n'est possible que si l'heure est plus petite que 12."
112              
113             [% LOCALE bg %]
114              
115             TIME_INVALID = "Невалиден час."
116             TIME_INVALID_AMPM = "Използването на AM/PM е разрешено за часове не по-големи от 12."
117              
118             __END__
119              
120             =head1 NAME
121              
122             Rose::HTML::Form::Field::Time - Text field that accepts only valid times and coerces valid input into HH:MM:SS AM/PM format.
123              
124             =head1 SYNOPSIS
125              
126             $field =
127             Rose::HTML::Form::Field::Time->new(
128             label => 'Time',
129             name => 'time',
130             default => '8am');
131              
132             print $field->internal_value; # "08:00:00 PM"
133              
134             $field->input_value('13:00:00 PM');
135              
136             # "AM/PM only valid with hours less than 12"
137             $field->validate or warn $field->error;
138              
139             $field->input_value('blah');
140              
141             # "Invalid time"
142             $field->validate or warn $field->error;
143              
144             $field->input_value('6:30 a.m.');
145              
146             print $field->internal_value; # "06:30:00 AM"
147              
148             print $field->html;
149             ...
150              
151             =head1 DESCRIPTION
152              
153             L<Rose::HTML::Form::Field::Time> is a subclass of L<Rose::HTML::Form::Field::Text> that only allows values that are valid times, which it coerces into the form HH:MM:SS AM/PM. It overrides the L<validate()|Rose::HTML::Form::Field/validate> and L<inflate_value()|Rose::HTML::Form::Field/inflate_value> methods of its parent class.
154              
155             This is a good example of a custom field class that constrains the kinds of inputs that it accepts and coerces all valid input and output to a particular format.
156              
157             =head1 SEE ALSO
158              
159             Other examples of custom fields:
160              
161             =over 4
162              
163             =item L<Rose::HTML::Form::Field::Email>
164              
165             A text field that only accepts valid email addresses.
166              
167             =item L<Rose::HTML::Form::Field::DateTime>
168              
169             Uses inflate/deflate to convert input to a L<DateTime> object.
170              
171             =item L<Rose::HTML::Form::Field::DateTime::Range>
172              
173             A compound field whose internal value consists of more than one object.
174              
175             =item L<Rose::HTML::Form::Field::PhoneNumber::US::Split>
176              
177             A simple compound field that coalesces multiple subfields into a single value.
178              
179             =item L<Rose::HTML::Form::Field::DateTime::Split::MonthDayYear>
180              
181             A compound field that uses inflate/deflate convert input from multiple subfields into a L<DateTime> object.
182              
183             =item L<Rose::HTML::Form::Field::DateTime::Split::MDYHMS>
184              
185             A compound field that includes other compound fields and uses inflate/deflate convert input from multiple subfields into a L<DateTime> object.
186              
187             =back
188              
189             =head1 AUTHOR
190              
191             John C. Siracusa (siracusa@gmail.com)
192              
193             =head1 LICENSE
194              
195             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.