File Coverage

blib/lib/Calendar/Model.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package Calendar::Model;
2 1     1   22844 use strict;
  1         2  
  1         54  
3              
4             =head1 NAME
5              
6             Calendar::Model - Simple class modelling Calendars
7              
8             =head1 VERSION
9              
10             Version 0.04
11              
12             =cut
13              
14             our $VERSION = '0.04';
15              
16             =head1 SYNOPSIS
17              
18             use Calendar::Model;
19              
20             my $cal = Calendar::Model->new();
21              
22             my $columns = $cal->columns;
23              
24             my $rows = $cal->rows;
25              
26             my $dates = $cal->as_list;
27              
28             my $start_date = $cal->start_date;
29              
30             my $selected_date = $cal->selected_date
31              
32             my $month = $cal->month; # 3
33              
34             my $year = $cal->year; # 1992
35              
36             my $next_month = $cal->next_month; # 4
37              
38             my $prev_month = $cal->previous_month; # 2
39              
40             my $month_name = $cal->month_name; # March
41              
42             my $next_month_name = $cal->month_name('next'); # April
43              
44             my $day = $cal->get_day($dt);
45              
46             my $events = $schema->resultset('events')->search( date => { between => [$cal->start_date->dmy,$cal->last_entry_day->dmy] });
47              
48              
49             =head1 DESCRIPTION
50              
51             A simple Model layer providing Classes representing A Calendar containing rows and days
52              
53             =cut
54              
55 1     1   858 use POSIX qw(locale_h);
  1         6439  
  1         7  
56 1         296 use I18N::Langinfo qw(langinfo DAY_1 DAY_2 DAY_3 DAY_4 DAY_5 DAY_6 DAY_7
57             MON_1 MON_2 MON_3 MON_4 MON_5 MON_6
58 1     1   4905 MON_7 MON_8 MON_9 MON_10 MON_11 MON_12);
  1         2094  
59 1     1   5355 use DateTime;
  1         296838  
  1         128  
60 1     1   15 use DateTime::Duration;
  1         2  
  1         22  
61 1     1   1781 use Calendar::List;
  1         77886  
  1         87  
62              
63 1     1   1757 use Calendar::Model::Day;
  0            
  0            
64              
65             use Data::Dumper;
66              
67             use Moose;
68             with 'MooseX::Role::Pluggable';
69             use namespace::autoclean;
70              
71              
72             =head1 ATTRIBUTES
73              
74             =over 4
75              
76             =item columns
77              
78             =item rows
79              
80             =item month
81              
82             =item LANG
83              
84             =item next_month
85              
86             =item previous_month
87              
88             =item year
89              
90             =item next_year
91              
92             =item previous_year
93              
94             =item seleted_date
95              
96             =item days_of_week
97              
98             =item months_of_year
99              
100             =back
101              
102             =cut
103              
104             has 'columns' => (
105             is => 'ro',
106             isa => 'ArrayRef',
107             init_arg => undef,
108             writer => '_columns'
109             );
110              
111             has 'rows' => (
112             is => 'ro',
113             isa => 'ArrayRef',
114             init_arg => undef,
115             writer => '_rows',
116             );
117              
118             has 'month' => (
119             is => 'ro',
120             isa => 'Int',
121             writer => '_month',
122             );
123              
124             has 'LANG' => (
125             is => 'ro',
126             isa => 'Str',
127             default => 'EN-GB',
128             );
129              
130             has 'next_month' => (
131             is => 'ro',
132             isa => 'Str',
133             init_arg => undef,
134             writer => '_next_month',
135             );
136              
137             has 'previous_month' => (
138             is => 'ro',
139             isa => 'Str',
140             init_arg => undef,
141             writer => '_previous_month',
142             );
143              
144             has 'year' => (
145             is => 'ro',
146             isa => 'Int',
147             writer => '_year',
148             );
149              
150             has 'next_year' => (
151             is => 'ro',
152             isa => 'Str',
153             init_arg => undef,
154             writer => '_next_year',
155             );
156              
157             has 'previous_year' => (
158             is => 'ro',
159             isa => 'Str',
160             init_arg => undef,
161             writer => '_previous_year',
162             );
163              
164             # has 'start_date' => (
165             # is => 'ro',
166             # isa => 'DateTime'
167             # );
168              
169             has 'selected_date' => (
170             is => 'ro',
171             isa => 'DateTime',
172             writer => '_selected_date',
173             );
174              
175             has 'first_entry_day' => (
176             is => 'ro',
177             isa => 'DateTime',
178             init_arg => undef,
179             writer => '_first_entry_day',
180             );
181              
182             has '_last_entry_day' => (
183             is => 'ro',
184             isa => 'DateTime',
185             init_arg => undef,
186             writer => '_set_last_entry_day',
187             );
188              
189              
190             has 'days_of_week' => (
191             is => 'ro',
192             isa => 'ArrayRef',
193             init_arg => undef,
194             writer => '_days_of_week',
195             );
196              
197             has 'months_of_year' => (
198             is => 'ro',
199             isa => 'ArrayRef',
200             init_arg => undef,
201             writer => '_months_of_year',
202             );
203              
204              
205             =head1 METHODS
206              
207             =head2 new
208              
209             Class constructor method, returns a Calendar::Model object based on the arguments :
210              
211             =over 4
212              
213             =item selected_date - optional, defaults to current local/system date, otherwise provide a DateTime object
214              
215             =item window - optional, defaults to current month + next/previous days to complete calendar rows,
216             otherwise provide number of days before selected date to show at start.
217              
218             =back
219              
220             =head2 BUILD
221              
222             Std Moose initialisation hook called by constructor method
223              
224             =cut
225              
226             sub BUILD {
227             my $self = shift;
228             my $args = shift;
229              
230             # get selected date, month, year
231             my $selected_date = $self->selected_date;
232             my $dd;
233             if ($self->month && $self->year) {
234             $selected_date ||= DateTime->new(year => $self->year, month => $self->month, day => 1);
235             $dd = 1 unless ($selected_date->month == $self->month and $selected_date->year == $self->year );
236             } else {
237             $selected_date ||= DateTime->now();
238             $self->_month($selected_date->month);
239             $self->_year($selected_date->year);
240             $dd = $selected_date->day;
241             }
242             $self->_selected_date($selected_date) unless ($self->selected_date);
243              
244             # get first entry
245             my $first_month_day = $selected_date->clone;
246             unless ($dd == 1) {
247             $first_month_day = DateTime->new(year => $self->year, month => $self->month, day => 1);
248             }
249             my $first_entry_day = $first_month_day->clone;
250             unless ($first_month_day->wday == 7) {
251             $first_entry_day->subtract(days => $first_month_day->wday);
252             }
253             $self->_first_entry_day($first_entry_day);
254              
255             # get next/prev month and year
256             $self->{previous_month} = ($self->month == 1) ? 12 : $self->month - 1;
257             $self->{next_month} = ($self->month == 12) ? 1 : $self->month + 1;
258             $self->{previous_year} = ($self->previous_month == 12) ? $self->year - 1 : $self->year;
259             $self->{next_year} = ($self->next_month == 1)? $self->year + 1 : $self->year;
260              
261             $self->_translate_days_months;
262              
263             # my $day_plugins = [];
264             # foreach my $plugin ( @{ $self->plugin_list } ) {
265             # $plugin->init() if ( $plugin->can( 'init' ));
266             # }
267              
268             return;
269             }
270              
271             =head2 weeks
272              
273             Object method (lazily) builds and returns rows of Calendar::Model::Day objects, 1 for each week.
274              
275             =cut
276              
277             sub weeks {
278             my $self = shift;
279              
280             unless ($self->rows) {
281             # build rows of days
282             my $day_plugins = [];
283             # foreach my $plugin ( @{ $self->plugin_list } ) {
284             # push if ( $plugin->can( 'init' ));
285             # }
286              
287             my $dow = 1;
288             $self->{rows} = [[
289             map { Calendar::Model::Day->new({ dmy => $_, dow_name => $self->days_of_week->[$dow], day_of_week => $dow++, }) }
290             calendar_list('DD-MM-YYYY',{start => $self->first_entry_day->dmy, "options" => 7})
291             ]];
292             foreach (1..4) {
293             $dow = 1;
294             my $last_day = $self->{rows}->[-1][-1];
295             my (undef,@days) = calendar_list('DD-MM-YYYY',{start => $last_day->dmy, "options" => 8} );
296             push (
297             @{$self->{rows}},
298             [ map { Calendar::Model::Day->new({ dmy => $_, dow_name => $self->days_of_week->[$dow],
299             day_of_week => $dow++, }) } @days ]
300             );
301             }
302             }
303             # natatime is iterator accessor for ArrayRef accessor in moose - built in, would be nice to wrap it
304             return $self->rows;
305             }
306              
307             =head2 as_list
308              
309             Object method returns all Calendar::Model::Day objects for calendar
310              
311             =cut
312              
313             sub as_list {
314             my $self = shift;
315             return [ map { @$_ } @{$self->weeks} ];
316             }
317              
318             =head2 month_name
319              
320             Object method, returns name of current/selected month or takes a string indicating whether to show 'next' or 'previous' month.
321              
322             my $month_name = $cal->month_name; # March
323              
324             my $next_month_name = $cal->month_name('next'); # April
325              
326              
327             =cut
328              
329             sub month_name {
330             my ($self, $delta) = @_;
331             my $monthname;
332             if ($delta) {
333             if ($delta eq 'next') {
334             $monthname = $self->months_of_year()->[$self->next_month];
335             } elsif ($delta eq 'previous') {
336             $monthname = $self->months_of_year()->[$self->previous_month];
337             } else {
338             die 'unrecognised month delta - needs to be undef, next or previous';
339             }
340             } else {
341             $monthname = $self->months_of_year()->[$self->month];
342             }
343             return $monthname;
344             }
345              
346             =head2 last_entry_day
347              
348             Get last day in calendar as a DateTime object
349              
350             =cut
351              
352             sub last_entry_day {
353             my $self = shift;
354              
355             my $last_day = $self->weeks->[-1][-1];
356              
357             $self->_set_last_entry_day($last_day->to_DateTime);
358              
359             return $self->_last_entry_day;
360             }
361              
362             =head2 get_day
363              
364             Get given day from Calendar, takes a DateTime object, returns a Calendar::Modal::Day object
365              
366             =cut
367              
368             sub get_day {
369             my ($self, $match) = @_;
370              
371             # get delta to start date in days
372             my $delta = $self->first_entry_day->delta_days( $match );
373             my ($w, $d) = $delta->in_units( 'weeks', 'days' );
374             # get delta-nth day from appropriate list
375              
376             my $last_day = $self->weeks->[$w][$d];
377             }
378              
379             ###
380              
381             sub _translate_days_months {
382             my $self = shift;
383              
384             # query and save the old locale
385             my $old_locale = POSIX::setlocale( &POSIX::LC_ALL);
386              
387             # set local from obj language
388             POSIX::setlocale( &POSIX::LC_ALL,$self->{LANG});
389             $self->_days_of_week([ undef, map { langinfo($_) } (DAY_1, DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7) ]);
390             $self->_months_of_year([ undef, map { langinfo($_) } (MON_1, MON_2, MON_3, MON_4, MON_5, MON_6,
391             MON_7, MON_8, MON_9, MON_10, MON_11, MON_12) ]);
392              
393             $self->_columns([@{$self->days_of_week}[1,2,3,4,5,6,7]]);
394              
395             # restore the old locale
396             setlocale(LC_CTYPE, $old_locale);
397             return;
398             }
399              
400              
401             no Moose;
402             __PACKAGE__->meta->make_immutable;
403              
404             =head1 AUTHOR
405              
406             Aaron Trevena, C<< <teejay at cpan.org> >>
407              
408             =head1 BUGS
409              
410             Please report any bugs or feature requests to C<bug-calendar-model at rt.cpan.org>, or through
411             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Calendar-Model>. I will be notified, and then you'll
412             automatically be notified of progress on your bug as I make changes.
413              
414             =head1 SUPPORT
415              
416             You can find documentation for this module with the perldoc command.
417              
418             perldoc Calendar::Model
419              
420              
421             You can also look for information at:
422              
423             =over 4
424              
425             =item * RT: CPAN's request tracker (report bugs here)
426              
427             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Calendar-Model>
428              
429             =item * AnnoCPAN: Annotated CPAN documentation
430              
431             L<http://annocpan.org/dist/Calendar-Model>
432              
433             =item * CPAN Ratings
434              
435             L<http://cpanratings.perl.org/d/Calendar-Model>
436              
437             =item * Search CPAN
438              
439             L<http://search.cpan.org/dist/Calendar-Model/>
440              
441             =back
442              
443             =head1 ACKNOWLEDGEMENTS
444              
445              
446             =head1 LICENSE AND COPYRIGHT
447              
448             Copyright 2012 Aaron Trevena.
449              
450             This program is free software; you can redistribute it and/or modify it
451             under the terms of either: the GNU General Public License as published
452             by the Free Software Foundation; or the Artistic License.
453              
454             See L<http://dev.perl.org/licenses/> for more information.
455              
456             =cut
457              
458             1;