--- loncom/interface/lonsearchcat.pm 2002/06/25 15:08:59 1.129 +++ loncom/interface/lonsearchcat.pm 2009/10/06 10:31:41 1.315 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Search Catalog # -# $Id: lonsearchcat.pm,v 1.129 2002/06/25 15:08:59 matthew Exp $ +# $Id: lonsearchcat.pm,v 1.315 2009/10/06 10:31:41 bisitz Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,14 +25,6 @@ # # http://www.lon-capa.org/ # -# YEAR=2001 -# 3/8, 3/12, 3/13, 3/14, 3/15, 3/19 Scott Harrison -# 3/20, 3/21, 3/22, 3/26, 3/27, 4/2, 8/15, 8/24, 8/25 Scott Harrison -# 10/12,10/14,10/15,10/16,11/28,11/29,12/10,12/12,12/16 Scott Harrison -# YEAR=2002 -# 1/17 Scott Harrison -# 6/17 Matthew Hall -# ############################################################################### ############################################################################### @@ -40,7 +32,7 @@ =head1 NAME -lonsearchcat +lonsearchcat - LONCAPA Search Interface =head1 SYNOPSIS @@ -56,7 +48,7 @@ described at http://www.lon-capa.org. lonsearchcat presents the user with an interface to search the LON-CAPA digital library. lonsearchcat also initiates the execution of a search by sending the search parameters to LON-CAPA servers. The progress of -search (on a server basis) is displayed to the user in a seperate window. +search (on a server basis) is displayed to the user in a separate window. =head1 Internals @@ -67,246 +59,781 @@ search (on a server basis) is displayed ############################################################################### ############################################################################### -############################################################################### -## ## -## ORGANIZATION OF THIS PERL MODULE ## -## ## -## 1. Modules used by this module ## -## 2. Variables used throughout the module ## -## 3. handler subroutine called via Apache and mod_perl ## -## 4. Other subroutines ## -## ## -############################################################################### - package Apache::lonsearchcat; -# ------------------------------------------------- modules used by this module use strict; -use Apache::Constants qw(:common); -use Apache::lonnet(); +use Apache::Constants qw(:common :http); +use Apache::lonnet; use Apache::File(); use CGI qw(:standard); use Text::Query; use GDBM_File; use Apache::loncommon(); - -# ---------------------------------------- variables used throughout the module +use Apache::lonmysql(); +use Apache::lonmeta; +use Apache::lonhtmlcommon; +use Apache::lonlocal; +use LONCAPA::lonmetadata(); +use HTML::Entities(); +use Parse::RecDescent; +use Apache::lonnavmaps; +use Apache::lonindexer(); +use LONCAPA; ###################################################################### ###################################################################### - -=pod - -=item Global variables - -=over 4 - -=item $closebutton - -button that closes the search window - -=item $importbutton - -button to take the selecte results and go to group sorting - -=item %hash - -The ubiquitous database hash - -=item $diropendb - -The full path to the (temporary) search database file. This is set and -used in &handler() and is also used in &output_results(). - -=back - -=cut - -###################################################################### -###################################################################### - -# -- dynamically rendered interface components -my $closebutton; # button that closes the search window -my $importbutton; # button to take the selected results and go to group sorting - -# -- miscellaneous variables -my %hash; # database hash -my $diropendb = ""; # db file - -###################################################################### -###################################################################### - -=pod - -=item &handler() - main handler invoked by httpd child - -=item Variables - -=over 4 - -=item $hidden - -holds 'hidden' html forms - -=item $scrout - -string that holds portions of the screen output - -=back - -=cut +## +## Global variables +## +###################################################################### +###################################################################### +my %groupsearch_db; # Database hash used to save values for the + # groupsearch RAT interface. +my %persistent_db; # gdbm hash which holds data which is supposed to + # persist across calls to lonsearchcat.pm + +# The different view modes and associated functions + +my %Views = ("detailed" => \&detailed_citation_view, + "detailedpreview" => \&detailed_citation_preview, + "summary" => \&summary_view, + "summarypreview" => \&summary_preview, + "fielded" => \&fielded_format_view, + "xml" => \&xml_sgml_view, + "compact" => \&compact_view); ###################################################################### ###################################################################### sub handler { my $r = shift; - untie %hash; +# &set_defaults(); + # + # set form defaults + # + my $hidden_fields;# Hold all the hidden fields used to keep track + # of the search system state + my $importbutton; # button to take the selected results and go to group + # sorting + my $diropendb; # The full path to the (temporary) search database file. + # This is set and used in &handler() and is also used in + # &output_results(). - $r->content_type('text/html'); + my $loaderror=&Apache::lonnet::overloaderror($r); + if ($loaderror) { return $loaderror; } + # + my $closebutton; # button that closes the search window + # This button is different for the RAT compared to + # normal invocation. + # + &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK if $r->header_only; - + ## + ## Prevent caching of the search interface window. Hopefully this means + ## we will get the launch=1 passed in a little more. + &Apache::loncommon::no_cache($r); + ## + ## Pick up form fields passed in the links. + ## + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['catalogmode','launch','acts','mode','form','element','pause', + 'phase','persistent_db_id','table','start','show', + 'cleargroupsort','titleelement','area','inhibitmenu']); + ## + ## The following is a trick - we wait a few seconds if asked to so + ## the daemon running the search can get ahead of the daemon + ## printing the results. We only need (theoretically) to do + ## this once, so the pause indicator is deleted + ## + if (exists($env{'form.pause'})) { + sleep(1); + delete($env{'form.pause'}); + } + ## + ## Initialize global variables + ## my $domain = $r->dir_config('lonDefDomain'); - $diropendb= "/home/httpd/perl/tmp/".&Apache::lonnet::escape($domain). - "\_".&Apache::lonnet::escape($ENV{'user.name'})."_searchcat.db"; + $diropendb= "/home/httpd/perl/tmp/". + "$env{'user.domain'}_$env{'user.name'}_sel_res.db"; + # + # set the name of the persistent database + # $env{'form.persistent_db_id'} can only have digits in it. + if (! exists($env{'form.persistent_db_id'}) || + ($env{'form.persistent_db_id'} =~ /\D/) || + ($env{'form.launch'} eq '1')) { + $env{'form.persistent_db_id'} = time; + } - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['catalogmode','launch','acts','mode','form','element', - 'reqinterface']); + my $persistent_db_file = "/home/httpd/perl/tmp/". + &escape($domain). + '_'.&escape($env{'user.name'}). + '_'.$env{'form.persistent_db_id'}.'_persistent_search.db'; + ## + &Apache::lonhtmlcommon::clear_breadcrumbs(); + + my @allowed_searches = ('portfolio'); + if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'})) { + push(@allowed_searches,'res'); + } + if (exists($env{'request.course.id'}) && $env{'request.course.id'} ne '') { + push(@allowed_searches,'course'); + } + my $crumb_text = 'Portfolio Search'; + if (@allowed_searches == 3) { + $crumb_text = 'Course, Portfolio and Catalog Search'; + } elsif (@allowed_searches ==2) { + if (grep(/^res$/,@allowed_searches)) { + $crumb_text = 'Portfolio and Catalog Search'; + } elsif (grep(/^course$/,@allowed_searches)) { + $crumb_text = 'Portfolio and Course Search'; + } + } + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/searchcat?'. + &Apache::loncommon::inhibit_menu_check(). + '&catalogmode='.$env{'form.catalogmode'}. + '&launch='.$env{'form.launch'}. + '&mode='.$env{'form.mode'}, + text=>"$crumb_text", + target=>'_top', + bug=>'Searching',}); + # + if ($env{'form.phase'} !~ m/(basic|adv|course)_search/) { + if (! &get_persistent_form_data($persistent_db_file)) { + if ($env{'form.phase'} =~ /(run_search|results)/) { + &Apache::lonnet::logthis('lonsearchcat:'. + 'Unable to recover data from '. + $persistent_db_file); + my $msg = + 'We were unable to retrieve data describing your search. '. + 'This is a serious error and has been logged. '. + 'Please alert your LON-CAPA administrator.'; + &Apache::loncommon::simple_error_page($r,'Search Error', + $msg); + return OK; + } + } + } else { + &clean_up_environment(); + } ## - ## Clear out old values from database + ## Clear out old values from groupsearch database ## - if ($ENV{'form.launch'} eq '1') { - if (tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) { + untie %groupsearch_db if (tied(%groupsearch_db)); + if (($env{'form.cleargroupsort'} eq '1') || + (($env{'form.launch'} eq '1') && + ($env{'form.catalogmode'} eq 'import'))) { + if (tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT(),0640)) { &start_fresh_session(); - untie %hash; + untie %groupsearch_db; + delete($env{'form.cleargroupsort'}); } else { - $r->print('
Unable to tie hash to db '. - 'file'); + # This is a stupid error to give to the user. + # It really tells them nothing. + my $msg = 'Unable to tie hash to db file.'; + &Apache::loncommon::simple_error_page($r,'Search Error', + $msg); return OK; } } ## - ## Produce some output, so people know it is working + ## Configure hidden fields ## - $r->print("\n"); - $r->rflush; + $hidden_fields = ''."\n"; + if (exists($env{'form.catalogmode'})) { + $hidden_fields .= &hidden_field('catalogmode'); + } + if (exists($env{'form.form'})) { + $hidden_fields .= &hidden_field('form'); + } + if (exists($env{'form.element'})) { + $hidden_fields .= &hidden_field('element'); + } + if (exists($env{'form.titleelement'})) { + $hidden_fields .= &hidden_field('titleelement'); + } + if (exists($env{'form.mode'})) { + $hidden_fields .= &hidden_field('mode'); + } + if (exists($env{'form.area'})) { + $hidden_fields .= &hidden_field('area'); + } + if (exists($env{'form.inhibitmenu'})) { + $hidden_fields .= &hidden_field('inhibitmenu'); + } ## ## Configure dynamic components of interface ## - my $hidden; # Holds 'hidden' html forms - if ($ENV{'form.catalogmode'} eq 'interactive') { - $hidden="". - "\n"; - $closebutton=""."\n"; - } elsif ($ENV{'form.catalogmode'} eq 'groupsearch') { - $hidden=<'.&mt('No matches found in resources.').'
'); + } + +# Check discussions if requested + if ($discuss) { + my $totaldiscussions = 0; + $r->print(''.&mt('No matches found in postings.').'
'); + } + } else { + $r->print('- - + + $closebutton - - - -
END - my $scrout=<<"ENDHEADER"; - - -'.
- ''.$uctitle.':
table: |'.$table.'|
' # SB + .''
+ .&mt('Unable to retrieve search results. '
+ .'Unable to determine the table results were saved in.')
+ .&Apache::loncommon::end_page()
+ );
+ return undef;
+ }
+ ##
+ ## Make sure we can connect and the table exists.
+ ##
+ my $connection_result = &Apache::lonmysql::connect_to_db();
+ if (!defined($connection_result)) {
+ $r->print("Unable to connect to the MySQL database where your results".
+ " are saved.".
+ &Apache::loncommon::end_page());
+ &Apache::lonnet::logthis("lonsearchcat: unable to get lonmysql to".
+ " connect to database.");
+ &Apache::lonnet::logthis(&Apache::lonmysql::get_error());
+ return undef;
+ }
+ my $table_check = &Apache::lonmysql::check_table($table);
+ if (! defined($table_check)) {
+ $r->print("A MySQL error has occurred.".
+ &Apache::loncommon::end_page());
+ &Apache::lonnet::logthis("lonmysql was unable to determine the status".
+ " of table ".$table);
+ return undef;
+ } elsif (! $table_check) {
+ $r->print("The table of results could not be found.");
+ &Apache::lonnet::logthis("The user requested a table, ".$table.
+ ", that could not be found.");
+ return undef;
+ }
+ return 1;
+}
+
+######################################################################
+######################################################################
+
+=pod
+
+=item &print_sort_form()
+
+The sort feature is not implemented at this time. This form just prints
+a link to change the search query.
+
+=cut
+
+######################################################################
+######################################################################
+sub print_sort_form {
+ my ($r,$pretty_query_string) = @_;
+
+ ##
+ my %SortableFields=&Apache::lonlocal::texthash(
+ id => 'Default',
+ title => 'Title',
+ author => 'Author',
+ subject => 'Subject',
+ url => 'URL',
+ version => 'Version Number',
+ mime => 'Mime type',
+ lang => 'Language',
+ owner => 'Owner/Publisher',
+ copyright => 'Copyright',
+ hostname => 'Host',
+ creationdate => 'Creation Date',
+ lastrevisiondate => 'Revision Date'
+ );
+ ##
+ my $table = $env{'form.table'};
+ return if (! &ensure_db_and_table($r,$table));
+ ##
+ ## Get the number of results
+ ##
+ my $total_results = &Apache::lonmysql::number_of_rows($table);
+ if (! defined($total_results)) {
+ $r->print("A MySQL error has occurred.".
+ &Apache::loncommon::end_page());
+ &Apache::lonnet::logthis("lonmysql was unable to determine the number".
+ " of rows in table ".$table);
+ &Apache::lonnet::logthis(&Apache::lonmysql::get_error());
+ return;
+ }
+ my $js =< '
+ .&mt('There are [_1] matches to your query.',$total_results)
+ .' '.$revise.' '.&mt('Search: ').$pretty_query_string
+ .' Basic search: '.$ENV{'form.basicexp'}.' Advanced search '.$query.' \n";
- if ($ENV{'form.catalogmode'} eq 'interactive') {
- my $titleesc=$Fields{'title'};
- $titleesc=~s/\'/\\'/; # '
- $compiledresult.=< '
+ .''
+ .' '
+ .''
+ .' '
+ .''
+ .' '
+ .&mt('Internal Error - Bad view selected.')
+ .' '.
+ &mt('Unable to save import results.').
+ ' '.
+ &mt('A MySQL error has occurred.').
+ 'Sort Results
+#Sort by: Search Catalog
-CATALOGBEGIN
- my $action = "/adm/searchcat";
- if ($mode eq 'Basic') {
- $action .= "?reqinterface=basic";
- } elsif ($mode eq 'Advanced') {
- $action .= "?reqinterface=advanced";
- }
- $r->print(<
-Search Query
-CATALOGCONTROLS
+}
+
+sub update_status {
+ my ($r,$text) = @_;
+ $text =~ s/\'/\\\'/g;
+ $r->print(<
+SCRIPT
+
+ $r->rflush();
+}
+
+{
+ my $max_time = 300; # seconds for the search to complete
+ my $start_time = 0;
+ my $last_time = 0;
+
+sub reset_timing {
+ $start_time = 0;
+ $last_time = 0;
+}
+
+sub time_left {
+ if ($start_time == 0) {
+ $start_time = time;
+ }
+ my $time_left = $max_time - (time - $start_time);
+ $time_left = 0 if ($time_left < 0);
+ return $time_left;
+}
+
+sub update_seconds {
+ my ($r) = @_;
+ my $time = &time_left();
+ if (($last_time-$time) > 0) {
+ $r->print(<
+SCRIPT
+
+ $r->rflush();
+ }
+ $last_time = $time;
+}
+
+}
+
+######################################################################
+######################################################################
+
+=pod
+
+=item &revise_button()
+
+Inputs: None
+
+Returns: html string for a 'revise search' button.
+
+=cut
+
+######################################################################
+######################################################################
+sub revise_button {
+ my $revisetext = &mt('Revise search');
+ my $revise_phase = 'disp_basic';
+ $revise_phase = 'disp_adv' if ($env{'form.searchmode'} eq 'advanced');
+ my $newloc = '/adm/searchcat'.
+ '?persistent_db_id='.$env{'form.persistent_db_id'}.
+ '&cleargroupsort=1'.
+ '&phase='.$revise_phase;
+ my $result = qq{ };
+ return $result;
+}
+
+######################################################################
+######################################################################
+
+=pod
+
+=item &run_search()
+
+Executes a search query by sending it the the other servers and putting the
+results into MySQL.
+
+=cut
+
+######################################################################
+######################################################################
+sub run_search {
+ my ($r,$query,$customquery,$customshow,$serverlist,
+ $pretty_string,$area) = @_;
+ my $tabletype = 'metadata';
+ if ($area eq 'portfolio') {
+ $tabletype = 'portfolio_search';
+ }
+ my $connection = $r->connection;
#
- # Remind them what they searched for
+ # Print run_search header
#
- if ($mode eq 'Basic') {
- $r->print('
::i;
+ $pretty_string =~ s:(
)*\s*$::im;
+ my @Lines = split("
",$pretty_string);
+ # I keep getting blank items at the end of the list, hence the following:
+ while ($Lines[-1] =~ /^\s*$/ && @Lines) {
+ pop(@Lines);
+ }
+ if (@Lines > 2) {
+ $pretty_string = join '
',(@Lines[0..2],'...
');
}
- $r->print('Search Results
');
+ $r->print(&mt("Search: [_1]",$pretty_string));
$r->rflush();
#
- # make the pop-up window for status
+ # Determine the servers we need to contact.
+ my @Servers_to_contact;
+ if (defined($serverlist)) {
+ if (ref($serverlist) eq 'ARRAY') {
+ @Servers_to_contact = @$serverlist;
+ } else {
+ @Servers_to_contact = ($serverlist);
+ }
+ } else {
+ my %all_library_servers = &Apache::lonnet::all_library();
+ @Servers_to_contact = sort(keys(%all_library_servers));
+ }
+ my %Server_status;
#
- $r->print(&make_popwin(%rhash));
- $r->rflush();
- ##
- ## Prepare for the main loop below
+ # Check on the mysql table we will use to store results.
+ my $table =$env{'form.table'};
+ if (! defined($table) || $table eq '' || $table =~ /\D/ ) {
+ $r->print("Unable to determine table id to save search results in.".
+ "The search has been aborted.".
+ &Apache::loncommon::end_page());
+ return;
+ }
+ my $table_status = &Apache::lonmysql::check_table($table);
+ if (! defined($table_status)) {
+ $r->print("Unable to determine status of table.".
+ &Apache::loncommon::end_page());
+ &Apache::lonnet::logthis("Bogus table id of $table for ".
+ "$env{'user.name'} @ $env{'user.domain'}");
+ &Apache::lonnet::logthis("lonmysql error = ".
+ &Apache::lonmysql::get_error());
+ return;
+ }
+ if (! $table_status) {
+ &Apache::lonnet::logthis("lonmysql error = ".
+ &Apache::lonmysql::get_error());
+ &Apache::lonnet::logthis("lonmysql debug = ".
+ &Apache::lonmysql::get_debug());
+ &Apache::lonnet::logthis('table status = "'.$table_status.'"');
+ $r->print("The table id,$table, we tried to use is invalid.".
+ "The search has been aborted.".
+ &Apache::loncommon::end_page());
+ return;
+ }
##
- my $servercount=0;
- my $hitcountsum=0;
- my $servernum=(keys %rhash);
- my $serversleft=$servernum;
- ##
- ## Run until we run out of time or we run out of servers
- ##
- while($serversleft && $timeremain) {
- ##
- ## %rhash has servers deleted from it as results come in
- ## (within the foreach loop below).
- ##
- foreach my $rkey (sort keys %rhash) {
-# &Apache::lonnet::logthis("Server $rkey:".time);
- $servercount++;
- $compiledresult='';
- my $reply=$rhash{$rkey};
- my @results;
- if ($reply eq 'con_lost') {
- &popwin_imgupdate($r,$rkey,"srvbad.gif");
- $serversleft--;
- delete $rhash{$rkey};
- } else {
- # must do since 'use strict' checks for tainting
- $reply=~/^([\.\w]+)$/;
- my $replyfile=$r->dir_config('lonDaemons').'/tmp/'.$1;
- $reply=~/(.*?)\_/;
- for (my $counter=0;$counter<2;$counter++) {
- if (-e $replyfile && ! -e "$replyfile.end") {
- &popwin_imgupdate($r,$rkey,"srvhalf.gif");
- &popwin_js($r,'popwin.hc["'.$rkey.'"]='.
- '"still transferring..."'.';');
- }
- # Are we finished transferring data?
- if (-e "$replyfile.end") {
- $serversleft--;
- delete $rhash{$rkey};
- if (-s $replyfile) {
- &popwin_imgupdate($r,$rkey,"srvgood.gif");
- my $fh;
- unless ($fh=Apache::File->new($replyfile)){
- # Is it really appropriate to die on this error?
- $r->print('ERROR: file '.
- $replyfile.' cannot be opened');
- return OK;
- }
- @results=<$fh> if $fh;
- my $hits =@results;
- &popwin_js($r,'popwin.hc["'.$rkey.'"]='.
- $hits.';');
- $hitcountsum+=$hits;
- &popwin_js($r,'popwin.document.forms.popremain.'.
- 'numhits.value='.$hitcountsum.';');
- } else {
- &popwin_imgupdate($r,$rkey,"srvempty.gif");
- &popwin_js($r,'popwin.hc["'.$rkey.'"]=0;');
- }
- last;
- } # end of if ( -e "$replyfile.end")
- last unless $timeremain;
- sleep 1; # wait for daemons to write files?
- $timeremain--;
- $elapsetime++;
- &popwin_js($r,"popwin.document.popremain.".
- "elapsetime.value=$elapsetime;");
- }
- &popwin_js($r,'popwin.document.whirly.'.
- 'src="/adm/lonIcons/lonanimend.gif";');
- } # end of if ($reply eq 'con_lost') else statement
- my %Fields = undef; # Holds the data to be sent to the various
- # *_view routines.
- my ($extrashow,$customfields,$customhash) = &handle_custom_fields(\@results);
- my @customfields = @$customfields;
- my %customhash = %$customhash;
- untie %hash if (keys %hash);
+ ## Prepare for the big loop.
+ my $hitcountsum;
+ my %matches;
+ my $server;
+ my $status;
+ my $revise = &revise_button();
+ $r->print('');
+ $r->rflush();
+ &reset_timing();
+ &update_seconds($r);
+ &update_status($r,&mt('contacting [_1]',$Servers_to_contact[0]));
+ while (&time_left() &&
+ ((@Servers_to_contact) || keys(%Server_status))) {
+ &update_seconds($r);
#
- if (! tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
- $r->print('Unable to tie hash to db '.
- 'file');
+ # Send out a search request
+ if (@Servers_to_contact) {
+ # Contact one server
+ my $server = shift(@Servers_to_contact);
+ &update_status($r,&mt('contacting [_1]',$server));
+ my $reply=&Apache::lonnet::metadata_query($query,$customquery,
+ $customshow,[$server]);
+ ($server) = keys(%$reply);
+ $Server_status{$server} = $reply->{$server};
} else {
- if ($ENV{'form.launch'} eq '1') {
- &start_fresh_session();
- }
- foreach my $result (@results) {
- next if $result=~/^custom\=/;
- chomp $result;
- next unless $result;
- %Fields = &parse_raw_result($result,$rkey);
- $Fields{'extrashow'}=$extrashow;
- if ($extrashow) {
- foreach my $field (@customfields) {
- my $value='';
- $value = $1 if ($customhash{$Fields{'url'}}=~/\<{$field}[^\>]*\>(.*?)\<\/{$field}[^\>]*\>/s);
- $Fields{'extrashow'}=~s/\<\!\-\- $field \-\-\>/ $value/g;
- }
+ # wait a sec. to give time for files to be written
+ # This sleep statement is here instead of outside the else
+ # block because we do not want to pause if we have servers
+ # left to contact.
+ if (scalar (keys(%Server_status))) {
+ &update_status($r,
+ &mt('waiting on [_1]',join(' ',keys(%Server_status))));
+ }
+ sleep(1);
+ }
+ #
+ # Loop through the servers we have contacted but do not
+ # have results from yet, looking for results.
+ foreach my $server (keys(%Server_status)) {
+ last if ($connection->aborted());
+ &update_seconds($r);
+ my $status = $Server_status{$server};
+ if ($status eq 'con_lost') {
+ delete ($Server_status{$server});
+ next;
+ }
+ $status=~s|/||g;
+ my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$status;
+ if (-e $datafile && ! -e "$datafile.end") {
+ &update_status($r,&mt('Receiving results from [_1]',$server));
+ next;
+ }
+ last if ($connection->aborted());
+ if (-e "$datafile.end") {
+ &update_status($r,&mt('Reading results from [_1]',$server));
+ if (-z "$datafile") {
+ delete($Server_status{$server});
+ next;
}
- if ($compiledresult or $servercount!=$servernum) {
- $compiledresult.="
";
+ my $fh;
+ if (!($fh=Apache::File->new($datafile))) {
+ $r->print("Unable to open search results file for ".
+ "server $server. Omitting from search");
+ delete($Server_status{$server});
+ next;
}
- $compiledresult.="\n
-END
+ # Read in the whole file.
+ while (my $result = <$fh>) {
+ last if ($connection->aborted());
+ #
+ # Records are stored one per line
+ chomp($result);
+ next if (! $result);
+ #
+ # Parse the result.
+ my %Fields = &parse_raw_result($result,$server,$tabletype);
+ $Fields{'hostname'} = $server;
+ #
+ # Skip based on copyright
+ next if (! ©right_check(\%Fields));
+
+ if ($area eq 'portfolio') {
+ next if (defined($matches{$Fields{'url'}}));
+ # Skip if inaccessible
+ next if (!&Apache::lonnet::portfolio_access($Fields{'url'}));
+ $matches{$Fields{'url'}} = 1;
+ }
+ #
+ # Store the result in the mysql database
+ my $result = &Apache::lonmysql::store_row($table,\%Fields);
+ if (! defined($result)) {
+ $r->print(&Apache::lonmysql::get_error());
+ }
+ #
+ $hitcountsum ++;
+ &update_seconds($r);
+ if ($hitcountsum % 50 == 0) {
+ &update_count_status($r,$hitcountsum);
+ }
}
- if ($ENV{'form.catalogmode'} eq 'groupsearch') {
- $fnum+=0;
- $hash{"pre_${fnum}_link"}=$Fields{'url'};
- $hash{"pre_${fnum}_title"}=$Fields{'title'};
- $compiledresult.=<
-END
-#
-#
- $fnum++;
- }
- my $viewselect;
- if ($mode eq 'Basic') {
- $viewselect=$ENV{'form.basicviewselect'};
- }
- elsif ($mode eq 'Advanced') {
- $viewselect=$ENV{'form.advancedviewselect'};
- }
- if ($viewselect eq 'Detailed Citation View') {
- $compiledresult.=&detailed_citation_view
- (%Fields, hostname => $rkey );
- }
- elsif ($viewselect eq 'Summary View') {
- $compiledresult.=&summary_view
- (%Fields, hostname => $rkey );
- }
- elsif ($viewselect eq 'Fielded Format') {
- $compiledresult.=&fielded_format_view
- (%Fields, hostname => $rkey );
- }
- elsif ($viewselect eq 'XML/SGML') {
- $compiledresult.=&xml_sgml_view
- (%Fields, hostname => $rkey );
- }
+ $fh->close();
+ # $server is only deleted if the results file has been
+ # found and (successfully) opened. This may be a bad idea.
+ delete($Server_status{$server});
}
- untie %hash;
+ last if ($connection->aborted());
+ &update_count_status($r,$hitcountsum);
}
- if ($compiledresult) {
- $resultflag=1;
- $r->print($compiledresult);
+ last if ($connection->aborted());
+ &update_seconds($r);
+ }
+ &update_status($r,&mt('Search Complete on Server [_1]',$server));
+ &update_seconds($r);
+ #
+ &Apache::lonmysql::disconnect_from_db(); # This is unneccessary
+ #
+ # We have run out of time or run out of servers to talk to and
+ # results to get, so let the client know the top frame needs to be
+ # loaded from /adm/searchcat
+ $r->print(&Apache::loncommon::end_page());
+# if ($env{'form.catalogmode'} ne 'import') {
+ $r->print(<
+SCRIPT
+# }
+ return;
+}
+
+######################################################################
+######################################################################
+
+=pod
+
+=item &prev_next_buttons()
+
+Returns html for the previous and next buttons on the search results page.
+
+=cut
+
+######################################################################
+######################################################################
+sub prev_next_buttons {
+ my ($current_min,$show,$total,$parms) = @_;
+ return '' if ($show eq 'all'); # No links if you get them all at once.
+ #
+ # Create buttons
+ return '