--- loncom/interface/lonsearchcat.pm 2006/04/07 21:56:01 1.261
+++ loncom/interface/lonsearchcat.pm 2006/09/26 15:24:18 1.276
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Search Catalog
#
-# $Id: lonsearchcat.pm,v 1.261 2006/04/07 21:56:01 albertel Exp $
+# $Id: lonsearchcat.pm,v 1.276 2006/09/26 15:24:18 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -78,6 +78,8 @@ use HTML::Entities();
use Parse::RecDescent;
use Apache::lonnavmaps;
use Apache::lonindexer();
+use lib '/home/httpd/lib/perl/';
+use LONCAPA;
######################################################################
######################################################################
@@ -137,7 +139,7 @@ sub handler {
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
['catalogmode','launch','acts','mode','form','element','pause',
'phase','persistent_db_id','table','start','show',
- 'cleargroupsort','titleelement']);
+ 'cleargroupsort','titleelement','area']);
##
## 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
@@ -153,7 +155,7 @@ sub handler {
##
my $domain = $r->dir_config('lonDefDomain');
$diropendb= "/home/httpd/perl/tmp/".
- "$env{'user.domain'}_$env{'user.name'}_searchcat.db";
+ "$env{'user.domain'}_$env{'user.name'}_sel_res.db";
#
# set the name of the persistent database
# $env{'form.persistent_db_id'} can only have digits in it.
@@ -164,8 +166,8 @@ sub handler {
}
my $persistent_db_file = "/home/httpd/perl/tmp/".
- &Apache::lonnet::escape($domain).
- '_'.&Apache::lonnet::escape($env{'user.name'}).
+ &escape($domain).
+ '_'.&escape($env{'user.name'}).
'_'.$env{'form.persistent_db_id'}.'_persistent_search.db';
##
&Apache::lonhtmlcommon::clear_breadcrumbs();
@@ -213,7 +215,7 @@ sub handler {
untie %groupsearch_db if (tied(%groupsearch_db));
if (($env{'form.cleargroupsort'} eq '1') ||
(($env{'form.launch'} eq '1') &&
- ($env{'form.catalogmode'} eq 'groupsearch'))) {
+ ($env{'form.catalogmode'} eq 'import'))) {
if (tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT(),0640)) {
&start_fresh_session();
untie %groupsearch_db;
@@ -247,6 +249,9 @@ sub handler {
if (exists($env{'form.mode'})) {
$hidden_fields .= &hidden_field('mode');
}
+ if (exists($env{'form.area'})) {
+ $hidden_fields .= &hidden_field('area');
+ }
##
## Configure dynamic components of interface
##
@@ -258,7 +263,7 @@ sub handler {
$closebutton .="onClick='self.close()'";
}
$closebutton .=">\n";
- } elsif ($env{'form.catalogmode'} eq 'groupsearch') {
+ } elsif ($env{'form.catalogmode'} eq 'import') {
$closebutton=" symb());
+ $url .= &escape($resource->symb());
my $title = $resource->compTitle();
$r->print(''.
($title?$title:$url).' - '.$disctype.' ');
@@ -587,7 +593,7 @@ sub checkonthis {
my ($extension)=($url=~/\.(\w+)$/);
if (&Apache::loncommon::fileembstyle($extension) eq 'ssi' &&
($url) && ($fulltext)) {
- $result.=&Apache::lonnet::ssi_body($url.'?symb='.&Apache::lonnet::escape($symb));
+ $result.=&Apache::lonnet::ssi_body($url.'?symb='.&escape($symb));
}
$result=~s/\s+/ /gs;
my $applies = 0;
@@ -603,7 +609,7 @@ sub checkonthis {
$href=&Apache::lonenc::encrypted($href)
.'?symb='.&Apache::lonenc::encrypted($symb);
} else {
- $href.='?symb='.&Apache::lonnet::escape($symb);
+ $href.='?symb='.&escape($symb);
}
$r->print(''.($title?$title:$url).
' ');
@@ -658,76 +664,18 @@ Prints the form for the basic search. S
######################################################################
sub print_basic_search_form {
my ($r,$closebutton,$hidden_fields) = @_;
- my $result = ($env{'form.catalogmode'} ne 'groupsearch');
+ my $result = ($env{'form.catalogmode'} ne 'import');
my $bread_crumb =
- &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching','Search_Basic',
- undef,undef,
- $env{'form.catalogmode'} ne 'groupsearch');
+ &Apache::lonhtmlcommon::breadcrumbs('Searching','Search_Basic',
+ $env{'form.catalogmode'} ne 'import');
my $scrout = &Apache::loncommon::start_page('Search').$bread_crumb;
+# Search form for resource space
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'},'related')).' ';
- my $onlysearchdomain=''.
- &mt('[_1] only search domain [_2]',
- &Apache::lonhtmlcommon::checkbox('domains',
- $env{'form.domains'},
- $r->dir_config('lonDefDomain')
- ),
- $r->dir_config('lonDefDomain')
- ).' ';
- my $inclext= ''.
- &mt('[_1] include external resources',
- &Apache::lonhtmlcommon::checkbox
- ('inclext',$env{'form.inclext'})).' ';
- my $adv_search_link =
- ''.&mt('Advanced Search').' ';
- #
- $scrout.='
';
+ $scrout .= &setup_basic_search($r,'res',$hidden_fields,$closebutton);
+ $scrout .= ' ';
}
+# Search form for accessible portfolio files
+ $scrout.= &setup_basic_search($r,'portfolio',$hidden_fields,$closebutton);
if ($env{'request.course.id'}) {
my %lt=&Apache::lonlocal::texthash('srch' => 'Search',
'header' => 'Course Search',
@@ -778,6 +726,75 @@ ENDENDCOURSE
$r->print($scrout);
return;
}
+
+sub setup_basic_search {
+ my ($r,$area,$hidden_fields,$closebutton) = @_;
+ # Define interface components
+ my %lt = &Apache::lonlocal::texthash (
+ res => 'LON-CAPA Catalog Search',
+ portfolio => 'Portfolio Search',
+ );
+ my ($userelatedwords,$onlysearchdomain,$inclext,$adv_search_link,$scrout);
+ $userelatedwords = ''.&mt('[_1] use related words',
+ &Apache::lonhtmlcommon::checkbox('related',$env{'form.related'},'related')).
+ ' ';
+ $onlysearchdomain = ''.&mt('[_1] only search domain [_2]',
+ &Apache::lonhtmlcommon::checkbox('domains',$env{'form.domains'},
+ $r->dir_config('lonDefDomain'))).
+ ' ';
+ if ($area eq 'res') {
+ $inclext= ''.&mt('[_1] include external resources',
+ &Apache::lonhtmlcommon::checkbox('inclext',$env{'form.inclext'})).
+ ' ';
+ }
+ $adv_search_link = ''.&mt('Advanced Search').' ';
+ #
+ $scrout.='';
+ return $scrout;
+}
+
######################################################################
######################################################################
@@ -794,10 +811,8 @@ Prints the advanced search form.
sub print_advanced_search_form{
my ($r,$closebutton,$hidden_fields) = @_;
my $bread_crumb =
- &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching',
- 'Search_Advanced',
- undef,undef,
- $env{'form.catalogmode'} ne 'groupsearch');
+ &Apache::lonhtmlcommon::breadcrumbs('Searching','Search_Advanced',
+ $env{'form.catalogmode'} ne 'import');
my %lt=&Apache::lonlocal::texthash('srch' => 'Search',
'reset' => 'Reset',
'help' => 'Help');
@@ -874,20 +889,26 @@ ENDHEADER
&titlefield(&mt('Domains')).''.
&Apache::loncommon::domain_select('domains',
$env{'form.domains'},1).
- ''.
- &mt('[_1] include external resources',
- &Apache::lonhtmlcommon::checkbox
- ('inclext',$env{'form.inclext'})).' '.$/;
+ '';
+ if ($env{'form.area'} ne 'portfolio') {
+ $scrout .= &mt('[_1] include external resources',
+ &Apache::lonhtmlcommon::checkbox
+ ('inclext',$env{'form.inclext'})).' '
+ }
+ $scrout .= ''.$/;
#
# Misc metadata
- $scrout.=''.
- &titlefield(&mt('Copyright/Distribution')).' '.
- &Apache::lonmeta::selectbox('copyright',
- $env{'form.copyright'},
- \&Apache::loncommon::copyrightdescription,
- ( undef,
- &Apache::loncommon::copyrightids)
- ).' '.$/;
+ if ($env{'form.area'} ne 'portfolio') {
+ $scrout.=''.
+ &titlefield(&mt('Copyright/Distribution')).
+ ' '.
+ &Apache::lonmeta::selectbox('copyright',
+ $env{'form.copyright'},
+ \&Apache::loncommon::copyrightdescription,
+ ( undef,
+ &Apache::loncommon::copyrightids)
+ ).' '.$/;
+ }
$scrout.=''.
&titlefield(&mt('Language')).' '.
&Apache::lonmeta::selectbox('language',
@@ -895,62 +916,94 @@ ENDHEADER
\&Apache::loncommon::languagedescription,
('any',&Apache::loncommon::languageids)
).' ';
- $scrout .= "\n";
- #
- # Dynamic metadata
- $scrout .= ''.&mt('Problem Statistics').' ';
- $scrout .= "\n";
- $scrout .= ' '.&mt('Minimum').' '.
- ''.&mt('Maximum').' '."\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 .= ''.
- &titlefield(&mt($statistic->{'description'})).
- ' '.
- ' '.
- ' '.
- ' '.
- ' '.$/;
- }
$scrout .= "
\n";
- $scrout .= ''.&mt('Evaluation Data').' ';
- $scrout .= "\n";
- $scrout .= ' '.&mt('Minimum').' '.
- ''.&mt('Maximum').' '."\n";
- foreach my $evaluation
- ( { name => 'clear',
- description => 'Material presented in clear way'},
- { name =>'depth',
- description => 'Material covered with sufficient depth'},
- { name => 'helpful',
- description => 'Material is helpful'},
- { name => 'correct',
- description => 'Material appears to be correct'},
- { name => 'technical',
- description => 'Resource is technically correct'}){
- $scrout .= ''.
- &titlefield(&mt($evaluation->{'description'})).
- ' '.
- ' '.
- ' '.
- ' '.
- ' '.$/;
+
+
+ if ($env{'form.area'} eq 'portfolio') {
+ # Added fields
+ $scrout .= ''.&mt('Custom Metadata fields').' ';
+ $scrout .= "';
+ } else {
+ #
+ # Dynamic metadata
+ $scrout .= ''.&mt('Problem Statistics').' ';
+ $scrout .= "\n";
+ $scrout .= ' '.
+ &mt('Minimum').' '.''.
+ &mt('Maximum').' '."\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 .= ''.
+ &titlefield(&mt($statistic->{'description'})).
+ ' '.
+ ' '.
+ ' '.$/;
+ }
+ $scrout .= "
\n";
+ $scrout .= ''.&mt('Evaluation Data').' ';
+ $scrout .= "\n";
}
- $scrout .= "
\n";
#
# Creation/Modification date limits
$scrout .= ''.&mt('Creation and Modification dates').' ';
@@ -1152,7 +1205,7 @@ sub get_persistent_form_data {
# End kludge (hopefully)
next if (exists($env{$name}));
my @values = map {
- &Apache::lonnet::unescape($_);
+ &unescape($_);
} split(',',$persistent_db{$name});
next if (@values <1);
if ($arrays_allowed{$name}) {
@@ -1198,7 +1251,7 @@ sub get_persistent_data {
next;
}
my @values = map {
- &Apache::lonnet::unescape($_);
+ &unescape($_);
} split(',',$persistent_db{$name});
if (@values <= 1) {
push @Values,$values[0];
@@ -1235,7 +1288,7 @@ sub make_persistent {
foreach my $name (keys(%save)) {
my @values = (ref($save{$name}) ? @{$save{$name}} : ($save{$name}));
# We handle array references, but not recursively.
- my $store = join(',', map { &Apache::lonnet::escape($_); } @values );
+ my $store = join(',', map { &escape($_); } @values );
$persistent_db{$name} = $store;
}
untie(%persistent_db);
@@ -1318,7 +1371,7 @@ sub parse_advanced_search {
foreach ('mode','form','element') {
# is this required? Hmmm.
next if (! exists($env{'form.'.$_}));
- $env{'form.'.$_}=&Apache::lonnet::unescape($env{'form.'.$_});
+ $env{'form.'.$_}=&unescape($env{'form.'.$_});
$env{'form.'.$_}=~s/[^\w\/\s\(\)\=\-\"\']//g;
}
# Preprocess the category form element.
@@ -1432,29 +1485,40 @@ sub parse_advanced_search {
&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.' ';
+ if ($env{'form.area'} eq 'portfolio') {
+ #
+ # Added metadata fields
+ for (my $i=0; $i<$env{'form.numaddedfields'} ; $i++) {
+ if (($env{'form.addedfield_'.$i} ne '') &&
+ ($env{'form.addedvalue_'.$i} ne '')) {
+ my $stuff = 1; #FIXME
+ }
+ }
+ } else {
+ #
+ # 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.' ';
+ }
}
}
#
@@ -1543,12 +1607,12 @@ sub parse_domain_restrictions {
$domain_hash{$_}++;
}
if ($domain_hash{'any'}) {
- $pretty_domains_string = "In all LON-CAPA domains.";
+ $pretty_domains_string = &mt("in all LON-CAPA domains.");
} else {
if (@allowed_domains > 1) {
- $pretty_domains_string = "In LON-CAPA domains:";
+ $pretty_domains_string = &mt("in LON-CAPA domains:");
} else {
- $pretty_domains_string = "In LON-CAPA domain ";
+ $pretty_domains_string = &mt("in LON-CAPA domain ");
}
foreach (sort @allowed_domains) {
$pretty_domains_string .= "".$_." ";
@@ -1586,7 +1650,7 @@ sub parse_basic_search {
foreach ('mode','form','element') {
# is this required? Hmmm.
next unless (exists($env{"form.$_"}));
- $env{"form.$_"}=&Apache::lonnet::unescape($env{"form.$_"});
+ $env{"form.$_"}=&unescape($env{"form.$_"});
$env{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
}
my ($libraries_to_query,$pretty_domains_string) = &parse_domain_restrictions();
@@ -1599,10 +1663,13 @@ sub parse_basic_search {
}
my $pretty_search_string=$search_string;
my @Queries;
- my $searchfield = 'concat_ws(" ",'.join(',',
- ('title','author','subject',
- 'notes','abstract','keywords')
- ).')';
+ my @fields = ('title','author','subject','notes','abstract','keywords');
+ my $searchfield;
+ if ($env{'form.area'} eq 'portfolio') {
+ $searchfield = 'concat_ws(" ",pm.'.join(',pm.',@fields).')';
+ } else {
+ $searchfield = 'concat_ws(" ",'.join(',',@fields).')';
+ }
my ($error,$SQLQuery) = &process_phrase_input($search_string,
$env{'form.related'},
$searchfield);
@@ -1615,14 +1682,22 @@ sub parse_basic_search {
#foreach my $q (@Queries) {
# &Apache::lonnet::logthis(' '.$q);
#}
- my $final_query = 'SELECT * FROM metadata WHERE '.join(" AND ",@Queries);
+ my $final_query;
+ if ($env{'form.area'} eq 'portfolio') {
+ $final_query = 'SELECT pm.*,pa.keynum,pa.scope FROM portfolio_metadata pm, portfolio_access pa WHERE (pm.url = pa.url AND (pa.start < NOW() AND (pa.end IS NULL OR pa.end > NOW())) AND '.join(" AND ",@Queries).')';
+ } else {
+ $final_query = 'SELECT * FROM metadata WHERE '.join(" AND ",@Queries);
+ }
#
+ if ($env{'form.related'}) {
+ $pretty_search_string.=' '.&mt('(including related words)');
+ }
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);
+ &Apache::lonnet::logthis('simple search final query = '.$/.$final_query);
return ($final_query,$pretty_search_string,
$libraries_to_query);
}
@@ -2107,17 +2182,17 @@ sub print_sort_form {
END
my $start_page = &Apache::loncommon::start_page('Results',$js,
- {'only_body' => 1});
+ {'no_title' => 1});
my $breadcrumbs=
- &Apache::lonhtmlcommon::breadcrumbs
- (undef,'Searching','Searching',undef,undef,
- $env{'form.catalogmode'} ne 'groupsearch');
+ &Apache::lonhtmlcommon::breadcrumbs('Searching','Searching',
+ $env{'form.catalogmode'} ne 'import');
my $result = <
-
+
END
@@ -2176,7 +2251,7 @@ my @Fullindicies;
Creates the table of search results by calling lonmysql. Stores the
table id in $env{'form.table'}
-Inputs: none.
+Inputs: search area - either res or portfolio
Returns: the identifier of the table on success, undef on error.
@@ -2185,8 +2260,9 @@ Returns: the identifier of the table on
######################################################################
######################################################################
sub set_up_table_structure {
+ my ($tabletype) = @_;
my ($datatypes,$fullindicies) =
- &LONCAPA::lonmetadata::describe_metadata_storage();
+ &LONCAPA::lonmetadata::describe_metadata_storage($tabletype);
# Copy the table description before modifying it...
@Datatypes = @{$datatypes};
unshift(@Datatypes,{name => 'id',
@@ -2199,7 +2275,12 @@ sub set_up_table_structure {
}
sub create_results_table {
- &set_up_table_structure();
+ my ($area) = @_;
+ if ($area eq 'portfolio') {
+ &set_up_table_structure('portfolio_search');
+ } else {
+ &set_up_table_structure('metadata');
+ }
my $table = &Apache::lonmysql::create_table
( { columns => \@Datatypes,
FULLTEXT => [{'columns' => \@Fullindicies},],
@@ -2331,22 +2412,26 @@ results into MySQL.
######################################################################
######################################################################
sub run_search {
- my ($r,$query,$customquery,$customshow,$serverlist,$pretty_string) = @_;
-
+ my ($r,$query,$customquery,$customshow,$serverlist,
+ $pretty_string,$area) = @_;
+ my $tabletype = 'metadata';
+ if ($area eq 'portfolio') {
+ $tabletype = 'portfolio_search';
+ }
my $connection = $r->connection;
#
# Print run_search header
#
my $start_page = &Apache::loncommon::start_page('Search Status',undef,
- {'only_body' => 1});
- my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs
- (undef,'Searching','Searching',undef,undef,
- $env{'form.catalogmode'} ne 'groupsearch');
+ {'no_title' => 1});
+ my $breadcrumbs =
+ &Apache::lonhtmlcommon::breadcrumbs('Searching','Searching',
+ $env{'form.catalogmode'} ne 'import');
$r->print(<
-
+
END
# Remove leading and trailing
$pretty_string =~ s:^\s* ::i;
@@ -2407,6 +2492,7 @@ END
##
## Prepare for the big loop.
my $hitcountsum;
+ my %matches;
my $server;
my $status;
my $revise = &revise_button();
@@ -2461,7 +2547,7 @@ END
delete ($Server_status{$server});
next;
}
- $status=~s|/||g;
+ $status=~s|/||g;
my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$status;
if (-e $datafile && ! -e "$datafile.end") {
&update_status($r,&mt('Receiving results from [_1]',$server));
@@ -2490,7 +2576,7 @@ END
next if (! $result);
#
# Parse the result.
- my %Fields = &parse_raw_result($result,$server);
+ my %Fields = &parse_raw_result($result,$server,$tabletype);
$Fields{'hostname'} = $server;
#
# Skip if external and we did not want that
@@ -2498,6 +2584,12 @@ END
# Skip based on copyright
next if (! ©right_check(\%Fields));
+ if ($area eq 'portfolio') {
+ next if (defined($matches{$Fields{'url'}}));
+ # Skip if inaccessible
+ next if (!&Apache::lonnet::portfolio_access($Fields{'url'}));
+ $matches{$Fields{'url'}} = 1;
+ }
#
# Store the result in the mysql database
my $result = &Apache::lonmysql::store_row($table,\%Fields);
@@ -2531,7 +2623,7 @@ END
# results to get, so let the client know the top frame needs to be
# loaded from /adm/searchcat
$r->print(&Apache::loncommon::end_page());
-# if ($env{'form.catalogmode'} ne 'groupsearch') {
+# if ($env{'form.catalogmode'} ne 'import') {
$r->print("
SCRIPT
@@ -3090,25 +3205,12 @@ SCRIPT
{'only_body' =>1});
my $result=<
-
+