--- loncom/interface/lonsearchcat.pm 2001/03/22 13:10:06 1.64
+++ loncom/interface/lonsearchcat.pm 2006/03/15 20:56:16 1.256
@@ -1,1043 +1,3733 @@
-# The LearningOnline Network
+# The LearningOnline Network with CAPA
# Search Catalog
#
-# 03/08/2001 Scott Harrison
-# Scott Harrison: 03/12/2001, 03/13/2001, 03/14/2001, 03/15/2001, 03/19/2001
-# Scott Harrison: 03/20/2001
+# $Id: lonsearchcat.pm,v 1.256 2006/03/15 20:56:16 albertel Exp $
#
-# Functions
+# Copyright Michigan State University Board of Trustees
#
-# handler(server reference) : interacts with the Apache server layer
-# (for /adm/searchcat URLs)
-# simpletextfield(name,value) : returns HTML formatted string for simple text
-# field
-# simplecheckbox(name,value) : returns HTML formatted string for simple
-# checkbox
-# searchphrasefield(title,name,value) : returns HTML formatted string for
-# a search expression phrase field
-# dateboxes(name, defaultmonth, defaultday, defaultyear) : returns HTML
-# formatted string
-# for a calendar date
-# selectbox(title,name,value,%HASH=options) : returns HTML formatted string for
-# a selection box field
-# advancedsearch(server reference, environment reference) : perform a complex
-# multi-field logical query
-# filled(field) : determines whether a given field has been filled
-# basicsearch(server reference, environment reference) : perform a simple
-# single-field logical query
-# output_blank_field_error(server reference) : outputs a message saying that
-# more fields need to be filled in
-# output_results(output mode,
-# server reference,
-# environment reference,
-# reply list reference) : outputs results from search
-# build_SQL_query(field name, logic) : builds a SQL query string from a
-# logical expression with AND/OR keywords
-# recursive_SQL_query_build(field name, reverse notation expression) :
-# builds a SQL query string from a reverse notation expression
-# logical expression with AND/OR keywords
+# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
+#
+# LON-CAPA is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# LON-CAPA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with LON-CAPA; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# /home/httpd/html/adm/gpl.txt
+#
+# http://www.lon-capa.org/
+#
+###############################################################################
+###############################################################################
+
+=pod
+
+=head1 NAME
+
+lonsearchcat - LONCAPA Search Interface
+
+=head1 SYNOPSIS
+
+Search interface to LON-CAPAs digital library
+
+=head1 DESCRIPTION
+
+This module enables searching for a distributed browseable catalog.
+
+This is part of the LearningOnline Network with CAPA project
+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 separate window.
+
+=head1 Internals
+
+=over 4
+
+=cut
+
+###############################################################################
+###############################################################################
package Apache::lonsearchcat;
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();
+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();
+
+######################################################################
+######################################################################
+##
+## 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);
-my %language;
-my $scrout;
-my %metadatafields;
-my %cprtag;
-my %mimetag;
-my $closebutton;
-my $basicviewselect=< '.&mt('No matches found in resources').'. '.&mt('No matches found in postings').'.
+$lt{'note'}.
+
+
+
+
'.&mt('Course content').':
');
+ $r->rflush();
+# ======================================================= Go through the course
+ my $c=$r->connection;
+ if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
+ &GDBM_READER(),0640)) {
+ foreach (sort(keys(%hash))) {
+ if ($c->aborted()) { last; }
+ if (($_=~/^src\_(.+)$/)) {
+ if ($hash{'randomout_'.$1} & !$env{'request.role.adv'}) {
+ next;
+ }
+ my $symb=&make_symb($1);
+ &checkonthis($r,$1,$hash{$_},0,&Apache::lonnet::gettitle($symb),
+ $fulltext,$symb,@allwords);
+ }
+ }
+ untie(%hash);
+ }
+ unless ($totalfound) {
+ $r->print('
'.&mt('Discussion postings').':
');
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ my @allres=$navmap->retrieveResources();
+ my %discussiontime = &Apache::lonnet::dump('discussiontimes',
+ $env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
+ foreach my $resource (@allres) {
+ my $result = '';
+ my $applies = 0;
+ my $symb = $resource->symb();
+ my $ressymb = $symb;
+ if ($symb =~ m#(___adm/\w+/\w+)/(\d+)/bulletinboard$#) {
+ $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard';
+ unless ($ressymb =~ m#bulletin___\d+___adm/wrapper#) {
+ $ressymb=~s#(bulletin___\d+___)#$1adm/wrapper/#;
+ }
+ }
+ if (defined($discussiontime{$ressymb})) {
+ my %contrib = &Apache::lonnet::restore($ressymb,$env{'request.course.id'},
+ $env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
+ if ($contrib{'version'}) {
+ for (my $id=1;$id<=$contrib{'version'};$id++) {
+ unless (($contrib{'hidden'}=~/\.$id\./) || ($contrib{'deleted'}=~/\.$id\./)) {
+ if ($contrib{$id.':subject'}) {
+ $result .= $contrib{$id.':subject'};
+ }
+ if ($contrib{$id.':message'}) {
+ $result .= $contrib{$id.':message'};
+ }
+ if ($contrib{$id,':attachmenturl'}) {
+ if ($contrib{$id,':attachmenturl'} =~ m-/([^/]+)$-) {
+ $result .= $1;
+ }
+ }
+ $applies = &checkwords($result,$applies,@allwords);
+ }
+ }
+ }
+ }
+# Does this discussion apply?
+ if ($applies) {
+ my ($map,$ind,$url)=&Apache::lonnet::decode_symb($ressymb);
+ my $disctype = &mt('resource');
+ if ($url =~ m#/bulletinboard$#) {
+ if ($url =~m#^adm/wrapper/adm/.*/bulletinboard$#) {
+ $url =~s#^adm/wrapper##;
+ }
+ $disctype = &mt('bulletin board');
+ } else {
+ $url = '/res/'.$url;
+ }
+ if ($url =~ /\?/) {
+ $url .= '&symb=';
+ } else {
+ $url .= '?symb=';
+ }
+ $url .= &Apache::lonnet::escape($resource->symb());
+ my $title = $resource->compTitle();
+ $r->print('
'.
+ ($title?$title:$url).' - '.$disctype.'
');
+ $totaldiscussions++;
+ } else {
+ $r->print(' .');
+ }
+ }
+ unless ($totaldiscussions) {
+ $r->print('
');
+ for (my $i=0;$i<=$level*5;$i++) {
+ $r->print(' ');
+ }
+ my $href=$url;
+ if ($hash{'encrypted_'.$id} && !$env{'request.role.adv'}) {
+ $href=&Apache::lonenc::encrypted($href)
+ .'?symb='.&Apache::lonenc::encrypted($symb);
+ } else {
+ $href.='?symb='.&Apache::lonnet::escape($symb);
+ }
+ $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{$id})) {
+ &checkonthis($r,$id,$_,$level+1,'',$fulltext,undef,@allwords);
+ }
+ }
+}
- $scrout.=&searchphrasefield('Limit by keywords','keywords',
- $ENV{'form.keywords'});
+sub checkwords {
+ my ($result,$applies,@allwords) = @_;
+ foreach (@allwords) {
+ if ($_=~/\w/) {
+ if ($result=~/$_/si) {
+ $applies++;
+ }
+ }
+ }
+ return $applies;
+}
- $scrout.=&searchphrasefield('Limit by URL','url',
- $ENV{'form.url'});
+sub untiehash {
+ if (tied(%hash)) {
+ untie(%hash);
+ }
+}
- $scrout.=&searchphrasefield('Limit by version','version',
- $ENV{'form.version'});
+} # End of course search scoping
- $scrout.=&searchphrasefield('Limit by notes','notes',
- $ENV{'form.notes'});
- $scrout.=&searchphrasefield('Limit by abstract','abstract',
- $ENV{'form.abstract'});
+######################################################################
+######################################################################
- $ENV{'form.mime'}='notxxx' unless length($ENV{'form.mime'});
- $scrout.=&selectbox('Limit by MIME type','mime',
- $ENV{'form.mime'},%mimetag);
+=pod
- $ENV{'form.language'}='any' unless length($ENV{'form.language'});
+=item &print_basic_search_form()
+
+Prints the form for the basic search. Sorry the name is so cryptic.
+
+=cut
+
+######################################################################
+######################################################################
+sub print_basic_search_form {
+ my ($r,$closebutton,$hidden_fields) = @_;
+ my $result = ($env{'form.catalogmode'} ne 'groupsearch');
+ my $bread_crumb =
+ &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching','Search_Basic',
+ undef,undef,
+ $env{'form.catalogmode'} ne 'groupsearch');
+ my $scrout = &Apache::loncommon::start_page('Search').$bread_crumb;
+ if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'})) {
+ # Define interface components
+ my $userelatedwords= '';
+ my $onlysearchdomain='';
+ my $inclext= '';
+ my $adv_search_link =
+ ''.&mt('Advanced Search').'';
+ #
+ $scrout.='';
+ }
+ if ($env{'request.course.id'}) {
+ 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)',
+ 'disc' => 'search discussion postings (resources and bulletin boards)',
+ );
+ $scrout.=(<
+$lt{'header'}
+
+$hidden_fields
+
+
+
+ENDCOURSESEARCH
+ $scrout.=' '.
+ &Apache::lonhtmlcommon::textbox('courseexp',
+ $env{'form.courseexp'},40);
+ my $crscheckbox =
+ &Apache::lonhtmlcommon::checkbox('crsfulltext',
+ $env{'form.crsfulltext'});
+ my $relcheckbox =
+ &Apache::lonhtmlcommon::checkbox('crsrelated',
+ $env{'form.crsrelated'});
+ my $discheckbox =
+ &Apache::lonhtmlcommon::checkbox('crsdiscuss',
+ $env{'form.crsrelated'});
+ $scrout.=(<
+
+
+
-between:
-CREATIONDATESTART
- $scrout.=&dateboxes('creationdatestart',1,1,1976,
- $ENV{'form.creationdatestart_month'},
- $ENV{'form.creationdatestart_day'},
- $ENV{'form.creationdatestart_year'},
- );
- $scrout.=<
between:
-LASTREVISIONDATESTART
- $scrout.=&dateboxes('lastrevisiondatestart',1,1,1976,
- $ENV{'form.lastrevisiondatestart_month'},
- $ENV{'form.lastrevisiondatestart_day'},
- $ENV{'form.lastrevisiondatestart_year'},
- );
- $scrout.=<
-Example: grandmother=75 OR grandfather=85
-
-CUSTOMMETADATA
-$scrout.=&simpletextfield('custommetadata',$ENV{'form.custommetadata'});
-$scrout.=' initial users of this system do not need to worry about this option';
-
-# ---------------------------------------------------------------- Print screen
- $r->print(<
-
Search Catalog
-
'. + (' 'x2).&searchhelp()." | |||
'.&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')).' | '. + &Apache::loncommon::filecategoryselect('category', + $env{'form.category'}). + ' | ||
'. + &titlefield(&mt('Domains')).' | '.
+ &Apache::loncommon::domain_select('domains',
+ $env{'form.domains'},1).
+ ' | ||
'. + &titlefield(&mt('Copyright/Distribution')).' | '. + &Apache::lonmeta::selectbox('copyright', + $env{'form.copyright'}, + \&Apache::loncommon::copyrightdescription, + ( undef, + &Apache::loncommon::copyrightids) + ).' | ||
'. + &titlefield(&mt('Language')).' | '. + &Apache::lonmeta::selectbox('language', + $env{'form.language'}, + \&Apache::loncommon::languagedescription, + ('any',&Apache::loncommon::languageids) + ).' |
'.&mt('Minimum').' | '. + ''.&mt('Maximum').' | |
'. + &titlefield(&mt($statistic->{'description'})). + ' | '. + ''. + ' | '. + ''. + ' |
'.&mt('Minimum').' | '. + ''.&mt('Maximum').' | |
'. + &titlefield(&mt($evaluation->{'description'})). + ' | '. + ''. + ' | '. + ''. + ' |
Created between | '. + '[_1] |
and | '. + '[_2] |
Last modified between | '. + '[_1] |
and | '. + '[_2] |
$uctitle:".
- "
".'';
-}
-
-# ----------------------------------------------- Performing an advanced search
-sub advancedsearch {
- my ($r,$envhash)=@_;
- my %ENV=%{$envhash};
+######################################################################
+######################################################################
+
+=pod
+
+=item &make_form_data_persistent()
+
+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 separated string.
+
+=cut
+
+######################################################################
+######################################################################
+sub make_form_data_persistent {
+ my $r = shift;
+ my $filename = shift;
+ my %save;
+ foreach (keys(%env)) {
+ next if (!/^form/ || /submit/);
+ $save{$_} = $env{$_};
+ }
+ return &make_persistent(\%save,$filename);
+}
+
+######################################################################
+######################################################################
+
+=pod
+
+=item &parse_advanced_search()
+
+Parse advanced search form and return the following:
+
+=over 4
+
+=item $query Scalar containing an SQL query.
+
+=item $customquery Scalar containing a custom query.
+
+=item $customshow Scalar containing commands to show custom metadata.
+
+=item $libraries_to_query Reference to array of domains to search.
+
+=back
+=cut
+
+######################################################################
+######################################################################
+sub parse_advanced_search {
+ my ($r,$closebutton,$hidden_fields)=@_;
+ my @BasicFields = ('title','author','subject','keywords','url','version',
+ 'notes','abstract','extension','owner','authorspace',
+# 'custommetadata','customshow',
+ 'modifyinguser','standards','mime');
+ my @StatsFields = &statfields();
+ my @EvalFields = &evalfields();
my $fillflag=0;
+ my $pretty_search_string = "";
# 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','mime','language','owner',
- 'custommetadata') {
- $ENV{"form.$field"}=~s/[^\w\s\(\)\-\"\']//g;
- }
- for my $field ('title','author','subject','keywords','url','version',
- 'notes','abstract','mime','language','owner',
- 'custommetadata') {
- if (&filled($ENV{"form.$field"})) {
+ 'lastrevisiondateend_day','lastrevisiondateend_year') {
+ $env{'form.'.$field}=~s/[^\w\/\s\(\)\=\-\"\']//g;
+ }
+ foreach ('mode','form','element') {
+ # is this required? Hmmm.
+ 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
+ foreach my $field (@BasicFields) {
+ if (&filled($env{'form.'.$field})) {
$fillflag++;
}
}
-
- unless ($fillflag) {
- &output_blank_field_error($r);
- return OK;
+ foreach my $field (@StatsFields,@EvalFields) {
+ if (&filled($env{'form.'.$field.'_max'})) {
+ $fillflag++;
+ }
+ if (&filled($env{'form.'.$field.'_min'})) {
+ $fillflag++;
+ }
}
- my $query='';
-
- my @queries;
- # Go through logical expression AND/OR/NOT phrase fields.
-
- foreach my $field ('title','author','subject','notes','abstract','url',
- 'keywords','version','owner') {
- if ($ENV{'form.'.$field}) {
- push @queries,&build_SQL_query($field,$ENV{'form.'.$field});
- }
+ for my $field ('lowestgradelevel','highestgradelevel') {
+ if ( $env{'form.'.$field} =~ /^\d+$/ &&
+ $env{'form.'.$field} > 0) {
+ $fillflag++;
+ }
}
- if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') {
- push @queries,"(language like \"\%$ENV{'form.language'}\%\")";
+ if (! $fillflag) {
+ &output_blank_field_error($r,$closebutton,
+ 'phase=disp_adv',$hidden_fields);
+ return ;
}
- if ($ENV{'form.mime'} and $ENV{'form.mime'} ne 'any') {
- push @queries,"(mime like \"\%$ENV{'form.mime'}\%\")";
+ # Turn the form input into a SQL-based query
+ my $query='';
+ my @queries;
+ my $font = '';
+ # Evaluate logical expression AND/OR/NOT phrase fields.
+ foreach my $field (@BasicFields) {
+ next if (!defined($env{'form.'.$field}) || $env{'form.'.$field} eq '');
+ my ($error,$SQLQuery) =
+ &process_phrase_input($env{'form.'.$field},
+ $env{'form.'.$field.'_related'},$field);
+ if (defined($error)) {
+ &output_unparsed_phrase_error($r,$closebutton,'phase=disp_adv',
+ $hidden_fields,$field);
+ return;
+ } else {
+ $pretty_search_string .=
+ $font.$field.': '.$env{'form.'.$field};
+ if ($env{'form.'.$field.'_related'}) {
+ my @Words =
+ &Apache::loncommon::get_related_words
+ ($env{'form.'.$field});
+ if (@Words) {
+ $pretty_search_string.= ' with related words: '.
+ join(', ',@Words[0..4]);
+ } else {
+ $pretty_search_string.= ' with related words.';
+ }
+ }
+ $pretty_search_string .= '
';
+ push (@queries,$SQLQuery);
+ }
}
- if ($ENV{'form.copyright'} and $ENV{'form.copyright'} ne 'any') {
- push @queries,"(copyright like \"\%$ENV{'form.copyright'}\%\")";
+ #
+ # 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);
+ }
}
- 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'},
- );
- if ($datequery=~/^Incorrect/) {
- &output_date_error($r,$datequery);
- return OK;
+ if (defined($searchphrase)) {
+ my ($error,$SQLsearch) = &process_phrase_input($searchphrase,0,'mime');
+ push @queries,$SQLsearch;
+ $pretty_search_string .=$font.'mime contains '.
+ $searchphrase.'
';
+ }
+ #
+ # 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= ".
+ &Apache::loncommon::languagedescription($env{'form.language'}).
+ "
\n";
+ }
+ if ($env{'form.copyright'} and $env{'form.copyright'} ne 'any') {
+ push @queries,"(copyright like \"$env{'form.copyright'}\")";
+ $pretty_search_string.=$font."copyright = ".
+ &Apache::loncommon::copyrightdescription($env{'form.copyright'}).
+ "
\n";
+ }
+ #
+ # Statistics
+ foreach my $field (@StatsFields,@EvalFields) {
+ my ($min,$max);
+ if (exists($env{'form.'.$field.'_min'}) &&
+ $env{'form.'.$field.'_min'} ne '') {
+ $min = $env{'form.'.$field.'_min'};
+ }
+ if (exists($env{'form.'.$field.'_max'}) &&
+ $env{'form.'.$field.'_max'} ne '') {
+ $max = $env{'form.'.$field.'_max'};
+ }
+ next if (! defined($max) && ! defined($min));
+ if (defined($min) && defined($max)) {
+ ($min,$max) = sort {$a <=>$b} ($min,$max);
+ }
+ if (defined($min) && $min =~ /^(\d+\.\d+|\d+|\.\d+)$/) {
+ push(@queries,'('.$field.'>'.$min.')');
+ $pretty_search_string.=$font.$field.'>'.$min.'
';
+ }
+ if (defined($max) && $max =~ /^(\d+\.\d+|\d+|\.\d+)$/) {
+ push(@queries,'('.$field.'<'.$max.')');
+ $pretty_search_string.=$font.$field.'<'.$max.'
';
+ }
}
- elsif ($datequery) {
+ #
+ # Evaluate date windows
+ 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;
}
- my $customquery;
- if ($ENV{'form.custommetadata'}) {
- $customquery=&build_custommetadata_query('custommetadata',
- $ENV{'form.custommetadata'});
+ #
+ # Process form information for custom metadata querying
+ my $customquery=undef;
+ ##
+ ## The custom metadata search was removed q long time ago mostly
+ ## because I was unable to figureout exactly how it worked and could
+ ## not imagine people actually using it. MH
+ ##
+ # if ($env{'form.custommetadata'}) {
+ # $pretty_search_string .=$font."Custom Metadata Search: ".
+ # $env{'form.custommetadata'}."
\n";
+ # $customquery=&build_custommetadata_query('custommetadata',
+ # $env{'form.custommetadata'});
+ # }
+ my $customshow=undef;
+ # if ($env{'form.customshow'}) {
+ # $pretty_search_string .=$font."Custom Metadata Display: ".
+ # $env{'form.customshow'}."
\n";
+ # $customshow=$env{'form.customshow'};
+ # $customshow=~s/[^\w\s]//g;
+ # my @fields=split(/\s+/,$customshow);
+ # $customshow=join(" ",@fields);
+ # }
+ ##
+ ## Deal with restrictions to given domains
+ ##
+ my ($libraries_to_query,$pretty_domains_string) = &parse_domain_restrictions();
+ if ($pretty_domains_string) {
+ $pretty_search_string .= $pretty_domains_string."
\n";
}
+ #
if (@queries) {
- $query=join(" AND ",@queries);
- $query="select * from metadata where $query";
- my $reply=&Apache::lonnet::metadata_query($query);
- &output_results('Advanced',$r,$envhash,$customquery,$reply);
+ $query="SELECT * FROM metadata WHERE (".join(") AND (",@queries).')';
+ } elsif ($customquery) {
+ $query = '';
+ }
+ #&Apache::lonnet::logthis('advanced query = '.$/.$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.
+ if (! exists($env{'form.domains'}) || $env{'form.domains'} eq '') {
+ return (undef,'',undef);
+ }
+ my @allowed_domains = &Apache::loncommon::get_env_multiple('form.domains');
+ #
+ my %domain_hash = ();
+ my $pretty_domains_string;
+ foreach (@allowed_domains) {
+ $domain_hash{$_}++;
+ }
+ if ($domain_hash{'any'}) {
+ $pretty_domains_string = "In all LON-CAPA domains.";
+ } else {
+ if (@allowed_domains > 1) {
+ $pretty_domains_string = "In LON-CAPA domains:";
+ } else {
+ $pretty_domains_string = "In LON-CAPA domain ";
+ }
+ foreach (sort @allowed_domains) {
+ $pretty_domains_string .= "".$_." ";
+ }
+ foreach (keys(%Apache::lonnet::libserv)) {
+ if (exists($domain_hash{$Apache::lonnet::hostdom{$_}})) {
+ push @$libraries_to_query,$_;
+ }
+ }
}
- else {
- &output_results('Advanced',$r,$envhash,$query);
+ return ($libraries_to_query,
+ $pretty_domains_string);
+}
+
+######################################################################
+######################################################################
+
+=pod
+
+=item &parse_basic_search()
+
+Parse the basic search form and return a scalar containing an sql query.
+
+=cut
+
+######################################################################
+######################################################################
+sub parse_basic_search {
+ my ($r,$closebutton)=@_;
+ #
+ # Clean up fields for safety
+ for my $field ('basicexp') {
+ $env{"form.$field"}=~s/[^\w\s\'\"\!\(\)\-]//g;
}
- return OK;
+ 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;
+ }
+ my ($libraries_to_query,$pretty_domains_string) = &parse_domain_restrictions();
+ #
+ # Check to see if enough of a query is filled in
+ my $search_string = $env{'form.basicexp'};
+ if (! &filled($search_string)) {
+ &output_blank_field_error($r,$closebutton,'phase=disp_basic');
+ return OK;
+ }
+ my $pretty_search_string=$search_string;
+ my @Queries;
+ my $searchfield = 'concat_ws(" ",'.join(',',
+ ('title','author','subject',
+ 'notes','abstract','keywords')
+ ).')';
+ my ($error,$SQLQuery) = &process_phrase_input($search_string,
+ $env{'form.related'},
+ $searchfield);
+ if ($error) {
+ &output_unparsed_phrase_error($r,$closebutton,'phase=disp_basic',
+ '','basicexp');
+ return;
+ }
+ push(@Queries,$SQLQuery);
+ #foreach my $q (@Queries) {
+ # &Apache::lonnet::logthis(' '.$q);
+ #}
+ my $final_query = 'SELECT * FROM metadata WHERE '.join(" AND ",@Queries);
+ #
+ if (defined($pretty_domains_string) && $pretty_domains_string ne '') {
+ $pretty_search_string .= ' '.$pretty_domains_string;
+ }
+ $pretty_search_string .= "
\n";
+ $pretty_search_string =~ s:^
and ::;
+ #&Apache::lonnet::logthis('simple search final query = '.$/.$final_query);
+ return ($final_query,$pretty_search_string,
+ $libraries_to_query);
}
-# ---------------------------------------------------- see if a field is filled
-sub filled {
- my ($field)=@_;
- if ($field=~/\S/) {
- return 1;
+
+###############################################################
+###############################################################
+
+my @Phrases;
+
+sub concat {
+ my ($item) = @_;
+ my $results = '';
+ foreach (@$item) {
+ if (ref($_) eq 'ARRAY') {
+ $results .= join(' ',@$_);
+ }
}
- else {
- return 0;
+ return $results;
+}
+
+sub process_phrase_input {
+ my ($phrase,$related,$field)=@_;
+ #&Apache::lonnet::logthis('phrase = :'.$phrase.':');
+ my $grammar = <<'ENDGRAMMAR';
+ searchphrase:
+ expression /^\Z/ {
+ # &Apache::lonsearchcat::print_item(\@item,0);
+ [@item];
+ }
+ expression:
+ phrase(s) {
+ [@item];
+ }
+ phrase:
+ orword {
+ [@item];
+ }
+ | andword {
+ [@item];
+ }
+ | minusword {
+ unshift(@::Phrases,$item[1]->[0]);
+ unshift(@::Phrases,$item[1]->[1]);
+ [@item];
+ }
+ | word {
+ unshift(@::Phrases,$item[1]);
+ [@item];
+ }
+ #
+ orword:
+ word 'OR' phrase {
+ unshift(@::Phrases,'OR');
+ unshift(@::Phrases,$item[1]);
+ [@item];
+ }
+ | word 'or' phrase {
+ unshift(@::Phrases,'OR');
+ unshift(@::Phrases,$item[1]);
+ [@item];
+ }
+ | minusword 'OR' phrase {
+ unshift(@::Phrases,'OR');
+ unshift(@::Phrases,$item[1]->[0]);
+ unshift(@::Phrases,$item[1]->[1]);
+ [@item];
+ }
+ | minusword 'or' phrase {
+ unshift(@::Phrases,'OR');
+ unshift(@::Phrases,$item[1]->[0]);
+ unshift(@::Phrases,$item[1]->[1]);
+ [@item];
+ }
+ andword:
+ word phrase {
+ unshift(@::Phrases,'AND');
+ unshift(@::Phrases,$item[1]);
+ [@item];
+ }
+ | minusword phrase {
+ unshift(@::Phrases,'AND');
+ unshift(@::Phrases,$item[1]->[0]);
+ unshift(@::Phrases,$item[1]->[1]);
+ [@item];
+ }
+ #
+ minusword:
+ '-' word {
+ [$item[2],'NOT'];
+ }
+ word:
+ "'" term(s) "'" {
+ &Apache::lonsearchcat::concat(\@item);
+ }
+ | '"' term(s) '"' {
+ &Apache::lonsearchcat::concat(\@item);
+ }
+ | term {
+ $item[1];
+ }
+ term:
+ /[\w\Q:!@#$%^&*()+_=|{}<>,.;\\\/?\E]+/ {
+ $item[1];
+ }
+ENDGRAMMAR
+ #
+ # The end result of parsing the phrase with the grammar is an array
+ # @::Phrases.
+ # $phrase = "gene splicing" or cat -> "gene splicing","OR","cat"
+ # $phrase = "genetic engineering" -dna ->
+ # "genetic engineering","AND","NOT","dna"
+ # $phrase = cat or dog -poodle -> "cat","OR","dog","AND","NOT","poodle"
+ undef(@::Phrases);
+ my $p = new Parse::RecDescent($grammar);
+ if (! defined($p->searchphrase($phrase))) {
+ &Apache::lonnet::logthis('lonsearchcat:unable to process:'.$phrase);
+ return 'Unable to process phrase '.$phrase;
+ }
+ #
+ # Go through the phrases and make sense of them.
+ # Apply modifiers NOT OR and AND to the phrases.
+ my @NewPhrases;
+ while(@::Phrases) {
+ my $phrase = shift(@::Phrases);
+ # &Apache::lonnet::logthis('phrase = '.$phrase);
+ my $phrasedata;
+ if ($phrase =~ /^(NOT|OR|AND)$/) {
+ if ($phrase eq 'OR') {
+ $phrasedata->{'or'}++;
+ if (! @::Phrases) { $phrasedata = undef; last; }
+ $phrase = shift(@::Phrases);
+ } elsif ($phrase eq 'AND') {
+ $phrasedata->{'and'}++;
+ if (! @::Phrases) { $phrasedata = undef; last; }
+ $phrase = shift(@::Phrases);
+ }
+ if ($phrase eq 'NOT') {
+ $phrasedata->{'negate'}++;
+ if (! @::Phrases) { $phrasedata = undef; last; }
+ $phrase = shift(@::Phrases);
+ }
+ }
+ $phrasedata->{'phrase'} = $phrase;
+ if ($related) {
+ my @NewWords;
+ (undef,@NewWords) = &related_version($phrasedata->{'phrase'});
+ $phrasedata->{'related_words'} = \@NewWords;
+ }
+ push(@NewPhrases,$phrasedata);
+ }
+ #
+ # Actually build the sql query from the phrases
+ my $SQLQuery;
+ foreach my $phrase (@NewPhrases) {
+ my $query;
+ if ($phrase->{'negate'}) {
+ $query .= $field.' NOT LIKE "%'.$phrase->{'phrase'}.'%"';
+ } else {
+ $query .= $field.' LIKE "%'.$phrase->{'phrase'}.'%"';
+ }
+ foreach my $related (@{$phrase->{'related_words'}}) {
+ if ($phrase->{'negate'}) {
+ $query .= ' AND '.$field.' NOT LIKE "%'.$related.'%"';
+ } else {
+ $query .= ' OR '.$field.' LIKE "%'.$related.'%"';
+ }
+ }
+ if ($SQLQuery) {
+ if ($phrase->{'or'}) {
+ $SQLQuery .= ' OR ('.$query.')';
+ } else {
+ $SQLQuery .= ' AND ('.$query.')';
+ }
+ } else {
+ $SQLQuery = '('.$query.')';
+ }
}
+ #
+ # &Apache::lonnet::logthis("SQLQuery = $SQLQuery");
+ #
+ return undef,$SQLQuery;
}
-# --------------------------------------------------- Performing a basic search
-sub basicsearch {
- my ($r,$envhash)=@_;
- my %ENV=%{$envhash};
+######################################################################
+######################################################################
- # Clean up fields for safety
- for my $field ('basicexp') {
- $ENV{"form.$field"}=~s/[^\w\s\(\)\-]//g;
+=pod
+
+=item &related_version()
+
+Modifies an input string to include related words. Words in the string
+are replaced with parenthesized lists of 'OR'd words. For example
+"torque" is replaced with "(torque OR word1 OR word2 OR ...)".
+
+Note: Using this twice on a string is probably silly.
+
+=cut
+
+######################################################################
+######################################################################
+sub related_version {
+ my ($word) = @_;
+ return (undef) if (lc($word) =~ /\b(or|and|not)\b/);
+ my @Words = &Apache::loncommon::get_related_words($word);
+ # Only use 4 related words
+ @Words = ($#Words>4? @Words[0..4] : @Words);
+ my $result = join " OR ", ($word,@Words);
+ return $result,sort(@Words);
+}
+
+
+######################################################################
+######################################################################
+
+=pod
+
+=item &build_custommetadata_query()
+
+Constructs a custom metadata query using a rather heinous regular
+expression.
+
+=cut
+
+######################################################################
+######################################################################
+sub build_custommetadata_query {
+ my ($field_name,$logic_statement)=@_;
+ my $q=new Text::Query('abc',
+ -parse => 'Text::Query::ParseAdvanced',
+ -build => 'Text::Query::BuildAdvancedString');
+ $q->prepare($logic_statement);
+ my $matchexp=${$q}{'-parse'}{'-build'}{'matchstring'};
+ # quick fix to change literal into xml tag-matching
+ # will eventually have to write a separate builder module
+ # wordone=wordtwo becomes\
' 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 ($result,$error,$pretty_string);
+}
- unless (&filled($ENV{'form.basicexp'})) {
- &output_blank_field_error($r);
- return OK;
+######################################################################
+######################################################################
+
+=pod
+
+=item ©right_check()
+
+Inputs: $Metadata, a hash pointer of metadata for a resource.
+
+Returns: 1 if the resource is available to the user making the query,
+ 0 otherwise.
+
+=cut
+
+######################################################################
+######################################################################
+sub copyright_check {
+ my $Metadata = shift;
+ # Check copyright tags and skip results the user cannot use
+ my (undef,undef,$resdom,$resname) = split('/',
+ $Metadata->{'url'});
+ # Check for priv
+ if (($Metadata->{'copyright'} eq 'priv') &&
+ (($env{'user.name'} ne $resname) &&
+ ($env{'user.domain'} ne $resdom))) {
+ return 0;
+ }
+ # Check for domain
+ if (($Metadata->{'copyright'} eq 'domain') &&
+ ($env{'user.domain'} ne $resdom)) {
+ return 0;
}
+ return 1;
+}
- my $query='';
- my $concatarg=join('," ",',
- ('title', 'author', 'subject', 'notes', 'abstract'));
+######################################################################
+######################################################################
- $query="select * from metadata where concat($concatarg) like '\%$ENV{'form.basicexp'}\%'";
- my $reply=&Apache::lonnet::metadata_query($query);
- &output_results('Basic',$r,$envhash,$query,$reply);
- return OK;
+=pod
+
+=item &ensure_db_and_table()
+
+Ensure we can get lonmysql to connect to the database and the table we
+need exists.
+
+Inputs: $r, table id
+
+Returns: undef on error, 1 if the table exists.
+
+=cut
+
+######################################################################
+######################################################################
+sub ensure_db_and_table {
+ my ($r,$table) = @_;
+ ##
+ ## Sanity check the table id.
+ ##
+ if (! defined($table) || $table eq '' || $table =~ /\D/ ) {
+ $r->print("Unable to retrieve search results. ".
+ "Unable to determine the table results were stored 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 stored.".
+ &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;
}
-# ---------------- Message to output when there are not enough fields filled in
-sub output_blank_field_error {
- my ($r)=@_;
- # make query information persistent to allow for subsequent revision
- my $persistent='';
- map {
- if (/^form\./ && !/submit/) {
- my $name=$_;
- my $key=$name;
- $name=~s/^form\.//;
- $persistent.=<
+Search:$pretty_query_string
- - -RESULTS + +END + $r->print($result.&Apache::loncommon::end_page()); + return; } -# ----------------------------- format and output results based on a reply list -sub output_results { - my ($mode,$r,$envhash,$query,@replylist)=@_; - my %ENV=%{$envhash}; - my $compiledresult=''; - - foreach my $reply (@replylist) { - - my @results; - - my $replyfile=''; - $reply=~/^([\.\w]+)$/; # must do since 'use strict' checks for tainting - $replyfile=$r->dir_config('lonDaemons').'/tmp/'.$1; - $reply=~/(.*?)\_/; - my $hostname=$1; - sleep 3; # temporary fix, need to check for completion and status - { - while (1) { - last if -e $replyfile; - sleep 1; - } - # QUESTION: how should I handle this error condition.. - # I'm sure there is syntax elsewhere I can use.. - my $fh=Apache::File->new($replyfile) or - ($r->print('file cannot be opened') and return OK); - @results=<$fh>; - } +##################################################################### +##################################################################### - foreach my $result (@results) { - my @fields=map - {&Apache::lonnet::unescape($_)} - (split(/\,/,$result)); - my ($title,$author,$subject,$url,$keywords,$version, - $notes,$abstract,$mime,$lang, - $creationdate,$lastrevisiondate,$owner,$copyright)=@fields; - my $shortabstract=$abstract; - $shortabstract=substr($abstract,0,200) if length($abstract)>200; - $fields[7]=$shortabstract; - $compiledresult.=<'.
+ ' | '. + &prev_next_buttons($min,$env{'form.show'},$total_results). + ' | '. + &viewoptions().' |
\n"; + if (! defined($Fields{'title'}) || $Fields{'title'} eq '') { + $Fields{'title'} = 'Untitled'; + } + 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. + $r->print($output); + $r->rflush(); + } + if (@Results < 1) { + $r->print(&mt("There were no results matching your query")); + } else { + $r->print + ('
-Subject: $subject
-Keyword(s): $keywords
-Notes: $notes
-MIME Type: $mimetag{$mime}
-Language: $language{$lang}
-Copyright/Distribution: $cprtag{$copyright}
-$shortabstract
-
\n";
+ $result .= ''.$values{'author'}.','.
+ ' '.$values{'owner'}.'
';
+ foreach my $field
+ (
+ { name=>'url',
+ translate => 'URL: [_1]',
+ special => 'url link',},
+ { name=>'subject',
+ translate => 'Subject: [_1]',},
+ { name=>'keywords',
+ translate => 'Keywords: [_1]',},
+ { name=>'notes',
+ translate => 'Notes: [_1]',},
+ { name=>'mimetag',
+ translate => 'MIME Type: [_1]',},
+ { name=>'standards',
+ translate => 'Standards:[_1]',},
+ { name=>'copyrighttag',
+ translate => 'Copyright/Distribution: [_1]',},
+ { name=>'count',
+ format => "%d",
+ translate => 'Access Count: [_1]',},
+ { name=>'stdno',
+ format => "%d",
+ translate => 'Number of Students: [_1]',},
+ { name=>'avetries',
+ format => "%.2f",
+ translate => 'Average Tries: [_1]',},
+ { name=>'disc',
+ format => "%.2f",
+ translate => 'Degree of Discrimination: [_1]',},
+ { name=>'difficulty',
+ format => "%.2f",
+ translate => 'Degree of Difficulty: [_1]',},
+ { name=>'clear',
+ format => "%.2f",
+ translate => 'Clear: [_1]',},
+ { name=>'depth',
+ format => "%.2f",
+ translate => 'Depth: [_1]',},
+ { name=>'helpful',
+ format => "%.2f",
+ translate => 'Helpful: [_1]',},
+ { name=>'correct',
+ format => "%.2f",
+ translate => 'Correct: [_1]',},
+ { name=>'technical',
+ format => "%.2f",
+ translate => 'Technical: [_1]',},
+ { name=>'comefrom_list',
+ type => 'list',
+ translate => 'Resources that lead up to this resource in maps',},
+ { name=>'goto_list',
+ type => 'list',
+ translate => 'Resources that follow this resource in maps',},
+ { name=>'sequsage_list',
+ type => 'list',
+ translate => 'Resources using or importing resource',},
+ ) {
+ next if (! exists($values{$field->{'name'}}) ||
+ $values{$field->{'name'}} eq '');
+ if (exists($field->{'type'}) && $field->{'type'} eq 'list') {
+ $result .= ''.&mt($field->{'translate'}).'
'.$values{'extrashow'}.'
'; + } + if (exists($values{'shortabstract'}) && $values{'shortabstract'} ne '') { + $result .= ''.$values{'shortabstract'}.'
'; + } + $result .= ''. + &detailed_citation_view($prefix,%values). + ' | '. + &Apache::lonindexer::showpreview($values{'url'}). + ' |
'. + &summary_view($prefix,%values). + ' | '. + &Apache::lonindexer::showpreview($values{'url'}). + ' |
+$errorstring +
++$revise +
+$end_page +ENDPAGE +} + +###################################################################### +###################################################################### + +=pod + +=item &output_blank_field_error() + +Output a complete page that indicates the user has not filled in enough +information to do a search. + +Inputs: $r (Apache request handle), $closebutton, $parms. + +Returns: nothing + +$parms is extra information to include in the 'Revise search request' link. + +=cut + +###################################################################### +###################################################################### +sub output_blank_field_error { + my ($r,$closebutton,$parms,$hidden_fields)=@_; + my $bodytag=&Apache::loncommon::bodytag('Search'); + my $errormsg = &mt('You did not fill in enough information for the search to be started. You need to fill in relevant fields on the search page in order for a query to be processed.'); + my $revise = &mt('Revise Search Request'); + my $heading = &mt('Unactionable Search Queary'); + my $start_page = &Apache::loncommon::start_page('Search'); + my $end_page = &Apache::loncommon::end_page(); + $r->print(<+$errormsg +
++$revise +
+$end_page +ENDPAGE + return; } +###################################################################### +###################################################################### + +=pod + +=item &output_date_error() + +Output a full html page with an error message. + +Inputs: + + $r, the request pointer. + $message, the error message for the user. + $closebutton, the specialized close button needed for groupsearch. + +=cut + +###################################################################### +###################################################################### sub output_date_error { - my ($r,$message)=@_; + my ($r,$message,$closebutton,$hidden_fields)=@_; # make query information persistent to allow for subsequent revision - my $persistent=''; - map { - if (/^form\./ && !/submit/) { - my $name=$_; - my $key=$name; - $name=~s/^form\.//; - $persistent.=<$message
- - +$end_page RESULTS } -sub make_persistent { - $ENV{"form.$field"}=~s/\"/\\\"/g; +###################################################################### +###################################################################### + +=pod + +=item &start_fresh_session() + +Cleans the global %groupsearch_db by removing all fields which begin with +'pre_' or 'store'. + +=cut + +###################################################################### +###################################################################### +sub start_fresh_session { + delete $groupsearch_db{'mode_catalog'}; + foreach (keys %groupsearch_db) { + if ($_ =~ /^pre_/) { + delete $groupsearch_db{$_}; + } + if ($_ =~ /^store/) { + delete $groupsearch_db{$_}; + } + } } + 1; + +sub cleanup { + if (tied(%groupsearch_db)) { + unless (untie(%groupsearch_db)) { + &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db'); + } + } + &untiehash(); + &Apache::lonmysql::disconnect_from_db(); + return OK; +} + __END__ + +=pod + +=back + +=cut