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              
2             use strict;
3 6     6   85370  
  6         21  
  6         152  
4             use Rose::HTML::Form::Field::Time::Hours;
5 6     6   2249 use Rose::HTML::Form::Field::Time::Minutes;
  6         28  
  6         32  
6 6     6   2317 use Rose::HTML::Form::Field::Time::Seconds;
  6         16  
  6         33  
7 6     6   2270 use Rose::HTML::Form::Field::PopUpMenu;
  6         16  
  6         35  
8 6     6   2385  
  6         19  
  6         43  
9             use base 'Rose::HTML::Form::Field::Time::Split';
10 6     6   38  
  6         11  
  6         2398  
11             our $VERSION = '0.606';
12              
13             {
14             my($self) = shift;
15              
16 21     21 1 67 $self->add_fields
17             (
18 21         400 hour =>
19             {
20             type => 'time hours',
21             size => 2,
22             maxlength => 2,
23             class => 'hour',
24             },
25              
26             minute =>
27             {
28             type => 'time minutes',
29             size => 2,
30             maxlength => 2,
31             class => 'minute',
32             },
33              
34             second =>
35             {
36             type => 'time seconds',
37             size => 2,
38             maxlength => 2,
39             class => 'second',
40             },
41              
42             ampm =>
43             {
44             type => 'pop-up menu',
45             choices => [ '', 'AM', 'PM' ],
46             class => 'ampm',
47             default => '',
48             },
49             );
50             }
51              
52             {
53             no warnings;
54             return (length $_[0]->field('hour')->internal_value &&
55             length $_[0]->field('ampm')->internal_value) ? 1 : 0;
56 6     6   42 }
  6         11  
  6         895  
57 324 100 100 324 1 718  
58             {
59             my($self, $value) = @_;
60              
61             return undef unless(defined $value);
62              
63 176     176 1 290 my $time = $self->inflate_value($value);
64              
65 176 100       576 unless($time =~ /^(\d\d):(\d\d):(\d\d) ([AP]M)$/)
66             {
67 19         75 no warnings;
68             return
69 19 100       80 {
70             hour => substr($value, 0, 2) || '',
71 6     6   49 minute => substr($value, 3, 2) || '',
  6         20  
  6         1753  
72             second => substr($value, 6, 2) || '',
73             ampm => '',
74 2   100     29 }
      50        
      50        
75             }
76              
77             return
78             {
79             hour => $1,
80             minute => $2,
81             second => $3,
82             ampm => $4,
83 17         127 };
84             }
85              
86             {
87             my($self) = shift;
88              
89             return
90             sprintf("%02d:%02d:%02d %s",
91             $self->field('hour')->internal_value,
92 11     11 1 25 $self->field('minute')->internal_value || 0,
93             $self->field('second')->internal_value || 0,
94             $self->field('ampm')->internal_value);
95 11   100     36 }
      100        
96              
97             {
98             my($self) = shift;
99              
100             return '<span class="time">' .
101             $self->field('hour')->html_field . ':' .
102             $self->field('minute')->html_field . ':' .
103             $self->field('second')->html_field .
104 9     9 1 717 $self->field('ampm')->html_field .
105             '</span>';
106 9         25 }
107              
108             {
109             my($self) = shift;
110              
111             return '<span class="time">' .
112             $self->field('hour')->xhtml_field . ':' .
113             $self->field('minute')->xhtml_field . ':' .
114             $self->field('second')->xhtml_field .
115             $self->field('ampm')->xhtml_field .
116 3     3 1 7 '</span>';
117             }
118 3         9  
119             1;
120              
121              
122             =head1 NAME
123              
124             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.
125              
126             =head1 SYNOPSIS
127              
128             $field =
129             Rose::HTML::Form::Field::Time::Split::HourMinuteSecond->new(
130             label => 'Time',
131             name => 'time',
132             default => '8am');
133              
134             print $field->field('hour')->internal_value; # "08"
135              
136             $field->input_value('13:00:00 PM');
137              
138             # "AM/PM only valid with hours less than 12"
139             $field->validate or warn $field->error;
140              
141             $field->input_value('blah');
142              
143             # "Invalid time"
144             $field->validate or warn $field->error;
145              
146             $field->input_value('6:30 a.m.');
147              
148             print $field->internal_value; # "06:30:00 AM"
149              
150             print $field->html;
151             ...
152              
153             =head1 DESCRIPTION
154              
155             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.
156              
157             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>.
158              
159             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.
160              
161             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.
162              
163             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).
164              
165             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.
166              
167             =head1 AUTHOR
168              
169             John C. Siracusa (siracusa@gmail.com)
170              
171             =head1 LICENSE
172              
173             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.