File Coverage

blib/lib/Data/SCORM.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Data::SCORM;
2              
3 4     4   115246 use Any::Moose;
  4         154016  
  4         27  
4 4     4   2686 use Any::Moose qw/ ::Util::TypeConstraints /;
  4         9  
  4         21  
5 4     4   3620 use Data::SCORM::Manifest;
  0            
  0            
6             use File::Temp qw/ tempdir /;
7             use Path::Class::Dir;
8             use IPC::Run qw/ run /;
9              
10             use Data::Dumper;
11              
12             =head1 NAME
13              
14             Data::SCORM - Parse SCO files (PIFs)
15              
16             =head1 VERSION
17              
18             Version 0.06
19              
20             =cut
21              
22             our $VERSION = '0.07';
23              
24              
25             =head1 SYNOPSIS
26              
27             see Data::SCORM::Manifest
28              
29             =cut
30              
31             has 'manifest' => (
32             is => 'rw',
33             isa => 'Data::SCORM::Manifest',
34             );
35              
36             subtype 'PathClassDir'
37             => as 'Path::Class::Dir';
38              
39             coerce 'PathClassDir'
40             => from 'Str'
41             => via { Path::Class::Dir->new($_) };
42              
43             has 'path' => (
44             is => 'rw',
45             isa => 'PathClassDir',
46             coerce => 1,
47             );
48              
49             sub extract_from_pif {
50             my ($class, $pif, $path) = @_;
51            
52             $path ||= tempdir; # no cleanup?, as caller may want to rename etc.
53            
54             my $status = unzip ($pif, $path);
55             die "Couldn't extract pif $pif, $status"
56             if $status;
57              
58             return $class->from_dir($path);
59             }
60              
61             sub unzip {
62             # Archive::Extract, Archive::Zip would arguably be the Right Thing
63             # to do here. But we have to handle some corrupt archives, e.g. without
64             # an EOCF (End of Central Directory) number.
65             # so we'll use unzip for now.
66              
67             my ($pif, $path) = @_;
68             my $status = run
69             [ unzip => $pif,
70             -d => $path ], '>', '/dev/null';
71              
72             my $ok = $status ?
73             ($status ~~ [1, 1<<8] ? 1 : 0) # oddity of unzip 'warning' status
74             : 1;
75              
76             if ($ok) {
77             return;
78             } else {
79             $status >>= 8; # oddity of 'system'
80             die "unzip(1) encountered warning/error $status";
81             return $status;
82             }
83             }
84              
85             sub from_dir {
86             my ($class, $path) = @_;
87             $path = Path::Class::Dir->new($path);
88             my $manifest = $path->file( 'imsmanifest.xml' );
89             if ($manifest->stat) { # if it exists
90             return $class->new(
91             path => $path,
92             manifest => Data::SCORM::Manifest->parsefile($manifest),
93             );
94             } else {
95             # may be a single directory
96             my @subdirectories =
97             grep {
98             my $name = ($_->dir_list)[-1];
99             $name !~/^__/
100             } # e.g. __MACOSX
101             grep $_->is_dir,
102             $path->children;
103             if (@subdirectories == 1) {
104             return $class->from_dir( $subdirectories[0] );
105             }
106             die "Invalid zip (must contain exactly 1 directory)";
107             }
108             }
109              
110             # __PACKAGE__->make_immutable;
111             no Any::Moose;
112              
113             =head1 AUTHOR
114              
115             osfameron, C<< >>
116              
117             =head1 BUGS
118              
119             Please report any bugs or feature requests to C, or through
120             the web interface at L. I will be notified, and then you'll
121             automatically be notified of progress on your bug as I make changes.
122              
123             =head1 SUPPORT
124              
125             You can find documentation for this module with the perldoc command.
126              
127             perldoc Data::SCORM
128              
129             You can also look for information at:
130              
131             =over 4
132              
133             =item * RT: CPAN's request tracker
134              
135             L
136              
137             =item * Search CPAN
138              
139             L
140              
141             =back
142              
143              
144             =head1 ACKNOWLEDGEMENTS
145              
146              
147             =head1 COPYRIGHT & LICENSE
148              
149             Copyright 2009-2011 OSFAMERON.
150              
151             This program is free software; you can redistribute it and/or modify it
152             under the terms of either: the GNU General Public License as published
153             by the Free Software Foundation; or the Artistic License.
154              
155             See http://dev.perl.org/licenses/ for more information.
156              
157             =cut
158              
159             1; # End of Data::SCORM