File Coverage

blib/lib/Date/Lectionary/Daily.pm
Criterion Covered Total %
statement 18 20 90.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 25 27 92.5


line stmt bran cond sub pod time code
1             package Date::Lectionary::Daily;
2              
3 1     1   48203 use v5.22;
  1         3  
4 1     1   5 use strict;
  1         1  
  1         16  
5 1     1   4 use warnings;
  1         5  
  1         26  
6              
7 1     1   516 use Moose;
  1         394875  
  1         6  
8 1     1   6294 use Carp;
  1         2  
  1         72  
9 1     1   7 use Try::Tiny;
  1         2  
  1         44  
10 1     1   276 use XML::LibXML;
  0            
  0            
11             use File::Share ':all';
12             use Time::Piece;
13             use Date::Lectionary::Time qw(isSunday prevSunday);
14             use Date::Lectionary::Day;
15             use namespace::autoclean;
16             use Moose::Util::TypeConstraints;
17              
18             =head1 NAME
19              
20             Date::Lectionary::Daily - Daily Readings for the Christian Lectionary
21              
22             =head1 VERSION
23              
24             Version 1.20170703
25              
26             =cut
27              
28             =head1 SYNOPSIS
29              
30             use Time::Piece;
31             use Date::Lectionary::Daily;
32              
33             my $dailyReading = Date::Lectionary::Daily->new('date' => Time::Piece->strptime("2017-12-24", "%Y-%m-%d"));
34             say $dailyReading->readings->{evening}->{1}; #First lesson for evening prayer
35              
36             =head1 DESCRIPTION
37              
38             Date::Lectionary::Daily takes a Time::Piece date and returns ACNA readings for morning and evening prayer for that date.
39              
40             =cut
41              
42             our $VERSION = '1.20170703';
43              
44             enum 'LectionaryType', [qw(acna)];
45             no Moose::Util::TypeConstraints;
46              
47             =head1 SUBROUTINES/METHODS
48              
49             =cut
50              
51             has 'date' => (
52             is => 'ro',
53             isa => 'Time::Piece',
54             required => 1,
55             );
56              
57             has 'week' => (
58             is => 'ro',
59             isa => 'Str',
60             writer => '_setWeek',
61             init_arg => undef,
62             );
63              
64             has 'day' => (
65             is => 'ro',
66             isa => 'Str',
67             writer => '_setDay',
68             init_arg => undef,
69             );
70              
71             has 'lectionary' => (
72             is => 'ro',
73             isa => 'LectionaryType',
74             default => 'acna',
75             );
76              
77             has 'readings' => (
78             is => 'ro',
79             isa => 'HashRef',
80             writer => '_setReadings',
81             init_arg => undef,
82             );
83              
84             =head2 BUILD
85              
86             Constructor for the Date::Lectionary object. Takes a Time::Piect object, C<date>, to create the object.
87              
88             =cut
89              
90             sub BUILD {
91             my $self = shift;
92              
93             my $sunday;
94             if ( isSunday( $self->date ) ) {
95             $sunday = $self->date;
96             }
97             else {
98             $sunday = prevSunday( $self->date );
99             }
100              
101             my $fixedHolyDay = 0;
102             if ( $self->date->mon == 1 || $self->date->mon == 12 ) {
103             $fixedHolyDay = _checkFixed( $self->date, $self->lectionary );
104             }
105              
106             $self->_setWeek(
107             Date::Lectionary::Day->new(
108             'date' => $sunday,
109             'lectionary' => $self->lectionary
110             )->name
111             );
112              
113             if ($fixedHolyDay) {
114             $self->_setReadings(
115             _buildReadings(
116             "Fixed Holy Days",
117             $self->date->fullmonth . " " . $self->date->mday,
118             $self->lectionary
119             )
120             );
121             }
122             else {
123             $self->_setReadings(
124             _buildReadings(
125             $self->week, $self->date->fullday, $self->lectionary
126             )
127             );
128             }
129             }
130              
131             =head2 _parseLectDB
132              
133             Private method to open and parse the lectionary XML to be used by other methods to XPATH queries.
134              
135             =cut
136              
137             sub _parseLectDB {
138             my $lectionary = shift;
139              
140             my $parser = XML::LibXML->new();
141             my $lectDB;
142              
143             try {
144             my $data_location = dist_file( 'Date-Lectionary-Daily',
145             $lectionary . '_lect_daily.xml' );
146             $lectDB = $parser->parse_file($data_location);
147             }
148             catch {
149             carp
150             "The readings database for the $lectionary daily lectionary could not be found or parsed.";
151             };
152              
153             return $lectDB;
154             }
155              
156             =head2 _checkFixed
157              
158             Private method to determine if the day given is a fixed holiday rather than a standard day.
159              
160             =cut
161              
162             sub _checkFixed {
163             my $date = shift;
164             my $lectionary = shift;
165              
166             my $searchDate = $date->fullmonth . " " . $date->mday;
167              
168             my $lectDB = _parseLectDB($lectionary);
169              
170             my $fixed_xpath
171             = XML::LibXML::XPathExpression->new(
172             "/daily-lectionary/week[\@name=\"Fixed Holy Days\"]/day[\@name=\"$searchDate\"]/lesson"
173             );
174              
175             if ( $lectDB->exists($fixed_xpath) ) {
176             return 1;
177             }
178              
179             return 0;
180             }
181              
182             =head2 _buildReadings
183              
184             Private method that returns an ArrayRef of strings for the lectionary readings associated with the date.
185              
186             =cut
187              
188             sub _buildReadings {
189             my $weekName = shift;
190             my $weekDay = shift;
191             my $lectionary = shift;
192              
193             my $readings = _parseLectDB($lectionary);
194              
195             my $morn1_xpath
196             = XML::LibXML::XPathExpression->new(
197             "/daily-lectionary/week[\@name=\"$weekName\"]/day[\@name=\"$weekDay\"]/lesson[\@service=\"morning\" and \@order=\"1\"]"
198             );
199             my $morn2_xpath
200             = XML::LibXML::XPathExpression->new(
201             "/daily-lectionary/week[\@name=\"$weekName\"]/day[\@name=\"$weekDay\"]/lesson[\@service=\"morning\" and \@order=\"2\"]"
202             );
203             my $eve1_xpath
204             = XML::LibXML::XPathExpression->new(
205             "/daily-lectionary/week[\@name=\"$weekName\"]/day[\@name=\"$weekDay\"]/lesson[\@service=\"evening\" and \@order=\"1\"]"
206             );
207             my $eve2_xpath
208             = XML::LibXML::XPathExpression->new(
209             "/daily-lectionary/week[\@name=\"$weekName\"]/day[\@name=\"$weekDay\"]/lesson[\@service=\"evening\" and \@order=\"2\"]"
210             );
211              
212             my %readings = (
213             morning => {
214             1 => $readings->find($morn1_xpath)->string_value(),
215             2 => $readings->find($morn2_xpath)->string_value()
216             },
217             evening => {
218             1 => $readings->find($eve1_xpath)->string_value(),
219             2 => $readings->find($eve2_xpath)->string_value()
220             }
221             );
222              
223             return \%readings;
224             }
225              
226             =head1 AUTHOR
227              
228             Michael Wayne Arnold, C<< <marmanold at cpan.org> >>
229              
230             =head1 BUGS
231              
232             Please report any bugs or feature requests to C<bug-date-lectionary-daily at rt.cpan.org>, or through
233             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Date-Lectionary-Daily>. I will be notified, and then you'll
234             automatically be notified of progress on your bug as I make changes.
235              
236             =head1 SUPPORT
237              
238             You can find documentation for this module with the perldoc command.
239              
240             perldoc Date::Lectionary::Daily
241              
242              
243             You can also look for information at:
244              
245             =over 4
246              
247             =item * RT: CPAN's request tracker (report bugs here)
248              
249             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Date-Lectionary-Daily>
250              
251             =item * AnnoCPAN: Annotated CPAN documentation
252              
253             L<http://annocpan.org/dist/Date-Lectionary-Daily>
254              
255             =item * CPAN Ratings
256              
257             L<http://cpanratings.perl.org/d/Date-Lectionary-Daily>
258              
259             =item * Search CPAN
260              
261             L<http://search.cpan.org/dist/Date-Lectionary-Daily/>
262              
263             =back
264              
265              
266             =head1 ACKNOWLEDGEMENTS
267              
268             Many thanks to my beautiful wife, Jennifer, and my amazing daughter, Rosemary. But, above all, SOLI DEO GLORIA!
269              
270             =head1 LICENSE AND COPYRIGHT
271              
272             Copyright 2017 Michael Wayne Arnold.
273              
274             This program is free software; you can redistribute it and/or modify it
275             under the terms of either: the GNU General Public License as published
276             by the Free Software Foundation; or the Artistic License.
277              
278             See L<http://dev.perl.org/licenses/> for more information.
279              
280              
281             =cut
282              
283             __PACKAGE__->meta->make_immutable;
284              
285             1; # End of Date::Lectionary::Daily