File Coverage

blib/lib/Yahoo/Search/Response.pm
Criterion Covered Total %
statement 6 101 5.9
branch 0 24 0.0
condition 0 10 0.0
subroutine 2 23 8.7
pod 19 20 95.0
total 27 178 15.1


line stmt bran cond sub pod time code
1             package Yahoo::Search::Response;
2 2     2   16 use strict;
  2         4  
  2         117  
3 2     2   1619 use Yahoo::Search::Result;
  2         7  
  2         3113  
4              
5             our $VERSION = "20100614.1"; # just to make CPAN happy
6              
7             =head1 NAME
8              
9              
10             =head1 VERSION
11              
12             version 1.11.3
13             Yahoo::Search::Response -- Container object for the result set of one query
14             to the Yahoo! Search API.
15             (This package is included in, and automatically loaded by, the Yahoo::Search package.)
16              
17             =head1 Package Use
18              
19             You never need to C this package directly -- it is loaded
20             automatically by Yahoo::Search.
21              
22             =head1 Object Creation
23              
24             C objects are created by the C method of a C
25             (Yahoo::Search::Request) object, e.g. by
26              
27             my $Response = Yahoo::Search->new(...)->Request()->Fetch();
28              
29             or by shortcuts to the same, such as:
30              
31             my $Response = Yahoo::Search->Query(...);
32              
33             =cut
34              
35             ##
36             ## Called from Request.pm after grokking the xml returned as the results of
37             ## a specific Request.
38             ##
39             sub new
40             {
41 0     0 0   my $class = shift;
42 0           my $Response = shift; # hashref of info
43              
44             ## We have the data; now bless it
45 0           bless $Response, $class;
46              
47             ## Initialize iterator for NextResult() method
48 0           $Response->{_NextIterator} = 0;
49              
50             ## But do a bit of cleanup and other preparation....
51 0 0         if (not $Response->{firstResultPosition}) {
52             ## Y! server bug -- this is sometimes empty
53 0           $Response->{firstResultPosition} = 1;
54             }
55              
56             ##
57             ## Fix up and bless each internal "Result" item -- turn into a Result
58             ## object. Set the ordinal to support the i() and I() methods.
59             ##
60 0           for (my $i = 0; $i < @{$Response->{Result}}; $i++)
  0            
61             {
62 0           my $Result = $Response->{Result}->[$i];
63              
64 0           $Result->{_ResponseOrdinal} = $i;
65 0           $Result->{_Response} = $Response;
66              
67             ##
68             ## Something like
69             ##
70             ## ends up being a ref to an empty hash. We'll remove those.
71             ##
72 0           for my $key (keys %$Result)
73             {
74 0 0 0       if (ref($Result->{$key}) eq "HASH"
  0            
75             and
76             not keys %{$Result->{$key}})
77             {
78 0           delete $Result->{$key};
79             }
80             }
81              
82 0           bless $Result, "Yahoo::Search::Result";
83             }
84              
85 0           return $Response;
86             }
87              
88              
89             =head1 Methods
90              
91             A C object has the following methods:
92              
93             =over 4
94              
95             =cut
96              
97              
98             ###########################################################################
99              
100             =item $Response->Count()
101              
102             Returns the number of C objects available in this C. See
103             Yahoo::Search::Result for details on C objects.
104              
105             =cut
106              
107             sub Count
108             {
109 0     0 1   my $Response = shift; #self;
110 0           return scalar @{$Response->{Result}};
  0            
111             }
112              
113              
114              
115              
116             ###########################################################################
117             sub _commaize($$)
118             {
119 0     0     my $num = shift;
120 0           my $comma = shift; # "," (English), "." (European), undef.....
121              
122 0 0         if ($comma) {
123 0           $num =~ s/(?<=\d)(?=(?:\d\d\d)+$)/$comma/g;
124             }
125 0           return $num;
126             }
127             ###########################################################################
128              
129             =item $Response->FirstOrdinal([ I ])
130              
131             Returns the index of the first C object (e.g. the "30" of I
132             30 through 40 out of 5,329>). This is the same as the C arg of the
133             C that generated this C.
134              
135             If an optional argument is given and is true, it is used as a separator
136             every three digits. In the US, one would use
137              
138             $Response->FirstOrdinal(',')
139              
140             to return, say, "1,230" instead of the "1230" that
141              
142             $Response->FirstOrdinal()
143              
144             might return.
145              
146             =cut
147              
148             sub FirstOrdinal
149             {
150 0     0 1   my $Response = shift; #self;
151 0           my $Comma = shift; # optional
152              
153             ## do the '-1' to convert from Y!'s 1-based system to our 0-based system
154 0   0       return _commaize(($Response->{firstResultPosition}||0) - 1, $Comma);
155             }
156              
157              
158              
159             ###########################################################################
160              
161             =item $Response->CountAvail([ I ])
162              
163             Returns an approximate number of total search results available, were you
164             to ask for them all (e.g. the "5329" of the I
165             5329>).
166              
167             If an optional argument is given and is true, it is used as a separator
168             every three digits. In the US, one would use
169              
170             $Response->CountAvail(',')
171              
172             to return, say, "5,329" instead of the "5329" that
173              
174             $Response->CountAvail()
175              
176             might return.
177              
178             =cut
179              
180             sub CountAvail
181             {
182 0     0 1   my $Response = shift; #self;
183 0           my $Comma = shift; # optional
184 0   0       return _commaize($Response->{totalResultsAvailable} || 0, $Comma)
185             }
186              
187              
188              
189             ###########################################################################
190              
191             =item $Response->Links()
192              
193             Returns a list of links from the response (one link per result):
194              
195             use Yahoo::Search;
196             if (my $Response = Yahoo::Search->Query(Doc => 'Britney'))
197             {
198             for my $link ($Response->Links) {
199             print "
$link\n";
200             }
201             }
202              
203             This prints one
204              
205            
title of the link
206              
207             line per result returned from the query.
208              
209             (I and B search results>)
210              
211             =cut
212              
213             sub Links
214             {
215 0     0 1   my $Response = shift; #self;
216 0           return map { $_->Link } $Response->Results;
  0            
217             }
218              
219              
220              
221              
222             ###########################################################################
223              
224             =item $Response->Terms()
225              
226             (I and B search results>)
227              
228             Returns a list of text terms.
229              
230             =cut
231              
232             sub Terms
233             {
234 0     0 1   my $Response = shift; #self;
235 0           return map { $_->Terms } $Response->Results;
  0            
236             }
237              
238              
239              
240              
241             ###########################################################################
242              
243             =item $Response->Results()
244              
245             Returns a list of Yahoo::Search::Result C objects representing
246             all the results held in this C. For example:
247              
248             use Yahoo::Search;
249             if (my $Response = Yahoo::Search->Query(Doc => 'Britney'))
250             {
251             for my $Result ($Response->Results) {
252             printf "%d: %s\n", $Result->I, $Result->Url;
253             }
254             }
255              
256             This is not valid for I and I searches.
257              
258             =cut
259              
260             sub Results
261             {
262 0     0 1   my $Response = shift; #self;
263 0           return @{$Response->{Result}};
  0            
264             }
265              
266              
267              
268              
269             ###########################################################################
270              
271             =item $Response->NextResult(options)
272              
273             Returns a C object, or nothing. (On error, returns nothing and sets
274             C<$@>.)
275              
276             The first time C is called for a given C object, it
277             returns the C object for the first result in the set. Returns
278             subsequent C objects for subsequent calls, until there are none
279             left, at which point what is returned depends upon whether the
280             auto-continuation feature is turned on (more on that in a moment).
281              
282             The following produces the same results as the C example above:
283              
284             use Yahoo::Search;
285             if (my $Response = Yahoo::Search->Query(Doc => 'Britney')) {
286             while (my $Result = $Response->NextResult) {
287             printf "%d: %s\n", $Result->I, $Result->Url;
288             }
289             }
290              
291             B
292              
293             If auto-continuation is turned on, then upon reaching the end of the result
294             set, C automatically fetches the next set of results and
295             returns I first result.
296              
297             This can be convenient, but B, as it means that a
298             loop which calls C, unless otherwise exited, will fetch results
299             from Yahoo! until there are no more results for the query, or until you
300             have exhausted your access limits.
301              
302             Auto-continuation can be turned on in several ways:
303              
304             =over 3
305              
306             =item *
307              
308             On a per C basis by calling as
309              
310             $Response->NextResult(AutoContinue => 1)
311              
312             as with this example
313              
314             use Yahoo::Search;
315             ##
316             ## WARNING: DANGEROUS DANGEROUS DANGEROUS
317             ##
318             if (my $Response = Yahoo::Search->Query(Doc => 'Britney')) {
319             while (my $Result = $Response->NextResult(AutoContinue => 1)) {
320             printf "%d: %s\n", $Result->I, $Result->Url;
321             }
322             }
323              
324              
325             =item *
326              
327             By using
328              
329             AutoContinue => 1
330              
331             when creating the request (e.g. in a Yahoo::Search->Query call), as
332             with this example:
333              
334             use Yahoo::Search;
335             ##
336             ## WARNING: DANGEROUS DANGEROUS DANGEROUS
337             ##
338             if (my $Response = Yahoo::Search->Query(Doc => 'Britney',
339             AutoContinue => 1))
340             {
341             while (my $Result = $Response->NextResult) {
342             printf "%d: %s\n", $Result->I, $Result->Url;
343             }
344             }
345              
346             =item *
347              
348             By creating a query via a search-engine object created with
349              
350             AutoContinue => 1
351              
352             as with this example:
353              
354             use Yahoo::Search;
355             ##
356             ## WARNING: DANGEROUS DANGEROUS DANGEROUS
357             ##
358             my $SearchEngine = Yahoo::Search->new(AutoContinue => 1);
359              
360             if (my $Response = $SearchEngine->Query(Doc => 'Britney')) {
361             while (my $Result = $Response->NextResult) {
362             printf "%d: %s\n", $Result->I, $Result->Url;
363             }
364             }
365              
366              
367             =item *
368              
369             By creating a query when Yahoo::Search had been loaded via:
370              
371             use Yahoo::Search AutoContinue => 1;
372              
373             as with this example:
374              
375             use Yahoo::Search AutoContinue => 1;
376             ##
377             ## WARNING: DANGEROUS DANGEROUS DANGEROUS
378             ##
379             if (my $Response = Yahoo::Search->Query(Doc => 'Britney')) {
380             while (my $Result = $Response->NextResult) {
381             printf "%d: %s\n", $Result->I, $Result->Url;
382             }
383             }
384              
385              
386             =back
387              
388              
389             All these examples are dangerous because they loop through results,
390             fetching more and more, until either all results that Yahoo! has for the
391             query at hand have been fetched, or the Yahoo! Search server access limits
392             have been reached and further access is denied. So, be sure to rate-limit
393             the accesses, or explicitly break out of the loop at some appropriate
394             point.
395              
396             =cut
397              
398             sub NextResult
399             {
400 0     0 1   my $Response = shift; #self;
401 0 0         if (@_ % 2 != 0) {
402 0           return Yahoo::Search::_carp_on_error("wrong number of args to NextResult");
403             }
404 0           my $AutoContinue = $Response->{_Request}->{AutoContinue};
405              
406             ## isolate args we allow...
407 0           my %Args = @_;
408 0 0         if (exists $Args{AutoContinue}) {
409 0           $AutoContinue = delete $Args{AutoContinue};
410             }
411              
412             ## anything left over is unexpected
413 0 0         if (%Args) {
414 0           my $list = join ', ', keys %Args;
415 0           return Yahoo::Search::_carp_on_error("unexpected args to NextResult: $list");
416             }
417              
418             ##
419             ## Setup is done -- now the real thing.
420             ## If the next slot is filled, return the result sitting there.
421             ##
422 0 0         if ($Response->{_NextIterator} < @{$Response->{Result}})
  0            
423             {
424 0           return $Response->{Result}->[$Response->{_NextIterator}++];
425             }
426              
427             ##
428             ## If we're auto-continuing and there is another response...
429             ##
430 0 0 0       if ($AutoContinue and my $next = $Response->NextResponse)
431             {
432             ## replace this $Response with the new one, _in_place_
433             ## (this destroys the old one)
434 0           %$Response = %$next;
435              
436             ## and return the first result from it...
437 0           return $Response->NextResult;
438             }
439              
440             ##
441             ## Oh well, reset the iterator and return nothing.
442             ##
443 0           $Response->{_NextIterator} = 0;
444 0           return ();
445             }
446              
447              
448             ###########################################################################
449              
450             =item $Response->Reset()
451              
452             Rests the iterator so that the next C returns the first of the
453             C object's C objects.
454              
455             =cut '
456              
457             sub Reset
458             {
459 0     0 1   my $Response = shift; #self;
460 0           $Response->{_NextIterator} = 0;
461             }
462              
463              
464              
465             ###########################################################################
466              
467             =item $Response->Request()
468              
469             Returns the C object from which this C object was
470             derived.
471              
472             =cut
473              
474             sub Request
475             {
476 0     0 1   my $Response = shift; #self;
477 0           return $Response->{_Request};
478             }
479              
480              
481             ###########################################################################
482              
483             =item $Response->NextRequest()
484              
485             Returns a C object which will fetch the subsequent set of results
486             (e.g. if the current C object represents the first 10 query
487             results, C returns a C object that represents a
488             query for the I 10 results.)
489              
490             Returns nothing if there were no results in the current C object
491             (thereby eliminating the possibility of there being a I result set).
492             On error, sets C<$@> and returns nothing.
493              
494             =cut
495              
496             sub NextRequest
497             {
498 0     0 1   my $Response = shift; #self
499              
500 0 0         if (not $Response->Count) {
501             ## No results last time, so can't expect any next time
502 0           return ();
503             }
504              
505 0 0         if ($Response->FirstOrdinal + $Response->Count >= $Response->CountAvail)
506             {
507             ## we have them all, so no reason to get more
508 0           return ();
509             }
510              
511 0 0         if ($Response->{_NoFurtherRequests}) {
512             ## no reason to get more
513 0           return ();
514             }
515              
516              
517             ## Make a copy of the request
518 0           my %Request = %{$Response->{_Request}};
  0            
519             ## want that copy to be deep
520 0           $Request{Params} = { %{$Request{Params}} };
  0            
521              
522             ## update the 'start' param
523 0           $Request{Params}->{start} += $Response->Count;
524              
525 0           return Yahoo::Search::Request->new(%Request);
526             }
527              
528              
529              
530             ###########################################################################
531              
532             =item $Response->NextResponse()
533              
534             Like C, but goes ahead and calls the C object's
535             C method to return the C object for the next set of results.
536              
537             =cut '
538              
539             sub NextResponse
540             {
541 0     0 1   my $Response = shift; #self
542              
543 0 0         if (my $Request = $Response->NextRequest) {
544 0           return $Request->Fetch();
545             } else {
546             # $@ must already be set
547 0           return ();
548             }
549             }
550              
551             ###########################################################################
552              
553             =item $Response->Uri()
554              
555             Returns the C object that was fetched to create this response.
556             It is the same as:
557              
558             $Response->Request->Uri()
559              
560             =cut
561              
562             sub Uri
563             {
564 0     0 1   my $Response = shift; #self;
565 0           return $Response->{_Request}->Uri;
566             }
567              
568              
569              
570              
571             ###########################################################################
572              
573             =item $Response->Url()
574              
575             Returns the url that was fetched to create this response.
576             It is the same as:
577              
578             $Response->Request->Url()
579              
580             =cut
581              
582             sub Url
583             {
584 0     0 1   my $Response = shift; #self;
585 0           return $Response->Request->Url;
586             }
587              
588              
589              
590             ###########################################################################
591              
592             =item $Response->RawXml()
593              
594             Returns a string holding the raw xml returned from the Yahoo! Search
595             servers.
596              
597             =cut
598              
599             sub RawXml
600             {
601 0     0 1   my $Response = shift; #self;
602 0           return $Response->{_XML};
603             }
604              
605             ##############################################################################
606              
607             =item $Response->MapUrl()
608              
609             Valid only for a I search, returns a url to a map showing all
610             results. (This is the same as each C object's C method.)
611              
612             =cut
613              
614             sub MapUrl
615             {
616 0     0 1   my $Response = shift; #self;
617 0           return $Response->{ResultSetMapUrl};
618             }
619              
620              
621              
622              
623             ##############################################################################
624              
625             =item $Response->RelatedRequest
626              
627             =item $Response->RelatedResponse
628              
629             Perform a I request for search terms related to the query phrase
630             of the current request, returning the new C or C object,
631             respectively.
632              
633             Both return nothing if the current request is already for a I
634             search.
635              
636             For example:
637              
638             print "Did you mean ", join(" or ", $Response->RelatedResponse->Terms()), "?";
639              
640             =cut
641              
642             sub RelatedRequest
643             {
644 0     0 1   my $Response = shift;
645 0           return $Response->Request->RelatedRequest;
646             }
647              
648             sub RelatedResponse
649             {
650 0     0 1   my $Response = shift;
651 0           return $Response->Request->RelatedResponse;
652             }
653              
654              
655             ##############################################################################
656              
657             =item $Response->SpellRequest
658              
659             =item $Response->SpellResponse
660              
661             Perform a I request for a search term that may reflect proper
662             spelling of the query phrase of the current request, returning the new
663             C or C object, respectively.
664              
665             Both return nothing if the current request is already for a I
666             search.
667              
668             =cut
669              
670              
671             sub SpellRequest
672             {
673 0     0 1   my $Response = shift;
674 0           return $Response->Request->SpellRequest;
675             }
676              
677             sub SpellResponse
678             {
679 0     0 1   my $Response = shift;
680 0           return $Response->Request->SpellResponse;
681             }
682              
683              
684              
685             ##############################################################################
686              
687              
688              
689             =pod
690              
691             =back
692              
693             =head1 Author
694              
695             Jeffrey Friedl (jfriedl@yahoo.com)
696              
697             =cut
698              
699              
700             1;