root/trunk/plagger/lib/Plagger/Plugin/Subscription/OPML.pm

Revision 1499 (checked in by miyagawa, 14 years ago)

Fixed Subscription::OPML bug that Conainers tag are not properly dereferenced. Added test.

  • Property svn:keywords set to Id Revision
Line 
1 package Plagger::Plugin::Subscription::OPML;
2 use strict;
3 use base qw( Plagger::Plugin );
4
5 use Plagger::Util;
6 use URI;
7 use XML::OPML;
8
9 our $HAS_LIBERAL;
10 BEGIN {
11     eval { require XML::Liberal; $HAS_LIBERAL = 1 };
12 }
13
14 sub register {
15     my($self, $context) = @_;
16
17     $context->register_hook(
18         $self,
19         'subscription.load' => \&load,
20     );
21 }
22
23 sub load {
24     my($self, $context) = @_;
25     my $uri = URI->new($self->conf->{url})
26         or $context->error("config 'url' is missing");
27
28     $self->load_opml($context, $uri);
29 }
30
31 sub load_opml {
32     my($self, $context, $uri) = @_;
33
34     my $xml = Plagger::Util::load_uri($uri, $self);
35
36     if ($HAS_LIBERAL) {
37         my $parser = XML::Liberal->new('LibXML');
38         my $doc = $parser->parse_string($xml);
39         $xml = $doc->toString;
40     }
41
42     my $opml = XML::OPML->new;
43     $opml->parse($xml);
44     for my $outline (@{ $opml->outline }) {
45         $self->walk_down($outline, $context, 0, []);
46     }
47 }
48
49 sub walk_down {
50     my($self, $outline, $context, $depth, $containers) = @_;
51
52     if (delete $outline->{opmlvalue}) {
53         my $title = delete $outline->{title} || delete $outline->{text};
54         push @$containers, $title if $title ne 'Subscriptions';
55         for my $channel (values %$outline) {
56             $self->walk_down($channel, $context, $depth + 1, $containers);
57         }
58         pop @$containers if $title ne 'Subscriptions';
59     } else {
60         my $feed = Plagger::Feed->new;
61         $feed->url($outline->{xmlUrl});
62         $feed->link($outline->{htmlUrl});
63         $feed->title($outline->{title} || $outline->{text});
64         $feed->tags([ @$containers ]);
65         $context->subscription->add($feed);
66     }
67 }
68
69 1;
70
71 __END__
72
73 =head1 NAME
74
75 Plagger::Plugin::Subscription::OPML - OPML subscription
76
77 =head1 SYNOPSIS
78
79   - module: Subscription::OPML
80     config:
81       url: http://example.com/mySubscriptions.opml
82
83 =head1 DESCRIPTION
84
85 This plugin creates Subscription by fetching remote OPML file by HTTP
86 or locally (with C<file://> URI). It supports nested folder structure
87 of OPML subscription.
88
89 =head1 AUTHOR
90
91 Tatsuhiko Miyagawa
92
93 =head1 SEE ALSO
94
95 L<Plagger>, L<XML::OPML>
96
97 =cut
Note: See TracBrowser for help on using the browser.