Skip to content

Commit b1aa7a6

Browse files
committed
Multiple enclosure support
1 parent 3e19dc0 commit b1aa7a6

File tree

9 files changed

+102
-13
lines changed

9 files changed

+102
-13
lines changed

Build.PL

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ my $build = Module::Build
1919
'URI::Fetch' => 0,
2020
'XML::Atom' => '0.32',
2121
'XML::LibXML' => '1.66',
22-
'XML::RSS' => '1.40',
22+
'XML::RSS' => '1.44',
2323
'Test::More' => 0,
2424
},
2525
create_makefile_pl => 'traditional',

Changes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
Revision history for XML::Feed
44

5+
0.43
6+
- Add optional multi enclosure support
7+
58
0.42
69
- Fix conversion of multi value fields
710
http://rt.cpan.org/Ticket/Display.html?id=41794

MANIFEST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ t/12-multi-categories.base
2828
t/12-multi-subjects-rss.t
2929
t/13-category-hash-bug.t
3030
t/14-enclosures.t
31+
t/14-multi-enclosures.t
3132
t/pod-coverage.t
3233
t/pod.t
3334
t/samples/atom-10-example.xml

lib/XML/Feed.pm

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use Module::Pluggable search_path => "XML::Feed::Format",
1212
require => 1,
1313
sub_name => 'formatters';
1414

15-
our $VERSION = '0.42';
15+
our $VERSION = '0.43';
16+
our $MULTIPLE_ENCLOSURES = 0;
1617
our @formatters;
1718
BEGIN {
1819
@formatters = __PACKAGE__->formatters;
@@ -366,8 +367,21 @@ B<Note:> this will only work for parsing feeds, not creating feeds.
366367
367368
B<Note:> Only C<XML::RSS::LibXML> version 0.3004 is known to work at the moment.
368369
370+
=item C<$XML::Feed::MULTIPLE_ENCLOSURES>
371+
372+
Although the RSS specification states that there can be at most one enclosure per item
373+
some feeds break this rule.
374+
375+
If this variable is set then C<XML::Feed> captures all of them and makes them available as a list.
376+
377+
Otherwise it returns the last enclosure parsed.
378+
379+
B<Note:> C<XML::RSS> version 1.44 is needed for this to work.
380+
369381
=back
370382
383+
=cut
384+
371385
=head1 VALID FEEDS
372386
373387
For reference, this cgi script will create valid, albeit nonsensical feeds

lib/XML/Feed/Format/Atom.pm

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,15 +299,16 @@ sub enclosure {
299299

300300
if (@_) {
301301
my $enclosure = shift;
302-
# TODO Atom can have multiple enclosures
303-
$entry->{entry}->link({ rel => 'enclosure', href => $enclosure->{url},
302+
my $method = ($XML::Feed::MULTIPLE_ENCLOSURES)? 'add_link' : 'link';
303+
$entry->{entry}->$method({ rel => 'enclosure', href => $enclosure->{url},
304304
length => $enclosure->{length},
305305
type => $enclosure->{type} });
306306
return 1;
307307
} else {
308-
my $l = first { defined $_->rel && $_->rel eq 'enclosure' } $entry->{entry}->link;
309-
return undef unless $l;
310-
return XML::Feed::Enclosure->new({ url => $l->href, length => $l->length, type => $l->type });
308+
my @links = grep { defined $_->rel && $_->rel eq 'enclosure' } $entry->{entry}->link;
309+
return undef unless @links;
310+
my @encs = map { XML::Feed::Enclosure->new({ url => $_->href, length => $_->length, type => $_->type }) } @links ;
311+
return ($XML::Feed::MULTIPLE_ENCLOSURES)? @encs : $encs[-1];
311312
}
312313
}
313314

lib/XML/Feed/Format/RSS.pm

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,12 @@ sub init_string {
3333
my $feed = shift;
3434
my($str) = @_;
3535
$feed->init_empty;
36+
my $opts = {
37+
hashrefs_instead_of_strings => 1,
38+
};
39+
$opts->{allow_multiple} = [ 'enclosure' ] if $XML::Feed::MULTIPLE_ENCLOSURES;
3640
if ($str) {
37-
$feed->{rss}->parse($$str, { hashrefs_instead_of_strings => 1 } );
41+
$feed->{rss}->parse($$str, $opts );
3842
}
3943
$feed;
4044
}
@@ -334,13 +338,20 @@ sub enclosure {
334338

335339
if (@_) {
336340
my $enclosure = shift;
337-
$entry->{entry}->{enclosure} = {
341+
my $val = {
338342
url => $enclosure->{url},
339343
type => $enclosure->{type},
340344
length => $enclosure->{length}
341-
};
345+
};
346+
if ($XML::Feed::MULTIPLE_ENCLOSURES) {
347+
push @{$entry->{entry}->{enclosure}}, $val;
348+
} else {
349+
$entry->{entry}->{enclosure} = $val;
350+
}
342351
} else {
343-
return XML::Feed::Enclosure->new($entry->{entry}->{enclosure});
352+
my $tmp = $entry->{entry}->{enclosure};
353+
my @encs = map { XML::Feed::Enclosure->new($_) } (ref $tmp eq 'ARRAY')? @$tmp : ($tmp);
354+
return ($XML::Feed::MULTIPLE_ENCLOSURES)? @encs : $encs[-1];
344355
}
345356
}
346357

t/14-multi-enclosures.t

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!perl -w
2+
3+
use strict;
4+
use Test::More;
5+
use XML::Feed;
6+
use XML::Feed::Enclosure;
7+
8+
$XML::Feed::MULTIPLE_ENCLOSURES=1;
9+
10+
my @formats = qw(atom rss20);
11+
plan tests => scalar(@formats)*38;
12+
13+
foreach my $format (@formats) {
14+
ok (my $feed = XML::Feed->parse("t/samples/$format-multi-enclosure.xml"), "Parsed $format");
15+
my ($entry) = $feed->entries;
16+
ok (my @enclosures = $entry->enclosure, "Got enclosure");
17+
ok ($enclosures[0]->isa("XML::Feed::Enclosure"), "Object isa XML::Feed::Enclosure");
18+
is ($enclosures[0]->type, "audio/mpeg", "Got the enclosure mime type");
19+
is ($enclosures[0]->length, "2478719", "Got enclosure length");
20+
is ($enclosures[0]->url, "http://example.com/sample_podcast.mp3", "Got enclosure url");
21+
ok ($enclosures[1]->isa("XML::Feed::Enclosure"), "Object isa XML::Feed::Enclosure");
22+
is ($enclosures[1]->type, "video/mpeg", "Got the enclosure mime type");
23+
is ($enclosures[1]->length, "8888", "Got enclosure length");
24+
is ($enclosures[1]->url, "http://example.com/sample_movie.mpg", "Got enclosure url");
25+
26+
ok (my $tmp = XML::Feed::Enclosure->new({ type => "image/jpeg" }), "Created a new enclosure");
27+
is ($tmp->type, "image/jpeg", "Got type back");
28+
ok ($tmp->url("http://example.com/sample_image.jpg"), "Set url");
29+
ok ($tmp->length("1337"), "Set length");
30+
ok ($entry->enclosure($tmp), "Set the enclosure");
31+
32+
ok (@enclosures = $entry->enclosure, "Got enclosure again");
33+
ok ($enclosures[-1]->isa("XML::Feed::Enclosure"), "Object still isa XML::Feed::Enclosure");
34+
is ($enclosures[-1]->type, "image/jpeg", "Got the enclosure mime type");
35+
is ($enclosures[-1]->length, "1337", "Got enclosure length again");
36+
is ($enclosures[-1]->url, "http://example.com/sample_image.jpg", "Got enclosure url again");
37+
38+
my $xml = $feed->as_xml;
39+
ok ($feed = XML::Feed->parse(\$xml), "Parsed xml again");
40+
ok (@enclosures = $entry->enclosure, "Got enclosure again");
41+
ok ($enclosures[0]->isa("XML::Feed::Enclosure"), "Object isa XML::Feed::Enclosure");
42+
is ($enclosures[0]->type, "audio/mpeg", "Got the enclosure mime type");
43+
is ($enclosures[0]->length, "2478719", "Got enclosure length");
44+
is ($enclosures[0]->url, "http://example.com/sample_podcast.mp3", "Got enclosure url");
45+
ok ($enclosures[1]->isa("XML::Feed::Enclosure"), "Object isa XML::Feed::Enclosure");
46+
is ($enclosures[1]->type, "video/mpeg", "Got the enclosure mime type");
47+
is ($enclosures[1]->length, "8888", "Got enclosure length");
48+
is ($enclosures[1]->url, "http://example.com/sample_movie.mpg", "Got enclosure url");
49+
ok ($enclosures[2]->isa("XML::Feed::Enclosure"), "Object still isa XML::Feed::Enclosure");
50+
is ($enclosures[2]->type, "image/jpeg", "Got the enclosure mime type");
51+
is ($enclosures[2]->length, "1337", "Got enclosure length again");
52+
is ($enclosures[2]->url, "http://example.com/sample_image.jpg", "Got enclosure url again");
53+
ok ($enclosures[-1]->isa("XML::Feed::Enclosure"), "Object still isa XML::Feed::Enclosure");
54+
is ($enclosures[-1]->type, "image/jpeg", "Got the enclosure mime type");
55+
is ($enclosures[-1]->length, "1337", "Got enclosure length again");
56+
is ($enclosures[-1]->url, "http://example.com/sample_image.jpg", "Got enclosure url again");
57+
58+
59+
}

t/samples/atom-multi-enclosure.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<updated>2004-11-02T14:44:33</updated>
99
<content>description</content>
1010
<link rel="enclosure" href="http://example.com/sample_podcast.mp3" length="2478719" type="audio/mpeg" />
11-
<link rel="enclosure" href="http://example.com/sample_movie.mpg" length="2478719" type="video/mpeg" />
11+
<link rel="enclosure" href="http://example.com/sample_movie.mpg" length="8888" type="video/mpeg" />
1212
</entry>
1313
</feed>
1414

t/samples/rss20-multi-enclosure.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<pubDate>Tue, 02 Nov 2004 09:44:33 -0500</pubDate>
1212
<description>description</description>
1313
<enclosure url="http://example.com/sample_podcast.mp3" length="2478719" type="audio/mpeg" />
14-
<enclosure url="http://example.com/sample_movie.mpg" length="2478719" type="video/mpeg" />
14+
<enclosure url="http://example.com/sample_movie.mpg" length="8888" type="video/mpeg" />
1515
</item>
1616
</channel>
1717
</rss>

0 commit comments

Comments
 (0)