File Coverage

blib/lib/Rose/HTML/Form/Field/Time/Split/HourMinuteSecond.pm
Criterion Covered Total %
statement 39 39 100.0
branch 6 6 100.0
condition 11 13 84.6
subroutine 14 14 100.0
pod 6 6 100.0
total 76 78 97.4


line stmt bran cond sub pod time code
1             package Rose::HTML::Form::Field::Time::Split::HourMinuteSecond;
2              
3 6     6   107679 use strict;
  6         28  
  6         197  
4              
5 6     6   2823 use Rose::HTML::Form::Field::Time::Hours;
  6         17  
  6         41  
6 6     6   2904 use Rose::HTML::Form::Field::Time::Minutes;
  6         18  
  6         44  
7 6     6   2874 use Rose::HTML::Form::Field::Time::Seconds;
  6         18  
  6         42  
8 6     6   3168 use Rose::HTML::Form::Field::PopUpMenu;
  6         21  
  6         57  
9              
10 6     6   44 use base 'Rose::HTML::Form::Field::Time::Split';
  6         15  
  6         3036  
11              
12             our $VERSION = '0.606';
13              
14             sub build_field
15             {
16 21     21 1 78 my($self) = shift;
17              
18 21         443 $self->add_fields
19             (
20             hour =>
21             {
22             type => 'time hours',
23             size => 2,
24             maxlength => 2,
25             class => 'hour',
26             },
27              
28             minute =>
29             {
30             type => 'time minutes',
31             size => 2,
32             maxlength => 2,
33             class => 'minute',
34             },
35              
36             second =>
37             {
38             type => 'time seconds',
39             size => 2,
40             maxlength => 2,
41             class => 'second',
42             },
43              
44             ampm =>
45             {
46             type => 'pop-up menu',
47             choices => [ '', 'AM', 'PM' ],
48             class => 'ampm',
49             default => '',
50             },
51             );
52             }
53              
54             sub is_full
55             {
56 6     6   54 no warnings;
  6         16  
  6         1069  
57 324 100 100 324 1 890 return (length $_[0]->field('hour')->internal_value &&
58             length $_[0]->field('ampm')->internal_value) ? 1 : 0;
59             }
60              
61             sub decompose_value
62             {
63 176     176 1 374 my($self, $value) = @_;
64              
65 176 100       680 return undef unless(defined $value);
66              
67 19         71 my $time = $self->inflate_value($value);
68              
69 19 100       130 unless($time =~ /^(\d\d):(\d\d):(\d\d) ([AP]M)$/)
70             {
71 6     6   62 no warnings;
  6         13  
  6         2263  
72             return
73             {
74 2   100     41 hour => substr($value, 0, 2) || '',
      50        
      50        
75             minute => substr($value, 3, 2) || '',
76             second => substr($value, 6, 2) || '',
77             ampm => '',
78             }
79             }
80              
81             return
82             {
83 17         166 hour => $1,
84             minute => $2,
85             second => $3,
86             ampm => $4,
87             };
88             }
89              
90             sub coalesce_value
91             {
92 11     11 1 27 my($self) = shift;
93              
94             return
95 11   100     38 sprintf("%02d:%02d:%02d %s",
      100        
96             $self->field('hour')->internal_value,
97             $self->field('minute')->internal_value || 0,
98             $self->field('second')->internal_value || 0,
99             $self->field('ampm')->internal_value);
100             }
101              
102             sub html_field
103             {
104 9     9 1 590 my($self) = shift;
105              
106 9         34 return '<span class="time">' .
107             $self->field('hour')->html_field . ':' .
108             $self->field('minute')->html_field . ':' .
109             $self->field('second')->html_field .
110             $self->field('ampm')->html_field .
111             '</span>';
112             }
113              
114             sub xhtml_field
115             {
116 3     3 1 10 my($self) = shift;
117              
118 3         10 return '<span class="time">' .
119             $self->field('hour')->xhtml_field . ':' .
120             $self->field('minute')->xhtml_field . ':' .
121             $self->field('second')->xhtml_field .
122             $self->field('ampm')->xhtml_field .
123             '</span>';
124             }
125              
126             1;
127              
128             __END__
129              
130             =head1 NAME
131              
132             Rose::HTML::Form::Field::Time::Split::HourMinuteSecond - Compound field for times with separate text fields for hour, minute, and second, and a pop-up menu for selecting AM or PM.
133              
134             =head1 SYNOPSIS
135              
136             $field =
137             Rose::HTML::Form::Field::Time::Split::HourMinuteSecond->new(
138             label => 'Time',
139             name => 'time',
140             default => '8am');
141              
142             print $field->field('hour')->internal_value; # "08"
143              
144             $field->input_value('13:00:00 PM');
145              
146             # "AM/PM only valid with hours less than 12"
147             $field->validate or warn $field->error;
148              
149             $field->input_value('blah');
150              
151             # "Invalid time"
152             $field->validate or warn $field->error;
153              
154             $field->input_value('6:30 a.m.');
155              
156             print $field->internal_value; # "06:30:00 AM"
157              
158             print $field->html;
159             ...
160              
161             =head1 DESCRIPTION
162              
163             L<Rose::HTML::Form::Field::Time::Split::HourMinuteSecond> is a compound field for times with separate text fields for hour, minute, and second, and a pop-up menu for selecting AM or PM.
164              
165             This class inherits (indirectly) from both L<Rose::HTML::Form::Field::Time> and L<Rose::HTML::Form::Field::Compound>. This doesn't quite work out as expected without a bit of tweaking. We'd like L<inflate_value()|Rose::HTML::Form::Field/inflate_value> and L<validate()|Rose::HTML::Form::Field/validate> methods to be inherited from L<Rose::HTML::Form::Field::Time>, but everything else to be inherited from L<Rose::HTML::Form::Field::Compound>.
166              
167             To solve this problem, there's an intermediate class that imports the correct set of methods. This class then inherits from the intermediate class. To solve this problem, there's an intermediate class that imports the correct set of methods. This class then inherits from the intermediate class. This works, and isolates the tricky bits to a single intermediate class, but it also demonstrates the problems that can crop up when multiple inheritance is combined with a strong aversion to code duplication.
168              
169             A simpler example of a compound field can be found in L<Rose::HTML::Form::Field::PhoneNumber::US::Split>. It too uses multiple inheritance, but its family tree is more conveniently built, saving it from selective method importing shenanigans.
170              
171             This field also overrides the C<is_full()|Rose::HTML::Form::Field::Compound/is_full> method. A valid time can be extracted from the field as long as both the hour and AM/PM subfields are not empty. All other empty fields will be treated as if they contained zeros (00).
172              
173             It is important that this class (indirectly) inherits from L<Rose::HTML::Form::Field::Compound>. See the L<Rose::HTML::Form::Field::Compound> documentation for more information.
174              
175             =head1 AUTHOR
176              
177             John C. Siracusa (siracusa@gmail.com)
178              
179             =head1 LICENSE
180              
181             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.