File Coverage

blib/lib/Rose/HTML/Form/Field/DateTime/Split/MonthDayYear.pm
Criterion Covered Total %
statement 44 44 100.0
branch 11 12 91.6
condition 5 6 83.3
subroutine 13 13 100.0
pod 7 7 100.0
total 80 82 97.5


line stmt bran cond sub pod time code
1              
2             use strict;
3 5     5   119422  
  5         18  
  5         127  
4             use Rose::DateTime::Util();
5 5     5   2174  
  5         1857770  
  5         130  
6             use Rose::HTML::Object::Messages qw(:date);
7 5     5   490  
  5         11  
  5         41  
8             use base 'Rose::HTML::Form::Field::DateTime::Split';
9 5     5   30  
  5         12  
  5         2380  
10             our $VERSION = '0.606';
11              
12             {
13             my($self) = shift;
14              
15 42     42 1 101 $self->add_fields
16             (
17 42         800 month =>
18             {
19             type => 'text',
20             size => 2,
21             maxlength => 2,
22             class => 'month',
23             label_id => FIELD_LABEL_MONTH,
24             error_label_id => FIELD_ERROR_LABEL_MONTH,
25             },
26              
27             day =>
28             {
29             type => 'text',
30             size => 2,
31             maxlength => 2,
32             class => 'day',
33             label_id => FIELD_LABEL_DAY,
34             error_label_id => FIELD_ERROR_LABEL_DAY,
35             },
36              
37             year =>
38             {
39             type => 'text',
40             size => 4,
41             maxlength => 4,
42             class => 'year',
43             label_id => FIELD_LABEL_YEAR,
44             error_label_id => FIELD_ERROR_LABEL_YEAR,
45             },
46             );
47             }
48              
49             {
50             my($self, $value) = @_;
51              
52             return undef unless(defined $value);
53 339     339 1 590  
54             my $date = $self->SUPER::inflate_value($value);
55 339 100       1034  
56             unless($date)
57 37         133 {
58             no warnings;
59 37 100       106 my($month, $day, $year) = split('/', $value);
60              
61 5     5   34 return
  5         10  
  5         2025  
62 3         15 {
63             month => $month || '',
64             day => $day || '',
65             year => $year || '',
66 3   50     33 }
      100        
      100        
67             }
68              
69             my($month, $day, $year) = Rose::DateTime::Util::format_date($date, '%m', '%d', '%Y');
70              
71             return
72 34         229 {
73             month => $month,
74             day => $day,
75             year => $year,
76 34         4226 };
77             }
78              
79             {
80             my($self) = shift;
81              
82             my $count = grep { defined && length }
83             map { $self->field($_)->internal_value } qw(month day year);
84 590     590 1 867  
85             return $count == 3 ? 1 : 0;
86 1770 100       5125 }
87 590         911  
  1770         5653  
88             {
89 590 100       1585 my($self) = shift;
90             return join('/', map { defined($_) ? $_ : '' }
91             map { $self->field($_)->internal_value } qw(month day year));
92             }
93              
94 25     25 1 61 {
95 75 50       255 my($self, $date) = @_;
96 25         59 return $self->input_value_filtered unless($date);
  75         166  
97             return Rose::DateTime::Util::format_date($date, '%m/%d/%Y');
98             }
99              
100             {
101 15     15 1 38 my($self) = shift;
102 15 100       57  
103 12         102 return '<span class="date">' .
104             $self->field('month')->html_field . '/' .
105             $self->field('day')->html_field . '/' .
106             $self->field('year')->html_field .
107             '</span>';
108 12     12 1 1054 }
109              
110 12         33 {
111             my($self) = shift;
112              
113             return '<span class="date">' .
114             $self->field('month')->xhtml_field . '/' .
115             $self->field('day')->xhtml_field . '/' .
116             $self->field('year')->xhtml_field .
117             '</span>';
118             }
119 4     4 1 10  
120             if(__PACKAGE__->localizer->auto_load_messages)
121 4         14 {
122             __PACKAGE__->localizer->load_all_messages;
123             }
124              
125             use utf8; # The __DATA__ section contains UTF-8 text
126              
127             1;
128              
129              
130             [% LOCALE en %]
131              
132             FIELD_LABEL_MONTH = "Month"
133 5     5   34 FIELD_LABEL_DAY = "Day"
  5         9  
  5         35  
134             FIELD_LABEL_YEAR = "Year"
135              
136             FIELD_ERROR_LABEL_MONTH = "month"
137             FIELD_ERROR_LABEL_DAY = "day"
138             FIELD_ERROR_LABEL_YEAR = "year"
139              
140             [% LOCALE de %]
141              
142             FIELD_LABEL_MONTH = "Monat"
143             FIELD_LABEL_DAY = "Tag"
144             FIELD_LABEL_YEAR = "Jahr"
145              
146             FIELD_ERROR_LABEL_MONTH = "Monat"
147             FIELD_ERROR_LABEL_DAY = "Tag"
148             FIELD_ERROR_LABEL_YEAR = "Jahr"
149              
150             [% LOCALE fr %]
151              
152             FIELD_LABEL_MONTH = "Mois"
153             FIELD_LABEL_DAY = "Jour"
154             FIELD_LABEL_YEAR = "Année"
155              
156             FIELD_ERROR_LABEL_MONTH = "mois"
157             FIELD_ERROR_LABEL_DAY = "jour"
158             FIELD_ERROR_LABEL_YEAR = "année"
159              
160             [% LOCALE bg %]
161              
162             FIELD_LABEL_MONTH = "Месец"
163             FIELD_LABEL_DAY = "Ден"
164             FIELD_LABEL_YEAR = "Година"
165              
166             FIELD_ERROR_LABEL_MONTH = "месец"
167             FIELD_ERROR_LABEL_DAY = "ден"
168             FIELD_ERROR_LABEL_YEAR = "година"
169              
170             __END__
171              
172             =head1 NAME
173              
174             Rose::HTML::Form::Field::DateTime::Split::MonthDayYear - Compound field for dates with separate text fields for month, day, and year.
175              
176             =head1 SYNOPSIS
177              
178             $field =
179             Rose::HTML::Form::Field::DateTime::Split::MonthDayYear->new(
180             label => 'Date',
181             name => 'date',
182             default => '12/31/2002');
183              
184             print $field->field('month')->internal_value; # "12"
185              
186             print $field->internal_value; # "2002-12-31T20:00:00"
187             print $field->output_value; # "2002-12-31 08:00:00 PM"
188              
189             $field->input_value('blah');
190              
191             # "Could not parse date: blah"
192             $field->validate or warn $field->error;
193              
194             $field->input_value('4/30/1980');
195              
196             $dt = $field->internal_value; # DateTime object
197              
198             print $dt->hour; # 17
199             print $dt->day_name; # Wednesday
200              
201             print $field->html;
202             ...
203              
204             =head1 DESCRIPTION
205              
206             L<Rose::HTML::Form::Field::DateTime::Split::MonthDayYear> a compound field for dates with separate text fields for month, day, and year.
207              
208             This class inherits (indirectly) from both L<Rose::HTML::Form::Field::DateTime> 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::DateTime>, but everything else to be inherited from L<Rose::HTML::Form::Field::Compound>.
209              
210             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.
211              
212             Inheritence shenanigans aside, this class is a good example of a compound field that also provides an "inflated" internal value (a L<DateTime> object).
213              
214             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.
215              
216             =head1 OBJECT METHODS
217              
218             =over 4
219              
220             =item B<date_parser [PARSER]>
221              
222             Get or set the date parser object. This object must include a C<parse_datetime()> method that takes a single string as an argument and returns a L<DateTime> object, or undef if parsing fails.
223              
224             If the parser object has an C<error()> method, it will be called to set the error message after a failed parsing attempt.
225              
226             The parser object defaults to L<Rose::DateTime::Parser-E<gt>new()|Rose::DateTime::Parser/new>.
227              
228             =item B<time_zone [TZ]>
229              
230             If the parser object has a L<time_zone()|/time_zone> method, this method simply calls it, passing all arguments. Otherwise, undef is returned.
231              
232             =back
233              
234             =head1 SEE ALSO
235              
236             Other examples of custom fields:
237              
238             =over 4
239              
240             =item L<Rose::HTML::Form::Field::Email>
241              
242             A text field that only accepts valid email addresses.
243              
244             =item L<Rose::HTML::Form::Field::Time>
245              
246             Uses inflate/deflate to coerce input into a fixed format.
247              
248             =item L<Rose::HTML::Form::Field::DateTime>
249              
250             Uses inflate/deflate to convert input to a L<DateTime> object.
251              
252             =item L<Rose::HTML::Form::Field::DateTime::Range>
253              
254             A compound field whose internal value consists of more than one object.
255              
256             =item L<Rose::HTML::Form::Field::PhoneNumber::US::Split>
257              
258             A simple compound field that coalesces multiple subfields into a single value.
259              
260             =item L<Rose::HTML::Form::Field::DateTime::Split::MDYHMS>
261              
262             A compound field that includes other compound fields and uses inflate/deflate convert input from multiple subfields into a L<DateTime> object.
263              
264             =back
265              
266             =head1 AUTHOR
267              
268             John C. Siracusa (siracusa@gmail.com)
269              
270             =head1 LICENSE
271              
272             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.