File Coverage

blib/lib/CPAN/PackageDetails/Header.pm
Criterion Covered Total %
statement 62 67 92.5
branch 11 14 78.5
condition 5 6 83.3
subroutine 16 18 88.8
pod 8 9 88.8
total 102 114 89.4


line stmt bran cond sub pod time code
1 14     14   2608 use 5.008;
  14         54  
2              
3             package CPAN::PackageDetails::Header;
4 14     14   93 use strict;
  14         26  
  14         318  
5 14     14   89 use warnings;
  14         32  
  14         867  
6              
7             our $VERSION = '0.263';
8              
9 14     14   96 use Carp;
  14         32  
  14         13716  
10              
11             =encoding utf8
12              
13             =head1 NAME
14              
15             CPAN::PackageDetails::Header - Handle the header of 02packages.details.txt.gz
16              
17             =head1 SYNOPSIS
18              
19             Used internally by CPAN::PackageDetails
20              
21             =head1 DESCRIPTION
22              
23             The 02packages.details.txt.gz header is a short preamble that give information
24             about the creation of the file, its intended use, and the number of entries in
25             the file. It looks something like:
26              
27             File: 02packages.details.txt
28             URL: http://www.perl.com/CPAN/modules/02packages.details.txt
29             Description: Package names found in directory $CPAN/authors/id/
30             Columns: package name, version, path
31             Intended-For: Automated fetch routines, namespace documentation.
32             Written-By: Id: mldistwatch.pm 1063 2008-09-23 05:23:57Z k
33             Line-Count: 59754
34             Last-Updated: Thu, 23 Oct 2008 02:27:36 GMT
35              
36             Note that there is a Columns field. This module tries to respect the ordering
37             of columns in there. The usual CPAN tools expect only three columns and in the
38             order in this example, but C tries to handle any number
39             of columns in any order.
40              
41             =head2 Methods
42              
43             =over 4
44              
45             =item new( HASH )
46              
47             Create a new Header object. Unless you want a lot of work so you
48             get more control, just let C's C or C
49             handle this for you.
50              
51             In most cases, you'll want to create the Entries object first then
52             pass a reference the the Entries object to C since the header
53             object needs to know how to get the count of the number of entries
54             so it can put it in the "Line-Count" header.
55              
56             CPAN::PackageDetails::Header->new(
57             _entries => $entries_object,
58             )
59              
60             =cut
61              
62             sub new {
63 24     24 1 83 my( $class, %args ) = @_;
64              
65 24         84 my %hash = (
66             _entries => undef,
67             %args
68             );
69              
70 24         122 bless \%hash, $_[0]
71             }
72              
73             =item format_date
74              
75             Write the date in PAUSE format. For example:
76              
77             Thu, 23 Oct 2008 02:27:36 GMT
78              
79             =cut
80              
81             sub format_date {
82 25     25 1 850 my( $second, $minute, $hour, $date, $monnum, $year, $wday ) = gmtime;
83 25         85 $year += 1900;
84              
85 25         80 my $day = ( qw(Sun Mon Tue Wed Thu Fri Sat) )[$wday];
86 25         62 my $month = ( qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) )[$monnum];
87              
88 25         219 sprintf "%s, %02d %s %4d %02d:%02d:%02d GMT",
89             $day, $date, $month, $year, $hour, $minute, $second;
90             }
91              
92             =item default_headers
93              
94             Returns a list of the the headers that should show up in the file. This
95             excludes various fake headers stored in the object.
96              
97             =cut
98              
99             sub default_headers {
100 7         19 map { $_, $_[0]->{$_} }
101 1     1 1 1 grep ! /^_|_class|allow/, keys %{ $_[0] }
  1         19  
102             }
103              
104             sub can {
105 15     15 0 1312 my( $self, @methods ) = @_;
106              
107 15   66     59 my $class = ref $self || $self; # class or instance
108              
109 15         33 foreach my $method ( @methods ) {
110             next if
111 15 100 100     58 defined &{"${class}::$method"} ||
  15         219  
112             $self->header_exists( $method );
113 2         61 return 0;
114             }
115              
116 13         60 return 1;
117             }
118              
119             =item set_header
120              
121             Add an entry to the collection. Call this on the C
122             object and it will take care of finding the right handler.
123              
124             =cut
125              
126             sub set_header {
127 283     283 1 528 my( $self, $field, $value ) = @_;
128              
129 283         884 $self->{$field} = $value;
130             }
131              
132             =item header_exists( FIELD )
133              
134             Returns true if the header has a field named FIELD, regardless of
135             its value.
136              
137             =cut
138              
139             sub header_exists {
140 117     117 1 231 my( $self, $field ) = @_;
141              
142 117         505 exists $self->{$field}
143             }
144              
145             =item get_header( FIELD )
146              
147             Returns the value for the named header FIELD. Carps and returns nothing
148             if the named header is not in the object. This method is available from
149             the C or C object:
150              
151             $package_details->get_header( 'url' );
152              
153             $package_details->header->get_header( 'url' );
154              
155             The header names in the Perl code are in a different format than they
156             are in the file. See C for an explanation of the
157             difference.
158              
159             For most headers, you can also use the header name as the method name:
160              
161             $package_details->header->url;
162              
163             =cut
164              
165             sub get_header {
166 71     71 1 193 my( $self, $field ) = @_;
167              
168 71 100       169 if( $self->header_exists( $field ) ) { $self->{$field} }
  69         286  
169 2         301 else { carp "No such header as $field!"; return }
  2         202  
170             }
171              
172             =item columns_as_list
173              
174             Returns the columns name as a list (rather than a comma-joined string). The
175             list is in the order of the columns in the output.
176              
177             =cut
178              
179 5     5 1 70 sub columns_as_list { split /,\s+/, $_[0]->{columns} }
180              
181             =item as_string
182              
183             Return the header formatted as a string.
184              
185             =cut
186              
187 0         0 BEGIN {
188 14     14   93 my %internal_field_name_mapping = (
189             url => 'URL',
190             );
191              
192 14         2006 my %external_field_name_mapping = reverse %internal_field_name_mapping;
193              
194             sub _internal_name_to_external_name {
195 41     41   72 my( $self, $internal ) = @_;
196              
197             return $internal_field_name_mapping{$internal}
198 41 100       87 if exists $internal_field_name_mapping{$internal};
199              
200 37         104 (my $external = $internal) =~ s/_/-/g;
201 37         123 $external =~ s/^(.)/ uc $1 /eg;
  37         124  
202 37         93 $external =~ s/-(.)/ "-" . uc $1 /eg;
  41         117  
203              
204 37         86 return $external;
205             }
206              
207             sub _external_name_to_internal_name {
208 0     0   0 my( $self, $external ) = @_;
209              
210             return $external_field_name_mapping{$external}
211 0 0       0 if exists $external_field_name_mapping{$external};
212              
213 0         0 (my $internal = $external) =~ s/-/_/g;
214              
215 0         0 lc $internal;
216             }
217              
218             sub as_string {
219 4     4 1 13 my( $self, $line_count ) = @_;
220              
221             # XXX: need entry count
222 4         11 my @lines;
223 4         31 foreach my $field ( keys %$self ) {
224 45 100       111 next if substr( $field, 0, 1 ) eq '_';
225 41         82 my $value = $self->get_header( $field );
226              
227 41         80 my $out_field = $self->_internal_name_to_external_name( $field );
228              
229 41         129 push @lines, "$out_field: $value";
230             }
231              
232 4 100       14 push @lines, "Line-Count: " . $self->_entries->as_unique_sorted_list
233             unless $self->header_exists( 'line_count' );
234              
235 4         67 join "\n", sort( @lines ), "\n";
236             }
237             }
238              
239             sub AUTOLOAD {
240 7     7   29 my $self = shift;
241              
242 7         47 ( my $method = $CPAN::PackageDetails::Header::AUTOLOAD ) =~ s/.*:://;
243              
244 7 50       28 carp "No such method as $method!" unless $self->can( $method );
245              
246 7         22 $self->get_header( $method );
247             }
248              
249       0     sub DESTROY { }
250              
251             =back
252              
253             =head1 TO DO
254              
255              
256             =head1 SEE ALSO
257              
258              
259             =head1 SOURCE AVAILABILITY
260              
261             This source is in Github:
262              
263             https://github.com/briandfoy/cpan-packagedetails
264              
265             =head1 AUTHOR
266              
267             brian d foy, C<< >>
268              
269             =head1 COPYRIGHT AND LICENSE
270              
271             Copyright © 2009-2021, brian d foy . All rights reserved.
272              
273             You may redistribute this under the terms of the Artistic License 2.0.
274              
275             =cut
276              
277             1;