File Coverage

blib/lib/Catmandu/Store/File/BagIt/Bag.pm
Criterion Covered Total %
statement 64 65 98.4
branch 3 4 75.0
condition n/a
subroutine 19 20 95.0
pod 0 5 0.0
total 86 94 91.4


line stmt bran cond sub pod time code
1             package Catmandu::Store::File::BagIt::Bag;
2              
3 3     3   23 use Catmandu::Sane;
  3         8  
  3         19  
4              
5             our $VERSION = '0.240';
6              
7 3     3   638 use Moo;
  3         7  
  3         21  
8 3     3   1085 use Carp;
  3         6  
  3         280  
9 3     3   60 use IO::File;
  3         6  
  3         459  
10 3     3   23 use Path::Tiny;
  3         6  
  3         206  
11 3     3   26 use File::Spec;
  3         5  
  3         89  
12 3     3   17 use Catmandu::Sane;
  3         6  
  3         14  
13 3     3   2180 use Catmandu::BagIt;
  3         10  
  3         126  
14 3     3   24 use Catmandu::Util qw(content_type);
  3         7  
  3         152  
15 3     3   18 use URI::Escape;
  3         7  
  3         221  
16 3     3   21 use POSIX qw(strftime);
  3         8  
  3         25  
17 3     3   218 use namespace::clean;
  3         7  
  3         14  
18              
19             with 'Catmandu::Bag';
20             with 'Catmandu::FileBag';
21             with 'Catmandu::Droppable';
22              
23             has _path => (is => 'lazy');
24             has _bagit => (is => 'lazy');
25              
26             sub _build__path {
27 1     1   13 my $self = shift;
28 1         8 $self->store->path_string($self->name);
29             }
30              
31             sub _build__bagit {
32 1     1   11 my $self = shift;
33 1         27 Catmandu::BagIt->read($self->_path);
34             }
35              
36             sub generator {
37 4     4 0 1578 my ($self) = @_;
38 4         91 my $path = $self->_path;
39 4         94 my $bagit = $self->_bagit;
40              
41             sub {
42 11     11   133 state $children = [$bagit->list_files];
43              
44 11         23 my $child = shift @$children;
45              
46 11 100       35 return undef unless $child;
47              
48 7         20 my $file = $child->filename;
49              
50 7         17 my $unpacked_key = $self->unpack_key($file);
51              
52 7         156 return $self->get($unpacked_key);
53 4         44 };
54             }
55              
56             sub exists {
57 3     3 0 1908 my ($self, $id) = @_;
58 3         76 my $path = $self->_path;
59 3         68 my $bagit = $self->_bagit;
60              
61 3         24 my $packed_key = $self->pack_key($id);
62              
63 3 50       44 $bagit->get_checksum($packed_key) ? 1 : 0;
64             }
65              
66             sub get {
67             my ($self, $id) = @_;
68              
69             my $path = $self->_path;
70             my $bagit = $self->_bagit;
71              
72             my $packed_key = $self->pack_key($id);
73              
74             my $file = $bagit->get_file($packed_key);
75              
76             return undef unless $file;
77              
78             my $stat = [stat $file->path];
79              
80             my $size = $stat->[7];
81             my $modified = $stat->[9];
82             my $created = $stat->[10]; # no real creation time exists on Unix
83              
84             my $content_type = content_type($id);
85              
86             return {
87             _id => $id,
88             size => $size,
89             md5 => $bagit->get_checksum($packed_key) // undef,
90             content_type => $content_type,
91             created => $created,
92             modified => $modified,
93             _stream => sub {
94             $self->file_streamer($file->path,shift);
95             }
96             };
97             }
98              
99             sub add {
100             my ($self, $data) = @_;
101             my $path = $self->_path;
102             my $bagit = $self->_bagit;
103              
104             my $update = 1;
105              
106             unless ($bagit) {
107             $update = 0;
108             $bagit = Catmandu::BagIt->new;
109             $self->{_bagit} = $bagit;
110             }
111              
112             my $id = $data->{_id};
113             my $io = $data->{_stream};
114              
115             return $self->get($id) unless $io;
116              
117             my $packed_key = $self->pack_key($id);
118              
119             $bagit->add_file($packed_key,$io,overwrite => 1);
120              
121             unless ($update) {
122             $bagit->remove_info('Bagging-Date');
123             $bagit->add_info('Bagging-Date', strftime("%Y-%M-%D", gmtime));
124             }
125              
126             $bagit->remove_info('Bagging-Update');
127             $bagit->add_info('Bagging-Update', strftime("%Y-%m-%d", gmtime));
128              
129             $bagit->write($path, overwrite => 1);
130              
131             my $new_data = $self->get($id);
132              
133             $data->{$_} = $new_data->{$_} for keys %$new_data;
134              
135             1;
136             }
137              
138             sub delete {
139             my ($self, $id) = @_;
140             my $path = $self->_path;
141             my $bagit = $self->_bagit;
142              
143             my $packed_key = $self->pack_key($id);
144              
145             my $file = $bagit->get_file($packed_key);
146              
147             return undef unless $file;
148              
149             $bagit->remove_file($packed_key);
150              
151             $bagit->write($path, overwrite => 1);
152             }
153              
154             sub delete_all {
155             my ($self) = @_;
156              
157             $self->each(
158             sub {
159             my $key = shift->{_id};
160             $self->delete($key);
161             }
162             );
163              
164             1;
165             }
166              
167             sub drop {
168 0     0 0 0 $_[0]->delete_all;
169             }
170              
171             sub commit {
172             return 1;
173             }
174              
175             sub pack_key {
176 26     26 0 50 my $self = shift;
177 26         46 my $key = shift;
178 26         85 utf8::encode($key);
179 26         78 uri_escape($key);
180             }
181              
182             sub unpack_key {
183 7     7 0 15 my $self = shift;
184 7         11 my $key = shift;
185 7         26 my $str = uri_unescape($key);
186 7         72 utf8::decode($str);
187 7         15 $str;
188             }
189              
190             1;
191              
192             __END__
193              
194             =pod
195              
196             =head1 NAME
197              
198             Catmandu::Store::File::BagIt::Bag - Index of all "files" in a Catmandu::Store::File::BagIt "folder"
199              
200             =head1 SYNOPSIS
201              
202             use Catmandu;
203              
204             my $store = Catmandu->store('File::BagIt' , root => 't/data');
205              
206             my $index = $store->index;
207              
208             # List all containers
209             $index->each(sub {
210             my $container = shift;
211              
212             print "%s\n" , $container->{_id};
213             });
214              
215             # Add a new folder
216             $index->add({_id => '1234'});
217              
218             # Delete a folder
219             $index->delete(1234);
220              
221             # Get a folder
222             my $folder = $index->get(1234);
223              
224             # Get the files in an folder
225             my $files = $index->files(1234);
226              
227             $files->each(sub {
228             my $file = shift;
229              
230             my $name = $file->_id;
231             my $size = $file->size;
232             my $content_type = $file->content_type;
233             my $created = $file->created;
234             my $modified = $file->modified;
235              
236             $file->stream(IO::File->new(">/tmp/$name"), file);
237             });
238              
239             # Add a file
240             $files->upload(IO::File->new("<data.dat"),"data.dat");
241              
242             # Retrieve a file
243             my $file = $files->get("data.dat");
244              
245             # Stream a file to an IO::Handle
246             $files->stream(IO::File->new(">data.dat"),$file);
247              
248             # Delete a file
249             $files->delete("data.dat");
250              
251             # Delete a folders
252             $index->delete("1234");
253              
254             =head1 INHERITED METHODS
255              
256             This Catmandu::Bag implements:
257              
258             =over 3
259              
260             =item L<Catmandu::Bag>
261              
262             =item L<Catmandu::FileBag>
263              
264             =item L<Catmandu::Droppable>
265              
266             =back
267              
268             =cut