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   51108 use v5.22;
  1         3  
4 1     1   5 use strict;
  1         2  
  1         16  
5 1     1   4 use warnings;
  1         5  
  1         20  
6              
7 1     1   342 use Moose;
  1         389592  
  1         8  
8 1     1   9866 use Carp;
  1         2  
  1         83  
9 1     1   8 use Try::Tiny;
  1         3  
  1         68  
10 1     1   192 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.20170809
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.20170809';
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             'includeFeasts' => 'no',
111             )->name
112             );
113              
114             if ($fixedHolyDay) {
115             $self->_setReadings(
116             _buildReadings(
117             "Fixed Holy Days",
118             $self->date->fullmonth . " " . $self->date->mday,
119             $self->lectionary
120             )
121             );
122             }
123             else {
124             $self->_setReadings(
125             _buildReadings(
126             $self->week, $self->date->fullday, $self->lectionary
127             )
128             );
129             }
130             }
131              
132             =head2 _parseLectDB
133              
134             Private method to open and parse the lectionary XML to be used by other methods to XPATH queries.
135              
136             =cut
137              
138             sub _parseLectDB {
139             my $lectionary = shift;
140              
141             my $parser = XML::LibXML->new();
142             my $lectDB;
143              
144             try {
145             my $data_location = dist_file( 'Date-Lectionary-Daily',
146             $lectionary . '_lect_daily.xml' );
147             $lectDB = $parser->parse_file($data_location);
148             }
149             catch {
150             carp
151             "The readings database for the $lectionary daily lectionary could not be found or parsed.";
152             };
153              
154             return $lectDB;
155             }
156              
157             =head2 _checkFixed
158              
159             Private method to determine if the day given is a fixed holiday rather than a standard day.
160              
161             =cut
162              
163             sub _checkFixed {
164             my $date = shift;
165             my $lectionary = shift;
166              
167             my $searchDate = $date->fullmonth . " " . $date->mday;
168              
169             my $lectDB = _parseLectDB($lectionary);
170              
171             my $fixed_xpath
172             = XML::LibXML::XPathExpression->new(
173             "/daily-lectionary/week[\@name=\"Fixed Holy Days\"]/day[\@name=\"$searchDate\"]/lesson"
174             );
175              
176             if ( $lectDB->exists($fixed_xpath) ) {
177             return 1;
178             }
179              
180             return 0;
181             }
182              
183             =head2 _buildReadings
184              
185             Private method that returns an ArrayRef of strings for the lectionary readings associated with the date.
186              
187             =cut
188              
189             sub _buildReadings {
190             my $weekName = shift;
191             my $weekDay = shift;
192             my $lectionary = shift;
193              
194             my $readings = _parseLectDB($lectionary);
195              
196             my $morn1_xpath
197             = XML::LibXML::XPathExpression->new(
198             "/daily-lectionary/week[\@name=\"$weekName\"]/day[\@name=\"$weekDay\"]/lesson[\@service=\"morning\" and \@order=\"1\"]"
199             );
200             my $morn2_xpath
201             = XML::LibXML::XPathExpression->new(
202             "/daily-lectionary/week[\@name=\"$weekName\"]/day[\@name=\"$weekDay\"]/lesson[\@service=\"morning\" and \@order=\"2\"]"
203             );
204             my $eve1_xpath
205             = XML::LibXML::XPathExpression->new(
206             "/daily-lectionary/week[\@name=\"$weekName\"]/day[\@name=\"$weekDay\"]/lesson[\@service=\"evening\" and \@order=\"1\"]"
207             );
208             my $eve2_xpath
209             = XML::LibXML::XPathExpression->new(
210             "/daily-lectionary/week[\@name=\"$weekName\"]/day[\@name=\"$weekDay\"]/lesson[\@service=\"evening\" and \@order=\"2\"]"
211             );
212              
213             my %readings = (
214             morning => {
215             1 => $readings->find($morn1_xpath)->string_value(),
216             2 => $readings->find($morn2_xpath)->string_value()
217             },
218             evening => {
219             1 => $readings->find($eve1_xpath)->string_value(),
220             2 => $readings->find($eve2_xpath)->string_value()
221             }
222             );
223              
224             return \%readings;
225             }
226              
227             =head1 AUTHOR
228              
229             Michael Wayne Arnold, C<< <marmanold at cpan.org> >>
230              
231             =head1 BUGS
232              
233             Please report any bugs or feature requests to C<bug-date-lectionary-daily at rt.cpan.org>, or through
234             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Date-Lectionary-Daily>. I will be notified, and then you'll
235             automatically be notified of progress on your bug as I make changes.
236              
237             =head1 SUPPORT
238              
239             You can find documentation for this module with the perldoc command.
240              
241             perldoc Date::Lectionary::Daily
242              
243              
244             You can also look for information at:
245              
246             =over 4
247              
248             =item * RT: CPAN's request tracker (report bugs here)
249              
250             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Date-Lectionary-Daily>
251              
252             =item * AnnoCPAN: Annotated CPAN documentation
253              
254             L<http://annocpan.org/dist/Date-Lectionary-Daily>
255              
256             =item * CPAN Ratings
257              
258             L<http://cpanratings.perl.org/d/Date-Lectionary-Daily>
259              
260             =item * Search CPAN
261              
262             L<http://search.cpan.org/dist/Date-Lectionary-Daily/>
263              
264             =back
265              
266              
267             =head1 ACKNOWLEDGEMENTS
268              
269             Many thanks to my beautiful wife, Jennifer, and my amazing daughter, Rosemary. But, above all, SOLI DEO GLORIA!
270              
271             =head1 LICENSE AND COPYRIGHT
272              
273             Copyright 2017 Michael Wayne Arnold.
274              
275             This program is free software; you can redistribute it and/or modify it
276             under the terms of either: the GNU General Public License as published
277             by the Free Software Foundation; or the Artistic License.
278              
279             See L<http://dev.perl.org/licenses/> for more information.
280              
281              
282             =cut
283              
284             __PACKAGE__->meta->make_immutable;
285              
286             1; # End of Date::Lectionary::Daily