--- loncom/interface/lonsearchcat.pm 2004/03/03 17:25:23 1.204 +++ loncom/interface/lonsearchcat.pm 2004/04/23 17:52:55 1.216 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Search Catalog # -# $Id: lonsearchcat.pm,v 1.204 2004/03/03 17:25:23 matthew Exp $ +# $Id: lonsearchcat.pm,v 1.216 2004/04/23 17:52:55 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -48,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 @@ -74,6 +74,7 @@ use Apache::lonmeta; use Apache::lonhtmlcommon; use Apache::lonlocal; use LONCAPA::lonmetadata(); +use HTML::Entities(); ###################################################################### ###################################################################### @@ -149,7 +150,8 @@ sub handler { ## Initialize global variables ## my $domain = $r->dir_config('lonDefDomain'); - $diropendb= "/home/httpd/perl/tmp/$ENV{'user.domain'}_$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. @@ -164,6 +166,25 @@ sub handler { '_'.&Apache::lonnet::escape($ENV{'user.name'}). '_'.$ENV{'form.persistent_db_id'}.'_persistent_search.db'; ## + &Apache::lonhtmlcommon::clear_breadcrumbs(); + if (exists($ENV{'request.course.id'}) && $ENV{'request.course.id'} ne '') { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/searchcat?'. + 'catalogmode='.$ENV{'form.catalogmode'}. + '&launch='.$ENV{'form.launch'}. + '&mode='.$ENV{'form.mode'}, + text=>"Course and Catalog Search", + bug=>'Searching',}); + } else { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/searchcat?'. + 'catalogmode='.$ENV{'form.catalogmode'}. + '&launch='.$ENV{'form.launch'}. + '&mode='.$ENV{'form.mode'}, + text=>"Catalog Search", + bug=>'Searching',}); + } + # if (! &get_persistent_form_data($persistent_db_file)) { if ($ENV{'form.phase'} =~ /(run_search|results)/) { &Apache::lonnet::logthis("lonsearchcat:Unable to recover data ". @@ -264,6 +285,32 @@ END } $ENV{'form.phase'} = 'disp_basic' if (! exists($ENV{'form.phase'})); $ENV{'form.show'} = 20 if (! exists($ENV{'form.show'})); + # + $ENV{'form.searchmode'} = 'basic'; + if ($ENV{'form.phase'} eq 'adv_search' || + $ENV{'form.phase'} eq 'disp_adv') { + $ENV{'form.searchmode'} = 'advanced'; + } elsif ($ENV{'form.phase'} eq 'course_search') { + $ENV{'form.searchmode'} = 'course_search'; + } + # + if ($ENV{'form.searchmode'} eq 'advanced') { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/searchcat?phase=disp_adv&'. + 'catalogmode='.$ENV{'form.catalogmode'}. + '&launch='.$ENV{'form.launch'}. + '&mode='.$ENV{'form.mode'}, + text=>"Advanced Search", + bug=>'Searching',}); + } elsif ($ENV{'form.searchmode'} eq 'course search') { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/searchcat?phase=disp_adv&'. + 'catalogmode='.$ENV{'form.catalogmode'}. + '&launch='.$ENV{'form.launch'}. + '&mode='.$ENV{'form.mode'}, + text=>"Course Search", + bug=>'Searching',}); + } ## ## Switch on the phase ## @@ -288,19 +335,17 @@ END &course_search($r); } elsif(($ENV{'form.phase'} eq 'basic_search') || ($ENV{'form.phase'} eq 'adv_search')) { - $ENV{'form.searchmode'} = 'basic'; - if ($ENV{'form.phase'} eq 'adv_search') { - $ENV{'form.searchmode'} = 'advanced'; - } # Set up table if (! defined(&create_results_table())) { my $errorstring=&Apache::lonmysql::get_error(); + &Apache::lonnet::logthis('lonsearchcat.pm: Unable to create '. + 'needed table. lonmysql error:'. + $errorstring); $r->print(<Search Error $bodytag Unable to create table in which to store search results. The search has been aborted. -
$errorstring END @@ -454,6 +499,23 @@ sub untiehash { } # End of course search scoping +sub search_html_header { + my $Str = < + +The LearningOnline Network with CAPA + + +ENDHEADER + return $Str; +} + ###################################################################### ###################################################################### @@ -470,80 +532,79 @@ Prints the form for the basic search. S sub print_basic_search_form { my ($r,$closebutton,$hidden_fields) = @_; my $bodytag=&Apache::loncommon::bodytag('Search'). - &Apache::loncommon::help_open_topic('Finding_Resources'). - &Apache::loncommon::help_open_bug('Searching'); - my $scrout=<<"ENDDOCUMENT"; - - -The LearningOnline Network with CAPA - - -$bodytag -ENDDOCUMENT -if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) { - my $CatalogSearch=&mt('Catalog Search'); - my $Statement=&searchhelp(); - $scrout.=(<$CatalogSearch -
- -$hidden_fields -

-$Statement. -

-

- - - - -
-ENDDOCUMENT - $scrout.=' '.&Apache::lonhtmlcommon::textbox('basicexp', - $ENV{'form.basicexp'},40). - ' '; - my $relatedcheckbox = &Apache::lonhtmlcommon::checkbox('related', - $ENV{'form.related'}); - my $domain = $r->dir_config('lonDefDomain'); - my $domaincheckbox = &Apache::lonhtmlcommon::checkbox('domains', - $ENV{'form.domains'}); - my $srch=&mt('Search'); - my $header=&mt('Advanced Search'); - my $userelatedwords=&mt('use related words'); - my $onlysearchdomain=&mt('only search domain'); - my $view=&viewoptions(); - $scrout.=<$header
$relatedcheckbox $userelatedwords$domaincheckbox $onlysearchdomain $domain
-

-$view -

  -$closebutton -END - $scrout.=< - -ENDDOCUMENT + &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching','Finding_Resources', + undef,undef,! $ENV{'form.launch'}); + my $scrout = &search_html_header().$bodytag; + if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) { + # Define interface components + my $userelatedwords= + &mt('[_1] use related words', + &Apache::lonhtmlcommon::checkbox + ('related',$ENV{'form.related'})); + my $onlysearchdomain= + &mt('[_1] only search domain [_2]', + &Apache::lonhtmlcommon::checkbox + ('domains',$ENV{'form.domains'}), + $r->dir_config('lonDefDomain')); + my $adv_search_link = + ''.&mt('Advanced Search').''; + # + $scrout.='

'. + ''. + $hidden_fields; + # + $scrout .= '
'.$/; + if ($ENV{'request.course.id'}) { + $scrout .= '

'.&mt('LON-CAPA Catalog Search').'

'; + } else { + # No need to tell them they are searching + $scrout.= ('
'x2); + } + $scrout.=''. + ''. + ''. + ''.$/; + # +# $scrout .= ''.$/; + $scrout .= ''.$/; + $scrout .= '
'. + &Apache::lonhtmlcommon::textbox('basicexp', + $ENV{'form.basicexp'},50).'
'. + ''.&searchhelp().''.'
'. + ''.(' 'x3).$adv_search_link.''.'
'. + ''.(' 'x1).$userelatedwords.''.'
'. + ''.(' 'x1).$onlysearchdomain.''.'
'. + '
'. +# ''. +# $userelatedwords.(' 'x3). +# $onlysearchdomain.(' 'x2).$adv_search_link. +# ''. +# '
'. + ''. + ''. + (' 'x2).$closebutton.(' 'x2).&viewoptions(). + ''. + '
'.$/.'
'.'
'; } if ($ENV{'request.course.id'}) { - my %lt=&Apache::lonlocal::texthash( - 'srch' => 'Search', + my %lt=&Apache::lonlocal::texthash('srch' => 'Search', 'header' => 'Course Search', 'note' => 'Enter terms or phrases, then press "Search" below', 'use' => 'use related words', 'full' =>'fulltext search (time consuming)' ); $scrout.=(< +

$lt{'header'}

-
$hidden_fields

@@ -569,6 +630,8 @@ ENDCOURSESEARCH

 

+
+ ENDENDCOURSE } $scrout.=(< $closebutton -

END - my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search'); + my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search'). + &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching', + 'Finding_Resources', + undef,undef, + ! $ENV{'form.launch'}); my $searchhelp=&searchhelp(); - my $scrout=<<"ENDHEADER"; - - -The LearningOnline Network with CAPA - - + my $scrout=&search_html_header(); + $scrout .= <<"ENDHEADER"; $bodytag -$searchhelp
$advanced_buttons -$hidden_fields - ENDHEADER - $scrout.=&viewoptions(); + $scrout.=(' 'x2).&viewoptions().'

'.$hidden_fields. + ''; my %fields=&Apache::lonmeta::fieldnames(); - - $scrout.=''; - $scrout.="\n"; - foreach ('title','author','owner','authorspace','modifyinguser', - 'keywords','notes','abstract','standards', - 'lowestgradelevel','highestgradelevel','mime') { - $scrout.=''; + # + $scrout.= '

'.$searchhelp.'

'. + "
".&mt('Field').''.&mt('Value').'' - .&mt('Related').'
'.&mt('Words')."
'.&titlefield($fields{$_}).''. - &Apache::lonmeta::prettyinput($_,$ENV{'form.'.$_},$_,'advsearch', - 1,'',$ENV{'form.'.$_.'_related'}). - '
\n"; + my %related_word_search = + ('title'=>1, + 'author'=>0, + 'owner'=>0, + 'authorspace'=>0, + 'modifyinguser'=>0, + 'keywords'=>1, + 'notes'=>1, + 'abstract'=>1, + 'standards'=>1, + 'mime'=>1, + ); + # + foreach my $field ('title','author','owner','authorspace','modifyinguser', + 'keywords','notes','abstract','standards','mime') { + $scrout.=''.$/; + } + foreach my $field ('lowestgradelevel','highestgradelevel') { + $scrout.=''. + ''. + ''.$/; } - $scrout.=''; - $scrout.=''.$/; + $scrout.=''; - my %dates=&Apache::lonlocal::texthash - ('creationdatestart' => 'Creation Date After', - 'creationdateend' => 'Creation Date Before', - 'lastrevisiondatestart' => 'Last Revision Date After', - 'lastrevisiondateend' => 'Last Revision Date Before'); - foreach (sort keys %dates) { - $scrout.=''. - ''. - ''; - } - + ''.$/; + $scrout .= "
'.&titlefield($fields{$field}).''. + &Apache::lonmeta::prettyinput($field, + $ENV{'form.'.$field}, + $field, + 'advsearch', + $related_word_search{$field}, + '', + $ENV{'form.'.$field.'_related'}, + 50); + if ($related_word_search{$field}) { + $scrout .= 'related words'; + } else { + $scrout .= ' '; + } + $scrout .= '
'.&titlefield($fields{$field}).''. + &Apache::lonmeta::prettyinput($field, + $ENV{'form.'.$field}, + $field, + 'advsearch', + 0). + '
'. - &titlefield(&mt('MIME Type Category')).''. + $scrout.='
'. + &titlefield(&mt('MIME Type Category')).''. &Apache::loncommon::filecategoryselect('category', $ENV{'form.category'}). - ' 
'. - &titlefield(&mt('Limit Search to Domains')).''. + '
'. + &titlefield(&mt('Domains')).''. &Apache::loncommon::domain_select('domains', $ENV{'form.domains'},1). - ' 
'.&titlefield($dates{$_}).''. - &Apache::lonhtmlcommon::date_setter('advsearch',$_,0,'',1). - ' 
\n
"; + # + # Creation/Modification date limits + $scrout .= "\n\n"; + my $cafter = + &Apache::lonhtmlcommon::date_setter('advsearch', # formname + 'creationdate1', # fieldname + 0, # current value + '', # special + 1, # includeempty + '', # state + 1, # no_hh_mm_ss + ); + my $cbefore = + &Apache::lonhtmlcommon::date_setter('advsearch', # formname + 'creationdate2', # fieldname + 0, # current value + '', # special + 1, # includeempty + '', # state + 1, # no_hh_mm_ss + ); + $scrout .= &mt(''. + ''. + ''. + '',$cafter,$cbefore); + my $lafter = + &Apache::lonhtmlcommon::date_setter('advsearch', + 'revisiondate1', + 0, # current value + '', # special + 1, # includeempty + '', # state + 1, # no_hh_mm_ss + ); + my $lbefore = + &Apache::lonhtmlcommon::date_setter('advsearch', + 'revisiondate2', + 0, # current value + '', # special + 1, # includeempty + '', # state + 1, # no_hh_mm_ss + ); + $scrout .= &mt(''. + ''. + ''. + '',$lafter,$lbefore); $scrout.="
Created between[_1]
and [_2]
Last modified between [_1]
and[_2]
\n"; $scrout.=<'.$title.''; + return $title; } ###################################################################### @@ -735,20 +857,21 @@ Outputs: text for box with view options ###################################################################### ###################################################################### sub viewoptions { - my $scrout="\n\n".''. - '
'.&mt('View Options').''. - &mt('Records per Page').'
'; - unless ($ENV{'form.viewselect'}) { $ENV{'form.viewselect'}='detailed'; } + my $scrout="\n".''; + if (! defined($ENV{'form.viewselect'})) { + $ENV{'form.viewselect'}='detailed'; + } $scrout.=&Apache::lonmeta::selectbox('viewselect', $ENV{'form.viewselect'}, \&viewoptiontext, sort(keys(%Views))); - $scrout.=''; - $scrout.=&Apache::lonmeta::selectbox('show', - $ENV{'form.show'}, - undef, - (10,20,50,100,1000,10000)); - $scrout.="
\n\n"; + $scrout.= '  '; + my $countselect = &Apache::lonmeta::selectbox('show', + $ENV{'form.show'}, + undef, + (10,20,50,100,1000,10000)); + $scrout .= (' 'x2).&mt('[_1] Records per Page',$countselect). + ''.$/; return $scrout; } @@ -882,7 +1005,7 @@ Inputs: Hash of values to save, filename Store variables away to the %persistent_db. Values will be escaped. Values that are array pointers will have their -elements escaped and concatenated in a comma seperated string. +elements escaped and concatenated in a comma separated string. =cut @@ -914,7 +1037,7 @@ Inputs: filename of persistent database. Store most form variables away to the %persistent_db. Values will be escaped. Values that are array pointers will have their -elements escaped and concatenated in a comma seperated string. +elements escaped and concatenated in a comma separated string. =cut @@ -958,39 +1081,46 @@ Parse advanced search form and return th ###################################################################### sub parse_advanced_search { my ($r,$closebutton,$hidden_fields)=@_; + my @BasicFields = ('title','author','subject','keywords','url','version', + 'notes','abstract','extension','language','owner', +# 'custommetadata','customshow', + 'modifyinguser','standards','mime'); + my $fillflag=0; my $pretty_search_string = "
\n"; # Clean up fields for safety - for my $field ('title','author','subject','keywords','url','version', - 'creationdatestart_month','creationdatestart_day', + for my $field (@BasicFields, + 'creationdatestart_month','creationdatestart_day', 'creationdatestart_year','creationdateend_month', 'creationdateend_day','creationdateend_year', 'lastrevisiondatestart_month','lastrevisiondatestart_day', 'lastrevisiondatestart_year','lastrevisiondateend_month', - 'lastrevisiondateend_day','lastrevisiondateend_year', - 'notes','abstract','extension','language','owner', - 'custommetadata','customshow','category') { - $ENV{"form.$field"}=~s/[^\w\/\s\(\)\=\-\"\']//g; + 'lastrevisiondateend_day','lastrevisiondateend_year') { + $ENV{'form.'.$field}=~s/[^\w\/\s\(\)\=\-\"\']//g; } foreach ('mode','form','element') { # is this required? Hmmm. - next unless (exists($ENV{"form.$_"})); - $ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"}); - $ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g; + next if (! exists($ENV{'form.'.$_})); + $ENV{'form.'.$_}=&Apache::lonnet::unescape($ENV{'form.'.$_}); + $ENV{'form.'.$_}=~s/[^\w\/\s\(\)\=\-\"\']//g; } # Preprocess the category form element. $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','category','extension','language', - 'owner','custommetadata') { - if (&filled($ENV{"form.$field"})) { + for my $field (@BasicFields) { + if (&filled($ENV{'form.'.$field})) { $fillflag++; } } - unless ($fillflag) { + for my $field ('lowestgradelevel','highestgradelevel') { + if ( $ENV{'form.'.$field} =~ /^\d+$/ && + $ENV{'form.'.$field} > 0) { + $fillflag++; + } + } + if (! $fillflag) { &output_blank_field_error($r,$closebutton, 'phase=disp_adv',$hidden_fields); return ; @@ -1000,8 +1130,7 @@ sub parse_advanced_search { my @queries; my $font = ''; # Evaluate logical expression AND/OR/NOT phrase fields. - foreach my $field ('title','author','subject','notes','abstract','url', - 'keywords','version','owner','standards') { + foreach my $field (@BasicFields) { if ($ENV{'form.'.$field}) { my $searchphrase = $ENV{'form.'.$field}; $pretty_search_string .= $font."$field contains ". @@ -1033,11 +1162,6 @@ sub parse_advanced_search { $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 '. @@ -1045,6 +1169,22 @@ sub parse_advanced_search { } # # Evaluate option lists + if ($ENV{'form.lowestgradelevel'} && + $ENV{'form.lowestgradelevel'} ne '0' && + $ENV{'form.lowestgradelevel'} =~ /^\d+$/) { + push(@queries, + '(lowestgradelevel>='.$ENV{'form.lowestgradelevel'}.')'); + $pretty_search_string.="lowestgradelevel>=". + $ENV{'form.lowestgradelevel'}."
\n"; + } + if ($ENV{'form.highestgradelevel'} && + $ENV{'form.highestgradelevel'} ne '0' && + $ENV{'form.highestgradelevel'} =~ /^\d+$/) { + push(@queries, + '(highestgradelevel<='.$ENV{'form.highestgradelevel'}.')'); + $pretty_search_string.="highestgradelevel<=". + $ENV{'form.highestgradelevel'}."
\n"; + } if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') { push @queries,"(language like \"$ENV{'form.language'}\")"; $pretty_search_string.=$font."language= ". @@ -1059,27 +1199,32 @@ sub parse_advanced_search { } # # Evaluate date windows - my $datequery=&build_date_queries( - $ENV{'form.creationdatestart_month'}, - $ENV{'form.creationdatestart_day'}, - $ENV{'form.creationdatestart_year'}, - $ENV{'form.creationdateend_month'}, - $ENV{'form.creationdateend_day'}, - $ENV{'form.creationdateend_year'}, - $ENV{'form.lastrevisiondatestart_month'}, - $ENV{'form.lastrevisiondatestart_day'}, - $ENV{'form.lastrevisiondatestart_year'}, - $ENV{'form.lastrevisiondateend_month'}, - $ENV{'form.lastrevisiondateend_day'}, - $ENV{'form.lastrevisiondateend_year'}, - ); - # Test to see if date windows are legitimate - if ($datequery=~/^Incorrect/) { - &output_date_error($r,$datequery,$closebutton,$hidden_fields); - return ; - } elsif ($datequery) { + my $cafter = + &Apache::lonhtmlcommon::get_date_from_form('creationdate1'); + my $cbefore = + &Apache::lonhtmlcommon::get_date_from_form('creationdate2'); + if ($cafter > $cbefore) { + my $tmp = $cafter; + $cafter = $cbefore; + $cbefore = $tmp; + } + my $mafter = + &Apache::lonhtmlcommon::get_date_from_form('revisiondate1'); + my $mbefore = + &Apache::lonhtmlcommon::get_date_from_form('revisiondate2'); + if ($mafter > $mbefore) { + my $tmp = $mafter; + $mafter = $mbefore; + $mbefore = $tmp; + } + my ($datequery,$error,$prettydate)=&build_date_queries($cafter,$cbefore, + $mafter,$mbefore); + if (defined($error)) { + &output_date_error($r,$error,$closebutton,$hidden_fields); + } elsif (defined($datequery)) { # Here is where you would set up pretty_search_string to output # date query information. + $pretty_search_string .= '
'.$prettydate.'
'; push @queries,$datequery; } # @@ -1113,8 +1258,7 @@ sub parse_advanced_search { $pretty_search_string .= $pretty_domains_string."
\n"; # if (@queries) { - $query=join(" AND ",@queries); - $query="select * from metadata where $query"; + $query="select * from metadata where ".join(" AND ",@queries); } elsif ($customquery) { $query = ''; } @@ -1372,51 +1516,73 @@ Also reports errors (check for /^Incorre ###################################################################### ###################################################################### sub build_date_queries { - my ($cmonth1,$cday1,$cyear1,$cmonth2,$cday2,$cyear2, - $lmonth1,$lday1,$lyear1,$lmonth2,$lday2,$lyear2)=@_; - my @queries; - if ($cmonth1 or $cday1 or $cyear1 or $cmonth2 or $cday2 or $cyear2) { - unless ($cmonth1 and $cday1 and $cyear1 and - $cmonth2 and $cday2 and $cyear2) { - return "Incorrect entry for the creation date. You must specify ". - "a starting month, day, and year and an ending month, ". - "day, and year."; - } - my $cnumeric1=sprintf("%d%2d%2d",$cyear1,$cmonth1,$cday1); - $cnumeric1+=0; - my $cnumeric2=sprintf("%d%2d%2d",$cyear2,$cmonth2,$cday2); - $cnumeric2+=0; - if ($cnumeric1>$cnumeric2) { - return "Incorrect entry for the creation date. The starting ". - "date must occur before the ending date."; - } - my $cquery="(creationdate BETWEEN '$cyear1-$cmonth1-$cday1' AND '". - "$cyear2-$cmonth2-$cday2 23:59:59')"; - push @queries,$cquery; - } - if ($lmonth1 or $lday1 or $lyear1 or $lmonth2 or $lday2 or $lyear2) { - unless ($lmonth1 and $lday1 and $lyear1 and - $lmonth2 and $lday2 and $lyear2) { - return "Incorrect entry for the last revision date. You must ". - "specify a starting month, day, and year and an ending ". - "month, day, and year."; - } - my $lnumeric1=sprintf("%d%2d%2d",$lyear1,$lmonth1,$lday1); - $lnumeric1+=0; - my $lnumeric2=sprintf("%d%2d%2d",$lyear2,$lmonth2,$lday2); - $lnumeric2+=0; - if ($lnumeric1>$lnumeric2) { - return "Incorrect entry for the last revision date. The ". - "starting date must occur before the ending date."; - } - my $lquery="(lastrevisiondate BETWEEN '$lyear1-$lmonth1-$lday1' AND '". - "$lyear2-$lmonth2-$lday2 23:59:59')"; - push @queries,$lquery; + my ($cafter,$cbefore,$mafter,$mbefore) = @_; + my ($result,$error,$pretty_string); + # + # Verify the input + if (! defined($cafter) && ! defined($cbefore) && + ! defined($mafter) && ! defined($mbefore)) { + # This is an okay situation, so return undef for the error + return (undef,undef,undef); + } + if ((defined($cafter) && ! defined($cbefore)) || + (defined($cbefore) && ! defined($cafter))) { + # This is bad, so let them know + $error = &mt('Incorrect entry for the creation date. '. + 'You must specify both the beginning and ending dates.'); + } + if (! defined($error) && + ((defined($mafter) && ! defined($mbefore)) || + (defined($mbefore) && ! defined($mafter)))) { + # This is also bad, so let them know + $error = &mt('Incorrect entry for the last revision date. '. + 'You must specify both the beginning and ending dates.'); } - if (@queries) { - return join(" AND ",@queries); + if (! defined($error)) { + # + # Build the queries + my @queries; + if (defined($cbefore) && defined($cafter)) { + my (undef,undef,undef,$caday,$camon,$cayear) = localtime($cafter); + my (undef,undef,undef,$cbday,$cbmon,$cbyear) = localtime($cbefore); + # Correct for year being relative to 1900 + $cayear+=1900; $cbyear+=1900; + my $cquery= + '(creationdate BETWEEN '. + "'".$cayear.'-'.$camon.'-'.$caday."'". + ' AND '. + "'".$cbyear.'-'.$cbmon.'-'.$cbday." 23:59:59')"; + $pretty_string .= '
' if (defined($pretty_string)); + $pretty_string .= + &mt('created between [_1] and [_2]', + &Apache::lonlocal::locallocaltime($cafter), + &Apache::lonlocal::locallocaltime($cbefore+24*60*60-1)); + push(@queries,$cquery); + $pretty_string =~ s/ 00:00:00//g; + } + if (defined($mbefore) && defined($mafter)) { + my (undef,undef,undef,$maday,$mamon,$mayear) = localtime($mafter); + my (undef,undef,undef,$mbday,$mbmon,$mbyear) = localtime($mbefore); + # Correct for year being relative to 1900 + $mayear+=1900; $mbyear+=1900; + my $mquery= + '(lastrevisiondate BETWEEN '. + "'".$mayear.'-'.$mamon.'-'.$maday."'". + ' AND '. + "'".$mbyear.'-'.$mbmon.'-'.$mbday." 23:59:59')"; + push(@queries,$mquery); + $pretty_string .= '
' if (defined($pretty_string)); + $pretty_string .= + &mt('last revised between [_1] and [_2]', + &Apache::lonlocal::locallocaltime($mafter), + &Apache::lonlocal::locallocaltime($mbefore+24*60*60-1)); + $pretty_string =~ s/ 00:00:00//g; + } + if (@queries) { + $result .= join(" AND ",@queries); + } } - return ''; + return ($result,$error,$pretty_string); } ###################################################################### @@ -1646,12 +1812,13 @@ Returns: the identifier of the table on sub set_up_table_structure { my ($datatypes,$fullindicies) = &LONCAPA::lonmetadata::describe_metadata_storage(); - unshift(@$datatypes,{name => 'id', + # Copy the table description before modifying it... + @Datatypes = @{$datatypes}; + unshift(@Datatypes,{name => 'id', type => 'MEDIUMINT', restrictions => 'UNSIGNED NOT NULL', primary_key => 'yes', auto_inc => 'yes' }); - @Datatypes = @{$datatypes}; @Fullindicies = @{$fullindicies}; return; } @@ -1714,12 +1881,37 @@ sub update_status { $r->rflush(); } +{ + my $max_time = 40; # 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,$text) = @_; - $text =~ s/\'/\\\'/g; - $r->print - ("\n"); - $r->rflush(); + my ($r) = @_; + my $time = &time_left(); + if (($last_time-$time) > 0) { + $r->print("\n"); + $r->rflush(); + } + $last_time = $time; +} + } ###################################################################### @@ -1768,11 +1960,6 @@ sub run_search { my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); my $connection = $r->connection; # - # Timing variables - # - my $starttime = time; - my $max_time = 30; # seconds for the search to complete - # # Print run_search header # $r->print(< 2) { $pretty_string = join '
',(@Lines[0..2],'....
'); } - $r->print(&mt("Search").": ".$pretty_string); + $r->print(&mt("Search: [_1]",$pretty_string)); $r->rflush(); # # Determine the servers we need to contact. @@ -1804,6 +1991,8 @@ END @Servers_to_contact = sort(keys(%Apache::lonnet::libserv)); } my %Server_status; + # + # 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 store search results in.". @@ -1848,17 +2037,18 @@ END END $r->rflush(); - my $time_remaining = $max_time - (time - $starttime) ; - my $last_time = $time_remaining; - &update_seconds($r,$time_remaining); - &update_status($r,'contacting '.$Servers_to_contact[0]); - while (($time_remaining > 0) && + &reset_timing(); + &update_seconds($r); + &update_status($r,&mt('contacting [_1]',$Servers_to_contact[0])); + while (&time_left() && ((@Servers_to_contact) || keys(%Server_status))) { - # Send out a search request if it needs to be done. + &update_seconds($r); + # + # Send out a search request if (@Servers_to_contact) { # Contact one server my $server = shift(@Servers_to_contact); - &update_status($r,&mt('contacting').' '.$server); + &update_status($r,&mt('contacting [_1]',$server)); my $reply=&Apache::lonnet::metadata_query($query,$customquery, $customshow,[$server]); ($server) = keys(%$reply); @@ -1870,7 +2060,7 @@ END # left to contact. if (scalar (keys(%Server_status))) { &update_status($r, - &mt('waiting on').' '.(join(' ',keys(%Server_status)))); + &mt('waiting on [_1]',join(' ',keys(%Server_status)))); } sleep(1); } @@ -1879,6 +2069,7 @@ END # have results from yet, looking for results. while (my ($server,$status) = each(%Server_status)) { last if ($connection->aborted()); + &update_seconds($r); if ($status eq 'con_lost') { delete ($Server_status{$server}); next; @@ -1886,12 +2077,12 @@ END $status=~/^([\.\w]+)$/; my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$1; if (-e $datafile && ! -e "$datafile.end") { - &update_status($r,&mt('Receiving results from').' '.$server); + &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').' '.$server); + &update_status($r,&mt('Reading results from [_1]',$server)); if (-z "$datafile") { delete($Server_status{$server}); next; @@ -1906,29 +2097,30 @@ END # Read in the whole file. while (my $result = <$fh>) { last if ($connection->aborted()); - # handle custom fields? Someday we will! + # + # Records are stored one per line chomp($result); - next unless $result; + next if (! $result); + # # Parse the result. my %Fields = &parse_raw_result($result,$server); $Fields{'hostname'} = $server; + # + # Skip based on copyright next if (! ©right_check(\%Fields)); + # # Store the result in the mysql database my $result = &Apache::lonmysql::store_row($table,\%Fields); if (! defined($result)) { $r->print(&Apache::lonmysql::get_error()); } - # $r->print(&Apache::lonmysql::get_debug()); + # $hitcountsum ++; - $time_remaining = $max_time - (time - $starttime) ; - if ($last_time - $time_remaining > 0) { - &update_seconds($r,$time_remaining); - $last_time = $time_remaining; - } + &update_seconds($r); if ($hitcountsum % 50 == 0) { &update_count_status($r,$hitcountsum); } - } # End of foreach (@results) + } $fh->close(); # $server is only deleted if the results file has been # found and (successfully) opened. This may be a bad idea. @@ -1938,21 +2130,16 @@ END &update_count_status($r,$hitcountsum); } 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; - &update_seconds($r,$time_remaining); - } + &update_seconds($r); } - &update_status($r,&mt('Search Complete').$server); - &update_seconds($r,0); + &update_status($r,&mt('Search Complete [_1]',$server)); + &update_seconds($r); # - &Apache::lonmysql::disconnect_from_db(); + &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. + # results to get, so let the client know the top frame needs to be + # loaded from /adm/searchcat $r->print(""); if ($ENV{'form.catalogmode'} ne 'groupsearch') { $r->print("