File Coverage

blib/lib/File/ArchivableFormats.pm
Criterion Covered Total %
statement 45 48 93.7
branch 3 6 50.0
condition 2 5 40.0
subroutine 15 15 100.0
pod 5 5 100.0
total 70 79 88.6


line stmt bran cond sub pod time code
1             package File::ArchivableFormats;
2 4     4   382558 use Moose;
  4         1892158  
  4         31  
3 4     4   32848 use namespace::autoclean;
  4         33514  
  4         19  
4              
5             # ABSTRACT: Be able to select archivable formats
6              
7 4     4   303 use File::Basename qw(fileparse);
  4         9  
  4         386  
8 4     4   2297 use File::MimeInfo::Magic;
  4         34179  
  4         265  
9 4     4   37 use List::Util qw(first);
  4         9  
  4         244  
10 4     4   2041 use Module::Pluggable::Object;
  4         27736  
  4         144  
11 4     4   30 use Moose::Util::TypeConstraints;
  4         11  
  4         50  
12              
13             our $VERSION = '1.8';
14              
15             subtype 'PluginRole'
16             => as 'Object'
17             => where sub { $_->does('File::ArchivableFormats::Plugin') };
18              
19             has driver => (
20             is => 'ro',
21             isa => 'Str',
22             predicate => 'has_driver',
23             );
24              
25             has _driver => (
26             is => 'ro',
27             isa => 'PluginRole',
28             builder => '_build_driver',
29             lazy => 1,
30             );
31              
32             sub _build_driver {
33 1     1   3 my $self = shift;
34 1     1   9 return first { $_->name eq $self->driver } $self->installed_drivers;
  1         39  
35             }
36              
37             my @DRIVERS;
38              
39             sub installed_drivers {
40 3 50   3 1 60086 if (!@DRIVERS) {
41 3         35 my $finder = Module::Pluggable::Object->new(
42             search_path => 'File::ArchivableFormats::Plugin',
43             instantiate => 'new',
44             );
45 3         46 @DRIVERS = $finder->plugins;
46             }
47 3         100 return @DRIVERS;
48             }
49              
50             sub identify_from_fh {
51 2     2 1 3198 my ($self, $fh) = @_;
52              
53 2 50 33     14 if (blessed($fh) && $fh->isa('Path::Tiny')) {
54             # Path::Tiny doesn't have a seek and it doesn't play well with .docx as
55             # it than identifies as a zip file. See t/200-dans.t for the test.
56 0         0 return $self->identify_from_fh("$fh");
57             }
58              
59 2         11 my $info = { mime_type => mimetype($fh)} ;
60 2         449 return $self->identify_from_mimetype($info->{mime_type});
61             }
62              
63             sub identify_from_path {
64 1     1 1 2401 my ($self, $path) = @_;
65 1         5 return $self->identify_from_fh($path);
66             }
67              
68             sub parse_extension {
69 1     1 1 632 my ($self, $filename) = @_;
70              
71 1         71 my (undef, undef, $ext) = fileparse($filename, '\.[^\.]*');
72 1         7 return lc($ext);
73             }
74              
75             sub identify_from_mimetype {
76 2     2 1 6 my ($self, $mimetype) = @_;
77              
78 2         7 my %rv = ( mime_type => $mimetype );
79              
80 2 50       101 if ($self->has_driver) {
81 2         64 $rv{ $self->driver } = $self->_driver_mimetype($self->_driver, $mimetype);
82             }
83             else {
84 0         0 for my $driver ($self->installed_drivers) {
85 0         0 $rv{ $driver->name } = $self->_driver_mimetype($driver, $mimetype);
86             }
87             }
88              
89 2         13 return \%rv;
90             }
91              
92             sub _driver_mimetype {
93 2     2   6 my ($self, $driver, $mimetype) = @_;
94             return {
95             archivable => $driver->is_archivable($mimetype) || 0,
96 2   50     86 %{ $driver->allowed_extensions($mimetype) },
  2         9  
97             };
98              
99             }
100              
101             __PACKAGE__->meta->make_immutable;
102              
103             __END__
104              
105             =pod
106              
107             =encoding UTF-8
108              
109             =head1 NAME
110              
111             File::ArchivableFormats - Be able to select archivable formats
112              
113             =head1 VERSION
114              
115             version 1.8
116              
117             =head1 SYNOPSIS
118              
119             use File::ArchivableFormats;
120              
121             my $archive = File::ArchivableFormats->new();
122              
123             open my $fh, '<', 'path/to/file';
124              
125             my $result_fh = $archive->identify_from_fh($fh);
126              
127             my $result_path = $archive->identify_from_path('/path/to/file');
128              
129             =head1 DESCRIPTION
130              
131             This module identifies filetypes and tells you whether they are considered
132             archivable by various institutes. This is done via a plugin mechanism.
133              
134             =head1 ATTRIBUTES
135              
136             =head1 METHODS
137              
138             =head2 parse_extension
139              
140             Parses the filename and returns the extension. Uses
141             L<File::Basename/fileparse>
142              
143             =head2 identify_from_fh
144              
145             Identify the file from a file handle. Please note that this does not
146             work with a L<File::Temp> filehandle.
147              
148             Returns a data structure like this:
149              
150             {
151             # DANS is the Prefered format list
152             'DANS' => {
153             # Types tell you something about why something is on the
154             # preferred format list
155             'types' => [
156             'Plain text (Unicode)',
157             'Plain text (Non-Unicode)',
158             'Statistical data (data (.csv) + setup)',
159             'Raspter GIS (ASCII GRID)',
160             'Raspter GIS (ASCII GRID)'
161             ],
162             # The extensions by which belongs to the mime type/file
163             'allowed_extensions' => ['.asc', '.txt'],
164             # Boolean which tells you if the file is archivable and
165             # therfore preferred.
166             'archivable' => 1
167             },
168             'mime_type' => 'text/plain'
169             };
170              
171             =head2 identify_from_path
172              
173             Identify the file from path/filename.
174              
175             =head2 identify_from_mimetype
176              
177             Identify based on the mimetype
178              
179             =head2 installed_drivers
180              
181             Returns an array with all the installed plugins.
182              
183             =head1 SEE ALSO
184              
185             =over
186              
187             =item L<File::MimeInfo::Magic>
188              
189             =item IANA
190              
191             L<http://www.iana.org/assignments/media-types/media-types.xhtml>
192              
193             L<http://www.iana.org/assignments/media-types/application.csv>
194              
195             =back
196              
197             =head1 AUTHOR
198              
199             Wesley Schwengle <wesley@mintlab.nl>
200              
201             =head1 COPYRIGHT AND LICENSE
202              
203             This software is Copyright (c) 2017 by Mintlab BV.
204              
205             This is free software, licensed under:
206              
207             The European Union Public License (EUPL) v1.1
208              
209             =cut