--- loncom/interface/lonsearchcat.pm 2001/03/22 14:10:12 1.71 +++ loncom/interface/lonsearchcat.pm 2001/04/02 16:57:38 1.92 @@ -3,7 +3,8 @@ # # 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 +# Scott Harrison: 03/20/2001, 03/21/2001, 03/22/2001, 03/26/2001, 03/27/2001 +# Scott Harrison: 04/02/2001 # # Functions # @@ -36,6 +37,21 @@ # 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 +# build_custommetadata_query(field_name, logic_statement) : builds a perl +# regular expression from a logical expression with AND/OR +# keywords +# detailed_citation_view, summary_view, fielded_format_view, xml_sgml_view: +# four different ways to view metadata records. Outputs a HTML-ified string. +# Input arguments are title, author, subject, url, keywords, version, notes, +# short abstract, mime, language, creation date, last revision date, owner, +# copyright, hostname, httphost, and extra custom metadata to show. +# build_date_queries(cmonth1, cday1, cyear1, cmonth2, cday2, cyear2, +# lmonth1, lday1, lyear1, lmonth2, lday2, lyear2) : +# Builds a SQL logic query to check time/date entries. +# output_date_error(server reference, error message) : outputs +# an error message specific to bad date format. +# make_persistent() : makes a set of hidden HTML fields to make +# SQL search interface information to be persistent package Apache::lonsearchcat; @@ -46,12 +62,19 @@ use Apache::File(); use CGI qw(:standard); use Text::Query; +# ---------------------------------------- variables used throughout the module my %language; my $scrout; my %metadatafields; my %cprtag; my %mimetag; my $closebutton; + +# ------ form selection elements that allow for choosing different output views +# Detailed Citation View ---> sub detailed_citationview +# Summary View ---> sub summary_view +# Fielded Format ---> sub fielded_format_view +# XML/SGML ---> sub xml_sgml_view my $basicviewselect=< @@ -69,6 +92,7 @@ my $advancedviewselect=< END +# ----------------------------- Handling routine called via Apache and mod_perl sub handler { my $r = shift; @@ -89,13 +113,14 @@ sub handler { %metadatafields=(); my $hidden=''; - $hidden=< END - - $closebutton=< END + } # ------------------------------------------------ First, check out environment $metadatafields{'owner'}=$ENV{'user.name'}.'@'.$ENV{'user.domain'}; @@ -132,6 +157,7 @@ END } <$fh>; } +# ----------------------------------- See if a search invocation should be done if ($ENV{'form.basicsubmit'} eq 'SEARCH') { return &basicsearch($r,\%ENV); } @@ -139,6 +165,7 @@ END return &advancedsearch($r,\%ENV); } +# ----------------------------- Else, begin building search interface to output $scrout=''; # building a part of screen output $scrout.=&searchphrasefield('Limit by title','title', $ENV{'form.title'}); @@ -229,9 +256,9 @@ LASTREVISIONDATEEND # ------------------------------------------- Compute customized metadata field $scrout.=< -LIMIT BY OTHER METADATA FIELDS: +LIMIT BY SPECIAL METADATA FIELDS: -For author-specific metadata, enter in an expression in the form of +For resource-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
@@ -239,6 +266,17 @@ CUSTOMMETADATA $scrout.=&simpletextfield('custommetadata',$ENV{'form.custommetadata'}); $scrout.=' initial users of this system do not need to worry about this option'; + $scrout.=< +SHOW SPECIAL METADATA FIELDS: + +Enter in a space-separated list of special metadata fields to show +in a fielded listing for each record result. +
+CUSTOMSHOW +$scrout.=&simpletextfield('customshow',$ENV{'form.customshow'}); +$scrout.=' initial users of this system do not need to worry about this option'; + # ---------------------------------------------------------------- Print screen $r->print(< @@ -487,9 +525,11 @@ sub advancedsearch { 'lastrevisiondatestart_year','lastrevisiondateend_month', 'lastrevisiondateend_day','lastrevisiondateend_year', 'notes','abstract','mime','language','owner', - 'custommetadata') { + 'custommetadata','customshow') { $ENV{"form.$field"}=~s/[^\w\s\(\)\=\-\"\']//g; } + + # Check to see if enough information was filled in for my $field ('title','author','subject','keywords','url','version', 'notes','abstract','mime','language','owner', 'custommetadata') { @@ -497,32 +537,34 @@ sub advancedsearch { $fillflag++; } } - unless ($fillflag) { &output_blank_field_error($r); return OK; } + + # Turn the form input into a SQL-based query my $query=''; my @queries; - # Go through logical expression AND/OR/NOT phrase fields. - + # Evaluate 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}); } } + # Evaluate option lists if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') { - push @queries,"(language like \"\%$ENV{'form.language'}\%\")"; + push @queries,"(language like \"$ENV{'form.language'}\")"; } if ($ENV{'form.mime'} and $ENV{'form.mime'} ne 'any') { - push @queries,"(mime like \"\%$ENV{'form.mime'}\%\")"; + push @queries,"(mime like \"$ENV{'form.mime'}\")"; } if ($ENV{'form.copyright'} and $ENV{'form.copyright'} ne 'any') { - push @queries,"(copyright like \"\%$ENV{'form.copyright'}\%\")"; + push @queries,"(copyright like \"$ENV{'form.copyright'}\")"; } + # Evaluate date windows my $datequery=&build_date_queries( $ENV{'form.creationdatestart_month'}, $ENV{'form.creationdatestart_day'}, @@ -537,6 +579,7 @@ sub advancedsearch { $ENV{'form.lastrevisiondateend_day'}, $ENV{'form.lastrevisiondateend_year'}, ); + # Test to see if date windows are legitimate if ($datequery=~/^Incorrect/) { &output_date_error($r,$datequery); return OK; @@ -544,27 +587,50 @@ sub advancedsearch { elsif ($datequery) { push @queries,$datequery; } - my $customquery; + + # Process form information for custom metadata querying + my $customquery=''; if ($ENV{'form.custommetadata'}) { $customquery=&build_custommetadata_query('custommetadata', $ENV{'form.custommetadata'}); } + my $customshow=''; + if ($ENV{'form.customshow'}) { + $customshow=$ENV{'form.customshow'}; + $customshow=~s/[^\w\s]//g; + my @fields=split(/\s+/,$customshow); + $customshow=join(" ",@fields); + } + # Send query statements over the network to be processed by either the SQL + # database or a recursive scheme of 'grep'-like actions (for custom + # metadata). if (@queries) { $query=join(" AND ",@queries); $query="select * from metadata where $query"; - my $reply=&Apache::lonnet::metadata_query($query); + my $reply; # reply hash reference + unless ($customquery or $customshow) { + $reply=&Apache::lonnet::metadata_query($query); + } + else { + $reply=&Apache::lonnet::metadata_query($query, + $customquery,$customshow); + } &output_results('Advanced',$r,$envhash,$customquery,$reply); } - else { - &output_results('Advanced',$r,$envhash,$query); + elsif ($customquery) { + my $reply; # reply hash reference + $reply=&Apache::lonnet::metadata_query('', + $customquery,$customshow); + &output_results('Advanced',$r,$envhash,$customquery,$reply); } - return OK; + # should not get to this point + return 'Error. Should not have gone to this point.'; } # ---------------------------------------------------- see if a field is filled sub filled { my ($field)=@_; - if ($field=~/\S/) { + if ($field=~/\S/ && $field ne 'any') { return 1; } else { @@ -582,18 +648,25 @@ sub basicsearch { $ENV{"form.$field"}=~s/[^\w\s\(\)\-]//g; } + # Check to see if enough is filled in unless (&filled($ENV{'form.basicexp'})) { &output_blank_field_error($r); return OK; } + # Build SQL query string based on form page my $query=''; my $concatarg=join('," ",', ('title', 'author', 'subject', 'notes', 'abstract')); + $query='select * from metadata where concat(' . $concatarg . ') like %' . + $ENV{'form.basicexp'} . '%'; - $query="select * from metadata where concat($concatarg) like '\%$ENV{'form.basicexp'}\%'"; + # Get reply (either a hash reference to filehandles or bad connection) my $reply=&Apache::lonnet::metadata_query($query); + + # Output search results &output_results('Basic',$r,$envhash,$query,$reply); + return OK; } @@ -633,24 +706,85 @@ RESULTS # ----------------------------- format and output results based on a reply list sub output_results { - my ($mode,$r,$envhash,$query,@replylist)=@_; + my ($mode,$r,$envhash,$query,$replyref)=@_; my %ENV=%{$envhash}; + my %rhash=%{$replyref}; my $compiledresult=''; + my $timeremain=30; + $r->print(< + +The LearningOnline Network with CAPA +BEGINNING + $r->print(< + function select_data(title,url) { + changeTitle(title); + changeURL(url); + } + function changeTitle(val) { + if (opener.inf.document.forms.resinfo.elements.t) { + opener.inf.document.forms.resinfo.elements.t.value=val; + } + } + function changeURL(val) { + if (opener.inf.document.forms.resinfo.elements.u) { + opener.inf.document.forms.resinfo.elements.u.value=val; + } + } + +SCRIPT + $r->print(< + + +

Search Catalog

+CATALOGBEGIN + $r->rflush(); + $r->print(< + popwin=open('','popwin','width=400,height=200'); + popwin.document.writeln(''+ + '

Search Results Progress

'+ + '
'+ + '
Server space '+ + '
Status '+ + '
Maximum remaining time '+ + '
'+ + ''); + popwin.document.close(); + +ENDPOP + $r->rflush(); - foreach my $reply (@replylist) { - + my $servernum=(keys %rhash)+0; + $r->print(''); + $r->rflush(); + foreach my $rkey (keys %rhash) { + $r->print(''); + $r->rflush(); + my $reply=$rhash{$rkey}; 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; + $r->print('') if -e $replyfile; + $r->rflush(); + last if -e "$replyfile.end"; + last unless $timeremain; sleep 1; + $timeremain--; + $r->print(''); + $r->rflush(); } # QUESTION: how should I handle this error condition.. # I'm sure there is syntax elsewhere I can use.. @@ -659,7 +793,34 @@ sub output_results { @results=<$fh>; } + my $customshow=''; + my $extrashow=''; + my @customfields; + if ($ENV{'form.customshow'}) { + $customshow=$ENV{'form.customshow'}; + $customshow=~s/[^\w\s]//g; + my @fields=map {"$_:"} + split(/\s+/,$customshow); + @customfields=split(/\s+/,$customshow); + if ($customshow) { + $extrashow="
  • ".join("
  • ",@fields)."
\n"; + } + } + my $customdata=''; + my %customhash; + foreach my $result (@results) { + if ($result=~/^(custom\=.*)$/) { # grab all custom metadata + my $tmp=$result; + $tmp=~s/^custom\=//; + my ($k,$v)=map {&Apache::lonnet::unescape($_); + } split(/\,/,$tmp); + $customhash{$k}=$v; + } + } foreach my $result (@results) { + next if $result=~/^custom\=/; + chomp $result; + next unless $result; my @fields=map {&Apache::lonnet::unescape($_)} (split(/\,/,$result)); @@ -669,10 +830,24 @@ sub output_results { my $shortabstract=$abstract; $shortabstract=substr($abstract,0,200) if length($abstract)>200; $fields[7]=$shortabstract; + my $extrashow2=$extrashow; + if ($extrashow) { + foreach my $field (@customfields) { + my $value=''; + if ($customhash{$url}=~/\<${field}[^\>]*\>(.*?)\<\/${field}[^\>]*\>/s) { + $value=$1; + } + $extrashow2=~s/\<\!\-\- $field \-\-\>/ $value/g; + } + } + + $compiledresult.=< +END $compiledresult.=< END - $compiledresult.=<
@@ -690,17 +865,20 @@ END if ($viewselect eq 'Detailed Citation View') { $compiledresult.=&detailed_citation_view(@fields, - $hostname,$httphost); + $hostname,$httphost, + $extrashow2); } elsif ($viewselect eq 'Summary View') { - $compiledresult.=&summary_view(@fields,$hostname,$httphost); + $compiledresult.=&summary_view(@fields,$hostname,$httphost, + $extrashow2); } elsif ($viewselect eq 'Fielded Format') { $compiledresult.=&fielded_format_view(@fields,$hostname, - $httphost); + $httphost,$extrashow2); } elsif ($viewselect eq 'XML/SGML') { - $compiledresult.=&xml_sgml_view(@fields,$hostname,$httphost); + $compiledresult.=&xml_sgml_view(@fields,$hostname,$httphost, + $extrashow2); } } @@ -712,35 +890,9 @@ END # make query information persistent to allow for subsequent revision my $persistent=&make_persistent(); - $r->print(< - -The LearningOnline Network with CAPA -BEGINNING - $r->print(< - function select_data(title,url) { - changeTitle(title); - changeURL(url); - } - function changeTitle(val) { - if (opener.inf.document.forms.resinfo.elements.t) { - opener.inf.document.forms.resinfo.elements.t.value=val; - } - } - function changeURL(val) { - if (opener.inf.document.forms.resinfo.elements.u) { - opener.inf.document.forms.resinfo.elements.u.value=val; - } - } - -SCRIPT $r->print(< - - -

Search Catalog

+$customdata $closebutton @@ -770,6 +922,7 @@ $compiledresult RESULTS } + $r->print(''); $r->rflush(); } # ------------------------------------------------------------- build_SQL_query @@ -793,7 +946,9 @@ sub build_custommetadata_query { $q->prepare($logic_statement); my $matchexp=${$q}{'-parse'}{'-build'}{'matchstring'}; # quick fix to change literal into xml tag-matching - $matchexp=~s/\(\?\:([^\)]*)\\\=([^\)]*)\)/\(\?\:\\\<$1\\\>\[\^\\\<\]\*$2\[\^\\\<\]\*\\\<\\\/$1\\\>)/g; + # will eventually have to write a separate builder module + my $oldmatchexp=$matchexp; + $matchexp=~s/(\w+)\\\=([\w\\\+]+)/\\\<$1\\\>\[\^\\\<\]\*$2\[\^\\\<\]\*\\\<\\\/$1\\\>/g; return $matchexp; } @@ -831,7 +986,7 @@ sub detailed_citation_view { my ($title,$author,$subject,$url,$keywords,$version, $notes,$shortabstract,$mime,$lang, $creationdate,$lastrevisiondate,$owner,$copyright, - $hostname,$httphost)=@_; + $hostname,$httphost,$extrashow)=@_; my $result=<$owner, last revised $lastrevisiondate

$title

@@ -844,6 +999,9 @@ sub detailed_citation_view { MIME Type: $mimetag{$mime}
Language: $language{$lang}
Copyright/Distribution: $cprtag{$copyright}
+

+$extrashow +

$shortabstract

END @@ -855,12 +1013,13 @@ sub summary_view { my ($title,$author,$subject,$url,$keywords,$version, $notes,$shortabstract,$mime,$lang, $creationdate,$lastrevisiondate,$owner,$copyright, - $hostname,$httphost)=@_; + $hostname,$httphost,$extrashow)=@_; my $result=<$author
$title
$owner -- $lastrevisiondate
$cprtag{$copyright}
+$extrashow

END return $result; @@ -871,7 +1030,7 @@ sub fielded_format_view { my ($title,$author,$subject,$url,$keywords,$version, $notes,$shortabstract,$mime,$lang, $creationdate,$lastrevisiondate,$owner,$copyright, - $hostname,$httphost)=@_; + $hostname,$httphost,$extrashow)=@_; my $result=<URL: $url
@@ -888,6 +1047,7 @@ sub fielded_format_view { Copyright/Distribution: $cprtag{$copyright}
Repository Location: $hostname
Abstract: $shortabstract
+$extrashow

END return $result; @@ -898,7 +1058,7 @@ sub xml_sgml_view { my ($title,$author,$subject,$url,$keywords,$version, $notes,$shortabstract,$mime,$lang, $creationdate,$lastrevisiondate,$owner,$copyright, - $hostname,$httphost)=@_; + $hostname,$httphost,$extrashow)=@_; my $result=< <LonCapaResource> @@ -927,6 +1087,7 @@ sub xml_sgml_view { <shortabstract>$shortabstract</shortabstract> </LonCapaResource> +$extrashow END return $result; }