File Coverage

blib/lib/Bootylicious/Plugin/Gallery.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Bootylicious::Plugin::Gallery;
2              
3 1     1   53717 use strict;
  1         3  
  1         45  
4 1     1   7 use warnings;
  1         2  
  1         31  
5 1     1   5 use base 'Mojolicious::Plugin';
  1         7  
  1         1138  
6              
7 1     1   14535 use Digest::MD5 qw( md5_hex );
  1         2  
  1         56  
8 1     1   1062 use Image::Magick::Thumbnail::Fixed;
  0            
  0            
9              
10             our $VERSION = '0.07';
11              
12             my %content_types = (
13             'jpg' => 'image/jpeg',
14             'jpeg' => 'image/jpeg',
15             'gif' => 'image/gif',
16             'png' => 'image/png'
17             );
18              
19             __PACKAGE__->attr('public_uri' => '/');
20             __PACKAGE__->attr('string_to_replace' => '%INSERT_GALLERY_HERE%');
21             __PACKAGE__->attr('columns' => 3);
22             __PACKAGE__->attr('thumb_width' => 144);
23             __PACKAGE__->attr('thumb_height' => 144);
24             __PACKAGE__->attr('bgcolor' => 'white');
25             __PACKAGE__->attr('padding' => 4);
26             __PACKAGE__->attr('imagetypes' => join('|', keys %content_types))
27             ; # build the list of valid image types
28              
29              
30             sub register {
31             my ($self, $app, $args) = @_;
32             $args ||= {};
33            
34             $self->public_uri($args->{'public_uri'} ) if $args->{'public_uri'};
35             $self->string_to_replace($args->{'string_to_replace'} ) if $args->{'string_to_replace'};
36             $self->columns($args->{'columns'} ) if $args->{'columns'};
37             $self->thumb_width($args->{'thumb_width'} ) if $args->{'thumb_width'};
38             $self->thumb_height($args->{'thumb_height'} ) if $args->{'thumb_height'};
39             $self->bgcolor($args->{'bgcolor'} ) if $args->{'bgcolor'};
40             $self->padding($args->{'padding'} ) if $args->{'padding'};
41             $self->imagetypes($args->{'imagetypes'} ) if $args->{'imagetypes'};
42            
43             $app->plugins->add_hook(after_dispatch => sub { shift; $self->gallery(@_) });
44             }
45              
46             sub gallery {
47             my $self = shift;
48             my $c = shift;
49             my $path = $c->req->url->path;
50              
51             return unless $path =~ /^\/articles/;
52              
53             $c->app->log->debug('imagetypes ' . $self->imagetypes);
54             my $publicdir = $c->app->home->rel_dir(main::config('publicdir'));
55              
56             my $article = $c->stash('article');
57             my $gallery_name = sprintf("%d%02d%02d-%s",$article->{year}, $article->{month}, $article->{day}, $article->{name});
58             my $gallerydir = $publicdir . '/' . $gallery_name;
59              
60             #not gallery article
61             unless (-d $gallerydir) {
62             $c->app->log->debug("Not a gallery article: $gallerydir");
63             return;
64             }
65              
66             my $cached_dir = $gallerydir . '/' . 'thumbs';
67             if (!-d $cached_dir) {
68             unless (mkdir($cached_dir)) {
69             $c->app->log->warn("Couldn't make dir $cached_dir: $!");
70             return;
71             }
72              
73             }
74             $c->stash('gallery_name' => $gallery_name);
75             $self->_print_gallery_thumbs(
76             $c,
77             { 'gallerydir' => $gallerydir,
78             'publicdir' => $publicdir,
79             'gallery_name' => $gallery_name,
80             'cached_dir' => $cached_dir,
81             }
82             );
83             }
84              
85             sub _print_gallery_thumbs {
86             my $self = shift;
87             my $c = shift;
88             my $opts = shift;
89              
90             my $publicdir = $opts->{publicdir};
91             my $gallerydir = $opts->{gallerydir};
92             my $cached_dir = $opts->{cached_dir};
93              
94             my @all_imgs = $self->_find_images($c, $opts->{gallerydir});
95              
96             my @images = ();
97             foreach my $img (@all_imgs) {
98             my $hashed_file = $self->_get_hashed_filename($c, $img);
99             next unless $hashed_file;
100              
101             $self->_cache_image(
102             $c,
103             { 'source_file' => "$opts->{gallerydir}/$img",
104             'cached_file' => "$opts->{cached_dir}/$hashed_file"
105             }
106             );
107              
108             my $thumbnail_url = $self->_build_thumb_url($c, $hashed_file);
109             my $large_url = $self->_build_img_url($c, $img);
110              
111             push(@images,
112             {'thumbnail_url' => $thumbnail_url, 'large_url' => $large_url});
113             }
114             $c->stash('images' => \@images);
115             $c->stash(
116             'columns' => $self->columns,
117             'padding' => $self->padding,
118             'bgcolor' => $self->bgcolor
119             );
120              
121             my $gallery_html =
122             $c->render_partial('gallery', template_class => __PACKAGE__);
123             my $body = $c->res->body;
124             my $str_replace = $self->string_to_replace;
125             $body =~ s/$str_replace/$gallery_html/;
126             $c->res->body($body);
127             }
128              
129             sub _build_thumb_url {
130             my $self = shift;
131             my $c = shift;
132             my $file = shift;
133              
134             return $self->public_uri . $c->stash('gallery_name') . '/thumbs/' . $file;
135             }
136              
137             sub _build_img_url {
138             my $self = shift;
139             my $c = shift;
140             my $file = shift;
141              
142             return $self->public_uri . $c->stash('gallery_name') . '/' . $file;
143             }
144              
145             sub _get_hashed_filename {
146             my ($self, $c, $img_path) = @_;
147              
148             my ($extension) = $img_path =~ m|\.(\w+)$| or return undef;
149             return (md5_hex($img_path) . ".$extension");
150             }
151              
152             sub _cache_image {
153             my ($self, $c, $opts) = @_;
154              
155             return
156             if (-e $opts->{cached_file})
157             && ((stat($opts->{source_file}))[9] < (stat($opts->{cached_file}))[9]);
158              
159              
160             return $self->_create_thubnail($c, $opts);
161             }
162              
163             sub _create_thubnail {
164             my $self = shift;
165             my $c = shift;
166             my $opts = shift;
167              
168             my $t = Image::Magick::Thumbnail::Fixed->new();
169              
170             $t->thumbnail(
171             input => $opts->{source_file},
172             output => $opts->{cached_file},
173             width => $self->thumb_width,
174             height => $self->thumb_height,
175             bgcolor => $self->bgcolor,
176             );
177              
178             return;
179             }
180              
181              
182             sub _find_images {
183             my ($self, $c, $path) = @_;
184              
185             unless (opendir(DIR, $path)) {
186             $c->app->log->warn("Couldn't open dir $path: $!");
187             return ();
188             }
189              
190             my @images;
191             my $imagetypes = $self->imagetypes;
192             foreach my $dentry (readdir(DIR)) {
193             my $can_read = -r "$path/$dentry";
194             if ($dentry =~ m{\.(?:$imagetypes)$}io && $can_read) {
195             push(@images, $dentry);
196             }
197             }
198              
199             unless (closedir(DIR)) {
200             $c->app->log->warn("Couldn't close dir $path: $!");
201             }
202              
203             return sort { $a cmp $b } @images;
204             }
205              
206              
207             1;
208             __DATA__