File Coverage

blib/lib/Flickr/Embed.pm
Criterion Covered Total %
statement 15 74 20.2
branch 2 32 6.2
condition 0 17 0.0
subroutine 5 9 55.5
pod 1 1 100.0
total 23 133 17.2


line stmt bran cond sub pod time code
1             package Flickr::Embed;
2              
3 1     1   741 use strict;
  1         2  
  1         89  
4 1     1   6 use warnings;
  1         2  
  1         27  
5 1     1   1186 use Flickr::API;
  1         106126  
  1         28  
6 1     1   933 use HTML::Entities;
  1         6333  
  1         1015  
7             our $VERSION = 0.01;
8             require 5.005;
9              
10             sub _get_cc_licences {
11 0     0   0 my ($xml) = @_;
12              
13 0         0 my @creativecommons;
14             my %licence_names;
15              
16 0         0 for my $e (@$xml) {
17 0 0 0     0 if ($e->{name} && $e->{name} eq 'licenses') {
18 0         0 for my $c (@{$e->{children}}) {
  0         0  
19 0 0 0     0 next unless $c->{name} && $c->{name} eq 'license';
20 0 0       0 if (index($c->{attributes}->{url}, 'creativecommons')!=-1) {
21 0         0 push @creativecommons, $c->{attributes}->{'id'};
22 0         0 $licence_names{$c->{attributes}->{id}} = $c->{attributes}->{name};
23             }
24             }
25             }
26             }
27              
28 0         0 return (join (',', @creativecommons), \%licence_names);
29             }
30              
31             sub _safe_execute {
32 0     0   0 my ($api, $method, @params) = @_;
33              
34 0         0 my $response = $api->execute_method($method, @params);
35              
36 0 0       0 die "Flickr::Embed ($method) " . $response->{error_message} unless $response->{success};
37              
38 0         0 return $response;
39             }
40              
41             sub _fish_out_attributes {
42 0     0   0 my ($tree) = @_;
43              
44 0         0 my @result;
45              
46 0 0       0 if (ref($tree) eq 'HASH') {
    0          
47              
48 0 0       0 push @result, $tree->{attributes} if $tree->{attributes};
49              
50 0 0       0 push @result, _fish_out_attributes ($tree->{children}) if $tree->{children};
51              
52              
53             } elsif (ref($tree) eq 'ARRAY') {
54 0         0 @result = map { _fish_out_attributes($_) } @$tree;
  0         0  
55             }
56              
57 0         0 return @result;
58             }
59              
60             sub _photo_details {
61 0     0   0 my ($api, $id) = @_;
62              
63 0         0 my %result;
64              
65 0         0 my $response = _safe_execute($api, 'flickr.photos.getSizes',
66             {photo_id => $id,}
67             );
68              
69 0         0 my @attrs = _fish_out_attributes($response->{tree});
70              
71 0         0 for (@attrs) {
72 0 0 0     0 %result = (%result, %$_) if
      0        
73             $_->{candownload} ||
74             ($_->{label} && $_->{label} eq 'Medium');
75             }
76              
77 0         0 return %result;
78             }
79              
80             sub embed {
81 1     1 1 38 my (%opts) = @_;
82              
83 1         3 for (qw(tags key secret)) {
84 2 100       18 die "Flickr::Embed::embed: $_ parameter is required"
85             unless $opts{$_};
86             }
87              
88 0           my %exclusions;
89              
90 0 0         %exclusions = map { $_=>1 } @{$opts{exclude}} if $opts{exclude};
  0            
  0            
91              
92 0           my $api = new Flickr::API({
93             key => $opts{key},
94             secret => $opts{secret},
95             });
96              
97 0           my $response = _safe_execute($api, 'flickr.photos.licenses.getInfo');
98              
99 0           my ($cc_licences, $licence_names) = _get_cc_licences($response->{tree}->{children});
100              
101 0   0       $response = _safe_execute($api, 'flickr.photos.search',
102             {tags => $opts{tags},
103             tag_mode => 'all',
104             license => $cc_licences,
105             per_page => $opts{per_page} || '100',
106             extras => 'license,owner_name',}
107             );
108              
109 0           my @photos;
110              
111 0           for (@{ $response->{tree}->{children} }) {
  0            
112 0           @photos = map {
113 0 0         $_->{attributes}
114             } grep {
115 0           $_->{name} && $_->{name} eq 'photo'
116 0 0 0       } @{ $_->{children} } if ($_->{name} && $_->{name} eq 'photos');
117             }
118              
119 0           my @result;
120              
121 0           for (@photos) {
122 0 0         next if $exclusions{$_->{id}};
123              
124 0           my %result = (
125             %$_,
126             _photo_details($api, $_->{id}),
127             );
128              
129             # should honour $result{canblog} here, but it's always 0 even on
130             # cc photos.
131              
132 0           my $title = encode_entities($result{title});
133 0           my $author = encode_entities($result{ownername});
134 0           my $url = $result{url};
135              
136 0           $url =~ s!sizes/./!!;
137              
138 0           $result{html} = "
139             "href=\"$result{source}\">" .
140             "\"$title\"
141             "width=\"$result{width}\" height=\"$result{height}\" align=\"right\" />";
142              
143 0           $result{attribution} = "Copyright © $author. ".
144             $licence_names->{$result{license}};
145              
146 0           push @result, \%result;
147              
148 0 0         last unless wantarray;
149             }
150              
151             # later, if result==(), and we've excluded any, go round and get the next ones
152              
153 0 0         return $result[0] unless wantarray;
154 0           return @result;
155             }
156              
157             1;
158              
159             =head1 NAME
160              
161             Flickr::Embed - Simple embedding of Flickr pictures into HTML
162              
163             =head1 SYNOPSIS
164              
165             use Flickr::Embed;
166              
167             my $fe = Flickr::Embed::embed(
168             tags=>'carrots',
169             key=>'key',
170             secret=>'secret',
171             );
172              
173             my $blog = "$fe{html}This is a post which will appear on my blog.".
174             "
$fe{attribution}";
175              
176             =head1 DESCRIPTION
177              
178             When you have an automated system to produce blog posts, sometimes you
179             want to attach random pictures to it on some theme or other. For example,
180             you might post the output of your unit tests every day and decide it would
181             look good if each one had a different picture of a camel next to it.
182             C will look up your search terms on Flickr and return a
183             given picture each time.
184              
185             =head1 SYNOPSIS
186              
187             =head2 embed()
188              
189             Returns a hash of information taken from Flickr. In list context, returns
190             everything it received from Flickr, subject to exclusions. In scalar context,
191             returns just the first one, subject to exclusions. The return type is
192             described in THE CONTENTS OF THE HASH, below. Takes a set of named parameters,
193             described below.
194              
195             =head1 PARAMETERS TO THE EMBED FUNCTION
196              
197             =head2 key
198              
199             A Flickr API key. See WHERE TO GET A KEY, below. Required.
200              
201             =head2 secret
202              
203             A Flickr API secret. See WHERE TO GET A KEY, below. Required.
204              
205             =head2 tags
206              
207             Tags to look for. Separate multiple tags with commas; only pictures which
208             match all given tags will be returned. Required.
209              
210             =head2 exclude
211              
212             An arrayref of IDs of photos not to retrieve, presumably because you've seen them
213             already.
214              
215             =head2 per_page
216              
217             How many photos to return (if this call is in list context). You will get at most
218             this many; if any exclusions match, or if there aren't enough photos on Flickr
219             with the given tags, you will get fewer.
220              
221             =head1 THE CONTENTS OF THE HASH
222              
223             =head2 html
224              
225             A block of HTML ready to paste into a blog post.
226              
227             =head2 attribution
228              
229             An attribution of the author, including the licence. Most Creative Commons licences
230             require attribution, and anyway it's good manners, so be sure to put this in
231             somewhere.
232              
233             =head2 Everything returned by flickr.photos.Search
234              
235             for this photo, and and also
236              
237             =head2 Everything returned by flickr.photos.getSizes
238              
239             for the current size; see the Flickr API documentation.
240              
241             =head1 WHERE TO GET A KEY
242              
243             http://www.flickr.com/services/api/keys/apply/
244              
245             If you don't have this, most of the tests will be skipped.
246              
247             =head1 BUGS
248              
249             If you exclude all the pictures in the first fetch, C does not yet
250             go back and get another batch; it behaves as if there were no pictures found.
251             By default this will only happen if you have at least 100 exclusions.
252             This will be fixed in a later release.
253              
254             =head1 SEE ALSO
255              
256             C.
257              
258             =head1 AUTHOR
259              
260             Thomas Thurman, tthurman@gnome.org.
261              
262             =head1 COPYRIGHT
263              
264             This Perl module is copyright (C) Thomas Thurman, 2009.
265             This is free software, and can be used/modified under the same terms as Perl itself.