File Coverage

blib/lib/Catmandu/Importer/Atom.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Catmandu::Importer::Atom;
2              
3 1     1   18678 use namespace::clean;
  1         11972  
  1         5  
4 1     1   514 use Catmandu::Sane;
  1         64390  
  1         5  
5 1     1   796 use Catmandu::Util qw(trim);
  1         34282  
  1         117  
6 1     1   154 use XML::Atom::Client;
  0            
  0            
7             use Moo;
8              
9             with 'Catmandu::Importer';
10              
11             my $ENTRY_ATTRS = [qw(id title published updated summary rights)];
12             my $CONTENT_ATTRS = [qw(mode type body)];
13             my $PERSON_ATTRS = [qw(name email uri homepage)];
14             my $LINK_ATTRS = [qw(rel href hreflang title type length)];
15             my $CATEGORY_ATTRS = [qw(term label scheme)];
16              
17             has url => (is => 'ro', required => 1);
18             has entries => (is => 'ro', init_arg => undef, lazy => 1, builder => '_build_entries');
19              
20             sub _build_entries {
21             my $self = $_[0];
22             my $feed = XML::Atom::Client->new->getFeed($self->url);
23             [map {
24             my $entry = $_;
25             my $entry_data = {};
26             for my $key (@$ENTRY_ATTRS) {
27             $entry_data->{$key} = trim($entry->$key || next) || next;
28             }
29             if (my $content = $entry->content) {
30             for my $key (@$CONTENT_ATTRS) {
31             $entry_data->{content}{$key} = trim($content->$key || next) || next;
32             }
33             }
34             if (my $author = $entry->author) {
35             for my $key (@$PERSON_ATTRS) {
36             $entry_data->{author}{$key} = trim($author->$key || next) || next;
37             }
38             }
39             if (my $contributor = $entry->contributor) {
40             for my $key (@$PERSON_ATTRS) {
41             $entry_data->{contributor}{$key} = trim($contributor->$key || next) || next;
42             }
43             }
44             if (my @category = $entry->category) {
45             $entry_data->{category} = [map {
46             my $category = $_;
47             my $category_data = {};
48             for my $key (@$CATEGORY_ATTRS) {
49             $category_data->{$key} = trim($category->$key || next) || next;
50             }
51             $category_data;
52             } @category];
53             }
54             if (my @links = $entry->link) {
55             $entry_data->{link} = [map {
56             my $link = $_;
57             my $link_data = {};
58             for my $key (@$LINK_ATTRS) {
59             $link_data->{$key} = trim($link->$key || next) || next;
60             }
61             $link_data;
62             } @links];
63             }
64             for my $node ($entry->elem->childNodes) {
65             my $uri = $node->namespaceURI;
66             next if (! $uri || $uri eq 'http://purl.org/atom/ns#');
67             my $name = $node->nodeName;
68             my $value = $node->textContent;
69             $entry_data->{$name} = $value;
70             }
71             $entry_data;
72             } $feed->entries];
73             }
74              
75             sub to_array { goto &entries }
76              
77             sub generator {
78             my ($self) = @_;
79             my $n = 0;
80             sub {
81             $self->entries->[$n++];
82             };
83             }
84              
85             =head1 NAME
86              
87             Catmandu::Importer::Atom - Package that imports Atom feeds
88              
89             =head1 SYNOPSIS
90              
91             use Catmandu::Importer::Atom;
92              
93             my $importer = Catmandu::Importer::Atom->new(url => "...");
94              
95             my $n = $importer->each(sub {
96             my $hashref = $_[0];
97             # ...
98             });
99              
100             =head1 DATA MODEL
101              
102             Each parsed Atom entry is transformed into a hash ref:
103              
104             {
105             id => '...' ,
106             title => '...' ,
107             published => '...' ,
108             updated => '...' ,
109             summary => '...' ,
110             rights => '...' ,
111             content => {
112             mode => '...' ,
113             type => '...' ,
114             body => '...' ,
115             } ,
116             author => {
117             name => '...' ,
118             email => '...' ,
119             uri => '...' ,
120             homepage => '...' ,
121             } ,
122             contributor => {
123             name => '...' ,
124             email => '...' ,
125             uri => '...' ,
126             homepage => '...' ,
127             } ,
128             category => [
129             { term => '...' , label => '...' , scheme => '....' } ,
130             ],
131             link => [
132             { rel => '...' , href => '...' , hreflang => '...' ,
133             title => '...' , type => '...' , length => '...'} ,
134             ],
135             <>
136             }
137              
138             =head1 METHODS
139              
140             =head2 new(url => URL,[entries => [qw(...)])
141              
142             Create a new Atom importer for the URL. Optionally provide a entries parameter with the
143             feed items you want to import.
144              
145             =head2 count
146              
147             =head2 each(&callback)
148              
149             =head2 ...
150              
151             Every Catmandu::Importer is a Catmandu::Iterable all its methods are inherited. The
152             Catmandu::Importer::Atom methods are not idempotent: Atom feeds can only be read once.
153              
154             =head1 SEE ALSO
155              
156             L
157              
158             =cut
159              
160             1;