1 package WWW::OpenSearch::Response;
6 use base qw( HTTP::Response Class::Accessor::Fast );
10 use WWW::OpenSearch::Agent;
11 use WWW::OpenSearch::Request;
13 __PACKAGE__->mk_accessors( qw( feed pager ) );
17 WWW::OpenSearch::Response - Encapsulate a response received from
18 an A9 OpenSearch compatible engine
24 my $url = "http://bulkfeeds.net/opensearch.xml";
25 my $engine = WWW::OpenSearch->new($url);
27 # Retrieve page 4 of search results for "iPod"
28 my $response = $engine->search("iPod",{ startPage => 4 });
29 for my $item (@{$response->feed->items}) {
30 print $item->{description};
33 # Retrieve page 3 of results
34 $response = $response->previous_page;
36 # Retrieve page 5 of results
37 $response = $response->next_page;
41 WWW::OpenSearch::Response is a module designed to encapsulate a
42 response received from an A9 OpenSearch compatible engine.
43 See http://opensearch.a9.com/spec/1.1/response/ for details.
47 =head2 new( $response )
49 Constructs a new instance of WWW::OpenSearch::Response from the
50 WWWW::OpenSearch: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
89 =item * Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>
91 =item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
95 =head1 COPYRIGHT AND LICENSE
97 Copyright 2005-2009 by Tatsuhiko Miyagawa and Brian Cassidy
99 This library is free software; you can redistribute it and/or modify
100 it under the same terms as Perl itself.
106 my $response = shift;
108 my $self = bless $response, $class;
110 return $self unless $self->is_success;
112 $self->parse_response;
120 my $content = $self->content;
121 my $feed = XML::Feed->parse( \$content );
123 return if XML::Feed->errstr;
124 $self->feed( $feed );
131 my $pager = Data::Page->new;
133 my $feed = $self->feed;
134 my $format = $feed->format;
135 my $ns = $self->request->opensearch_url->ns;
138 # adapt these for any number of opensearch elements in
139 # the feed or in each entry
141 if ( my $atom = $feed->{ atom } ) {
142 my $total = $atom->get( $ns, 'totalResults' );
143 my $perpage = $atom->get( $ns, 'itemsPerPage' );
144 my $start = $atom->get( $ns, 'startIndex' );
146 $pager->total_entries( $total );
147 $pager->entries_per_page( $perpage );
148 $pager->current_page( $start ? ( $start - 1 ) / $perpage + 1 : 0 );
150 elsif ( my $rss = $feed->{ rss } ) {
151 if ( my $page = $rss->channel->{ $ns } ) {
152 $pager->total_entries( $page->{ totalResults } );
153 $pager->entries_per_page( $page->{ itemsPerPage } );
154 my $start = $page->{ startIndex };
155 $pager->current_page(
156 $start ? ( $start - 1 ) / $page->{ itemsPerPage } + 1 : 0 );
159 $self->pager( $pager );
164 return $self->_get_page( 'next' );
169 return $self->_get_page( 'previous' );
173 my ( $self, $direction ) = @_;
174 my $pager = $self->pager;
175 my $pagermethod = "${direction}_page";
176 my $page = $pager->$pagermethod;
180 my $osu = $self->request->opensearch_url;
182 # this code is too fragile -- deparse depends on the order of query
183 # params and the like. best just to use the last query params and
184 # do the paging from there.
186 # if( lc $osu->method ne 'post' ) { # force query build on POST
187 # my $link = $self->_get_link( $direction );
189 # $params = $osu->deparse( $link );
195 $params = $self->request->opensearch_params;
197 # handle paging via a page #
198 $params->{ startPage } = $page;
200 # handle paging via an index
201 if ( exists $params->{ startIndex } ) {
203 # start index is pre-existing
204 if ( $params->{ startIndex } ) {
205 if ( $direction eq 'previous' ) {
206 $params->{ startIndex } -= $pager->entries_per_page;
209 $params->{ startIndex } += $pager->entries_per_page;
213 # start index did not exist previously
215 if ( $direction eq 'previous' ) {
216 $params->{ startIndex } = 1;
219 $params->{ startIndex } = $pager->entries_per_page + 1;
226 my $agent = WWW::OpenSearch::Agent->new;
227 return $agent->search( WWW::OpenSearch::Request->new( $osu, $params ) );
233 my $feed = $self->feed->{ atom };
237 for ( $feed->link ) {
238 return $_->href if $_->rel eq $type;