| blib/lib/WWW/SherlockSearch/Results.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % | 
| statement | 3 | 165 | 1.8 | 
| branch | 0 | 24 | 0.0 | 
| condition | 0 | 6 | 0.0 | 
| subroutine | 1 | 32 | 3.1 | 
| pod | 0 | 29 | 0.0 | 
| total | 4 | 256 | 1.5 | 
| line | stmt | bran | cond | sub | pod | time | code | 
|---|---|---|---|---|---|---|---|
| 1 | # $File: //member/autrijus/WWW-SherlockSearch/lib/WWW/SherlockSearch/Results.pm $ $Author: autrijus $ | ||||||
| 2 | # $Revision: #10 $ $Change: 10623 $ $DateTime: 2004/05/22 08:07:29 $ vim: expandtab shiftwidth=4 | ||||||
| 3 | |||||||
| 4 | package WWW::SherlockSearch::Results; | ||||||
| 5 | |||||||
| 6 | 1 | 1 | 9 | use strict; | |||
| 1 | 3 | ||||||
| 1 | 7816 | ||||||
| 7 | |||||||
| 8 | =head1 NAME | ||||||
| 9 | |||||||
| 10 | WWW::SherlockSearch::Results - Sherlock search results | ||||||
| 11 | |||||||
| 12 | =head1 SYNOPSIS | ||||||
| 13 | |||||||
| 14 | use WWW::SherlockSearch::Results; | ||||||
| 15 | |||||||
| 16 | my $resultStruct = WWW::SherlockSearch::Results->new; | ||||||
| 17 | |||||||
| 18 | $resultStruct->setServiceName($name); | ||||||
| 19 | $resultStruct->setServiceDescription($description); | ||||||
| 20 | $resultStruct->setBaseHREF($base_href); | ||||||
| 21 | $resultStruct->setHost($host); | ||||||
| 22 | $resultStruct->setPictureUrl($picture_url); | ||||||
| 23 | $resultStruct->setChannelUrl($channel_url); | ||||||
| 24 | $resultStruct->setQueryAttr($query_attr); | ||||||
| 25 | $resultStruct->setBannerImage($banner_image_url); | ||||||
| 26 | $resultStruct->setBannerLink($banner_url); | ||||||
| 27 | |||||||
| 28 | $resultStruct->add($itemurl, $content, $relev, $rest, $fulltext, $date); | ||||||
| 29 | # ... add some more entries | ||||||
| 30 | |||||||
| 31 | my $text = $results->asString; | ||||||
| 32 | my $atom = $results->asAtomString; | ||||||
| 33 | my $rss = $results->asRssString; | ||||||
| 34 | my $html = $results->asHtmlString; | ||||||
| 35 | |||||||
| 36 | =head1 DESCRIPTION | ||||||
| 37 | |||||||
| 38 | This module represents the result set returned by a Sherlock query. | ||||||
| 39 | |||||||
| 40 | =cut | ||||||
| 41 | |||||||
| 42 | sub new { | ||||||
| 43 | 0 | 0 | 0 | my $type = shift; | |||
| 44 | 0 | my $self = {}; | |||||
| 45 | 0 | $self->{'index'} = 0; | |||||
| 46 | 0 | $self->{'array'} = (); | |||||
| 47 | 0 | bless($self, $type); | |||||
| 48 | 0 | return $self; | |||||
| 49 | } | ||||||
| 50 | |||||||
| 51 | sub add { | ||||||
| 52 | 0 | 0 | 0 | my ($self, $url, $content, $rel, $summary, $fulltext, $date) = @_; | |||
| 53 | 0 | push ( | |||||
| 54 | 0 | @{ $self->{'array'} }, | |||||
| 55 | { | ||||||
| 56 | 'url' => $url, | ||||||
| 57 | 'content' => $content, | ||||||
| 58 | 'rel' => $rel, | ||||||
| 59 | 'summary' => $summary, | ||||||
| 60 | 'fulltext'=> $fulltext, | ||||||
| 61 | 'date' => $date, | ||||||
| 62 | } | ||||||
| 63 | ); | ||||||
| 64 | 0 | return $self; | |||||
| 65 | } | ||||||
| 66 | |||||||
| 67 | sub get { | ||||||
| 68 | 0 | 0 | 0 | my ($self, $index) = @_; | |||
| 69 | 0 | 0 | if (!$index) { | ||||
| 70 | 0 | $index = $self->{'index'}; | |||||
| 71 | 0 | 0 | if ($index == $self->getNumResults) { $self->{'index'} = 0; return; } | ||||
| 0 | |||||||
| 0 | |||||||
| 72 | 0 | $self->{'index'}++; | |||||
| 73 | } | ||||||
| 74 | 0 | my $temp = $self->{'array'}->[$index]; | |||||
| 75 | 0 | return (@{$temp}{qw/url content rel summary fulltext date/}); | |||||
| 0 | |||||||
| 76 | } | ||||||
| 77 | |||||||
| 78 | sub reset { | ||||||
| 79 | 0 | 0 | 0 | my $self = shift; | |||
| 80 | 0 | $self->{'index'} = 0; | |||||
| 81 | 0 | return $self; | |||||
| 82 | } | ||||||
| 83 | |||||||
| 84 | sub getNumResults { | ||||||
| 85 | 0 | 0 | 0 | my $self = shift; | |||
| 86 | 0 | 0 | return scalar(@{ $self->{'array'} || [] }); | ||||
| 0 | |||||||
| 87 | } | ||||||
| 88 | |||||||
| 89 | sub getBannerLink { | ||||||
| 90 | 0 | 0 | 0 | my $self = shift; | |||
| 91 | 0 | return $self->{banURL}; | |||||
| 92 | } | ||||||
| 93 | |||||||
| 94 | sub setBannerLink { | ||||||
| 95 | 0 | 0 | 0 | my $self = shift; | |||
| 96 | 0 | $self->{banURL} = shift; | |||||
| 97 | 0 | return $self; | |||||
| 98 | } | ||||||
| 99 | |||||||
| 100 | sub getBannerImage { | ||||||
| 101 | 0 | 0 | 0 | my $self = shift; | |||
| 102 | 0 | return $self->{banImageURL}; | |||||
| 103 | } | ||||||
| 104 | |||||||
| 105 | sub setBannerImage { | ||||||
| 106 | 0 | 0 | 0 | my $self = shift; | |||
| 107 | 0 | $self->{banImageURL} = shift; | |||||
| 108 | 0 | return $self; | |||||
| 109 | } | ||||||
| 110 | |||||||
| 111 | sub getServiceName { | ||||||
| 112 | 0 | 0 | 0 | my $self = shift; | |||
| 113 | 0 | return $self->{serviceName}; | |||||
| 114 | } | ||||||
| 115 | |||||||
| 116 | sub setServiceName { | ||||||
| 117 | 0 | 0 | 0 | my $self = shift; | |||
| 118 | 0 | $self->{serviceName} = shift; | |||||
| 119 | 0 | return $self; | |||||
| 120 | } | ||||||
| 121 | |||||||
| 122 | sub getChannelUrl { | ||||||
| 123 | 0 | 0 | 0 | my $self = shift; | |||
| 124 | 0 | return $self->{channelUrl}; | |||||
| 125 | } | ||||||
| 126 | |||||||
| 127 | sub setChannelUrl { | ||||||
| 128 | 0 | 0 | 0 | my $self = shift; | |||
| 129 | 0 | $self->{channelUrl} = shift; | |||||
| 130 | 0 | return $self; | |||||
| 131 | } | ||||||
| 132 | |||||||
| 133 | sub getQueryAttr { | ||||||
| 134 | 0 | 0 | 0 | my $self = shift; | |||
| 135 | 0 | return $self->{queryAttr}; | |||||
| 136 | } | ||||||
| 137 | |||||||
| 138 | sub setQueryAttr { | ||||||
| 139 | 0 | 0 | 0 | my $self = shift; | |||
| 140 | 0 | $self->{queryAttr} = shift; | |||||
| 141 | 0 | return $self; | |||||
| 142 | } | ||||||
| 143 | |||||||
| 144 | sub getServiceDescription { | ||||||
| 145 | 0 | 0 | 0 | my $self = shift; | |||
| 146 | 0 | return $self->{serviceDescription}; | |||||
| 147 | } | ||||||
| 148 | |||||||
| 149 | sub setServiceDescription { | ||||||
| 150 | 0 | 0 | 0 | my $self = shift; | |||
| 151 | 0 | $self->{serviceDescription} = shift; | |||||
| 152 | 0 | return $self; | |||||
| 153 | } | ||||||
| 154 | |||||||
| 155 | sub getPictureUrl { | ||||||
| 156 | 0 | 0 | 0 | my $self = shift; | |||
| 157 | 0 | return $self->{pictureUrl}; | |||||
| 158 | } | ||||||
| 159 | |||||||
| 160 | sub setPictureUrl { | ||||||
| 161 | 0 | 0 | 0 | my $self = shift; | |||
| 162 | 0 | $self->{pictureUrl} = shift; | |||||
| 163 | 0 | return $self; | |||||
| 164 | } | ||||||
| 165 | |||||||
| 166 | sub getBaseHREF { | ||||||
| 167 | 0 | 0 | 0 | my $self = shift; | |||
| 168 | 0 | return $self->{baseHREF}; | |||||
| 169 | } | ||||||
| 170 | |||||||
| 171 | sub setBaseHREF { | ||||||
| 172 | 0 | 0 | 0 | my $self = shift; | |||
| 173 | 0 | $self->{baseHREF} = shift; | |||||
| 174 | 0 | return $self; | |||||
| 175 | } | ||||||
| 176 | |||||||
| 177 | sub getHost { | ||||||
| 178 | 0 | 0 | 0 | my $self = shift; | |||
| 179 | 0 | return $self->{host}; | |||||
| 180 | } | ||||||
| 181 | |||||||
| 182 | sub setHost { | ||||||
| 183 | 0 | 0 | 0 | my $self = shift; | |||
| 184 | 0 | $self->{host} = shift; | |||||
| 185 | 0 | return $self; | |||||
| 186 | } | ||||||
| 187 | |||||||
| 188 | sub asString { | ||||||
| 189 | 0 | 0 | 0 | my $self = shift; | |||
| 190 | |||||||
| 191 | 0 | my $string .= "\nResults :\n\n"; | |||||
| 192 | |||||||
| 193 | 0 | $string .= "Banner Link : " . $self->getBannerLink . "\nBanner Image : "; | |||||
| 194 | 0 | $string .= $self->getBannerImage . "\n\n"; | |||||
| 195 | |||||||
| 196 | 0 | 0 | if ($self->getNumResults == 0) { $string .= "No hits\n"; return $string; } | ||||
| 0 | |||||||
| 0 | |||||||
| 197 | |||||||
| 198 | 0 | $self->reset; | |||||
| 199 | 0 | my ($url, $cont, $rel, $summary, $fulltext, $date); | |||||
| 200 | 0 | while (($url, $cont, $rel, $summary, $fulltext, $date) = $self->get) { | |||||
| 201 | 0 | $string .= "Hit := $url\nRelevance : $rel\n"; | |||||
| 202 | 0 | $string .= "Content := $cont\nSummary := $summary\nFulltext := $fulltext\n\n"; | |||||
| 203 | } | ||||||
| 204 | 0 | return $string; | |||||
| 205 | } | ||||||
| 206 | |||||||
| 207 | sub asHtmlString { | ||||||
| 208 | 0 | 0 | 0 | my $self = shift; | |||
| 209 | 0 | my ($url, $cont, $rel, $summary, $fulltext, $date); | |||||
| 210 | 0 | my $string; | |||||
| 211 | 0 | 0 | if ($url = $self->getBannerLink) { | ||||
| 212 | 0 |  	$string .= " | |||||
| 213 | 0 | $string .= $self->getBannerImage . "\"> \n"; | |||||
| 214 | } | ||||||
| 215 | |||||||
| 216 | 0 | 0 | if ($self->getNumResults == 0) { | ||||
| 217 | 0 |  	$string .= " No hits\n";  | 
|||||
| 218 | 0 | return $string; | |||||
| 219 | } | ||||||
| 220 | |||||||
| 221 | 0 | $self->reset; | |||||
| 222 | 0 | while (($url, $cont, $rel, $summary, $fulltext, $date) = $self->get) { | |||||
| 223 | 0 |  	$string .= " $cont ";  | 
|||||
| 224 | 0 | 0 | $string .= "$rel%" if ($rel); | ||||
| 225 | 0 | 0 |  	$string .= " $summary" if ($summary);  | 
||||
| 226 | 0 | 0 |  	$string .= " $fulltext" if ($fulltext);  | 
||||
| 227 | 0 | $string .= "\n\n"; | |||||
| 228 | } | ||||||
| 229 | 0 | return $string; | |||||
| 230 | } | ||||||
| 231 | |||||||
| 232 | sub asAtomString { | ||||||
| 233 | 0 | 0 | 0 | my $self = shift; | |||
| 234 | |||||||
| 235 | 0 | require DateTime; | |||||
| 236 | 0 | require XML::Atom::Feed; | |||||
| 237 | 0 | require XML::Atom::Link; | |||||
| 238 | 0 | require XML::Atom::Entry; | |||||
| 239 | |||||||
| 240 | 0 | my $feed = XML::Atom::Feed->new; | |||||
| 241 | 0 | $feed->title($self->getServiceName); | |||||
| 242 | 0 | $feed->info($self->getServiceDescription); | |||||
| 243 | |||||||
| 244 | 0 | my $link = XML::Atom::Link->new; | |||||
| 245 | 0 | $link->type('text/html'); | |||||
| 246 | 0 | $link->rel('alternate'); | |||||
| 247 | 0 | $link->title($self->getServiceName); | |||||
| 248 | 0 | $link->href($self->getChannelUrl); | |||||
| 249 | 0 | $feed->add_link($link); | |||||
| 250 | 0 | $feed->modified(DateTime->now->iso8601 . 'Z'); | |||||
| 251 | |||||||
| 252 | 0 | my $author = XML::Atom::Person->new; | |||||
| 253 | 0 | $author->name($self->getServiceName); | |||||
| 254 | |||||||
| 255 | $self->entry_callback(sub { | ||||||
| 256 | 0 | 0 | my ($url, $cont, $rel, $summary, $fulltext, $date) = @_; | ||||
| 257 | |||||||
| 258 | 0 | my $dt = DateTime->from_epoch( epoch => $date ); | |||||
| 259 | 0 | my $entry = XML::Atom::Entry->new; | |||||
| 260 | 0 | $entry->title($cont); | |||||
| 261 | 0 | $entry->content($fulltext); | |||||
| 262 | 0 | $entry->summary($summary); | |||||
| 263 | 0 | $entry->issued($dt->iso8601 . 'Z'); | |||||
| 264 | 0 | $entry->modified($dt->iso8601 . 'Z'); | |||||
| 265 | 0 | $entry->id($url); | |||||
| 266 | 0 | $entry->author($author); | |||||
| 267 | |||||||
| 268 | 0 | my $link = XML::Atom::Link->new; | |||||
| 269 | 0 | $link->type('text/html'); | |||||
| 270 | 0 | $link->rel('alternate'); | |||||
| 271 | 0 | $link->href($url); | |||||
| 272 | 0 | $link->title($cont); | |||||
| 273 | 0 | $entry->add_link($link); | |||||
| 274 | 0 | $feed->add_entry($entry); | |||||
| 275 | 0 | }); | |||||
| 276 | |||||||
| 277 | 0 | my $xml = $feed->as_xml; | |||||
| 278 | 0 |      $xml =~ s/ | |||||
| 279 | 0 | return $xml; | |||||
| 280 | } | ||||||
| 281 | |||||||
| 282 | sub asRssString { | ||||||
| 283 | 0 | 0 | 0 | my $self = shift; | |||
| 284 | |||||||
| 285 | 0 | require XML::RSS; | |||||
| 286 | 0 | my $rss = XML::RSS->new(version => '1.0'); | |||||
| 287 | |||||||
| 288 | 0 | $rss->add_module( | |||||
| 289 | prefix => 'content', | ||||||
| 290 | uri => 'http://purl.org/rss/1.0/modules/content/', | ||||||
| 291 | ); | ||||||
| 292 | |||||||
| 293 | 0 | $rss->channel( | |||||
| 294 | title => fixEm($self->getServiceName), | ||||||
| 295 | link => fixEm($self->getChannelUrl), | ||||||
| 296 | description => fixEm($self->getServiceDescription) | ||||||
| 297 | ); | ||||||
| 298 | |||||||
| 299 | 0 | $rss->image( | |||||
| 300 | title => fixEm($self->getServiceName), | ||||||
| 301 | url => fixEm($self->getPictureUrl), | ||||||
| 302 | link => fixEm($self->getHost) | ||||||
| 303 | ); | ||||||
| 304 | |||||||
| 305 | 0 | $rss->textinput( | |||||
| 306 | title => fixEm($self->getServiceName), | ||||||
| 307 | description => "Search this site", | ||||||
| 308 | name => fixEm($self->getQueryAttr), | ||||||
| 309 | link => fixEm($self->getChannelUrl) | ||||||
| 310 | ); | ||||||
| 311 | |||||||
| 312 | $self->entry_callback(sub { | ||||||
| 313 | 0 | 0 | my ($url, $cont, $rel, $summary, $fulltext, $date) = @_; | ||||
| 314 | 0 | 0 | $rss->add_item( | ||||
| 315 | title => fixEm($cont), | ||||||
| 316 | link => fixEm($url), | ||||||
| 317 | description => fixEm($summary), | ||||||
| 318 | (length $fulltext) ? ( | ||||||
| 319 | content => { | ||||||
| 320 | encoded => fixEm($fulltext), | ||||||
| 321 | } | ||||||
| 322 | ) : (), | ||||||
| 323 | ); | ||||||
| 324 | 0 | }); | |||||
| 325 | |||||||
| 326 | 0 | return $rss->as_string; | |||||
| 327 | } | ||||||
| 328 | |||||||
| 329 | sub entry_callback { | ||||||
| 330 | 0 | 0 | 0 | my ($self, $callback) = @_; | |||
| 331 | 0 | $self->reset; | |||||
| 332 | |||||||
| 333 | 0 | while (my ($url, $cont, $rel, $summary, $fulltext, $date) = $self->get) { | |||||
| 334 | 0 | 0 | 0 | if (!length $summary and length $fulltext and $WWW::SherlockSearch::ExcerptLength) { | |||
| 0 | |||||||
| 335 | 0 | $summary = substr($fulltext, 0, $WWW::SherlockSearch::ExcerptLength); | |||||
| 336 | 0 | 0 | $summary .= '...' unless $summary eq $fulltext; | ||||
| 337 | } | ||||||
| 338 | 0 | $callback->($url, $cont, $rel, $summary, $fulltext, $date); | |||||
| 339 | } | ||||||
| 340 | } | ||||||
| 341 | |||||||
| 342 | #This is a cludge to fix xml problems | ||||||
| 343 | |||||||
| 344 | sub fixEm { | ||||||
| 345 | 0 | 0 | 0 | my $text = shift; | |||
| 346 | |||||||
| 347 | 0 | $text =~ s/&/&/gs; | |||||
| 348 | 0 | $text =~ s/</gs; | |||||
| 349 | 0 | $text =~ s/>/>/gs; | |||||
| 350 | |||||||
| 351 | 0 | return $text; | |||||
| 352 | } | ||||||
| 353 | |||||||
| 354 | 1; | ||||||
| 355 | |||||||
| 356 | =head1 SEE ALSO | ||||||
| 357 | |||||||
| 358 |  L | 
||||||
| 359 | |||||||
| 360 | =head1 AUTHORS | ||||||
| 361 | |||||||
| 362 | =over 4 | ||||||
| 363 | |||||||
| 364 | =item * | ||||||
| 365 | |||||||
| 366 |  Damian Steer E | 
||||||
| 367 | |||||||
| 368 | =item * | ||||||
| 369 | |||||||
| 370 |  Kang-min Liu E | 
||||||
| 371 | |||||||
| 372 | =item * | ||||||
| 373 | |||||||
| 374 |  Autrijus Tang E | 
||||||
| 375 | |||||||
| 376 | =back | ||||||
| 377 | |||||||
| 378 | =head1 COPYRIGHT | ||||||
| 379 | |||||||
| 380 | Copyright 1999, 2000, 2001 by Damian Steer. | ||||||
| 381 | |||||||
| 382 | Copyright 2002, 2003 by Kang-min Liu. | ||||||
| 383 | |||||||
| 384 | Copyright 2002, 2003, 2004 by Autrijus Tang. | ||||||
| 385 | |||||||
| 386 | |||||||
| 387 | This program is free software; you can redistribute it and/or modify it | ||||||
| 388 | under the same terms as Perl itself. | ||||||
| 389 | |||||||
| 390 |  See L | 
||||||
| 391 | |||||||
| 392 | =cut |