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