1 package WWW::OpenSearch::Response;
6 use base qw( HTTP::Response Class::Accessor::Fast );
12 __PACKAGE__->mk_accessors( qw( feed pager parent ) );
16 WWW::OpenSearch::Response - Encapsulate a response received from
17 an A9 OpenSearch compatible engine
23 my $url = "http://bulkfeeds.net/opensearch.xml";
24 my $engine = WWW::OpenSearch->new($url);
26 # Retrieve page 4 of search results for "iPod"
27 my $response = $engine->search("iPod",{ startPage => 4 });
28 for my $item (@{$response->feed->items}) {
29 print $item->{description};
32 # Retrieve page 3 of results
33 $response = $response->previous_page;
35 # Retrieve page 5 of results
36 $response = $response->next_page;
40 WWW::OpenSearch::Response is a module designed to encapsulate a
41 response received from an A9 OpenSearch compatible engine.
42 See http://opensearch.a9.com/spec/1.1/response/ for details.
46 =head2 new( $parent, $response )
48 Constructs a new instance of WWW::OpenSearch::Response. Arguments
49 include the WWW::OpenSearch object which initiated the search (parent)
50 and the HTTP::Response returned by the search request.
54 =head2 parse_response( )
56 Parses the content of the HTTP response using XML::Feed. If successful,
57 parse_feed( ) is also called.
61 Parses the XML::Feed originally parsed from the HTTP response content.
62 Sets the pager object appropriately.
64 =head2 previous_page( ) / next_page( )
66 Performs another search on the parent object, returning a
67 WWW::OpenSearch::Response instance containing the previous/next page
68 of results. If the current response includes a <link rel="previous/next"
69 href="..." /> tag, the page will simply be the parsed content of the URL
70 specified by the tag's href attribute. However, if the current response does not
71 include the appropriate link, a new query is constructed using the startPage
72 or startIndex query arguments.
74 =head2 _get_link( $type )
76 Gets the href attribute of the first link whose rel attribute
91 =item * Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>
93 =item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
97 =head1 COPYRIGHT AND LICENSE
99 Copyright 2006 by Tatsuhiko Miyagawa and Brian Cassidy
101 This library is free software; you can redistribute it and/or modify
102 it under the same terms as Perl itself.
109 my $response = shift;
111 my $self = bless $response, $class;
113 $self->parent( $parent );
114 return $self unless $self->is_success;
116 $self->parse_response;
124 my $content = $self->content;
125 my $feed = XML::Feed->parse( \$content );
127 return if XML::Feed->errstr;
128 $self->feed( $feed );
135 my $pager = Data::Page->new;
137 my $feed = $self->feed;
138 my $format = $feed->format;
139 my $ns = $self->parent->description->ns;
142 # adapt these for any number of opensearch elements in
143 # the feed or in each entry
145 if( my $atom = $feed->{ atom } ) {
146 my $total = $atom->get( $ns, 'totalResults' );
147 my $perpage = $atom->get( $ns, 'itemsPerPage' );
148 my $start = $atom->get( $ns, 'startIndex' );
150 $pager->total_entries( $total );
151 $pager->entries_per_page( $perpage );
152 $pager->current_page( $start ? ( $start - 1 ) / $perpage + 1 : 0 )
154 elsif( my $rss = $feed->{ rss } ) {
155 if ( my $page = $rss->channel->{ $ns } ) {
156 $pager->total_entries( $page->{ totalResults } );
157 $pager->entries_per_page( $page->{ itemsPerPage } );
158 my $start = $page->{ startIndex };
159 $pager->current_page( $start ? ( $start - 1 ) / $page->{ itemsPerPage } + 1 : 0 )
162 $self->pager( $pager );
167 return $self->_get_page( 'next' );
172 return $self->_get_page( 'previous' );
176 my( $self, $direction ) = @_;
177 my $pager = $self->pager;
178 my $pagermethod = "${direction}_page";
179 my $page = $pager->$pagermethod;
182 my $request = $self->request;
183 my $method = lc $request->method;
185 if( $method ne 'post' ) { # force query build on POST
186 my $link = $self->_get_link( $direction );
187 return $self->parent->do_search( $link, $method ) if $link;
190 my $template = $self->parent->description->get_best_url;
191 my( $param, $query );
192 if( $method eq 'post' ) {
193 my $uri = URI->new( 'http://foo.com/?' . $request->content );
194 $query = { $uri->query_form };
197 $query = { $self->request->uri->query_form };
200 if( $param = $template->macros->{ startPage } ) {
201 $query->{ $param } = $pager->$pagermethod
203 elsif( $param = $template->macros->{ startIndex } ) {
204 if( $query->{ $param } ) {
205 $query->{ $param } = $direction eq 'previous'
206 ? $query->{ $param } -= $pager->entries_per_page
207 : $query->{ $param } += $pager->entries_per_page;
210 $query->{ $param } = $direction eq 'previous'
212 : $pager->entries_per_page + 1;
216 return $self->parent->do_search( $template->prepare_query( $query ), $method );
222 my $feed = $self->feed->{ atom };
227 return $_->get( 'href' ) if $_->get( 'rel' ) eq $type;