e15b841b79e236c3ed89dbfc2ff87fee602f990c
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / WWW / SuperCat / Feed.pm
1 package OpenILS::WWW::SuperCat::Feed;
2 use strict; use warnings;
3 use vars qw/$parser/;
4 use OpenSRF::EX qw(:try);
5 use XML::LibXML;
6 use CGI;
7
8 sub new {
9         my $class = shift;
10         my $type = shift;
11         if ($type) {
12                 $class .= '::'.$type;
13                 return $class->new;
14         }
15         throw OpenSRF::EX::ERROR ("I need a feed type!") ;
16 }
17
18 sub build {
19         my $class = shift;
20         my $xml = shift;
21
22         $parser = new XML::LibXML if (!$parser);
23
24         my $self = { doc => $parser->parse_string($xml), items => [] };
25
26         return bless $self => $class;
27 }
28
29 sub type {
30         my $self = shift;
31         my $type = shift;
32         $self->{type} = $type if ($type);
33         return $self->{type};
34 }
35
36 sub base {
37         my $self = shift;
38         my $base = shift;
39         $self->{base} = $base if ($base);
40         return $self->{base};
41 }
42
43 sub unapi {
44         my $self = shift;
45         my $unapi = shift;
46         $self->{unapi} = $unapi if ($unapi);
47         return $self->{unapi};
48 }
49
50 sub push_item {
51         my $self = shift;
52         push @{ $self->{items} }, @_;
53 }
54
55 sub items {
56         my $self = shift;
57         return @{ $self->{items} } if (wantarray);
58         return $self->{items};
59 }
60
61 sub _add_node {
62         my $self = shift;
63
64         my $xpath = shift;
65         my $new = shift;
66
67         for my $node ($self->{doc}->findnodes($xpath)) {
68                 $node->appendChild($new);
69                 last;
70         }
71 }
72
73 sub _create_node {
74         my $self = shift;
75
76         my $xpath = shift;
77         my $ns = shift;
78         my $name = shift;
79         my $text = shift;
80         my $attrs = shift;
81
82         for my $node ($self->{doc}->findnodes($xpath)) {
83                 my $new = $self->{doc}->createElement($name) if (!$ns);
84                 $new = $self->{doc}->createElementNS($ns,$name) if ($ns);
85
86                 $new->appendChild( $self->{doc}->createTextNode( $text ) )
87                         if (defined $text);
88
89                 if (ref($attrs)) {
90                         for my $key (keys %$attrs) {
91                                 $new->setAttribute( $key => $$attrs{$key} );
92                         }
93                 }
94
95                 $node->appendChild( $new );
96
97                 return $new;
98         }
99 }
100
101 sub add_item {
102         my $self = shift;
103         my $class = ref($self) || $self;
104         $class .= '::item';
105
106         my $item_xml = shift;
107         my $entry = $class->new($item_xml);
108
109         $entry->base($self->base);
110         $entry->unapi($self->unapi);
111
112         $self->push_item($entry);
113         return $entry;
114 }
115
116 sub toString {
117         my $self = shift;
118         for my $root ( $self->{doc}->findnodes($self->{item_xpath}) ) {
119                 for my $item ( $self->items ) {
120                         $root->appendChild( $item->{doc}->documentElement );
121                 }
122                 last;
123         }
124
125         return $self->{doc}->toString(1);
126 }
127
128 sub id {};
129 sub link {};
130 sub title {};
131 sub update_ts {};
132 sub creator {};
133
134 #----------------------------------------------------------
135
136 package OpenILS::WWW::SuperCat::Feed::atom;
137 use base 'OpenILS::WWW::SuperCat::Feed';
138
139 sub new {
140         my $class = shift;
141         my $self = $class->SUPER::build('<atom:feed xmlns:atom="http://www.w3.org/2005/Atom"/>');
142         $self->{type} = 'application/xml';
143         $self->{item_xpath} = '/atom:feed';
144         return $self;
145 }
146
147 sub title {
148         my $self = shift;
149         my $text = shift;
150         $self->_create_node('/atom:feed','http://www.w3.org/2005/Atom','atom:title', $text);
151 }
152
153 sub update_ts {
154         my $self = shift;
155         my $text = shift;
156         $self->_create_node('/atom:feed','http://www.w3.org/2005/Atom','atom:updated', $text);
157 }
158
159 sub creator {
160         my $self = shift;
161         my $text = shift;
162         $self->_create_node('/atom:feed','http://www.w3.org/2005/Atom','atom:author');
163         $self->_create_node('/atom:feed/atom:author', 'http://www.w3.org/2005/Atom','atom:name', $text);
164 }
165
166 sub link {
167         my $self = shift;
168         my $type = shift;
169         my $id = shift;
170         my $mime = shift || "application/$type+xml";
171
172         $type = 'self' if ($type eq 'atom');
173
174         $self->_create_node(
175                 $self->{item_xpath},
176                 'http://www.w3.org/2005/Atom',
177                 'atom:link',
178                 undef,
179                 { rel => $type,
180                   href => $id,
181                   type => $mime,
182                 }
183         );
184 }
185
186 sub id {
187         my $self = shift;
188         my $id = shift;
189
190         $self->_create_node( '/atom:feed', 'http://www.w3.org/2005/Atom', 'atom:id', $id );
191 }
192
193 package OpenILS::WWW::SuperCat::Feed::atom::item;
194 use base 'OpenILS::WWW::SuperCat::Feed::atom';
195
196 sub new {
197         my $class = shift;
198         my $xml = shift;
199         my $self = $class->SUPER::build($xml);
200         $self->{doc}->documentElement->setNamespace('http://www.w3.org/2005/Atom', 'atom');
201         $self->{item_xpath} = '/atom:entry';
202         $self->{type} = 'application/xml';
203         return $self;
204 }
205
206
207 #----------------------------------------------------------
208
209 package OpenILS::WWW::SuperCat::Feed::rss2;
210 use base 'OpenILS::WWW::SuperCat::Feed';
211
212 sub new {
213         my $class = shift;
214         my $self = $class->SUPER::build('<rss version="2.0"><channel/></rss>');
215         $self->{type} = 'application/xml';
216         $self->{item_xpath} = '/rss/channel';
217         return $self;
218 }
219
220 sub title {
221         my $self = shift;
222         my $text = shift;
223         $self->_create_node('/rss/channel',undef,'title', $text);
224 }
225
226 sub update_ts {
227         my $self = shift;
228         my $text = shift;
229         $self->_create_node('/rss/channel',undef,'lastBuildDate', $text);
230 }
231
232 sub creator {
233         my $self = shift;
234         my $text = shift;
235         $self->_create_node('/rss/channel', undef,'generator', $text);
236 }
237
238 sub link {
239         my $self = shift;
240         my $type = shift;
241         my $id = shift;
242         my $mime = shift || "application/$type+xml";
243
244         $type = 'self' if ($type eq 'rss2');
245
246         $self->_create_node(
247                 $self->{item_xpath},
248                 undef,
249                 'link',
250                 $id,
251                 { rel => $type,
252                   type => $mime,
253                 }
254         );
255 }
256
257 package OpenILS::WWW::SuperCat::Feed::rss2::item;
258 use base 'OpenILS::WWW::SuperCat::Feed::rss2';
259
260 sub new {
261         my $class = shift;
262         my $xml = shift;
263         my $self = $class->SUPER::build($xml);
264         $self->{type} = 'application/xml';
265         $self->{item_xpath} = '/item';
266         return $self;
267 }
268
269
270 #----------------------------------------------------------
271
272 package OpenILS::WWW::SuperCat::Feed::mods;
273 use base 'OpenILS::WWW::SuperCat::Feed';
274
275 sub new {
276         my $class = shift;
277         my $self = $class->SUPER::build('<mods:modsCollection version="3.0" xmlns:mods="http://www.loc.gov/mods/"/>');
278         $self->{type} = 'application/xml';
279         $self->{item_xpath} = '/mods:modsCollection';
280         return $self;
281 }
282
283 package OpenILS::WWW::SuperCat::Feed::mods::item;
284 use base 'OpenILS::WWW::SuperCat::Feed::mods';
285
286 sub new {
287         my $class = shift;
288         my $xml = shift;
289         my $self = $class->SUPER::build($xml);
290         $self->{doc}->documentElement->setNamespace('http://www.loc.gov/mods/', 'mods');
291         $self->{type} = 'application/xml';
292         return $self;
293 }
294
295 my $linkid = 1;
296
297 sub link {
298         my $self = shift;
299         my $type = shift;
300         my $id = shift;
301
302         if ($type eq 'unapi' || $type eq 'opac') {
303                 $self->_create_node(
304                         'mods:mods',
305                         'http://www.loc.gov/mods/',
306                         'mods:relatedItem',
307                         undef,
308                         { type => 'otherFormat', id => 'link-'.$linkid }
309                 );
310                 $self->_create_node(
311                         "mods:mods/mods:relatedItem[\@id='link-$linkid']",
312                         'http://www.loc.gov/mods/',
313                         'mods:recordIdentifier',
314                         $id
315                 );
316                 $linkid++;
317         }
318 }
319
320
321 #----------------------------------------------------------
322
323 package OpenILS::WWW::SuperCat::Feed::marcxml;
324 use base 'OpenILS::WWW::SuperCat::Feed';
325
326 sub new {
327         my $class = shift;
328         my $self = $class->SUPER::build('<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim"/>');
329         $self->{type} = 'application/xml';
330         $self->{item_xpath} = '/marc:collection';
331         return $self;
332 }
333
334 package OpenILS::WWW::SuperCat::Feed::marcxml::item;
335 use base 'OpenILS::WWW::SuperCat::Feed::marcxml';
336
337 sub new {
338         my $class = shift;
339         my $xml = shift;
340         my $self = $class->SUPER::build($xml);
341         $self->{doc}->documentElement->setNamespace('http://www.loc.gov/MARC21/slim', 'marc');
342         $self->{type} = 'application/xml';
343         return $self;
344 }
345
346 #----------------------------------------------------------
347
348 package OpenILS::WWW::SuperCat::Feed::html;
349 use base 'OpenILS::WWW::SuperCat::Feed::atom';
350
351 sub new {
352         my $class = shift;
353         my $self = $class->SUPER::new;
354         $self->{type} = 'application/xml';
355         return $self;
356 }
357
358
359 sub toString {
360         my $self = shift;
361         my $stuff = $self->SUPER::toString;
362         my $base = $self->base;
363         $stuff =~ s{\n}{\n<?xml-stylesheet href="../../../../os.xsl" type="text/xsl" ?>\n}so;
364         return $stuff;
365 }
366
367
368 package OpenILS::WWW::SuperCat::Feed::html::item;
369 use base 'OpenILS::WWW::SuperCat::Feed::atom::item';
370
371 1;