1package Yahoo::Search::Result; 2use strict; 3 4our $VERSION = "20100614.1"; # just to make CPAN happy 5 6=head1 NAME 7 8 9=head1 VERSION 10 11version 1.11.3 12Yahoo::Search::Result -- class representing a single result (single web 13page, image, video file, etc) from a Yahoo! search-engine query. 14(This package is included in, and automatically loaded by, the Yahoo::Search package.) 15 16=head1 Package Use 17 18You never need to C<use> this package directly -- it is loaded 19automatically by Yahoo::Search. 20 21=head1 Object Creation 22 23C<Result> objects are created automatically when a C<Response> object is 24created (when a C<Request> object's C<Fetch> method is called, either 25directly, or indirectly via a shortcut such as 26C<Yahoo::Search-E<gt>Query()>. 27 28=head1 Methods Overview 29 30This table shows the methods available on a per-search-space basis: 31 32 33 34 Terms 35 Related | 36 Spell | | 37 Local | | | 38 News | | | | 39 Video | | | | | 40 Image | | | | | | 41 Doc | | | | | | | 42 | | | | | | | | 43 Next [X] [X] [X] [X] [X] [X] [X] [X] 44 Prev [X] [X] [X] [X] [X] [X] [X] [X] 45 Response [X] [X] [X] [X] [X] [X] [X] [X] 46 Request [X] [X] [X] [X] [X] [X] [X] [X] 47 SearchSpace [X] [X] [X] [X] [X] [X] [X] [X] 48 49 * I [X] [X] [X] [X] [X] [X] [X] . 50 * i [X] [X] [X] [X] [X] [X] [X] . 51 as_html [X] [X] [X] [X] [X] [X] [X] . 52 as_string [X] [X] [X] [X] [X] [X] [X] . 53 Data [X] [X] [X] [X] [X] [X] [X] . 54 55 * Url [X] [X] [X] [X] [X] . . . 56 * ClickUrl [X] [X] [X] [X] [X] . . . 57 * Title [X] [X] [X] [X] [X] . . . 58 TitleAsHtml [X] [X] [X] [X] [X] . . . 59 Link [X] [X] [X] [X] [X] . . . 60 * Summary [X] [X] [X] [X] . . . . 61 SummaryAsHtml [X] [X] [X] [X] . . . . 62 63 * CacheUrl [X] . . . . . . . 64 * CacheSize [X] . . . . . . . 65 * ModTimestamp [X] . . [X] . . . . 66 67 * Width . [X] [X] . . . . . 68 * Height . [X] [X] . . . . . 69 70 * ThumbUrl . [X] [X] [X] . . . . 71 * ThumbWidth . [X] [X] [X] . . . . 72 * ThumbHeight . [X] [X] [X] . . . . 73 ThumbImg . [X] [X] [X] . . . . 74 ThumbLink . [X] [X] [X] . . . . 75 76 * HostUrl . [X] [X] . . . . . 77 * Copyright . [X] [X] . . . . . 78 * Publisher . [X] [X] . . . . . 79 * Restrictions . [X] [X] . . . . . 80 81 * Type [X] [X] [X] . . . . . 82 * Bytes . [X] [X] . . . . . 83 * Channels . . [X] . . . . . 84 * Seconds . . [X] . . . . . 85 * Duration . . [X] . . . . . 86 * Streaming . . [X] . . . . . 87 88 * SourceName . . . [X] . . . . 89 SourceNameAsHtml . . . [X] . . . . 90 * SourceUrl . . . [X] . . . . 91 * Language . . . [X] . . . . 92 * PublishTime . . . [X] . . . . 93 * PublishWhen . . . [X] . . . . 94 95 * Address . . . . [X] . . . 96 * City . . . . [X] . . . 97 * State . . . . [X] . . . 98 * Phone . . . . [X] . . . 99 * Miles . . . . [X] . . . 100 * Kilometers . . . . [X] . . . 101 * Rating . . . . [X] . . . 102 * MapUrl . . . . [X] . . . 103 * BusinessUrl . . . . [X] . . . 104 * BusinessClickUrl . . . . [X] . . . 105 * AllMapUrl . . . . [X] . . . 106 107 * Term . . . . . [X] [X] [X] 108 TermAsHtml . . . . . [X] [X] [X] 109 110 | | | | | | | | 111 Doc | | | | | | | 112 Image | | | | | | 113 Video | | | | | 114 News | | | | 115 Local | | | 116 Spell | | 117 Related | 118 Terms 119 120 121Those items marked with a '*' are also available via the C<Data> method 122 123=cut ' 124 125 126 127my @DOW = qw[x Sun Mon Tue Wed Thu Fri Sat]; 128my @MON = qw[x Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec]; 129 130## helper function -- returns the given text cooked for html 131sub _cook_for_html($) 132{ 133 my $text = shift; 134 135 #die join(',', caller) if not defined $text; 136 137 $text =~ s/&/&/g; 138 $text =~ s/</</g; 139 $text =~ s/>/>/g; 140 return $text; 141} 142 143## 144## helper function -- given a key in a result object, a result object (the 145## "self" from a method), and an indication of whether we want text or 146## html, return the appropriate text or html. 147## 148sub _text_or_html($@) 149{ 150 my $Key = shift; 151 my $Result = shift; 152 my $AsHtml = shift; #optional 153 154 my $Text = $Result->{$Key}; 155 156 if (not defined $Text) { 157 return (); 158 } elsif ($AsHtml) { 159 return _cook_for_html($Text); 160 } else { 161 return $Text; 162 } 163} 164 165 166## 167## helper function -- if passed one arg, it's a url, and simply return it. 168## 169## If passed multiple args, the 2nd is an attribute (e.g. "href", "src"), 170## which causes the return of a string like 171## href="$url" 172## where we're sure the quoting of the url is safe. 173## 174sub _url($@) 175{ 176 my $Url = shift; 177 my $Attrib = shift; 178 179 if (not $Url) 180 { 181 return (); 182 } 183 elsif (not $Attrib) 184 { 185 return $Url; 186 } 187 elsif (not $Url =~ m/\x22/) { 188 return qq/$Attrib="$Url"/; 189 } elsif (not $Url =~ m/\x27/) { 190 return qq/$Attrib='$Url'/; 191 } else { 192 $Url =~ s/\x22/%22/g; # double qoute 193 $Url =~ s/\x27/%27/g; # single quote 194 return qq/$Attrib="$Url"/; 195 } 196} 197 198 199## 200## Want to be able to dump a hash of most data, so note which items are 201## available and interesting on a per-search-space basis. 202## 203my @CommonItems = qw[Url ClickUrl Summary Title i I]; 204 205my %ItemsBySpace = 206( 207 Video => [@CommonItems, qw"Type Bytes HostUrl Copyright Publisher Restrictions Channels Seconds Duration Streaming Width Height ThumbUrl ThumbWidth ThumbHeight"], 208 Image => [@CommonItems, qw"Type Bytes HostUrl Copyright Publisher Restrictions Width Height ThumbUrl ThumbWidth ThumbHeight"], 209 Doc => [@CommonItems, qw"Type CacheUrl CacheSize ModTimestamp"], 210 Local => [@CommonItems, qw"Address City State Phone Miles Kilometers Rating MapUrl AllMapUrl"], 211 News => [@CommonItems, qw"SourceName SourceUrl Language ModTimestamp PublishTime ThumbUrl ThumbWidth ThumbHeight"], 212 Spell => [@CommonItems, "Term"], 213 Related => [@CommonItems, "Term"], 214 Terms => [@CommonItems, "Term"], 215); 216 217 218 219 220=head1 METHODS 221 222=over 4 223 224=cut 225 226############################################################################## 227 228=item $Result->Next([I<boolean>]) 229 230Returns the next C<Result> object from among the list of result objects 231that are part of one C<Response> object. 232 233Returns nothing when called on the last result in a response, unless 234auto-continuation is turned on, in which case the next set is automatically 235fetched and the first C<Result> from that set's C<Response> is returned. 236 237An optional defined boolean argument turns auto-continuation on (true) or 238off (false). If the argument is not defined, or not provided, the value for 239the original request's C<AutoContinue> option (default off) is used. 240 241Note that using auto-continuation can be dangerous. See the docs for 242C<NextResult> in Yahoo::Search::Response. 243 244=cut 245 246sub Next 247{ 248 my $Result = shift; # self 249 my $AutoContinue = shift; 250 251 if ($Result->{_ResponseOrdinal} < $#{ $Result->{_Response}->{Result} }) 252 { 253 return $Result->{_Response}->{Result}->[$Result->{_ResponseOrdinal} + 1]; 254 } 255 else 256 { 257 if (not defined $AutoContinue) { 258 $AutoContinue = $Result->{_Response}->{_Request}->{AutoContinue}; 259 } 260 261 if ($AutoContinue 262 and 263 my $NextResponse = $Result->{_Response}->NextSet) 264 { 265 return $NextResponse->NextResult(); 266 } 267 else 268 { 269 return () 270 } 271 } 272} 273 274 275 276 277############################################################################## 278 279=item $Result->Prev 280 281The opposite of C<Next>. No auto-continuation feature. 282 283=cut 284 285## does not auto-fetch when fetching result[-1] 286sub Prev 287{ 288 my $Result = shift; # self 289 290 if ($Result->{_ResponseOrdinal} == 0) { 291 return (); 292 } else { 293 return $Result->{_Response}->{Result}->[$Result->{_ResponseOrdinal} - 1]; 294 } 295} 296 297 298 299############################################################################## 300 301=item $Result->Response 302 303Returns the C<Response> object of which this C<Result> object is a part. 304 305=cut 306 307sub Response 308{ 309 my $Result = shift; # self 310 return $Result->{_Response}; 311} 312 313 314 315############################################################################## 316 317=item $Result->Request 318 319Returns the original C<Request> object from which this C<Result> object's 320C<Response> was derived. 321 322=cut ' 323 324sub Request 325{ 326 my $Result = shift; # self 327 return $Result->{_Response}->{_Request}; 328} 329 330 331 332 333############################################################################## 334 335=item $Result->SearchSpace 336 337Returns a string which indicates the search space of the original query 338that this result was part of. (That is, it returns C<Doc>, C<Image>, 339C<News>, C<Local>, or C<Video>.) 340 341It's the same as 342 343 $Result->Request->SearchSpace; 344 345=cut 346 347sub SearchSpace 348{ 349 my $Result = shift; # self 350 return $Result->{_Response}->{_Request}->{Space}; 351} 352 353 354 355############################################################################## 356 357 358=item $Result->i[ I<separator> ] 359 360=item $Result->I[ I<separator> ] 361 362The first (lower-case letter "i") returns the zero-based ordinal of the 363result from among those in the current C<Response>. 364 365The latter (upper-case letter "I") returns the zero-based ordinal of the 366result from among all search results that might be returned by Yahoo! for 367the given query. 368 369For example, after 370 371 my @Results = Yahoo::Search->Results(Image => "Briteny", 372 AppId => "my app id", 373 Start => 45, 374 Count => 15); 375 376the C<$Results[0]> result object has an C<I> of 45 (the 45th result of all 377"Briteny" image results) and an C<i> of 0 (the 0th result among those 378returned this time.) 379 380In either case, if an optional argument is given and is true, it is used as 381a separator every three digits. In the US, one would use 382 383 $Result->I(',') 384 385to return "1,234" where 386 387 $Result->I() 388 389would return "1234". 390 391=cut 392 393 394sub i 395{ 396 my $Result = shift; # self 397 my $Comma = shift; # optional 398 return Yahoo::Search::Response::_commaize($Result->{_ResponseOrdinal}, $Comma); 399} 400 401sub I 402{ 403 my $Result = shift; # self 404 my $Comma = shift; # optional 405 return Yahoo::Search::Response::_commaize($Result->{_ResponseOrdinal} + $Result->{_Response}->{firstResultPosition} - 1, $Comma); 406} 407 408 409 410 411############################################################################## 412 413=item $Result->as_html 414 415Returns a string of HTML that represents the result, as appropriate to the 416result's query search space. 417 418There are many ways one may wish to display query results -- this method 419returns one display that the author finds useful. It may come in useful for 420quick prototyping of web applications, e.g. 421 422 sub ShowRelated 423 { 424 print join "<hr>", map { $_->as_html } Yahoo::Search->Results(@_); 425 } 426 427(Also see C<Yahoo::Search-E<gt>HtmlResults>) 428 429The HTML returned by C<as_html> contains class references, thereby allowing 430the look-and-feel to be easily adjusted. Here's a style sheet that makes 431Image search results look palatable. 432 433 <style> 434 .yResult { display: block; border: #CCF 3px solid ; padding:10px } 435 .yLink { } 436 .yTitle { display:none } 437 .yImg { border: solid 1px } 438 .yUrl { display:none } 439 .yMeta { font-size: 80% } 440 .ySrcUrl { } 441 .ySum { font-family: arial; font-size: 90% } 442 </style> 443 444B<Bugs>: English-centric 445 446=cut ' 447 448sub as_html 449{ 450 my $Result = shift; # self 451 my $SearchSpace = $Result->SearchSpace; 452 my $summary = $Result->Summary(1); 453 454 if ($SearchSpace eq 'Doc') 455 { 456 my $link = $Result->Link; 457 my $url = $Result->Url; 458 459 my $html = "$link<span class=yUrl><br>$url</span>"; 460 if ($summary) { 461 $html .= "<span class=ySum><br>$summary</span>"; 462 } 463 return "<span class=yResult>$html</span>"; 464 } 465 466 if ($SearchSpace eq 'Video') 467 { 468 my $HREF = $Result->ClickUrl('HREF'); 469 my $title = $Result->Title(1); 470 my $html; 471 if (my $img = $Result->ThumbImg) { 472 $html = "<a class=yLink $HREF>$img<span class=yTitle> $title</span></a>"; 473 } else { 474 $html = "<a class=yLink $HREF><span class=yTitle>$title</span></a>"; 475 } 476 477 $html .= "<span class=yUrl><br>" . $Result->Url . "</span>"; 478 479 my @extra; 480 if (my $duration = $Result->Duration) { 481 push @extra, "Duration: $duration"; 482 } 483 484 if (my $width = $Result->Width and my $height = $Result->Height) { 485 push @extra, "Video resolution $width x $height"; 486 } 487 488 if (my $size = $Result->Bytes) { 489 push @extra, "File size: $size"; 490 } 491 492 if (my $chan = $Result->Channels) { 493 push @extra, "$chan-channel audio"; 494 } 495 496 if (my $HREF = $Result->HostUrl('href')) { 497 push @extra, "<a class=ySrcUrl $HREF>Source page</a>"; 498 } 499 if (@extra) { 500 $html .= "<span class=yMeta><br>" . join(" | ", @extra) . "</span>"; 501 } 502 503 if ($summary) { 504 $html .= "<span class=ySum><br>$summary</span>"; 505 } 506 return "<span class=yResult>$html</span>"; 507 } 508 509 if ($SearchSpace eq 'Image') 510 { 511 my $HREF = $Result->ClickUrl('href'); 512 my $title = $Result->Title(1); 513 my $html; 514 if (my $img = $Result->ThumbImg) { 515 $html = "<a class=yLink $HREF>$img<span class=yTitle> $title</span></a>"; 516 } else { 517 $html = "<a class=yLink $HREF><span class=yTitle>$title</span></a>"; 518 } 519 520 $html .= "<span class=yUrl><br>" . $Result->Url . "</span>"; 521 522 my @extra; 523 if (my $size = $Result->Bytes) { 524 push @extra, "File size: $size"; 525 } 526 if (my $width = $Result->Width and my $height = $Result->Height) { 527 push @extra, "Image size: $width x $height"; 528 } 529 if (my $HREF = $Result->HostUrl('HREF')) { 530 push @extra, "<a class=ySrcUrl $HREF>Source page</a>"; 531 } 532 if (@extra) { 533 $html .= "<span class=yMeta><br>" . join(" | ", @extra) . "</span>"; 534 } 535 536 if ($summary) { 537 $html .= "<span class=ySum><br>$summary</span>"; 538 } 539 return "<span class=yResult>$html</span>"; 540 } 541 542 if ($SearchSpace eq "News") 543 { 544 my $HREF = $Result->ClickUrl('HREF'); 545 my $title = $Result->Title(1); 546 my $html = "<span class=yResult>"; 547 if (my $img = $Result->ThumbImg) { 548 $html .= "<a class=yLink $HREF>$img<span class=yTitle> $title</span></a>"; 549 } else { 550 $html .= "<a class=yLink $HREF><span class=yTitle>$title</span></a>"; 551 } 552 my $src_name = $Result->SourceNameAsHtml; 553 my $src_href = $Result->SourceUrl('HREF'); 554 if ($src_name and $src_href) { 555 $html .= "<a class=yNewsSrc $src_href><br>" . _cook_for_html($src_name) . "</a>"; 556 } 557 if (my $when = $Result->PublishWhen) { 558 $html .= " <span class=yWhen>($when)</span>"; 559 } 560 561 if ($summary) { 562 $html .= "<span class=ySum><br>$summary</span>"; 563 } 564 return "<span class=yResult>$html</span>"; 565 } 566 567 if ($SearchSpace eq "Local") 568 { 569 my $html = $Result->Link; 570 571 if (my $addr = join(', ', grep { $_ } $Result->Address, $Result->City . " " . $Result->State)) { 572 $html .= "<span class=yAddr><br>$addr</span>"; 573 } 574 575 my @extra; 576 if (my $phone = $Result->Phone) { 577 push @extra, "<span class=yPhone>$phone</span>"; 578 } 579 if (my $HREF = $Result->MapUrl('href')) { 580 push @extra, "<a class=yMap $HREF>Map</a>"; 581 } 582 if (@extra) { 583 $html .= "<span class=yMeta><br>" . join(" | ",@extra) . "</span>"; 584 } 585 586 if ($summary) { 587 $html .= "<span class=ySum><br>$summary</span>"; 588 } 589 return "<span class=yResult>$html</span>"; 590 } 591 592 if ($SearchSpace eq "Spell") 593 { 594 my $item = $Result->TermAsHtml; 595 return "Did you mean <i>$item</i>?"; 596 } 597 598 if ($SearchSpace eq "Related") 599 { 600 my $item = $Result->TermAsHtml; 601 return "Also try: <i>$item</i>"; 602 } 603 604 if ($SearchSpace eq "Terms") 605 { 606 my $item = $Result->TermAsHtml; 607 return "Term: <i>$item</i>"; 608 } 609 610 return "???"; 611} 612 613 614############################################################################## 615 616=item $Result->as_string 617 618Returns a textual representation of the C<Result>, which may be useful for 619quick prototyping or debugging. 620 621=cut 622 623 624## must create, for all spaces 625sub as_string 626{ 627 my $Result = shift; # self 628 my $ref = $Result->Data; 629 630 my $txt = ""; 631 632 for my $item (@{$ItemsBySpace{$Result->SearchSpace}}) 633 { 634 if (defined(my $val = $Result->$item)) { 635 $txt .= "$item: $val\n"; 636 } 637 } 638 return $txt; 639} 640 641############################################################################## 642 643=item $Result->Data 644 645Returns a list of key/value pairs containing the fundamental data for the 646result (those items marked with '*' in the table at the start of this 647document). 648 649 my %Data = $Result->Data; 650 651=cut 652 653 654sub Data 655{ 656 my $Result = shift; # self 657 my %Data; 658 659 for my $item (@{$ItemsBySpace{$Result->SearchSpace}}) 660 { 661 $Data{$item} = $Result->$item; 662 } 663 return %Data; 664} 665 666 667 668############################################################################## 669 670=item $Result->Url 671 672=item $Result->ClickUrl 673 674C<Url> returns the raw url of the item (web page, image, etc.), appropriate 675for display to the user. 676 677C<ClickUrl> returns a url appropriate for the href attribute of a link. 678 679In some cases, the two return the same url. 680 681As with all Result-object methods which return a url of some sort, you can 682provide a single argument such as C<href> and receive a string such as 683 href="..." 684appropriate to be used directly in html. For example, 685 686 my $HREF = $Result->ClickUrl('href'); 687 print "<a $HREF>click</a>"; 688 689is preferable to 690 691 my $url = $Result->ClickUrl; 692 print "<a href='$url'>click</a>"; 693 694since the latter would break if C<$url> contains a singlequote. 695 696=cut 697 698sub Url 699{ 700 my $Result = shift; # self 701 return _url($Result->{Url} || $Result->{ClickUrl}, @_); 702} 703 704sub ClickUrl 705{ 706 my $Result = shift; # self 707 return _url($Result->{ClickUrl} || $Result->{Url}, @_); 708} 709 710 711 712 713 714############################################################################## 715 716=item $Result->Title([ I<as_html> ]) 717 718=item $Result->TitleAsHtml 719 720C<Title> returns the raw title text associated with the result. If an 721optional argument is provided and is true, the title text is returned as 722html. 723 724C<TitleAsHtml> is the same as 725 726 $Result->Title(1) 727 728=cut 729 730sub Title 731{ 732 return _text_or_html(Title => @_); 733} 734 735sub TitleAsHtml 736{ 737 my $Result = shift; #self 738 return $Result->Title(1); 739} 740 741 742 743 744############################################################################## 745 746=item $Result->Link 747 748Returns a link made from the C<ClickUrl> and the C<Title>, with class 749"yLink", e.g. 750 751 <a class=yLink href='$URL'>$TITLE</a> 752 753=cut 754 755sub Link 756{ 757 my $Result = shift; # self 758 759 if (my $HREF = $Result->ClickUrl('href') 760 and 761 my $title = $Result->Title(1)) 762 { 763 return "<a class=yLink $HREF>$title</a>"; 764 } 765 else 766 { 767 return (); 768 } 769} 770 771 772 773############################################################################## 774 775=item $Result->Summary([ I<as_html> ]) 776 777=item $Result->SummaryAsHtml 778 779Like C<Title> and C<TitleAsHtml>, but for the summary associated with the 780result. 781 782=cut 783 784sub Summary 785{ 786 return _text_or_html(Summary => @_); 787} 788 789sub SummaryAsHtml 790{ 791 my $Result = shift; #self 792 return $Result->Summary(1); 793} 794 795 796=item $Result->CacheUrl 797 798=item $Result->CacheSize 799 800(I<Appropriate for B<Doc> search results>) 801 802C<CacheUrl> returns the url of the document in the Yahoo! cache. 803See the documentation for the C<Url> method for information on the 804one-argument version of this method. 805 806C<CacheSize> returns the size (as a string like "22k"). 807 808=cut 809 810sub CacheUrl 811{ 812 my $Result = shift; # self 813 return _url($Result->{Cache} ? $Result->{Cache}->{Url} : (), @_) 814} 815 816sub CacheSize 817{ 818 my $Result = shift; # self 819 return $Result->{Cache} ? $Result->{Cache}->{Size} : (); 820} 821 822 823 824############################################################################## 825 826=item $Result->ModTimestamp 827 828(I<Appropriate for B<Doc> and B<News> search results>) 829 830The Unix timestamp of the Last-Modified time associated with the the url 831when it was last checked by Yahoo!'s backend crawlers. 832 833=cut 834 835sub ModTimestamp 836{ 837 my $Result = shift; # self 838 return defined($Result->{ModificationDate}) ? $Result->{ModificationDate}: (); 839} 840 841 842############################################################################## 843 844=item $Result->Width 845 846=item $Result->Height 847 848(I<Appropriate for B<Image> and B<Video> search results>) 849 850The width and height (in pixels) of the image or video. 851 852=cut 853 854## for image, video 855sub Width 856{ 857 my $Result = shift; # self 858 return defined($Result->{Width}) ? $Result->{Width} : (); 859} 860 861sub Height 862{ 863 my $Result = shift; # self 864 return defined($Result->{Height}) ? $Result->{Height} : (); 865} 866 867 868 869############################################################################## 870 871=item $Result->ThumbUrl 872 873=item $Result->ThumbWidth 874 875=item $Result->ThumbHeight 876 877(I<Appropriate for B<Image>, B<Video>, and B<News> search results>) 878 879The url of a thumbnail image, and its width and height. 880 881(Note: few I<News> results have a thumbnail, but some do.) 882 883See the documentation for the C<Url> method for information on the 884one-argument version of C<ThumbUrl>. 885 886=cut 887 888sub ThumbUrl 889{ 890 my $Result = shift; # self 891 return _url($Result->{Thumbnail} ? $Result->{Thumbnail}->{Url} : (), @_); 892} 893 894sub ThumbWidth 895{ 896 my $Result = shift; # self 897 return $Result->{Thumbnail} ? $Result->{Thumbnail}->{Width} : (); 898} 899 900sub ThumbHeight 901{ 902 my $Result = shift; # self 903 return $Result->{Thumbnail} ? $Result->{Thumbnail}->{Height} : (); 904} 905 906 907############################################################################## 908 909=item $Result->ThumbImg 910 911(I<Appropriate for B<Image>, B<Video>, and B<News> search results>) 912 913Returns a C<E<lt>imgE<gt>> tag representing the thumbnail image, e.g. 914 915 <img class=yImg src='$IMGURL' width=$WIDTH height=$HEIGHT> 916 917=cut 918 919 920sub ThumbImg 921{ 922 my $Result = shift; # self 923 924 my $SRC = $Result->ThumbUrl('src'); 925 my $Width = $Result->ThumbWidth; 926 my $Height = $Result->ThumbHeight; 927 928 if ($SRC) { 929 return "<img class=yImg $SRC width=$Width height=$Height>"; 930 } else { 931 return (); 932 } 933} 934 935 936############################################################################## 937 938=item $Result->ThumbLink 939 940(I<Appropriate for B<Image>, B<Video>, and B<News> search results>) 941 942Returns a link from the thumbnail to the C<ClickUrl> of the result, 943e.g. 944 945 <a class=yLink href='$CLICKURL'> 946 <img class=yImg src='$IMGURL' width=$WIDTH height=$HEIGHT> 947 </a> 948 949=cut 950 951 952sub ThumbLink 953{ 954 my $Result = shift; # self 955 my $HREF = $Result->ClickUrl('href'); 956 my $img = $Result->ThumbImg; 957 if ($HREF and $img) { 958 return "<a class=yLink $HREF>$img</a>"; 959 } else { 960 return (); 961 } 962} 963 964 965 966############################################################################## 967 968=item $Result->HostUrl 969 970(I<Appropriate for B<Image> and B<Video> search results>) 971 972Returns the url of the web page containing a link to the image/video 973item that the C<Result> represents. 974 975See the documentation for the C<Url> method for information on the 976one-argument version of this method. 977 978=cut 979 980sub HostUrl 981{ 982 my $Result = shift; # self 983 return _url($Result->{RefererUrl}, @_); 984} 985 986=cut 987 988 989 990########################################################################### 991 992=item $Result->Type 993 994(<Appropriate for B<Doc>, B<Image>, and B<Video> search results>) 995 996Returns a string representing the file type of the item to which 997C<$Result-E<gt>Url> points. For I<Doc> searches, the MIME type (e.g. 998"text/html") is returned. 999 1000For other search spaces, here are the possible return values: 1001 1002 Video: avi flash mpeg msmedia quicktime realmedia 1003 Image: bmp gif jpg png. 1004 1005Yahoo! Search derives these Video/Image C<Type> value by actually 1006inspecting the file contents, and as such it is more reliable than looking 1007at the file extension. 1008 1009=cut 1010 1011sub Type 1012{ 1013 my $Result = shift; #self 1014 if (defined $Result->{MimeType}) { 1015 return $Result->{MimeType}; 1016 } elsif (defined $Result->{FileFormat}) { 1017 return $Result->{FileFormat}; 1018 } else { 1019 return (); 1020 } 1021} 1022 1023 1024 1025########################################################################### 1026 1027=item $Result->Copyright([ I<as_html> ]) 1028 1029(<Appropriate for B<Image> and B<Video> search results>) 1030 1031Returns any copyright notice associated with the result. If an optional 1032argument is provided and is true, the copyright text is returned as html. 1033 1034=cut 1035 1036sub Copyright 1037{ 1038 return _text_or_html(Copyright => @_); 1039} 1040 1041 1042 1043########################################################################### 1044 1045=item $Result->Publisher([ I<as_html> ]) 1046 1047(<Appropriate for B<Image>, and B<Video> search results>) 1048 1049Returns any publisher information (as a string) associated with the result. 1050If an optional argument is provided and is true, the publisher information 1051is returned as html. 1052 1053=cut 1054 1055sub Publisher 1056{ 1057 return _text_or_html(Publisher => @_); 1058} 1059 1060 1061 1062########################################################################### 1063 1064=item $Result->Restrictions 1065 1066(<Appropriate for B<Image>, and B<Video> search results>) 1067 1068A (possibly zero-length) string containing zero or more of the following 1069space-separated words: 1070 1071 noframe 1072 noinline 1073 1074See Yahoo!'s web site (http://developer.yahoo.net/) for information on them. 1075 1076=cut 1077 1078sub Restrictions 1079{ 1080 my $Result = shift; #self 1081 if (not defined $Result->{Restrictions}) { 1082 return ""; 1083 } else { 1084 return $Result->{Restrictions}; 1085 } 1086} 1087 1088 1089 1090############################################################################## 1091 1092=item $Result->Bytes 1093 1094(I<Appropriate for B<Image>, and B<Video> search results>) 1095 1096The size of the image/video item, in bytes. 1097 1098=cut 1099 1100sub Bytes 1101{ 1102 my $Result = shift; #self 1103 1104 if ($Result->{FileSize}) { 1105 return $Result->{FileSize}; 1106 } else { 1107 return (); 1108 } 1109} 1110 1111 1112 1113 1114############################################################################## 1115 1116=item $Result->Channels 1117 1118(I<Appropriate for B<Video> search results>) 1119 1120Returns the number of channels in the audio, if known. 1121Examples are "1", "2", "4.1", "5.1", etc.... 1122 1123=cut 1124 1125sub Channels 1126{ 1127 my $Result = shift; # self 1128 if ($Result->{Channels}) { 1129 return $Result->{Channels}; 1130 } else { 1131 return (); 1132 } 1133} 1134 1135 1136 1137############################################################################## 1138 1139=item $Result->Seconds 1140 1141(I<Appropriate for B<Video> search results>) 1142 1143Returns the duration of the video clip, if known, in (possibly fractional) 1144seconds. 1145 1146=cut 1147 1148sub Seconds 1149{ 1150 my $Result = shift; #self 1151 1152 if ($Result->{Duration}) { 1153 return $Result->{Duration}; 1154 } 1155 return (); 1156} 1157 1158 1159 1160############################################################################## 1161 1162=item $Result->Duration 1163 1164(I<Appropriate for B<Video> search results>) 1165 1166Returns a string representing the duration of the video clip, if known, in 1167the form of "37 sec", "1:23", or "4:56:23", as appropriate. 1168 1169B<Bugs>: English-centric 1170 1171=cut 1172 1173sub Duration 1174{ 1175 my $Result = shift; #self 1176 1177 if (my $sec = $Result->Seconds) 1178 { 1179 if ($sec < 60) { 1180 return sprintf "%d sec", $sec; 1181 } 1182 if ($sec < 3600) { 1183 return sprintf "%d:%02d", int($sec/60), $sec%60; 1184 } 1185 my $hours = int($sec/3600); 1186 $sec = $sec % 3600; 1187 return sprintf "%d:%02d:%02d", $hours, int($sec/60), $sec%60; 1188 } 1189 1190 return (); 1191} 1192 1193 1194 1195############################################################################## 1196 1197=item $Result->Streaming 1198 1199(I<Appropriate for B<Video> search results>) 1200 1201Returns "1" if the multimedia is streaming, "0" if not. 1202If not known, an empty list is returned. 1203 1204=cut 1205 1206sub Streaming 1207{ 1208 my $Result = shift; #self 1209 1210 my $Stream = $Result->{Streaming} || ''; 1211 if ($Stream eq 'true') { 1212 return 1; 1213 } elsif ($Stream eq 'false') { 1214 return 0; 1215 } else { 1216 return (); 1217 } 1218} 1219 1220 1221 1222############################################################################## 1223 1224=item $Result->SourceUrl 1225 1226(I<Appropriate for B<News> search results>) 1227 1228The main url of the news provider hosting the article that the C<Result> 1229refers to. 1230 1231See the documentation for the C<Url> method for information on the 1232one-argument version of this method. 1233 1234=cut 1235 1236sub SourceUrl 1237{ 1238 my $Result = shift; # self 1239 return _url($Result->{NewsSourceUrl}, @_); 1240} 1241 1242 1243 1244 1245############################################################################## 1246 1247=item $Result->SourceName([ I<as_html> ]) 1248 1249=item $Result->SourceNameAsHtml 1250 1251(I<Appropriate for B<News> search results>) 1252 1253Similar to C<Title> and C<TitleAsHtml>, but the name of the organization 1254associated with the news article (and, by extension, with C<SourceUrl>). 1255 1256=cut 1257 1258sub SourceName 1259{ 1260 return _text_or_html(NewsSource => @_); 1261} 1262 1263sub SourceNameAsHtml 1264{ 1265 my $Result = shift; # self 1266 return $Result->SourceName(1); 1267} 1268 1269 1270 1271############################################################################## 1272 1273=item $Result->Language 1274 1275(I<Appropriate for B<News> search results>) 1276 1277A code representing the language in which the article is written (e.g. "en" 1278for English, "ja" for Japanese, etc.). See the list of language codes at 1279C<perldoc> Yahoo::Search. 1280 1281=cut 1282 1283sub Language 1284{ 1285 my $Result = shift; # self 1286 return $Result->{Language}; 1287} 1288 1289 1290############################################################################## 1291 1292=item $Result->PublishTime 1293 1294=item $Result->PublishWhen 1295 1296(I<Appropriate for B<News> search results>) 1297 1298C<PublishTime> is the Unix time associated with the article, e.g. 1299 1300 print "Published ", scalar(localtime $Result->PublishTime), "\n"; 1301 1302C<PublishWhen> gives a string along the lines of 1303 1304 3h 25m ago (if less than 12 hours ago) 1305 Tue 9:47am (if less than 5 days ago) 1306 Sat, Dec 25 (if less than 100 days ago) 1307 Sat, Dec 25, 2004 (if >= 100 days ago) 1308 1309B<Bug>: C<PublishWhen> is English-centric. 1310 1311=cut 1312 1313sub PublishTime 1314{ 1315 my $Result = shift; # self 1316 if (defined $Result->{PublishDate}) { 1317 return $Result->{PublishDate}; 1318 } else { 1319 return (); 1320 } 1321} 1322 1323sub PublishWhen 1324{ 1325 my $Result = shift; #self 1326 1327 my $time = $Result->PublishTime; 1328 if (not $time) { 1329 return (); 1330 } 1331 1332 my $delta = time - $time; 1333 if ($delta < 3600 * 12) 1334 { 1335 my $h = int( $delta / 3600); 1336 my $m = int(($delta % 3600)/60 + 0.5); 1337 return "${h}h ${m}m ago"; 1338 } 1339 1340 if ($delta < 5 * 3600 * 24) 1341 { 1342 ## give day and time 1343 my ($m,$h, $DOW) = (localtime $time)[1,2,6]; 1344 my $ampm = "am"; 1345 if ($h == 0) { 1346 $h = 12; 1347 } elsif ($h >= 12) { 1348 $ampm = "pm"; 1349 if ($h > 12) { 1350 $h -= 12; 1351 } 1352 } 1353 return sprintf("%s %d:%02d%s", $DOW[$DOW], $h, $m, $ampm); 1354 } 1355 1356 if ($delta < 100 * 3600 * 24) 1357 { 1358 my ($D,$M,$Y,$DOW) = (localtime $time)[3..6]; 1359 return sprintf("%s %s %d", $DOW[$DOW], $MON[$M], $D); 1360 } 1361 else 1362 { 1363 my ($D,$M,$Y,$DOW) = (localtime $time)[3..6]; 1364 return sprintf("%s %s %d, %04d", $DOW[$DOW], $MON[$M], $D, $Y+1900); 1365 } 1366} 1367 1368 1369############################################################################## 1370 1371=item $Result->Address 1372 1373=item $Result->City 1374 1375=item $Result->State 1376 1377=item $Result->Phone 1378 1379(I<Appropriate for B<Local> search results>) 1380 1381Location and Phone number for the business that the C<Result> refers to. 1382 1383=cut 1384 1385## for local 1386sub Address 1387{ 1388 my $Result = shift; # self 1389 return $Result->{Address}; 1390} 1391 1392sub City 1393{ 1394 my $Result = shift; # self 1395 return $Result->{City}; 1396} 1397 1398sub State 1399{ 1400 my $Result = shift; # self 1401 return $Result->{State}; 1402} 1403 1404sub Phone 1405{ 1406 my $Result = shift; # self 1407 return $Result->{Phone}; 1408} 1409 1410 1411 1412 1413 1414############################################################################## 1415 1416=item $Result->Miles 1417 1418=item $Result->Kilometers 1419 1420(I<Appropriate for B<Local> search results>) 1421 1422The distance (in miles and kilometers) from the location used to make the 1423query to the location of this result. 1424 1425=cut 1426 1427sub Kilometers 1428{ 1429 my $Result = shift; # self 1430 return defined($Result->{Distance}) ? $Result->{Distance} * 1.609 : (); 1431} 1432 1433sub Miles 1434{ 1435 my $Result = shift; # self 1436 return defined($Result->{Distance}) ? $Result->{Distance} : (); 1437} 1438 1439 1440 1441 1442 1443############################################################################## 1444 1445=item $Result->Rating 1446 1447(I<Appropriate for B<Local> search results>) 1448 1449Returns the rating associated with the result, if there is one. If there is 1450a rating, it is from 1 (lowest) to 5 (highest) in 0.5-sized steps. If not, 1451nothing is returned. 1452 1453=cut 1454 1455sub Rating 1456{ 1457 my $Result = shift; # self 1458 return defined($Result->{Rating}) ? $Result->{Rating} : (); 1459} 1460 1461 1462 1463############################################################################## 1464 1465=item $Result->MapUrl 1466 1467=item $Result->AllMapUrl 1468 1469(I<Appropriate for B<Local> search results>) 1470 1471C<MapUrl> is a url to a Yahoo! Maps map showing the business' location. 1472 1473C<AllMapUrl> is a url to a Yahoo! Maps map showing all the businesses 1474found in the same result-set that the current C<Result> was part of. 1475 1476See the documentation for the C<Url> method for information on the 1477one-argument versions of these methods. 1478 1479=cut 1480 1481sub MapUrl 1482{ 1483 my $Result = shift; # self 1484 return _url($Result->{MapUrl}, @_); 1485} 1486 1487sub AllMapUrl 1488{ 1489 my $Result = shift; # self 1490 return _url($Result->Response->MapUrl, @_); 1491} 1492 1493 1494 1495############################################################################## 1496 1497=item $Result->BusinessUrl 1498 1499=item $Result->BusinessClickUrl 1500 1501(I<Appropriate for B<Local> search results>) 1502 1503The business' home page, if available. C<BusinessUrl> is appropriate for 1504display, while C<BusinessClickUrl> is appropriate for the href of a link. 1505 1506See the documentation for the C<Url> method for information on the 1507one-argument versions of these methods. 1508 1509=cut 1510 1511sub BusinessUrl 1512{ 1513 my $Result = shift; # self 1514 return _url($Result->{BusinessUrl}, @_); 1515} 1516 1517sub BusinessClickUrl 1518{ 1519 my $Result = shift; # self 1520 return _url($Result->{BusinessClickUrl} || $Result->{BusinessUrl}, @_); 1521} 1522 1523 1524 1525############################################################################## 1526 1527=item $Result->Term([ I<as_html> ]) 1528 1529=item $Result->TermAsHtml 1530 1531(I<Appropriate for B<Spell>, B<Related>, and B<Terms> search results>) 1532 1533C<Term> returns the term associated with the result. If an optional 1534argument is provided and is true, the term text is returned as html. 1535 1536C<TermAsHtml> is the same as 1537 1538 $Result->Term(1) 1539 1540=cut 1541 1542sub Term 1543{ 1544 _text_or_html(Term => @_); 1545} 1546 1547sub TermAsHtml 1548{ 1549 my $Result = shift; #self 1550 return $Result->Term(1); 1551} 1552 1553 1554############################################################################## 1555 1556=pod 1557 1558=back 1559 1560=head1 Author 1561 1562Jeffrey Friedl (jfriedl@yahoo.com) 1563 1564=cut 1565 15661;