File Coverage

blib/lib/WWW/MeGa/Item.pm
Criterion Covered Total %
statement 22 61 36.0
branch 0 18 0.0
condition n/a
subroutine 8 11 72.7
pod n/a
total 30 90 33.3


line stmt bran cond sub pod time code
1             # $Id: Item.pm 193 2009-01-16 13:42:25Z fish $
2             package WWW::MeGa::Item;
3 1     1   5 use strict;
  1         2  
  1         38  
4 1     1   5 use warnings;
  1         3  
  1         38  
5              
6             =head1 NAME
7              
8             WWW::MeGa::Item - Representing a item in L
9              
10             =head1 SYNOPSIS
11              
12             use WWW::MeGa::Item;
13             my $item = WWW::MeGa::Item->new('some/file.jpg', $config, $cache);
14             print $item->thumbnail(1);
15              
16             =head1 DESCRIPTION
17              
18             WWW::MeGa::Item represents a "item" in L.
19              
20             Passing a relative path to a arbitrary file to the new-method will
21             return one of the following specific objects based on the mime type:
22              
23             =over
24              
25             =item * L
26              
27             =item * L - represents an album
28              
29             =item * L
30              
31             =item * L - represents an item for which no
32             specific object was found
33              
34             =item * L
35              
36             =item * L
37              
38             =back
39              
40              
41             =head1 METHODS
42              
43             =cut
44              
45 1     1   6 use Carp qw(confess);
  1         2  
  1         54  
46 1     1   6 use File::Basename qw(basename dirname);
  1         2  
  1         50  
47 1     1   6 use constant ICON_TYPE => 'png';
  1         1  
  1         181  
48              
49             our $VERSION = '0.11';
50              
51             =head2 new($relative_path, $config, $cache)
52              
53             creates a new WWW::MeGa::Item::* object based on the mime type of the file specified by $relative_path.
54              
55             $config is a Config::Simple object, containing, amongst other things, the root-path to build the absolute path.
56              
57             $cache is a hash reference to cache the exif data
58              
59             =cut
60              
61             sub new
62             {
63 0     0     my $proto = shift;
64 0           my $self = {};
65 0           $self->{path_rel} = shift; # relative path
66 0           $self->{config} = shift;
67 0           $self->{cache} = shift;
68              
69 0           $self->{path} = File::Spec->catfile($self->{config}->param('root'), $self->{path_rel}); # absolute path to filename
70 0           $self->{file} = basename $self->{path}; # filename
71 0           $self->{folder} = dirname $self->{path}; # folder
72              
73              
74 0           my $type;
75 0 0         if (-d $self->{path})
76             {
77 0           $type = 'Folder';
78             } else
79             {
80 1     1   882 use MIME::Types;
  1         3833  
  1         317  
81 0           my $mt = MIME::Types->new();
82 0           my $mime = $mt->mimeTypeOf($self->{path});
83 0           $self->{mime} = $mime;
84              
85 0 0         $type = $mime ? ucfirst ((split '/', $mime)[0]) : 'Other';
86             }
87 0           my $class = 'WWW::MeGa::Item::' . ucfirst $type;
88             # there is no other way to load the module in runtime, so please:
89 0 0         unless (eval "require $class") ## no critic
90             {
91 0           $class = 'WWW::MeGa::Item::Other';
92 0 0         require WWW::MeGa::Item::Other or confess "$class: $! (@INC)";
93             }
94              
95 0           $self->{type} = $type;
96              
97 0           bless $self, $class;
98 0           return $self;
99             }
100              
101              
102             =head2 data
103              
104             returns necessary data for rendering the template
105              
106             =cut
107              
108             sub data
109             {
110              
111 0     0     my $self = shift;
112 0           my $data =
113             {
114             FILE => $self->{file},
115             PATH => $self->{path},
116             PATH_REL => $self->{path_rel},
117             NAME => $self->{file},
118             };
119 0           $data->{EXIF} = $self->exif;
120 0           $data->{TYPE} = (split(/::/, Scalar::Util::blessed($self)))[-1];
121 0           return $data;
122             }
123              
124              
125             =head2 exif
126              
127             read, return and cache the exif data for the represented file
128              
129             =cut
130              
131             sub exif
132             {
133 0     0     my $self = shift;
134 0 0         return unless $self->{config}->param('exif');
135             #$self->{cache}->{exif}->{23} = "foo";
136              
137 0 0         return $self->{cache}->{exif}->{$self->{path}} if ($self->{cache}->{exif}->{$self->{path}});
138              
139 1     1   2286 use Image::ExifTool;
  1         55778  
  1         666  
140 0           my $et = Image::ExifTool->new();
141 0           my %data;
142 0 0         warn "reading exif from $self->{path}" if $self->{config}->param('debug');
143 0 0         my $exif = $et->ImageInfo((-d $self->{path}) ? $self->thumbnail_source : $self->{path});
144 0 0         return if $exif->{Error};
145 0           $self->{cache}->{exif}->{$self->{path}} = $exif;
146 0           return $exif;
147             }
148              
149              
150             =head2 thumbnail_sized($size)
151              
152             reads C<$self->thumbnail_source> and returns a thumbnail in the
153             requested size. If C<$self->thumbnail_source> does not exist, it use
154             a icon based on the mime type.
155              
156             It should not be called directly but through the caching methode C<$self->thumbnail>.
157              
158             =cut
159              
160             sub thumbnail_sized
161             {
162 1     1   552 use Image::Magick;
  0            
  0            
163              
164             my $self = shift;
165             my $size = shift;
166             my $type = $self->{config}->param('thumb-type');
167             my $img = $self->thumbnail_source;
168              
169             $img = File::Spec->catdir($self->{config}->param('icons'), $self->{type} .'.'. ICON_TYPE)
170             if !$img or not -r $img;
171              
172             my @magick =
173             (
174             [ 'Read', $img ],
175             [ 'Resize', $size . 'x' . $size],
176             [ 'AutoOrient', 1],
177             [ 'ImageToBlob', { magick => $type } ]
178             );
179              
180             my $image = Image::Magick->new;
181             foreach my $cmd (@magick)
182             {
183             my ($m, $p) = @$cmd;
184             my $ret = $image->$m($p);
185             return $ret if $m eq $magick[@magick-1]->[0];
186              
187             warn $ret and return if $ret;
188             }
189             }
190              
191              
192             =head2 thumbnail_source
193              
194             returns the source for the thumbnail.
195             Thats the original file that can be scaled via thumbnail_sized. Think
196             of it as a image represenation for the file type.
197             This method is empty and should be overwritten for images and videos to
198             have a real thumbnail.
199              
200             =cut
201              
202             sub thumbnail_source
203             {
204             }
205              
206              
207             =head2 thumbnail($size)
208              
209             returns the actual thumbnail.
210             If the resized thumb already exist, return the path to that one.
211             If no, try to create it first by calling C<$self->thumbnail_sized>
212              
213             =cut
214              
215             sub thumbnail
216             {
217             my $self = shift;
218             my $size = shift or return $self->{path};
219             my $type = $self->{config}->param('thumb-type');
220             my $cache = $self->{config}->param('cache');
221             my $sized = File::Spec->catdir($cache, $self->{path} . '_' . $size . '.' . $type);
222             warn "sized: $sized" if $self->{config}->param('debug');
223              
224             return $sized if -e $sized;
225              
226             $self->prepare_dir($sized) or warn "could not create dir for $sized";
227              
228             my $data = $self->thumbnail_sized($size);
229              
230             if ($data and open my $fh, '>', $sized)
231             {
232             binmode($fh);
233             print $fh $data;
234             close $fh;
235             return $sized;
236             }
237             warn "could not write thumbnail to $sized: $!";
238             }
239              
240             sub prepare_dir
241             {
242             my $self = shift;
243             my $file = shift;
244             my $folder = dirname $file;
245            
246             unless ( -d $folder )
247             {
248             use File::Path;
249             unless(mkpath $folder)
250             {
251             warn "could not create $folder";
252             return;
253             }
254             }
255             return $folder;
256             }
257             1;