--- loncom/interface/lonsearchcat.pm 2001/03/21 01:19:37 1.49
+++ loncom/interface/lonsearchcat.pm 2006/05/30 12:46:09 1.265
@@ -1,762 +1,3723 @@
-# 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
-#
-# Functions
-#
-# 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
+# $Id: lonsearchcat.pm,v 1.265 2006/05/30 12:46:09 www Exp $
+#
+# Copyright Michigan State University Board of Trustees
+#
+# 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();
+use lib '/home/httpd/lib/perl/';
+use LONCAPA;
+
+######################################################################
+######################################################################
+##
+## 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 $viewselect=<
-
-
-
-END
-
+######################################################################
+######################################################################
sub handler {
my $r = shift;
-
-# -------------------------------------- see if called from an interactive mode
- map {
- my ($name, $value) = split(/=/,$_);
- $value =~ tr/+/ /;
- $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
- if ($name eq 'catalogmode') {
- $ENV{'form.'.$name}=$value;
- }
- } (split(/&/,$ENV{'QUERY_STRING'}));
-
- $r->content_type('text/html');
+# &set_defaults();
+ #
+ # set form defaults
+ #
+ my $hidden_fields;# Hold all the hidden fields used to keep track
+ # of the search system state
+ my $importbutton; # button to take the selected results and go to group
+ # sorting
+ my $diropendb; # The full path to the (temporary) search database file.
+ # This is set and used in &handler() and is also used in
+ # &output_results().
+
+ my $loaderror=&Apache::lonnet::overloaderror($r);
+ if ($loaderror) { return $loaderror; }
+ #
+ my $closebutton; # button that closes the search window
+ # This button is different for the RAT compared to
+ # normal invocation.
+ #
+ &Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
return OK if $r->header_only;
+ ##
+ ## Prevent caching of the search interface window. Hopefully this means
+ ## we will get the launch=1 passed in a little more.
+ &Apache::loncommon::no_cache($r);
+ ##
+ ## Pick up form fields passed in the links.
+ ##
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
+ ['catalogmode','launch','acts','mode','form','element','pause',
+ 'phase','persistent_db_id','table','start','show',
+ 'cleargroupsort','titleelement']);
+ ##
+ ## The following is a trick - we wait a few seconds if asked to so
+ ## the daemon running the search can get ahead of the daemon
+ ## printing the results. We only need (theoretically) to do
+ ## this once, so the pause indicator is deleted
+ ##
+ if (exists($env{'form.pause'})) {
+ sleep(1);
+ delete($env{'form.pause'});
+ }
+ ##
+ ## Initialize global variables
+ ##
+ my $domain = $r->dir_config('lonDefDomain');
+ $diropendb= "/home/httpd/perl/tmp/".
+ "$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.
+ if (! exists($env{'form.persistent_db_id'}) ||
+ ($env{'form.persistent_db_id'} =~ /\D/) ||
+ ($env{'form.launch'} eq '1')) {
+ $env{'form.persistent_db_id'} = time;
+ }
- %metadatafields=();
-
- my $hidden='';
- $hidden=<
-END
-
- $closebutton=<
+ my $persistent_db_file = "/home/httpd/perl/tmp/".
+ &escape($domain).
+ '_'.&escape($env{'user.name'}).
+ '_'.$env{'form.persistent_db_id'}.'_persistent_search.db';
+ ##
+ &Apache::lonhtmlcommon::clear_breadcrumbs();
+ 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",
+ target=>'_top',
+ 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",
+ target=>'_top',
+ bug=>'Searching',});
+ }
+ #
+ if ($env{'form.phase'} !~ m/(basic|adv|course)_search/) {
+ if (! &get_persistent_form_data($persistent_db_file)) {
+ if ($env{'form.phase'} =~ /(run_search|results)/) {
+ &Apache::lonnet::logthis('lonsearchcat:'.
+ 'Unable to recover data from '.
+ $persistent_db_file);
+ my $msg =
+ 'We were unable to retrieve data describing your search. '.
+ 'This is a serious error and has been logged. '.
+ 'Please alert your LON-CAPA administrator.';
+ &Apache::loncommon::simple_error_page($r,'Search Error',
+ $msg);
+ return OK;
+ }
+ }
+ } else {
+ &clean_up_environment();
+ }
+ ##
+ ## Clear out old values from groupsearch database
+ ##
+ untie %groupsearch_db if (tied(%groupsearch_db));
+ 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.
+ my $msg = 'Unable to tie hash to db file.';
+ &Apache::loncommon::simple_error_page($r,'Search Error',
+ $msg);
+ return OK;
+ }
+ }
+ ##
+ ## Configure hidden fields
+ ##
+ $hidden_fields = ''."\n";
+ if (exists($env{'form.catalogmode'})) {
+ $hidden_fields .= &hidden_field('catalogmode');
+ }
+ if (exists($env{'form.form'})) {
+ $hidden_fields .= &hidden_field('form');
+ }
+ if (exists($env{'form.element'})) {
+ $hidden_fields .= &hidden_field('element');
+ }
+ if (exists($env{'form.titleelement'})) {
+ $hidden_fields .= &hidden_field('titleelement');
+ }
+ if (exists($env{'form.mode'})) {
+ $hidden_fields .= &hidden_field('mode');
+ }
+ ##
+ ## Configure dynamic components of interface
+ ##
+ if ($env{'form.catalogmode'} eq 'interactive') {
+ $closebutton="
END
-
-# ------------------------------------------------ First, check out environment
- $metadatafields{'owner'}=$ENV{'user.name'}.'@'.$ENV{'user.domain'};
-
-# --------------------------------- Compute various listings of metadata values
-
- %language=();
- $language{'any'}='Any language';
- {
- my $fh=Apache::File->new($r->dir_config('lonTabDir').'/language.tab');
- map {
- $_=~/(\w+)\s+([\w\s\-]+)/;
- $language{$1}=$2;
- } <$fh>;
+ } else {
+ $closebutton = '';
+ $importbutton = '';
+ }
+ ##
+ ## Sanity checks on form elements
+ ##
+ if (!defined($env{'form.viewselect'})) {
+ $env{'form.viewselect'} ="summary";
+ }
+ $env{'form.phase'} = 'disp_basic' if (! exists($env{'form.phase'}));
+ $env{'form.show'} = 20 if (! exists($env{'form.show'}));
+ #
+ $env{'form.searchmode'} = 'basic' if (! exists($env{'form.searchmode'}));
+ 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
+ ##
+ if ($env{'form.phase'} eq 'disp_basic') {
+ &print_basic_search_form($r,$closebutton,$hidden_fields);
+ } elsif ($env{'form.phase'} eq 'disp_adv') {
+ &print_advanced_search_form($r,$closebutton,$hidden_fields);
+ } elsif ($env{'form.phase'} eq 'results') {
+ &display_results($r,$importbutton,$closebutton,$diropendb);
+ } elsif ($env{'form.phase'} =~ /^(sort|run_search)$/) {
+ my ($query,$customquery,$customshow,$libraries,$pretty_string) =
+ &get_persistent_data($persistent_db_file,
+ ['query','customquery','customshow',
+ 'libraries','pretty_string']);
+ if ($env{'form.phase'} eq 'sort') {
+ &print_sort_form($r,$pretty_string);
+ } elsif ($env{'form.phase'} eq 'run_search') {
+ &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')) {
+ #
+ # We are running a search, try to parse it
+ my ($query,$customquery,$customshow,$libraries) =
+ (undef,undef,undef,undef);
+ my $pretty_string;
+ if ($env{'form.phase'} eq 'basic_search') {
+ ($query,$pretty_string,$libraries) =
+ &parse_basic_search($r,$closebutton,$hidden_fields);
+ return OK if (! defined($query));
+ &make_persistent({ basicexp => $env{'form.basicexp'}},
+ $persistent_db_file);
+ } else { # Advanced search
+ ($query,$customquery,$customshow,$libraries,$pretty_string)
+ = &parse_advanced_search($r,$closebutton,$hidden_fields);
+ return OK if (! defined($query));
+ }
+ &make_persistent({ query => $query,
+ customquery => $customquery,
+ customshow => $customshow,
+ libraries => $libraries,
+ pretty_string => $pretty_string },
+ $persistent_db_file);
+ #
+ # 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);
+
+ my $msg =
+ 'Unable to create table in which to store search results. '.
+ 'The search has been aborted.';
+ &Apache::loncommon::simple_error_page($r,'Search Error',
+ $msg);
+ return OK;
+ }
+ delete($env{'form.launch'});
+ if (! &make_form_data_persistent($r,$persistent_db_file)) {
+ my $msg=
+ 'Unable to properly store search information. '.
+ 'The search has been aborted.';
+ &Apache::loncommon::simple_error_page($r,'Search Error',
+ $msg);
+ return OK;
+ }
+ ##
+ ## Print out the frames interface
+ ##
+ if (defined($query)) {
+ &print_frames_interface($r);
+ }
}
+ return OK;
+}
- %cprtag=();
- $cprtag{'any'}='Any copyright/distribution';
- {
- my $fh=Apache::File->new($r->dir_config('lonIncludes').'/copyright.tab');
- map {
- $_=~/(\w+)\s+([\w\s\-]+)/;
- $cprtag{$1}=$2;
- } <$fh>;
+#
+# The mechanism used to store values away and retrieve them does not
+# handle the case of missing environment variables being significant.
+#
+# This routine sets non existant checkbox form elements to ''.
+#
+sub clean_up_environment {
+ if ($env{'form.phase'} eq 'basic_search') {
+ if (! exists($env{'form.related'})) {
+ $env{'form.related'} = '';
+ }
+ if (! exists($env{'form.domains'})) {
+ $env{'form.domains'} = '';
+ }
+ } elsif ($env{'form.phase'} eq 'adv_search') {
+ foreach my $field ('title','keywords','notes',
+ 'abstract','standards','mime') {
+ if (! exists($env{'form.'.$field.'_related'})) {
+ $env{'form.'.$field.'_related'} = '';
+ }
+ }
+ } elsif ($env{'form.phase'} eq 'course_search') {
+ if (! exists($env{'form.crsrelated'})) {
+ $env{'form.crsrelated'} = '';
+ }
}
+}
- %mimetag=();
- $mimetag{'any'}='Any type';
- {
- my $fh=Apache::File->new($r->dir_config('lonTabDir').'/filetypes.tab');
- map {
- $_=~/(\w+)\s+(\w+)\s+([\w\s\-]+)/;
- $mimetag{$1}=".$1 $3";
- } <$fh>;
+sub hidden_field {
+ my ($name,$value) = @_;
+ if (! defined($value)) {
+ $value = $env{'form.'.$name};
}
+ return ''.$/;
+}
+
+######################################################################
+######################################################################
+##
+## Course Search
+##
+######################################################################
+######################################################################
+{ # Scope the course search to avoid global variables
+#
+# Variables For course search
+my %alreadyseen;
+my %hash;
+my $totalfound;
+
+sub make_symb {
+ my ($id)=@_;
+ my ($mapid,$resid)=split(/\./,$id);
+ my $map=$hash{'map_id_'.$mapid};
+ my $res=$hash{'src_'.$id};
+ my $symb=&Apache::lonnet::encode_symb($map,$resid,$res);
+ return $symb;
+}
- if ($ENV{'form.basicsubmit'} eq 'SEARCH') {
- return &basicsearch($r,\%ENV);
+sub course_search {
+ my $r=shift;
+ my $pretty_search_string = ''.$env{'form.courseexp'}.'';
+ my $search_string = $env{'form.courseexp'};
+ my @New_Words;
+ undef(%alreadyseen);
+ if ($env{'form.crsrelated'}) {
+ ($search_string,@New_Words) = &related_version($env{'form.courseexp'});
+ if (@New_Words) {
+ $pretty_search_string .= ' '.&mt("with related words").": @New_Words.";
+ } else {
+ $pretty_search_string .= ' '.&mt('with no related words').".";
+ }
}
- elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {
- return &advancedsearch($r,\%ENV);
+ my $fulltext=$env{'form.crsfulltext'};
+ my $discuss=$env{'form.crsdiscuss'};
+ my @allwords=($search_string,@New_Words);
+ $totalfound=0;
+ $r->print(&Apache::loncommon::start_page('Course Search').
+ '
'.
+ $pretty_search_string.'
'.
+ ''.&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('No matches found in resources').'.
');
}
- $scrout=''; # building a part of screen output
- $scrout.=&searchphrasefield('Limit by title','title',
- $ENV{'form.title'});
+# Check discussions if requested
+ if ($discuss) {
+ my $totaldiscussions = 0;
+ $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 .= &escape($resource->symb());
+ my $title = $resource->compTitle();
+ $r->print(' '.
+ ($title?$title:$url).' - '.$disctype.' ');
+ $totaldiscussions++;
+ } else {
+ $r->print(' .');
+ }
+ }
+ unless ($totaldiscussions) {
+ $r->print('
'.&mt('No matches found in postings').'.
');
+ }
+ }
+
+# =================================================== Done going through course
+ $r->print(&Apache::loncommon::end_page());
+}
- $scrout.=&searchphrasefield('Limit by author','author',
- $ENV{'form.author'});
+# =============================== This pulls up a resource and its dependencies
- $scrout.=&searchphrasefield('Limit by subject','subject',
- $ENV{'form.subject'});
+sub checkonthis {
+ my ($r,$id,$url,$level,$title,$fulltext,$symb,@allwords)=@_;
+ $alreadyseen{$id}=1;
+ if (&Apache::loncommon::connection_aborted($r)) { return; }
+ $r->rflush();
+
+ my $result=$title.' ';
+ if ($env{'request.role.adv'} || !$hash{'encrypted_'.$id}) {
+ $result.=&Apache::lonnet::metadata($url,'title').' '.
+ &Apache::lonnet::metadata($url,'subject').' '.
+ &Apache::lonnet::metadata($url,'abstract').' '.
+ &Apache::lonnet::metadata($url,'keywords');
+ }
+ my ($extension)=($url=~/\.(\w+)$/);
+ if (&Apache::loncommon::fileembstyle($extension) eq 'ssi' &&
+ ($url) && ($fulltext)) {
+ $result.=&Apache::lonnet::ssi_body($url.'?symb='.&escape($symb));
+ }
+ $result=~s/\s+/ /gs;
+ my $applies = 0;
+ $applies = &checkwords($result,$applies,@allwords);
+# Does this resource apply?
+ if ($applies) {
+ $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='.&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('Searching','Search_Basic',
+ $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.=(<
+
+
+ENDENDCOURSE
+ }
+ $scrout .= &Apache::loncommon::end_page();
+ $r->print($scrout);
+ return;
+}
+######################################################################
+######################################################################
- $scrout.=&selectbox('Limit by language','language',
- $ENV{'form.language'},%language);
-
+=pod
-# ------------------------------------------------ Compute date selection boxes
- $scrout.=<
-LIMIT BY CREATION DATE RANGE:
-
-
-between:
-CREATIONDATESTART
- $scrout.=&dateboxes('creationdatestart',1,1,1976,
- $ENV{'form.creationdatestart_month'},
- $ENV{'form.creationdatestart_day'},
- $ENV{'form.creationdatestart_year'},
- );
- $scrout.=<";
+=item &advanced_search_form()
- $scrout.=<
-LIMIT BY LAST REVISION DATE RANGE:
-
- between:
-LASTREVISIONDATESTART
- $scrout.=&dateboxes('lastrevisiondatestart',1,1,1976,
- $ENV{'form.lastrevisiondatestart_month'},
- $ENV{'form.lastrevisiondatestart_day'},
- $ENV{'form.lastrevisiondatestart_year'},
- );
- $scrout.=<';
-
- $scrout.=&searchphrasefield('Limit by publisher/owner','owner',
- $ENV{'form.owner'});
-# $metadatafields{'owner'});
-
- $ENV{'form.copyright'}='any' unless length($ENV{'form.copyright'});
- $scrout.=&selectbox('Limit by copyright/distribution','copyright',
- $ENV{'form.copyright'},%cprtag);
+Prints the advanced search form.
-# ------------------------------------------- Compute customized metadata field
- $scrout.=<
-LIMIT BY OTHER METADATA FIELDS:
-
-For author-specific metadata, enter in an expression in the form of
-key=value separated by operators such as AND or OR.
-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(<
-
-The LearningOnline Network with CAPA
-
-
-
-
'."\n";
+ foreach my $statistic
+ ({ name=>'count',
+ description=>'Network-wide number of accesses (hits)',},
+ { name=>'stdno',
+ description=>
+ 'Total number of students who have worked on this problem',},
+ { name => 'avetries',
+ description=>'Average number of tries till solved',},
+ { name => 'difficulty',
+ description=>'Degree of difficulty',},
+ { name => 'disc',
+ description=>'Degree of discrimination'}) {
+ $scrout .= '