File Coverage

blib/lib/App/calendr.pm
Criterion Covered Total %
statement 23 89 25.8
branch 0 52 0.0
condition 0 6 0.0
subroutine 8 13 61.5
pod 1 3 33.3
total 32 163 19.6


line stmt bran cond sub pod time code
1             package App::calendr;
2              
3             $App::calendr::VERSION = '0.26';
4             $App::calendr::AUTHORITY = 'cpan:MANWAR';
5              
6             =head1 NAME
7              
8             App::calendr - Application to display supported Calendar.
9              
10             =head1 VERSION
11              
12             Version 0.26
13              
14             =cut
15              
16 2     2   138478 use 5.006;
  2         10  
17 2     2   1073 use Data::Dumper;
  2         12811  
  2         131  
18 2     2   736 use App::calendr::Option;
  2         6  
  2         95  
19             use Module::Pluggable
20 2         14 search_path => [ 'Calendar' ],
21             require => 1,
22             inner => 0,
23 2     2   1008 max_depth => 2;
  2         14850  
24              
25 2     2   156 use Moo;
  2         5  
  2         14  
26 2     2   620 use namespace::autoclean;
  2         4  
  2         14  
27              
28             our $DEFAULT_CALENDAR = 'Gregorian';
29             our $FAILED_CALENDARS = {};
30              
31 2     2   215 use Types::Standard -all;
  2         4  
  2         17  
32 2     2   79021 use MooX::Options;
  2         3  
  2         18  
33             with 'App::calendr::Option';
34              
35              
36             =head1 DESCRIPTION
37              
38             It provides simple command line interface to the package L. The
39             distribution contains a script C, using package L.
40              
41             =head1 SYNOPSIS
42              
43             You can list all command line options by giving C<--help> flag.The C<--name> flag
44             is only mandatory. Rest of all are optionals. If C<--month> flag is passed then
45             the C<--year> flag becomes mandatory and vice versa. In case neither of them is
46             passed in then it would look for C<--gdate>/C<--jday> flag and accordingly act on
47             it. In case none C passed in it would show the current calendar month.
48              
49             $ calendr --help
50              
51             USAGE: calendr [-h] [long options...]
52              
53             --name: String
54             Calendar name e.g. Bahai,Gregorian,Hebrew,Hijri,Julian,Persian,Saka.
55             Default is Gregorian.
56              
57             --month: String
58             Month number/name e.g. 1,2,3... or January,February...
59              
60             --year: Int
61             Year number (3/4 digits)
62              
63             --gdate: String
64             Gregorian date (YYYY-MM-DD)
65              
66             --jday: Int
67             Julian day
68              
69             --as_svg:
70             Generate calendar in SVG format
71              
72             --list_month_names:
73             List calendar month names
74              
75             --usage:
76             show a short help message
77              
78             -h:
79             show a compact help message
80              
81             --help:
82             show a long help message
83              
84             --man:
85             show the manual
86              
87             =head1 SUPPORTED CALENDARS
88              
89             The following supported calendars can be installed individually.
90              
91             =over 4
92              
93             =item * L
94              
95             =item * L
96              
97             =item * L
98              
99             =item * L
100              
101             =item * L
102              
103             =item * L
104              
105             =item * L
106              
107             =back
108              
109             Or they all can be installed in one go using L package.
110              
111             $ cpanm Task::Calendar
112              
113             =cut
114              
115             sub BUILD {
116 0     0 0   my ($self) = @_;
117              
118 0           my $plugins = [ plugins ];
119 0           foreach my $plugin (@$plugins) {
120 0           my $cal = _load_calendar($plugin);
121 0 0         if (defined $cal) {
122 0           my $inst_ver = ${plugin}->VERSION;
123 0           my $min_ver = $cal->{min_ver};
124 0           my $cal_name = $cal->{name};
125 0 0         if ($inst_ver >= $min_ver) {
126 0           $self->{calendars}->{$cal_name} = $plugin->new;
127             }
128             else {
129 0           $FAILED_CALENDARS->{$cal_name} = {
130             cal_name => $cal_name,
131             min_ver => $min_ver,
132             inst_ver => $inst_ver,
133             };
134             }
135             }
136             }
137             }
138              
139             =head1 METHODS
140              
141             =head2 run()
142              
143             This is the only method provided by package L. It does not expect
144             any parameter. Here is the code from the supplied C script.
145              
146             use strict; use warnings;
147             use App::calendr;
148              
149             App::calendr->new_with_options->run;
150              
151             =cut
152              
153             sub run {
154 0     0 1   my ($self) = @_;
155              
156 0           my $month = $self->month;
157 0           my $year = $self->year;
158 0   0       my $name = $self->name || $DEFAULT_CALENDAR;
159              
160 0           my $supported_calendars = _supported_calendars();
161 0           my $supported_cal = $supported_calendars->{uc($name)};
162 0 0         die "ERROR: Unsupported calendar [$name] received.\n" unless defined $supported_cal;
163              
164 0           my $calendar = $self->get_calendar($name);
165             # Is supported calendar installed?
166 0 0         if (!defined $calendar) {
167             # Is the calendar failed version pass min ver?
168 0 0         if (exists $FAILED_CALENDARS->{$supported_cal->{name}}) {
169 0           my $min_ver = $FAILED_CALENDARS->{$supported_cal->{name}}->{min_ver};
170 0           my $inst_ver = $FAILED_CALENDARS->{$supported_cal->{name}}->{inst_ver};
171 0           my $cal_name = $FAILED_CALENDARS->{$supported_cal->{name}}->{cal_name};
172 0           die sprintf("ERROR: Found %s v%s but required v%s.\n", $cal_name, $inst_ver, $min_ver);
173             }
174              
175 0           die "ERROR: Calendar [$name] is not installed.\n";
176             }
177              
178 0 0 0       if (defined $month || defined $year) {
    0          
    0          
    0          
179 0 0         if (defined $month) {
180 0 0         die "ERROR: Missing year.\n" unless defined $year;
181             }
182             else {
183 0 0         die "ERROR: Missing month.\n" if defined $year;
184             }
185              
186 0 0         if (defined $month) {
187 0 0         if (ref($calendar) eq 'Calendar::Hebrew') {
188 0           $calendar->date->validate_hebrew_month($month, $year);
189             }
190             else {
191 0           $calendar->date->validate_month($month, $year);
192             }
193 0 0         if ($month =~ /^[A-Z]+$/i) {
194 0           $month = $calendar->date->get_month_number($month);
195             }
196 0           $calendar->month($month);
197             }
198              
199 0 0         if (defined $year) {
200 0           $calendar->date->validate_year($year);
201 0           $calendar->year($year);
202             }
203             }
204             elsif (defined $self->gdate) {
205 0           my $gdate = $self->gdate;
206 0 0         die "ERROR: Invalid gregorian date '$gdate'.\n"
207             unless ($gdate =~ /^\d{4}\-\d{2}\-\d{2}$/);
208              
209 0           my ($year, $month, $day) = split /\-/, $gdate, 3;
210 0 0         print $calendar->from_gregorian($year, $month, $day) and return;
211             }
212             elsif (defined $self->jday) {
213 0           my $julian_day = $self->jday;
214 0 0         die "ERROR: Invalid julian day '$julian_day'.\n"
215             unless ($julian_day =~ /^\d+\.?\d?$/);
216              
217 0 0         print $calendar->from_julian($julian_day) and return;
218             }
219             elsif (defined $self->list_month_names) {
220 0           my $month_names = $calendar->date->months;
221 0           shift @$month_names; # Remove empty entry.
222 0 0         print join("\n", @$month_names), "\n" and return;
223             }
224              
225 0 0         if (defined $self->as_svg) {
226 0           print $calendar->as_svg, "\n";
227             }
228             else {
229 0           print $calendar, "\n";
230             }
231             }
232              
233             sub get_calendar {
234 0     0 0   my ($self, $name) = @_;
235              
236 0 0         return unless defined $name;
237 0           my $supported_cals = _supported_calendars();
238 0           my $cal_pkg = $supported_cals->{uc($name)}->{name};
239 0 0         return $self->{calendars}->{$cal_pkg} if exists $self->{calendars}->{$cal_pkg};
240 0           return;
241             }
242              
243             #
244             #
245             # PRIVATE METHODS
246              
247             sub _load_calendar {
248 0     0     my ($plugin) = @_;
249 0 0         return unless defined $plugin;
250              
251 0           my $calendars = _supported_calendars();
252 0           foreach my $key (keys %$calendars) {
253 0 0         return $calendars->{$key} if ($calendars->{$key}->{name} eq $plugin);
254             }
255 0           return;
256             }
257              
258             sub _supported_calendars {
259              
260             return {
261 0     0     'BAHAI' => { name => 'Calendar::Bahai', min_ver => 0.46 },
262             'GREGORIAN' => { name => 'Calendar::Gregorian', min_ver => 0.15 },
263             'HEBREW' => { name => 'Calendar::Hebrew', min_ver => 0.03 },
264             'HIJRI' => { name => 'Calendar::Hijri', min_ver => 0.33 },
265             'JULIAN' => { name => 'Calendar::Julian', min_ver => 0.01 },
266             'PERSIAN' => { name => 'Calendar::Persian', min_ver => 0.35 },
267             'SAKA' => { name => 'Calendar::Saka', min_ver => 1.34 },
268             };
269             }
270              
271             =head1 AUTHOR
272              
273             Mohammad S Anwar, C<< >>
274              
275             =head1 REPOSITORY
276              
277             L
278              
279             =head1 BUGS
280              
281             Please report any bugs or feature requests to C,
282             or through the web interface at L.
283             I will be notified and then you'll automatically be notified of progress on your
284             bug as I make changes.
285              
286             =head1 SUPPORT
287              
288             You can find documentation for this module with the perldoc command.
289              
290             perldoc App::calendr
291              
292             You can also look for information at:
293              
294             =over 4
295              
296             =item * RT: CPAN's request tracker (report bugs here)
297              
298             L
299              
300             =item * AnnoCPAN: Annotated CPAN documentation
301              
302             L
303              
304             =item * CPAN Ratings
305              
306             L
307              
308             =item * Search CPAN
309              
310             L
311              
312             =back
313              
314             =head1 LICENSE AND COPYRIGHT
315              
316             Copyright (C) 2015 - 2017 Mohammad S Anwar.
317              
318             This program is free software; you can redistribute it and / or modify it under
319             the terms of the the Artistic License (2.0). You may obtain a copy of the full
320             license at:
321              
322             L
323              
324             Any use, modification, and distribution of the Standard or Modified Versions is
325             governed by this Artistic License.By using, modifying or distributing the Package,
326             you accept this license. Do not use, modify, or distribute the Package, if you do
327             not accept this license.
328              
329             If your Modified Version has been derived from a Modified Version made by someone
330             other than you,you are nevertheless required to ensure that your Modified Version
331             complies with the requirements of this license.
332              
333             This license does not grant you the right to use any trademark, service mark,
334             tradename, or logo of the Copyright Holder.
335              
336             This license includes the non-exclusive, worldwide, free-of-charge patent license
337             to make, have made, use, offer to sell, sell, import and otherwise transfer the
338             Package with respect to any patent claims licensable by the Copyright Holder that
339             are necessarily infringed by the Package. If you institute patent litigation
340             (including a cross-claim or counterclaim) against any party alleging that the
341             Package constitutes direct or contributory patent infringement,then this Artistic
342             License to you shall terminate on the date that such litigation is filed.
343              
344             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND
345             CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
346             WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
347             NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS
348             REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT,
349             INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
350             OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351              
352             =cut
353              
354             1; # End of App::calendr