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