--- loncom/interface/lonsearchcat.pm 2002/08/26 14:34:19 1.155 +++ loncom/interface/lonsearchcat.pm 2003/09/28 00:14:25 1.187 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Search Catalog # -# $Id: lonsearchcat.pm,v 1.155 2002/08/26 14:34:19 matthew Exp $ +# $Id: lonsearchcat.pm,v 1.187 2003/09/28 00:14:25 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -74,15 +74,15 @@ package Apache::lonsearchcat; # ------------------------------------------------- modules used by this module use strict; -use Apache::Constants qw(:common); +use Apache::Constants qw(:common :http); use Apache::lonnet(); use Apache::File(); use CGI qw(:standard); use Text::Query; -use DBI; use GDBM_File; use Apache::loncommon(); use Apache::lonmysql(); +use Apache::lonlocal; # ---------------------------------------- variables used throughout the module @@ -143,6 +143,14 @@ my %persistent_db; my $hidden_fields; my $bodytag; +# +# For course search +# +my %alreadyseen; +my $hashtied; +my %hash; +my $totalfound; + ###################################################################### ###################################################################### @@ -171,19 +179,28 @@ string that holds portions of the screen sub handler { my $r = shift; # + + 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. # - $r->content_type('text/html'); + &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']); + 'phase','persistent_db_id','table','start','show', + 'cleargroupsort']); ## ## 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 @@ -191,15 +208,14 @@ sub handler { ## this once, so the pause indicator is deleted ## if (exists($ENV{'form.pause'})) { - sleep(3); + 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'}_searchcat.db"; # # set the name of the persistent database # $ENV{'form.persistent_db_id'} can only have digits in it. @@ -234,12 +250,13 @@ END ## Clear out old values from groupsearch database ## untie %groupsearch_db if (tied(%groupsearch_db)); - if ($ENV{'form.launch'} eq '1' && - ($ENV{'form.catalogmode'} eq 'groupsearch') && - ($ENV{'form.phase'} eq 'results')) { + if (($ENV{'form.cleargroupsort'} eq '1') || + (($ENV{'form.launch'} eq '1') && + ($ENV{'form.catalogmode'} eq 'groupsearch'))) { if (tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT(),0640)) { &start_fresh_session(); untie %groupsearch_db; + delete($ENV{'form.cleargroupsort'}); } else { # This is a stupid error to give to the user. # It really tells them nothing. @@ -329,6 +346,8 @@ END &run_search($r,$query,$customquery,$customshow, $libraries,$pretty_string); } + } elsif ($ENV{'form.phase'} eq 'course_search') { + &course_search($r); } elsif(($ENV{'form.phase'} eq 'basic_search') || ($ENV{'form.phase'} eq 'adv_search')) { $ENV{'form.searchmode'} = 'basic'; @@ -364,7 +383,8 @@ END (undef,undef,undef,undef); my $pretty_string; if ($ENV{'form.phase'} eq 'basic_search') { - ($query,$pretty_string) = &parse_basic_search($r,$closebutton); + ($query,$pretty_string,$libraries) = + &parse_basic_search($r,$closebutton); } else { # Advanced search ($query,$customquery,$customshow,$libraries,$pretty_string) = &parse_advanced_search($r,$closebutton); @@ -387,6 +407,111 @@ END ###################################################################### ###################################################################### +sub course_search { + my $r=shift; + my $bodytag=&Apache::loncommon::bodytag('Course Search'); + my $pretty_search_string = ''.$ENV{'form.courseexp'}.''; + my $search_string = $ENV{'form.courseexp'}; + my @New_Words; + if ($ENV{'form.crsrelated'}) { + ($search_string,@New_Words) = &related_version($ENV{'form.courseexp'}); + if (@New_Words) { + $pretty_search_string .= " with related words: @New_Words."; + } else { + $pretty_search_string .= " with no related words."; + } + } + my $fulltext=$ENV{'form.crsfulltext'}; + my @allwords=($search_string,@New_Words); + $totalfound=0; + $r->print('LON-CAPA Course Search'. + $bodytag.$pretty_search_string); + $r->rflush(); +# ======================================================= Go through the course + $hashtied=0; + undef %alreadyseen; + %alreadyseen=(); + my $c=$r->connection; + &tiehash(); + foreach (keys %hash) { + if ($c->aborted()) { last; } + if (($_=~/^src\_(.+)$/) && (!$alreadyseen{$hash{$_}})) { + &checkonthis($r,$hash{$_},0,$hash{'title_'.$1},$fulltext,@allwords); + } + } + &untiehash(); + unless ($totalfound) { + $r->print('

'.&mt('No resources found').'.

'); + } +# =================================================== Done going through course + $r->print(''); +} + +# ---------------------------------------------------------------- tie the hash + +sub tiehash { + $hashtied=0; + if ($ENV{'request.course.fn'}) { + if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db", + &GDBM_READER(),0640)) { + $hashtied=1; + } + } +} + +sub untiehash { + if ($hashtied) { untie %hash; } + $hashtied=0; +} + +# =============================== This pulls up a resource and its dependencies + +sub checkonthis { + my ($r,$url,$level,$title,$fulltext,@allwords)=@_; + $alreadyseen{$url}=1; + $r->rflush(); + my $result=&Apache::lonnet::metadata($url,'title').' '. + &Apache::lonnet::metadata($url,'subject').' '. + &Apache::lonnet::metadata($url,'abstract').' '. + &Apache::lonnet::metadata($url,'keywords'); + if (($url) && ($fulltext)) { + $result.=&Apache::lonnet::ssi_body($url); + } + $result=~s/\s+/ /gs; + my $applies=0; + foreach (@allwords) { + if ($_=~/\w/) { + if ($result=~/$_/si) { + $applies++; + } + } + } +# Does this resource apply? + if ($applies) { + $r->print('
'); + for (my $i=0;$i<=$level*5;$i++) { + $r->print(' '); + } + $r->print(''. + ($title?$title:$url).'
'); + $totalfound++; + } elsif ($fulltext) { + $r->print(' .'); + } + $r->rflush(); +# Check also the dependencies of this one + my $dependencies= + &Apache::lonnet::metadata($url,'dependencies'); + foreach (split(/\,/,$dependencies)) { + if (($_=~/^\/res\//) && (!$alreadyseen{$_})) { + &checkonthis($r,$_,$level+1,'',$fulltext,@allwords); + } + } +} + +###################################################################### +###################################################################### + =pod =item &print_basic_search_form() @@ -400,7 +525,7 @@ Returns a scalar which holds html for th sub print_basic_search_form{ my ($r,$closebutton) = @_; - my $bodytag=&Apache::loncommon::bodytag('Catalog Search'); + my $bodytag=&Apache::loncommon::bodytag('Search'); my $scrout=<<"ENDDOCUMENT"; @@ -414,6 +539,10 @@ sub print_basic_search_form{ $bodytag +ENDDOCUMENT +if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) { + $scrout.=(<Catalog Search
$hidden_fields @@ -427,28 +556,71 @@ then press SEARCH below. ENDDOCUMENT $scrout.=' '.&simpletextfield('basicexp',$ENV{'form.basicexp'},40). ' '; - my $checkbox = &simplecheckbox('related',$ENV{'form.related'}); + my $relatedcheckbox = &simplecheckbox('related',$ENV{'form.related'}); + my $domain = $r->dir_config('lonDefDomain'); + my $domaincheckbox = &simplecheckbox('domains',$domain); + my $srch=&mt('Search'); + my $header=&mt('Advanced Search'); $scrout.=<Advanced Search -$checkbox use related words +$header +$relatedcheckbox use related words + $domaincheckbox only search domain $domain

  +   $closebutton END - $scrout.=&selectbox(undef,'viewselect', + $scrout.=&selectbox('View','viewselect', $ENV{'form.viewselect'}, undef,undef,undef, sort(keys(%Views))); - $scrout.=&selectbox(undef,'show', + $scrout.=&selectbox('Per page','show', $ENV{'form.show'}, undef,undef,undef, (10,20,50,100)); $scrout.=< +ENDDOCUMENT + } + if ($ENV{'request.course.id'}) { + my %lt=&Apache::lonlocal::texthash( + 'srch' => 'Search', + 'header' => 'Course Search', + 'note' => 'Enter terms or phrases, then press "Search" below', + ); + $scrout.=(< +

$lt{'header'}

+
+ +$hidden_fields +

+$lt{'note'}. +

+

+ + + + +
+ENDCOURSESEARCH + $scrout.=' '. + &simpletextfield('courseexp',$ENV{'form.courseexp'},40); + my $crscheckbox = + &simplecheckbox('crsfulltext',$ENV{'form.crsfulltext'}); + my $relcheckbox = + &simplecheckbox('crsrelated',$ENV{'form.crsrelated'}); + $scrout.=(<
$relcheckbox use related words
$crscheckbox fulltext search (time consuming)

+

+ENDENDCOURSE + } + $scrout.=(< ENDDOCUMENT @@ -516,8 +688,8 @@ ENDHEADER undef,undef,undef, (10,20,50,100)); $scrout.=' '. - 'Per Page'; - $scrout.="Related
Words\n"; + ''.&mt('Per Page').''; + $scrout.="".&mt('Related').'
'.&mt('Words')."\n"; $scrout.=&searchphrasefield_with_related('title', 'title' , $ENV{'form.title'}); $scrout.=&searchphrasefield('author', 'author' ,$ENV{'form.author'}); @@ -532,13 +704,13 @@ ENDHEADER $ENV{'form.abstract'}); # Hack - an empty table row. $scrout.="   \n"; - $scrout.=&searchphrasefield('file
extension','mime', - $ENV{'form.mime'}); + $scrout.=&searchphrasefield('file
extension','extension', + $ENV{'form.extension'}); $scrout.="   \n"; $scrout.=&searchphrasefield('publisher
owner','owner', $ENV{'form.owner'}); $scrout.="\n"; - $ENV{'form.category'}='any' unless length($ENV{'form.category'}); + $ENV{'form.category'}='any' if (! defined($ENV{'form.category'})); $scrout.=&selectbox('File Category','category', $ENV{'form.category'}, 'any','Any category', @@ -559,9 +731,9 @@ ENDHEADER my @domains =&Apache::loncommon::get_domains(); # adjust the size of the select box my $size = 4; - my $size = (scalar @domains < ($size - 1) ? scalar @domains + 1 : $size); + $size = (scalar @domains < ($size - 1) ? scalar @domains + 1 : $size); $scrout.="\n".''. - 'DOMAINS
'. + 'DOMAINS TO BE SEARCHED
'. ''; +sub simplecheckbox{ + my ($name,$value,$checked)=@_; + $checked="checked" if ($value eq 'on'); + return ''; } ############################################### @@ -884,7 +1064,7 @@ field heading. ############################################### sub fieldtitle { - my $title = uc(shift()); + my $title = uc(&mt(shift())); return ''.$title. ': '; } @@ -979,7 +1159,7 @@ END my $i = 1; foreach (qw/January February March April May June July August September October November December /){ - $month .="\n"; + $month .="\n"; $i++; } $month.="\n"; @@ -1056,6 +1236,7 @@ sub selectbox { my ($title,$name,$default,$anyvalue,$anytag,$functionref,@idlist)=@_; if (! defined($functionref)) { $functionref = sub { $_[0]}; } my $selout=''; + $title=&mt($title); if (defined($title)) { my $uctitle=uc($title); $selout="\n".'

'. @@ -1066,12 +1247,12 @@ sub selectbox { foreach (@idlist) { $selout.=''; } elsif ($_ eq $default and /^$anyvalue$/) { - $selout.=' selected >'.$anytag.''; + $selout.=' selected >'.&mt($anytag).''; } - else {$selout.='>'.&{$functionref}($_).'';} + else {$selout.='>'.&mt(&{$functionref}($_)).'';} } return $selout.''.(defined($title)?'

':' '); } @@ -1124,7 +1305,7 @@ sub parse_advanced_search { 'lastrevisiondatestart_month','lastrevisiondatestart_day', 'lastrevisiondatestart_year','lastrevisiondateend_month', 'lastrevisiondateend_day','lastrevisiondateend_year', - 'notes','abstract','mime','language','owner', + 'notes','abstract','extension','language','owner', 'custommetadata','customshow','category') { $ENV{"form.$field"}=~s/[^\w\/\s\(\)\=\-\"\']//g; } @@ -1135,16 +1316,13 @@ sub parse_advanced_search { $ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g; } # Preprocess the category form element. - $ENV{'form.category'} = 'any' if (ref($ENV{'form.category'})); - if ($ENV{'form.category'} ne 'any') { - my @extensions = &Apache::loncommon::filecategorytypes - ($ENV{'form.category'}); - $ENV{'form.mime'} = join ' OR ',@extensions; - } + $ENV{'form.category'} = 'any' if (! defined($ENV{'form.category'}) || + ref($ENV{'form.category'})); + # # Check to see if enough information was filled in for my $field ('title','author','subject','keywords','url','version', - 'notes','abstract','mime','language','owner', - 'custommetadata') { + 'notes','abstract','category','extension','language', + 'owner','custommetadata') { if (&filled($ENV{"form.$field"})) { $fillflag++; } @@ -1159,7 +1337,7 @@ sub parse_advanced_search { my $font = ''; # Evaluate logical expression AND/OR/NOT phrase fields. foreach my $field ('title','author','subject','notes','abstract','url', - 'keywords','version','owner','mime') { + 'keywords','version','owner') { if ($ENV{'form.'.$field}) { my $searchphrase = $ENV{'form.'.$field}; $pretty_search_string .= $font."$field contains ". @@ -1178,10 +1356,30 @@ sub parse_advanced_search { push @queries,&build_SQL_query($field,$searchphrase); } } - # I dislike the hack below. - if ($ENV{'form.category'}) { - $ENV{'form.mime'}=''; + # + # Make the 'mime' from 'form.category' and 'form.extension' + # + my $searchphrase; + if (exists($ENV{'form.category'}) && + $ENV{'form.category'} !~ /^\s*$/ && + $ENV{'form.category'} ne 'any') { + my @extensions = &Apache::loncommon::filecategorytypes + ($ENV{'form.category'}); + if (scalar(@extensions) > 0) { + $searchphrase = join(' OR ',@extensions); + } + } + if (exists($ENV{'form.extension'}) && $ENV{'form.extension'} !~ /^\s*$/) { + $searchphrase .= ' OR ' if (defined($searchphrase)); + my @extensions = split(/,/,$ENV{'form.extension'}); + $searchphrase .= join(' OR ',@extensions); + } + if (defined($searchphrase)) { + push @queries,&build_SQL_query('mime',$searchphrase); + $pretty_search_string .=$font.'mime contains '. + $searchphrase.'
'; } + ##### # Evaluate option lists if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') { push @queries,"(language like \"$ENV{'form.language'}\")"; @@ -1240,11 +1438,33 @@ sub parse_advanced_search { ## --------------------------------------------------------------- ## Deal with restrictions to given domains ## + my ($libraries_to_query,$pretty_domains_string) = + &parse_domain_restrictions(); + $pretty_search_string .= $pretty_domains_string."
\n"; + # + if (@queries) { + $query=join(" AND ",@queries); + $query="select * from metadata where $query"; + } elsif ($customquery) { + $query = ''; + } + return ($query,$customquery,$customshow,$libraries_to_query, + $pretty_search_string); +} + +sub parse_domain_restrictions { my $libraries_to_query = undef; # $ENV{'form.domains'} can be either a scalar or an array reference. # We need an array. - my @allowed_domains = (ref($ENV{'form.domains'}) ? @{$ENV{'form.domains'}} - : ($ENV{'form.domains'}) ); + if (! exists($ENV{'form.domains'})) { + return (undef,''); + } + my @allowed_domains; + if (ref($ENV{'form.domains'})) { + @allowed_domains = @{$ENV{'form.domains'}}; + } else { + @allowed_domains = ($ENV{'form.domains'}); + } my %domain_hash = (); my $pretty_domains_string; foreach (@allowed_domains) { @@ -1267,16 +1487,7 @@ sub parse_advanced_search { } } } - $pretty_search_string .= $pretty_domains_string."
\n"; - # - if (@queries) { - $query=join(" AND ",@queries); - $query="select * from metadata where $query"; - } elsif ($customquery) { - $query = ''; - } - return ($query,$customquery,$customshow,$libraries_to_query, - $pretty_search_string); + return ($libraries_to_query,$pretty_domains_string); } ###################################################################### @@ -1304,7 +1515,8 @@ sub parse_basic_search { $ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"}); $ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g; } - + my ($libraries_to_query,$pretty_domains_string) = + &parse_domain_restrictions(); # Check to see if enough is filled in unless (&filled($ENV{'form.basicexp'})) { &output_blank_field_error($r,$closebutton,'phase=disp_basic'); @@ -1323,13 +1535,19 @@ sub parse_basic_search { } # Build SQL query string based on form page my $query=''; - my $concatarg=join('," ",', + my $concatarg=join(',', ('title', 'author', 'subject', 'notes', 'abstract', 'keywords')); $concatarg='title' if $ENV{'form.titleonly'}; - $query=&build_SQL_query('concat('.$concatarg.')',$search_string); + $query=&build_SQL_query('concat_ws(" ",'.$concatarg.')',$search_string); + if (defined($pretty_domains_string) && $pretty_domains_string ne '') { + $pretty_search_string .= ' '.$pretty_domains_string; + } $pretty_search_string .= "
\n"; - return 'select * from metadata where '.$query,$pretty_search_string; + my $final_query = 'SELECT * FROM metadata WHERE '.$query; +# &Apache::lonnet::logthis($final_query); + return ($final_query,$pretty_search_string, + $libraries_to_query); } @@ -1442,30 +1660,26 @@ sub recursive_SQL_query_build { my @matches=($pattern=~/(\[[^\]|\[]*\])/g); return $pattern unless @matches; foreach my $match (@matches) { - $match=~/\[ (\w+)\s(.*) \]/; - my ($key,$value)=($1,$2); - my $replacement=''; - if ($key eq 'literal') { - $replacement="($dkey like \"\%$value\%\")"; - } - elsif ($key eq 'not') { - $value=~s/like/not like/; -# $replacement="($dkey not like $value)"; - $replacement="$value"; - } - elsif ($key eq 'and') { - $value=~/(.*[\"|\)]) ([|\(|\^].*)/; - $replacement="($1 AND $2)"; - } - elsif ($key eq 'or') { - $value=~/(.*[\"|\)]) ([|\(|\^].*)/; - $replacement="($1 OR $2)"; + $match=~/\[ (\w+)\s(.*) \]/; + my ($key,$value)=($1,$2); + my $replacement=''; + if ($key eq 'literal') { + $replacement="($dkey LIKE \"\%$value\%\")"; + } elsif (lc($key) eq 'not') { + $value=~s/LIKE/NOT LIKE/; +# $replacement="($dkey not like $value)"; + $replacement="$value"; + } elsif ($key eq 'and') { + $value=~/(.*[\"|\)]) ([|\(|\^].*)/; + $replacement="($1 AND $2)"; + } elsif ($key eq 'or') { + $value=~/(.*[\"|\)]) ([|\(|\^].*)/; + $replacement="($1 OR $2)"; } substr($pattern, - index($pattern,$match), - length($match), - $replacement - ); + index($pattern,$match), + length($match), + $replacement); } &recursive_SQL_query_build($dkey,$pattern); } @@ -1633,8 +1847,8 @@ sub ensure_db_and_table { sub print_sort_form { my ($r,$pretty_query_string) = @_; ## - my %SortableFields = - (id => 'Default', + my %SortableFields=&Apache::lonlocal::texthash( + id => 'Default', title => 'Title', author => 'Author', subject => 'Subject', @@ -1646,7 +1860,7 @@ sub print_sort_form { copyright => 'Copyright', hostname => 'Host', creationdate => 'Creation Date', - lastrevisiondate => 'Revision Date', + lastrevisiondate => 'Revision Date' ); ## my $table = $ENV{'form.table'}; @@ -1722,37 +1936,31 @@ the following format: =cut -## -## Restrictions: -## columns of type 'text' and 'blob' cannot have defaults. -## columns of type 'enum' cannot be used for FULLTEXT. -## -my @DataOrder = qw/id title author subject url keywords version notes - abstract mime lang owner copyright creationdate lastrevisiondate hostname/; - -my %Datatypes = - ( id =>{ type => 'MEDIUMINT', - restrictions => 'UNSIGNED NOT NULL', - primary_key => 'yes', - auto_inc => 'yes' - }, - title =>{ type=>'TEXT'}, - author =>{ type=>'TEXT'}, - subject =>{ type=>'TEXT'}, - url =>{ type=>'TEXT', - restrictions => 'NOT NULL' }, - keywords =>{ type=>'TEXT'}, - version =>{ type=>'TEXT'}, - notes =>{ type=>'TEXT'}, - abstract =>{ type=>'TEXT'}, - mime =>{ type=>'TEXT'}, - lang =>{ type=>'TEXT'}, - owner =>{ type=>'TEXT'}, - copyright =>{ type=>'TEXT'}, - hostname =>{ type=>'TEXT'}, +##################################################################### +##################################################################### + +my @Datatypes = + ( { name => 'id', + type => 'MEDIUMINT', + restrictions => 'UNSIGNED NOT NULL', + primary_key => 'yes', + auto_inc => 'yes' }, + { name => 'title', type=>'TEXT'}, + { name => 'author', type=>'TEXT'}, + { name => 'subject', type=>'TEXT'}, + { name => 'url', type=>'TEXT', restrictions => 'NOT NULL' }, + { name => 'keywords', type=>'TEXT'}, + { name => 'version', type=>'TEXT'}, + { name => 'notes', type=>'TEXT'}, + { name => 'abstract', type=>'TEXT'}, + { name => 'mime', type=>'TEXT'}, + { name => 'lang', type=>'TEXT'}, + { name => 'owner', type=>'TEXT'}, + { name => 'copyright', type=>'TEXT'}, + { name => 'hostname', type=>'TEXT'}, #-------------------------------------------------- - creationdate =>{ type=>'DATETIME'}, - lastrevisiondate =>{ type=>'DATETIME'}, + { name => 'creationdate', type=>'DATETIME'}, + { name => 'lastrevisiondate', type=>'DATETIME'}, #-------------------------------------------------- ); @@ -1780,9 +1988,8 @@ Returns: the identifier of the table on ###################################################################### sub create_results_table { my $table = &Apache::lonmysql::create_table - ( { columns => \%Datatypes, - column_order => \@DataOrder, - fullindex => \@Fullindicies, + ( { columns => \@Datatypes, + FULLTEXT => [{'columns' => \@Fullindicies},], } ); if (defined($table)) { $ENV{'form.table'} = $table; @@ -1831,6 +2038,7 @@ sub update_count_status { sub update_status { my ($r,$text) = @_; $text =~ s/\'/\\\'/g; + $text=&mt($text); $r->print ("\n"); $r->rflush(); @@ -1864,6 +2072,7 @@ sub revise_button { $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{ }; @@ -1906,7 +2115,7 @@ END if (@Lines > 2) { $pretty_string = join '
',(@Lines[0..2],'....
'); } - $r->print("Search: ".$pretty_string); + $r->print(&mt("Search").": ".$pretty_string); $r->rflush(); # # Determine the servers we need to contact. @@ -1965,25 +2174,33 @@ END my $time_remaining = $max_time - (time - $starttime) ; my $last_time = $time_remaining; &update_seconds($r,$time_remaining); - while (($time_remaining > 0) && + &update_status($r,'contacting '.$Servers_to_contact[0]); + while (($time_remaining > 0) && ((@Servers_to_contact) || keys(%Server_status))) { # Send out a search request if it needs to be done. if (@Servers_to_contact) { # Contact one server my $server = shift(@Servers_to_contact); + &update_status($r,'contacting '.$server); my $reply=&Apache::lonnet::metadata_query($query,$customquery, $customshow,[$server]); ($server) = keys(%$reply); $Server_status{$server} = $reply->{$server}; - &update_status($r,'contacting '.$server); } else { # 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, + 'waiting on '.(join(' ',keys(%Server_status)))); + } sleep(1); } - &update_status($r,'waiting on '.(join(' ',keys(%Server_status)))); + # + # + # Loop through the servers we have contacted but do not + # have results from yet, looking for results. while (my ($server,$status) = each(%Server_status)) { last if ($connection->aborted()); if ($status eq 'con_lost') { @@ -2046,6 +2263,7 @@ END } last if ($connection->aborted()); # Finished looping through the servers + $starttime = time if (@Servers_to_contact); $time_remaining = $max_time - (time - $starttime) ; if ($last_time - $time_remaining > 0) { $last_time = $time_remaining; @@ -2137,6 +2355,10 @@ sub display_results { return; } ## + ## $checkbox_num is a count of the number of checkboxes output on the + ## page this is used only during catalogmode=groupsearch. + my $checkbox_num = 0; + ## ## Get the catalog controls setup ## my $action = "/adm/searchcat?phase=results"; @@ -2192,7 +2414,8 @@ sub display_results { ."\n" ); if ($total_results == 0) { - $r->print("There are currently no results.\n". + $r->print(''. + '

'.&mt('There are currently no results').'.

'. ""); return; } else { @@ -2209,13 +2432,13 @@ sub display_results { ## foreach my $row (@Results) { if ($connection->aborted()) { - untie %groupsearch_db if (tied(%groupsearch_db)); - &Apache::lonmysql::disconnect_from_db(); + &cleanup(); return; } my %Fields = %{&parse_row(@$row)}; my $output="

\n"; - my $prefix=&catalogmode_output($Fields{'title'},$Fields{'url'}); + my $prefix=&catalogmode_output($Fields{'title'},$Fields{'url'}, + $Fields{'id'},$checkbox_num++); # Render the result into html $output.= &$viewfunction($prefix,%Fields); # Print them out as they come in. @@ -2223,7 +2446,7 @@ sub display_results { $r->rflush(); } if (@Results < 1) { - $r->print("There were no results matching your query"); + $r->print(&mt("There were no results matching your query")); } else { $r->print ('

'. @@ -2246,22 +2469,18 @@ sub display_results { =pod -=item &catalogmode_output($title,$url) +=item &catalogmode_output($title,$url,$fnum,$checkbox_num) Returns html needed for the various catalog modes. Gets inputs from -$ENV{'form.catalogmode'}. Stores data in %groupsearch_db and $fnum -(local variable). +$ENV{'form.catalogmode'}. Stores data in %groupsearch_db. =cut ###################################################################### ###################################################################### -{ -my $fnum = 0; - sub catalogmode_output { my $output = ''; - my ($title,$url) = @_; + my ($title,$url,$fnum,$checkbox_num) = @_; if ($ENV{'form.catalogmode'} eq 'interactive') { $title=~ s/\'/\\\'/g; if ($ENV{'form.catalogmode'} eq 'interactive') { @@ -2277,15 +2496,12 @@ END $output.=< +onClick="javascript:queue($checkbox_num,$fnum)" /> END - $fnum++; } return $output; } - -} ###################################################################### ###################################################################### @@ -2303,7 +2519,7 @@ sub parse_row { my @Row = @_; my %Fields; for (my $i=0;$i<=$#Row;$i++) { - $Fields{$DataOrder[$i]}=&Apache::lonnet::unescape($Row[$i]); + $Fields{$Datatypes[$i]->{'name'}}=&Apache::lonnet::unescape($Row[$i]); } $Fields{'language'} = &Apache::loncommon::languagedescription($Fields{'lang'}); @@ -2533,11 +2749,20 @@ SCRIPT } $result.=< LON-CAPA Digital Library Search Results @@ -2927,6 +3153,17 @@ sub start_fresh_session { 1; +sub cleanup { + if (tied(%groupsearch_db)) { + &Apache::lonnet::logthis('Cleanup searchcat: groupsearch_db'); + unless (untie(%groupsearch_db)) { + &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db'); + } + } + &untiehash(); + &Apache::lonmysql::disconnect_from_db(); +} + __END__ =pod 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.