Annotation of loncom/interface/lonsearchcat.pm, revision 1.192.2.1

1.98      harris41    1: # The LearningOnline Network with CAPA
1.108     harris41    2: # Search Catalog
                      3: #
1.192.2.1! albertel    4: # $Id: lonsearchcat.pm,v 1.192 2003/11/17 20:53:28 albertel Exp $
1.108     harris41    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
1.98      harris41   14: #
1.108     harris41   15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
1.1       www        27: #
1.121     matthew    28: ###############################################################################
                     29: ###############################################################################
                     30: 
                     31: =pod 
                     32: 
                     33: =head1 NAME
                     34: 
1.140     matthew    35: lonsearchcat - LONCAPA Search Interface
1.121     matthew    36: 
                     37: =head1 SYNOPSIS
                     38: 
                     39: Search interface to LON-CAPAs digital library
                     40: 
                     41: =head1 DESCRIPTION
                     42: 
                     43: This module enables searching for a distributed browseable catalog.
1.104     harris41   44: 
1.121     matthew    45: This is part of the LearningOnline Network with CAPA project
                     46: described at http://www.lon-capa.org.
                     47: 
                     48: lonsearchcat presents the user with an interface to search the LON-CAPA
                     49: digital library.  lonsearchcat also initiates the execution of a search
                     50: by sending the search parameters to LON-CAPA servers.  The progress of 
                     51: search (on a server basis) is displayed to the user in a seperate window.
                     52: 
                     53: =head1 Internals
                     54: 
                     55: =over 4
                     56: 
                     57: =cut
                     58: 
                     59: ###############################################################################
1.98      harris41   60: ###############################################################################
1.121     matthew    61: 
1.128     harris41   62: ###############################################################################
1.98      harris41   63: ##                                                                           ##
                     64: ## ORGANIZATION OF THIS PERL MODULE                                          ##
                     65: ##                                                                           ##
1.105     harris41   66: ## 1. Modules used by this module                                            ##
1.128     harris41   67: ## 2. Variables used throughout the module                                   ##
                     68: ## 3. handler subroutine called via Apache and mod_perl                      ##
                     69: ## 4. Other subroutines                                                      ##
1.98      harris41   70: ##                                                                           ##
                     71: ###############################################################################
                     72: 
1.1       www        73: package Apache::lonsearchcat;
                     74: 
1.98      harris41   75: # ------------------------------------------------- modules used by this module
1.1       www        76: use strict;
1.167     www        77: use Apache::Constants qw(:common :http);
1.6       harris41   78: use Apache::lonnet();
                     79: use Apache::File();
1.7       harris41   80: use CGI qw(:standard);
1.41      harris41   81: use Text::Query;
1.101     harris41   82: use GDBM_File;
1.112     harris41   83: use Apache::loncommon();
1.144     matthew    84: use Apache::lonmysql();
1.186     www        85: use Apache::lonlocal;
1.1       www        86: 
1.90      harris41   87: # ---------------------------------------- variables used throughout the module
                     88: 
1.121     matthew    89: ######################################################################
                     90: ######################################################################
                     91: 
                     92: =pod 
                     93: 
                     94: =item Global variables
                     95: 
                     96: =over 4
                     97: 
                     98: =item $importbutton
                     99: 
1.134     matthew   100: button to take the select results and go to group sorting
1.121     matthew   101: 
1.142     matthew   102: =item %groupsearch_db   
1.121     matthew   103: 
1.142     matthew   104: Database hash used to save values for the groupsearch RAT interface.
1.121     matthew   105: 
                    106: =item $diropendb 
                    107: 
                    108: The full path to the (temporary) search database file.  This is set and
                    109: used in &handler() and is also used in &output_results().
                    110: 
1.139     matthew   111: =item %Views
                    112: 
                    113: Hash which associates an output view description with the function
                    114: that produces it.  Adding a new view type should be as easy as
                    115: adding a line to the definition of this hash and making sure the function
                    116: takes the proper parameters.
                    117: 
1.155     matthew   118: =item $bodytag
                    119: 
                    120: LON-CAPA standard body tag, gotten from &Apache::lonnet::bodytag.
                    121: No title, no table, just a <body> tag.
                    122: 
1.121     matthew   123: =back 
                    124: 
                    125: =cut
                    126: 
                    127: ######################################################################
                    128: ######################################################################
                    129: 
1.98      harris41  130: # -- dynamically rendered interface components
                    131: my $importbutton; # button to take the selected results and go to group sorting
                    132: 
                    133: # -- miscellaneous variables
1.142     matthew   134: my %groupsearch_db;     # database hash
1.127     matthew   135: my $diropendb = "";    # db file
1.139     matthew   136: #             View Description           Function Pointer
                    137: my %Views = ("Detailed Citation View" => \&detailed_citation_view,
                    138:              "Summary View"           => \&summary_view,
                    139:              "Fielded Format"         => \&fielded_format_view,
1.150     matthew   140:              "XML/SGML"               => \&xml_sgml_view,
                    141:              "Compact View"           => \&compact_view);
1.145     matthew   142: my %persistent_db;
                    143: my $hidden_fields;
1.155     matthew   144: my $bodytag;
                    145: 
1.169     www       146: #
                    147: # For course search
                    148: #
1.167     www       149: my %alreadyseen;
                    150: my $hashtied;
                    151: my %hash;
1.169     www       152: my $totalfound;
1.167     www       153:  
1.121     matthew   154: ######################################################################
                    155: ######################################################################
                    156: 
                    157: =pod 
                    158: 
                    159: =item &handler() - main handler invoked by httpd child
                    160: 
1.124     matthew   161: =item Variables
                    162: 
                    163: =over 4
                    164: 
                    165: =item $hidden
                    166: 
                    167: holds 'hidden' html forms
                    168: 
                    169: =item $scrout
                    170: 
                    171: string that holds portions of the screen output
                    172: 
                    173: =back 
                    174: 
1.121     matthew   175: =cut
1.101     harris41  176: 
1.121     matthew   177: ######################################################################
                    178: ######################################################################
1.98      harris41  179: sub handler {
                    180:     my $r = shift;
1.145     matthew   181:     #
1.157     www       182: 
                    183:     my $loaderror=&Apache::lonnet::overloaderror($r);
                    184:     if ($loaderror) { return $loaderror; }
                    185: 
1.145     matthew   186:     my $closebutton;  # button that closes the search window 
                    187:                       # This button is different for the RAT compared to
                    188:                       # normal invocation.
                    189:     #
1.186     www       190:     &Apache::loncommon::content_type($r,'text/html');
1.98      harris41  191:     $r->send_http_header;
                    192:     return OK if $r->header_only;
1.156     matthew   193:     ##
                    194:     ## Prevent caching of the search interface window.  Hopefully this means
                    195:     ## we will get the launch=1 passed in a little more.
                    196:     &Apache::loncommon::no_cache($r);
1.145     matthew   197:     ## 
                    198:     ## Pick up form fields passed in the links.
                    199:     ##
                    200:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.146     matthew   201:              ['catalogmode','launch','acts','mode','form','element','pause',
1.158     matthew   202:               'phase','persistent_db_id','table','start','show',
1.191     albertel  203:               'cleargroupsort','titleelement']);
1.146     matthew   204:     ##
                    205:     ## The following is a trick - we wait a few seconds if asked to so
                    206:     ##     the daemon running the search can get ahead of the daemon
                    207:     ##     printing the results.  We only need (theoretically) to do
                    208:     ##     this once, so the pause indicator is deleted
                    209:     ##
                    210:     if (exists($ENV{'form.pause'})) {
1.181     matthew   211:         sleep(1);
1.146     matthew   212:         delete($ENV{'form.pause'});
                    213:     }
1.143     matthew   214:     ##
                    215:     ## Initialize global variables
                    216:     ##
1.121     matthew   217:     my $domain  = $r->dir_config('lonDefDomain');
1.177     albertel  218:     $diropendb= "/home/httpd/perl/tmp/$ENV{'user.domain'}_$ENV{'user.name'}_searchcat.db";
1.145     matthew   219:     #
                    220:     # set the name of the persistent database
1.146     matthew   221:     #          $ENV{'form.persistent_db_id'} can only have digits in it.
1.145     matthew   222:     if (! exists($ENV{'form.persistent_db_id'}) ||
1.147     matthew   223:         ($ENV{'form.persistent_db_id'} =~ /\D/) ||
                    224:         ($ENV{'form.launch'} eq '1')) {
1.145     matthew   225:         $ENV{'form.persistent_db_id'} = time;
                    226:     }
1.155     matthew   227:     $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);
1.146     matthew   228:     my $persistent_db_file = "/home/httpd/perl/tmp/".
1.145     matthew   229:         &Apache::lonnet::escape($domain).
                    230:             '_'.&Apache::lonnet::escape($ENV{'user.name'}).
                    231:                 '_'.$ENV{'form.persistent_db_id'}.'_persistent_search.db';
1.146     matthew   232:     ##
1.152     matthew   233:     if (! &get_persistent_form_data($persistent_db_file)) {
1.150     matthew   234:         if ($ENV{'form.phase'} =~ /(run_search|results)/) {
                    235:             &Apache::lonnet::logthis("lonsearchcat:Unable to recover data ".
                    236:                                      "from $persistent_db_file");
                    237:             $r->print(<<END);
                    238: <html>
                    239: <head><title>LON-CAPA Search Error</title></head>
1.155     matthew   240: $bodytag
1.150     matthew   241: We were unable to retrieve data describing your search.  This is a serious
                    242: error and has been logged.  Please alert your LON-CAPA administrator.
                    243: </body>
                    244: </html>
                    245: END
                    246:             return OK;
                    247:         }
1.147     matthew   248:     }
1.124     matthew   249:     ##
1.143     matthew   250:     ## Clear out old values from groupsearch database
1.124     matthew   251:     ##
1.146     matthew   252:     untie %groupsearch_db if (tied(%groupsearch_db));
1.158     matthew   253:     if (($ENV{'form.cleargroupsort'} eq '1') || 
                    254:         (($ENV{'form.launch'} eq '1') && 
                    255:          ($ENV{'form.catalogmode'} eq 'groupsearch'))) {
1.148     matthew   256: 	if (tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT(),0640)) {
1.101     harris41  257: 	    &start_fresh_session();
1.142     matthew   258: 	    untie %groupsearch_db;
1.158     matthew   259:             delete($ENV{'form.cleargroupsort'});
1.122     matthew   260: 	} else {
1.155     matthew   261:             # This is a stupid error to give to the user.  
                    262:             # It really tells them nothing.
                    263: 	    $r->print('<html><head></head>'.$bodytag.
                    264:                       'Unable to tie hash to db file</body></html>');
1.101     harris41  265: 	    return OK;
                    266: 	}
                    267:     }
1.124     matthew   268:     ##
1.150     matthew   269:     ## Configure hidden fields
1.124     matthew   270:     ##
1.145     matthew   271:     $hidden_fields = '<input type="hidden" name="persistent_db_id" value="'.
1.150     matthew   272:         $ENV{'form.persistent_db_id'}.'" />'."\n";
                    273:     if (exists($ENV{'form.catalogmode'})) {
                    274:         $hidden_fields .= '<input type="hidden" name="catalogmode" value="'.
                    275:                 $ENV{'form.catalogmode'}.'" />'."\n";
                    276:     }
                    277:     if (exists($ENV{'form.form'})) {
                    278:         $hidden_fields .= '<input type="hidden" name="form" value="'.
                    279:                 $ENV{'form.form'}.'" />'."\n";
                    280:     }
                    281:     if (exists($ENV{'form.element'})) {
                    282:         $hidden_fields .= '<input type="hidden" name="element" value="'.
                    283:                 $ENV{'form.element'}.'" />'."\n";
                    284:     }
1.191     albertel  285:     if (exists($ENV{'form.titleelement'})) {
                    286:         $hidden_fields .= '<input type="hidden" name="titleelement" value="'.
                    287:                 $ENV{'form.titleelement'}.'" />'."\n";
                    288:     }
1.150     matthew   289:     if (exists($ENV{'form.mode'})) {
                    290:         $hidden_fields .= '<input type="hidden" name="mode" value="'.
                    291:                 $ENV{'form.mode'}.'" />'."\n";
                    292:     }
                    293:     ##
                    294:     ## Configure dynamic components of interface
1.146     matthew   295:     ##
1.98      harris41  296:     if ($ENV{'form.catalogmode'} eq 'interactive') {
1.150     matthew   297:         $closebutton="<input type='button' name='close' value='CLOSE' ";
                    298:         if ($ENV{'form.phase'} =~ /(results|run_search)/) {
                    299: 	    $closebutton .="onClick='parent.close()'";
                    300:         } else {
                    301:             $closebutton .="onClick='self.close()'";
                    302:         }
                    303:         $closebutton .=">\n";
1.124     matthew   304:     } elsif ($ENV{'form.catalogmode'} eq 'groupsearch') {
1.150     matthew   305:         $closebutton="<input type='button' name='close' value='CLOSE' ";
                    306:         if ($ENV{'form.phase'} =~ /(results|run_search)/) {
                    307: 	    $closebutton .="onClick='parent.close()'";
                    308:         } else {
                    309:             $closebutton .="onClick='self.close()'";
                    310:         }
                    311:         $closebutton .= ">";
1.98      harris41  312:         $importbutton=<<END;
                    313: <input type='button' name='import' value='IMPORT'
                    314: onClick='javascript:select_group()'>
                    315: END
1.146     matthew   316:     } else {
                    317:         $closebutton = '';
                    318:         $importbutton = '';
1.98      harris41  319:     }
1.124     matthew   320:     ##
1.146     matthew   321:     ## Sanity checks on form elements
1.124     matthew   322:     ##
1.146     matthew   323:     if (!defined($ENV{'form.viewselect'})) {
1.150     matthew   324:         if (($ENV{'form.catalogmode'} eq 'groupsearch') ||
                    325:             ($ENV{'form.catalogmode'} eq 'interactive')) {
                    326:             $ENV{'form.viewselect'} ="Compact View";
                    327:         } else {
                    328:             $ENV{'form.viewselect'} ="Detailed Citation View";
                    329:         }
1.146     matthew   330:     }
1.149     matthew   331:     $ENV{'form.phase'} = 'disp_basic' if (! exists($ENV{'form.phase'}));
1.151     matthew   332:     $ENV{'form.show'} = 20 if (! exists($ENV{'form.show'}));
1.146     matthew   333:     ##
                    334:     ## Switch on the phase
                    335:     ##
                    336:     if ($ENV{'form.phase'} eq 'disp_basic') {
                    337:         &print_basic_search_form($r,$closebutton);
                    338:     } elsif ($ENV{'form.phase'} eq 'disp_adv') {
                    339:         &print_advanced_search_form($r,$closebutton);
                    340:     } elsif ($ENV{'form.phase'} eq 'results') {
                    341:         &display_results($r,$importbutton,$closebutton);
1.151     matthew   342:     } elsif ($ENV{'form.phase'} =~ /^(sort|run_search)$/) {
1.146     matthew   343:         my ($query,$customquery,$customshow,$libraries,$pretty_string) =
                    344:             &get_persistent_data($persistent_db_file,
                    345:                  ['query','customquery','customshow',
                    346:                   'libraries','pretty_string']);
1.151     matthew   347:         if ($ENV{'form.phase'} eq 'sort') {
                    348:             &print_sort_form($r,$pretty_string);
                    349:         } elsif ($ENV{'form.phase'} eq 'run_search') {
                    350:             &run_search($r,$query,$customquery,$customshow,
                    351:                         $libraries,$pretty_string);
                    352:         }
1.167     www       353:     } elsif ($ENV{'form.phase'} eq 'course_search') {
                    354:         &course_search($r);
1.146     matthew   355:     } elsif(($ENV{'form.phase'} eq 'basic_search') ||
                    356:             ($ENV{'form.phase'} eq 'adv_search')) {
1.151     matthew   357:         $ENV{'form.searchmode'} = 'basic';
                    358:         if ($ENV{'form.phase'} eq 'adv_search') {
                    359:             $ENV{'form.searchmode'} = 'advanced';
                    360:         }
1.146     matthew   361:         # Set up table
                    362:         if (! defined(&create_results_table())) {
1.147     matthew   363:             $r->print(<<END);
                    364: <html><head><title>Search Error</title></head>
1.155     matthew   365: $bodytag
1.147     matthew   366: Unable to create table in which to store search results.  
                    367: The search has been aborted.
                    368: </body>
                    369: </html>
                    370: END
                    371:             return OK;
1.146     matthew   372:         }
1.147     matthew   373:         delete($ENV{'form.launch'});
1.146     matthew   374:         if (! &make_form_data_persistent($r,$persistent_db_file)) {
1.147     matthew   375:             $r->print(<<END);
                    376: <html><head><title>Search Error</title></head>
1.155     matthew   377: $bodytag
1.147     matthew   378: Unable to properly store search information.  The search has been aborted.
                    379: </body>
                    380: </html>
                    381: END
                    382:             return OK;
1.146     matthew   383:         }
1.145     matthew   384:         #
1.139     matthew   385:         # We are running a search
1.134     matthew   386:         my ($query,$customquery,$customshow,$libraries) = 
                    387:             (undef,undef,undef,undef);
1.143     matthew   388:         my $pretty_string;
1.146     matthew   389:         if ($ENV{'form.phase'} eq 'basic_search') {
1.180     matthew   390:             ($query,$pretty_string,$libraries) = 
                    391:                 &parse_basic_search($r,$closebutton);
1.146     matthew   392:         } else {                      # Advanced search
1.143     matthew   393:             ($query,$customquery,$customshow,$libraries,$pretty_string) 
1.145     matthew   394:                 = &parse_advanced_search($r,$closebutton);
1.134     matthew   395:             return OK if (! defined($query));
                    396:         }
1.152     matthew   397:         &make_persistent({ query => $query,
1.146     matthew   398:                            customquery => $customquery,
                    399:                            customshow => $customshow,
                    400:                            libraries => $libraries,
                    401:                            pretty_string => $pretty_string },
                    402:                          $persistent_db_file);
1.145     matthew   403:         ##
1.146     matthew   404:         ## Print out the frames interface
1.145     matthew   405:         ##
1.146     matthew   406:         &print_frames_interface($r);
1.124     matthew   407:     }
                    408:     return OK;
                    409: } 
1.98      harris41  410: 
1.124     matthew   411: ######################################################################
                    412: ######################################################################
                    413: 
1.167     www       414: sub course_search {
                    415:     my $r=shift;
                    416:     my $bodytag=&Apache::loncommon::bodytag('Course Search');
                    417:     my $pretty_search_string = '<b>'.$ENV{'form.courseexp'}.'</b>';
                    418:     my $search_string = $ENV{'form.courseexp'};
                    419:     my @New_Words;
                    420:     if ($ENV{'form.crsrelated'}) {
                    421:         ($search_string,@New_Words) = &related_version($ENV{'form.courseexp'});
                    422:         if (@New_Words) {
                    423:             $pretty_search_string .= " with related words: <b>@New_Words</b>.";
                    424:         } else {
                    425:             $pretty_search_string .= " with no related words.";
                    426:         }
                    427:     }
                    428:     my $fulltext=$ENV{'form.crsfulltext'};
                    429:     my @allwords=($search_string,@New_Words);
1.169     www       430:     $totalfound=0;
1.167     www       431:     $r->print('<html><head><title>LON-CAPA Course Search</title></head>'.
                    432: 	      $bodytag.$pretty_search_string);
                    433:     $r->rflush();
                    434: # ======================================================= Go through the course
                    435:    $hashtied=0;
                    436:    undef %alreadyseen;
                    437:    %alreadyseen=();
1.169     www       438:     my $c=$r->connection;
1.167     www       439:    &tiehash();
                    440:    foreach (keys %hash) {
1.169     www       441:        if ($c->aborted()) { last; }
1.167     www       442:        if (($_=~/^src\_(.+)$/) && (!$alreadyseen{$hash{$_}})) {
1.168     www       443:            &checkonthis($r,$hash{$_},0,$hash{'title_'.$1},$fulltext,@allwords);
1.167     www       444:        }
                    445:    }
                    446:    &untiehash();
1.169     www       447:     unless ($totalfound) {
1.187     www       448: 	$r->print('<p>'.&mt('No resources found').'.</p>');
1.169     www       449:     }
1.167     www       450: # =================================================== Done going through course
                    451:     $r->print('</body></html>');
                    452: }
                    453: 
                    454: # ---------------------------------------------------------------- tie the hash
                    455: 
                    456: sub tiehash {
                    457:     $hashtied=0;
                    458:     if ($ENV{'request.course.fn'}) {
                    459:         if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db",
                    460:             &GDBM_READER(),0640)) {
                    461:                 $hashtied=1;
                    462:         }
                    463:     }    
                    464: }
                    465: 
                    466: sub untiehash {
                    467:     if ($hashtied) { untie %hash; }
                    468:     $hashtied=0;
                    469: }
                    470: 
                    471: # =============================== This pulls up a resource and its dependencies
                    472: 
                    473: sub checkonthis {
1.168     www       474:     my ($r,$url,$level,$title,$fulltext,@allwords)=@_;
1.167     www       475:     $alreadyseen{$url}=1;
                    476:     $r->rflush();
                    477:     my $result=&Apache::lonnet::metadata($url,'title').' '.
                    478:                &Apache::lonnet::metadata($url,'subject').' '.
                    479:                &Apache::lonnet::metadata($url,'abstract').' '.
                    480:                &Apache::lonnet::metadata($url,'keywords');
                    481:     if (($url) && ($fulltext)) {
1.168     www       482: 	$result.=&Apache::lonnet::ssi_body($url);
1.167     www       483:     }
                    484:     $result=~s/\s+/ /gs;
                    485:     my $applies=0;
                    486:     foreach (@allwords) {
                    487:         if ($_=~/\w/) {
                    488: 	   if ($result=~/$_/si) {
                    489: 	      $applies++;
                    490:            }
                    491:        }
                    492:     }
                    493: # Does this resource apply?
                    494:     if ($applies) {
                    495:        $r->print('<br />');
                    496:        for (my $i=0;$i<=$level*5;$i++) {
                    497:            $r->print('&nbsp;');
                    498:        }
                    499:        $r->print('<a href="'.$url.'" target="cat">'.
1.169     www       500: 		 ($title?$title:$url).'</a><br />');
                    501:        $totalfound++;
                    502:     } elsif ($fulltext) {
                    503:        $r->print(' .');
1.167     www       504:     }
1.169     www       505:     $r->rflush();
1.167     www       506: # Check also the dependencies of this one
                    507:     my $dependencies=
                    508:                 &Apache::lonnet::metadata($url,'dependencies');
                    509:     foreach (split(/\,/,$dependencies)) {
                    510:        if (($_=~/^\/res\//) && (!$alreadyseen{$_})) {
1.168     www       511:           &checkonthis($r,$_,$level+1,'',$fulltext,@allwords);
1.167     www       512:        }
                    513:     }
                    514: }
                    515: 
                    516: ######################################################################
                    517: ######################################################################
                    518: 
1.124     matthew   519: =pod 
                    520: 
1.146     matthew   521: =item &print_basic_search_form() 
1.124     matthew   522: 
                    523: Returns a scalar which holds html for the basic search form.
                    524: 
                    525: =cut
                    526: 
                    527: ######################################################################
                    528: ######################################################################
1.3       harris41  529: 
1.146     matthew   530: sub print_basic_search_form{
                    531:     my ($r,$closebutton) = @_;
1.167     www       532:     my $bodytag=&Apache::loncommon::bodytag('Search');
1.124     matthew   533:     my $scrout=<<"ENDDOCUMENT";
                    534: <html>
                    535: <head>
                    536: <title>The LearningOnline Network with CAPA</title>
                    537: <script type="text/javascript">
                    538:     function openhelp(val) {
                    539: 	openhelpwin=open('/adm/help/searchcat.html','helpscreen',
                    540: 	     'scrollbars=1,width=600,height=300');
                    541: 	openhelpwin.focus();
1.6       harris41  542:     }
1.124     matthew   543: </script>
                    544: </head>
1.154     www       545: $bodytag
1.167     www       546: ENDDOCUMENT
                    547: if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) {
                    548:     $scrout.=(<<ENDDOCUMENT);
                    549: <h1>Catalog Search</h1>
1.124     matthew   550: <form method="post" action="/adm/searchcat">
1.146     matthew   551: <input type="hidden" name="phase" value="basic_search" />
1.145     matthew   552: $hidden_fields
1.124     matthew   553: <p>
1.131     matthew   554: Enter terms or phrases separated by AND, OR, or NOT 
1.129     matthew   555: then press SEARCH below.
1.124     matthew   556: </p>
                    557: <p>
                    558: <table>
                    559: <tr><td>
                    560: ENDDOCUMENT
                    561:     $scrout.='&nbsp;'.&simpletextfield('basicexp',$ENV{'form.basicexp'},40).
                    562:         '&nbsp;';
1.180     matthew   563:     my $relatedcheckbox = &simplecheckbox('related',$ENV{'form.related'});
                    564:     my $domain = $r->dir_config('lonDefDomain');
1.184     matthew   565:     my $domaincheckbox = &simplecheckbox('domains',$domain);
1.187     www       566:     my $srch=&mt('Search');
                    567:     my $header=&mt('Advanced Search');
1.139     matthew   568:     $scrout.=<<END;
1.160     www       569: </td><td><a
1.190     matthew   570: href="/adm/searchcat?phase=disp_adv&catalogmode=$ENV{'form.catalogmode'}&launch=$ENV{'form.launch'}&mode=$ENV{'form.mode'}"
1.187     www       571: >$header</a></td></tr>
1.180     matthew   572: <tr><td>$relatedcheckbox use related words</td>
                    573:     <td>$domaincheckbox only search domain <b>$domain</b></td></tr>
1.141     matthew   574: </table>
1.124     matthew   575: </p>
                    576: <p>
1.187     www       577: &nbsp;<input type="submit" name="basicsubmit" value='$srch' />&nbsp;
1.124     matthew   578: $closebutton
1.139     matthew   579: END
1.187     www       580:     $scrout.=&selectbox('View','viewselect',
1.139     matthew   581: 			$ENV{'form.viewselect'},
                    582: 			undef,undef,undef,
                    583: 			sort(keys(%Views)));
1.188     www       584:     $scrout.=&selectbox('Per Page','show',
1.151     matthew   585: 			$ENV{'form.show'},
                    586: 			undef,undef,undef,
                    587: 			(10,20,50,100));
1.139     matthew   588:     $scrout.=<<ENDDOCUMENT;
1.124     matthew   589: </p>
                    590: </form>
1.167     www       591: ENDDOCUMENT
1.180     matthew   592:     }
                    593:     if ($ENV{'request.course.id'}) {
1.187     www       594: 	my %lt=&Apache::lonlocal::texthash(
                    595: 					   'srch' => 'Search',
                    596:                                            'header' => 'Course Search',
                    597: 	 'note' => 'Enter terms or phrases, then press "Search" below',
                    598: 					   );
1.180     matthew   599:         $scrout.=(<<ENDCOURSESEARCH);
                    600: <hr />
1.187     www       601: <h1>$lt{'header'}</h1>    
1.167     www       602: <form method="post" action="/adm/searchcat">
                    603: <input type="hidden" name="phase" value="course_search" />
                    604: $hidden_fields
                    605: <p>
1.187     www       606: $lt{'note'}.
1.167     www       607: </p>
                    608: <p>
                    609: <table>
                    610: <tr><td>
                    611: ENDCOURSESEARCH
1.180     matthew   612:         $scrout.='&nbsp;'.
                    613:             &simpletextfield('courseexp',$ENV{'form.courseexp'},40);
                    614:         my $crscheckbox = 
                    615:             &simplecheckbox('crsfulltext',$ENV{'form.crsfulltext'});
                    616:         my $relcheckbox = 
                    617:             &simplecheckbox('crsrelated',$ENV{'form.crsrelated'});
                    618:         $scrout.=(<<ENDENDCOURSE);
1.167     www       619: </td></tr>
                    620: <tr><td>$relcheckbox use related words</td><td></td></tr>
                    621: <tr><td>$crscheckbox fulltext search (time consuming)</td><td></td></tr>
                    622: </table><p>
1.187     www       623: &nbsp;<input type="submit" name="coursesubmit" value='$lt{'srch'}' />
1.167     www       624: </p>
                    625: ENDENDCOURSE
1.180     matthew   626:     }
1.167     www       627:     $scrout.=(<<ENDDOCUMENT);
1.124     matthew   628: </body>
                    629: </html>
                    630: ENDDOCUMENT
1.146     matthew   631:     $r->print($scrout);
                    632:     return;
1.124     matthew   633: }
                    634: ######################################################################
                    635: ######################################################################
                    636: 
                    637: =pod 
                    638: 
                    639: =item &advanced_search_form() 
                    640: 
                    641: Returns a scalar which holds html for the advanced search form.
                    642: 
                    643: =cut
                    644: 
                    645: ######################################################################
                    646: ######################################################################
                    647: 
1.146     matthew   648: sub print_advanced_search_form{
                    649:     my ($r,$closebutton) = @_;
1.129     matthew   650:     my $advanced_buttons = <<"END";
                    651: <p>
                    652: <input type="submit" name="advancedsubmit" value='SEARCH' />
                    653: <input type="reset" name="reset" value='RESET' />
                    654: $closebutton
                    655: <input type="button" value="HELP" onClick="openhelp()" />
                    656: </p>
                    657: END
1.139     matthew   658:     if (!defined($ENV{'form.viewselect'})) {
                    659:         $ENV{'form.viewselect'} ="Detailed Citation View";
                    660:     }
1.154     www       661:     my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search');
1.124     matthew   662:     my $scrout=<<"ENDHEADER";
                    663: <html>
                    664: <head>
                    665: <title>The LearningOnline Network with CAPA</title>
                    666: <script type="text/javascript">
                    667:     function openhelp(val) {
                    668: 	openhelpwin=open('/adm/help/searchcat.html','helpscreen',
                    669: 	     'scrollbars=1,width=600,height=300');
                    670: 	openhelpwin.focus();
1.18      harris41  671:     }
1.124     matthew   672: </script>
                    673: </head>
1.154     www       674: $bodytag
1.131     matthew   675: Enter terms or phrases separated by search operators 
1.129     matthew   676: such as AND, OR, or NOT.<br />
1.130     matthew   677: <form method="post" action="/adm/searchcat">
1.129     matthew   678: $advanced_buttons
1.145     matthew   679: $hidden_fields
1.146     matthew   680: <input type="hidden" name="phase" value="adv_search" />
1.129     matthew   681: <table>
1.130     matthew   682: <tr><td><font color="#800000" face="helvetica"><b>VIEW:</b></font></td>
                    683: <td>
1.124     matthew   684: ENDHEADER
1.139     matthew   685:     $scrout.=&selectbox(undef,'viewselect',
                    686: 			$ENV{'form.viewselect'},
                    687: 			undef,undef,undef,
                    688: 			sort(keys(%Views)));
1.151     matthew   689:     $scrout.='&nbsp;';
                    690:     $scrout.=&selectbox(undef,'show',
                    691: 			$ENV{'form.show'},
                    692: 			undef,undef,undef,
                    693: 			(10,20,50,100));
                    694:     $scrout.='&nbsp;'.
1.187     www       695:         '<font color="#800000" face="helvetica">'.&mt('Per Page').'</font>';
                    696:     $scrout.="</td><td>".&mt('Related').'<br />'.&mt('Words')."</td></tr>\n";
1.142     matthew   697:     $scrout.=&searchphrasefield_with_related('title',   'title'   ,
                    698:                                              $ENV{'form.title'});
1.135     matthew   699:     $scrout.=&searchphrasefield('author',  'author'  ,$ENV{'form.author'});
1.142     matthew   700:     $scrout.=&searchphrasefield_with_related('subject', 'subject' ,
                    701:                                              $ENV{'form.subject'});
                    702:     $scrout.=&searchphrasefield_with_related('keywords','keywords',
                    703:                                              $ENV{'form.keywords'});
1.135     matthew   704:     $scrout.=&searchphrasefield('URL',     'url'     ,$ENV{'form.url'});
1.142     matthew   705:     $scrout.=&searchphrasefield_with_related('notes',   'notes'   ,
                    706:                                              $ENV{'form.notes'});
                    707:     $scrout.=&searchphrasefield_with_related('abstract','abstract',
                    708:                                              $ENV{'form.abstract'});
1.129     matthew   709:     # Hack - an empty table row.
1.142     matthew   710:     $scrout.="<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
1.161     matthew   711:     $scrout.=&searchphrasefield('file<br />extension','extension',
                    712:                         $ENV{'form.extension'});
1.142     matthew   713:     $scrout.="<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
1.129     matthew   714:     $scrout.=&searchphrasefield('publisher<br />owner','owner',
                    715: 				$ENV{'form.owner'});
                    716:     $scrout.="</table>\n";
1.161     matthew   717:     $ENV{'form.category'}='any' if (! defined($ENV{'form.category'}));
1.132     matthew   718:     $scrout.=&selectbox('File Category','category',
1.131     matthew   719: 			$ENV{'form.category'},
                    720: 			'any','Any category',
                    721: 			undef,
                    722: 			(&Apache::loncommon::filecategories()));
1.11      harris41  723:     $ENV{'form.language'}='any' unless length($ENV{'form.language'});
1.133     matthew   724:     #----------------------------------------------------------------
1.132     matthew   725:     # Allow restriction to multiple domains.
                    726:     #   I make the crazy assumption that there will never be a domain 'any'.
                    727:     #
1.133     matthew   728:     $ENV{'form.domains'} = 'any' if (! exists($ENV{'form.domains'}));
                    729:     my @allowed_domains = (ref($ENV{'form.domains'}) ? @{$ENV{'form.domains'}} 
                    730:                            :  ($ENV{'form.domains'}) );
                    731:     my %domain_hash = ();
                    732:     foreach (@allowed_domains) {
                    733:         $domain_hash{$_}++;
                    734:     }
1.132     matthew   735:     my @domains =&Apache::loncommon::get_domains();
                    736:     # adjust the size of the select box
                    737:     my $size = 4;
1.165     albertel  738:     $size = (scalar @domains < ($size - 1) ? scalar @domains + 1 : $size);
1.145     matthew   739:     $scrout.="\n".'<font color="#800000" face="helvetica"><b>'.
1.174     albertel  740:         'DOMAINS TO BE SEARCHED</b></font><br />'.
1.145     matthew   741:             '<select name="domains" size="'.$size.'" multiple>'."\n".
                    742:                 '<option name="any" value="any" '.
                    743:                     ($domain_hash{'any'}? 'selected ' :'').
1.133     matthew   744:                         '>all domains</option>'."\n";
1.145     matthew   745:     foreach my $dom (sort @domains) {
                    746:         $scrout.="<option name=\"$dom\" ".
                    747:             ($domain_hash{$dom} ? 'selected ' :'').">$dom</option>\n";
1.132     matthew   748:     }
1.145     matthew   749:     $scrout.="</select>\n";
1.133     matthew   750:     #----------------------------------------------------------------
1.3       harris41  751:     $scrout.=&selectbox('Limit by language','language',
1.111     harris41  752: 			$ENV{'form.language'},'any','Any Language',
1.166     albertel  753: 			\&Apache::loncommon::languagedescription,
1.111     harris41  754: 			(&Apache::loncommon::languageids),
                    755: 			);
1.8       harris41  756: # ------------------------------------------------ Compute date selection boxes
                    757:     $scrout.=<<CREATIONDATESTART;
1.3       harris41  758: <p>
                    759: <font color="#800000" face="helvetica"><b>LIMIT BY CREATION DATE RANGE:</b>
                    760: </font>
1.98      harris41  761: <br />
1.8       harris41  762: between:
                    763: CREATIONDATESTART
1.11      harris41  764:     $scrout.=&dateboxes('creationdatestart',1,1,1976,
                    765: 			$ENV{'form.creationdatestart_month'},
                    766: 			$ENV{'form.creationdatestart_day'},
                    767: 			$ENV{'form.creationdatestart_year'},
                    768: 			);
1.124     matthew   769:     $scrout.="and:\n";
1.11      harris41  770:     $scrout.=&dateboxes('creationdateend',12,31,2051,
                    771: 			$ENV{'form.creationdateend_month'},
                    772: 			$ENV{'form.creationdateend_day'},
                    773: 			$ENV{'form.creationdateend_year'},
                    774: 			);
1.8       harris41  775:     $scrout.="</p>";
                    776:     $scrout.=<<LASTREVISIONDATESTART;
                    777: <p>
                    778: <font color="#800000" face="helvetica"><b>LIMIT BY LAST REVISION DATE RANGE:
                    779: </b></font>
1.98      harris41  780: <br />between:
1.8       harris41  781: LASTREVISIONDATESTART
1.11      harris41  782:     $scrout.=&dateboxes('lastrevisiondatestart',1,1,1976,
                    783: 			$ENV{'form.lastrevisiondatestart_month'},
                    784: 			$ENV{'form.lastrevisiondatestart_day'},
                    785: 			$ENV{'form.lastrevisiondatestart_year'},
                    786: 			);
1.8       harris41  787:     $scrout.=<<LASTREVISIONDATEEND;
                    788: and:
                    789: LASTREVISIONDATEEND
1.11      harris41  790:     $scrout.=&dateboxes('lastrevisiondateend',12,31,2051,
                    791: 			$ENV{'form.lastrevisiondateend_month'},
                    792: 			$ENV{'form.lastrevisiondateend_day'},
                    793: 			$ENV{'form.lastrevisiondateend_year'},
                    794: 			);
1.8       harris41  795:     $scrout.='</p>';
1.11      harris41  796:     $ENV{'form.copyright'}='any' unless length($ENV{'form.copyright'});
1.8       harris41  797:     $scrout.=&selectbox('Limit by copyright/distribution','copyright',
1.111     harris41  798: 			 $ENV{'form.copyright'},
                    799: 			 'any','Any copyright/distribution',
1.166     albertel  800: 			 \&Apache::loncommon::copyrightdescription,
1.111     harris41  801: 			 (&Apache::loncommon::copyrightids),
                    802: 			 );
1.14      harris41  803: # ------------------------------------------- Compute customized metadata field
1.152     matthew   804: #    $scrout.=<<CUSTOMMETADATA;
                    805: #<p>
                    806: #<font color="#800000" face="helvetica"><b>LIMIT BY SPECIAL METADATA FIELDS:</b>
                    807: #</font>
                    808: #For resource-specific metadata, enter in an expression in the form of 
                    809: #<i>key</i>=<i>value</i> separated by operators such as AND, OR or NOT.<br />
                    810: #<b>Example:</b> grandmother=75 OR grandfather=85
                    811: #<br />
                    812: #CUSTOMMETADATA
                    813: #    $scrout.=&simpletextfield('custommetadata',$ENV{'form.custommetadata'});
                    814: #    $scrout.=<<CUSTOMSHOW;
                    815: #<p>
                    816: #<font color="#800000" face="helvetica"><b>SHOW SPECIAL METADATA FIELDS:</b>
                    817: #</font>
                    818: #Enter in a space-separated list of special metadata fields to show
                    819: #in a fielded listing for each record result.
                    820: #<br />
                    821: #CUSTOMSHOW
                    822: #    $scrout.=&simpletextfield('customshow',$ENV{'form.customshow'});
1.124     matthew   823:     $scrout.=<<ENDDOCUMENT;
1.129     matthew   824: $advanced_buttons
1.8       harris41  825: </form>
                    826: </body>
                    827: </html>
                    828: ENDDOCUMENT
1.146     matthew   829:     $r->print($scrout);
                    830:     return;
1.124     matthew   831: }
1.8       harris41  832: 
1.121     matthew   833: ######################################################################
                    834: ######################################################################
                    835: 
                    836: =pod 
                    837: 
1.146     matthew   838: =item &get_persistent_form_data
1.145     matthew   839: 
1.146     matthew   840: Inputs: filename of database
                    841: 
                    842: Outputs: returns undef on database errors.
                    843: 
                    844: This function is the reverse of &make_persistent() for form data.
1.145     matthew   845: Retrieve persistent data from %persistent_db.  Retrieved items will have their
1.146     matthew   846: values unescaped.  If a form value already exists in $ENV, it will not be
                    847: overwritten.  Form values that are array references may have values appended
                    848: to them.
1.145     matthew   849: 
                    850: =cut
                    851: 
                    852: ######################################################################
                    853: ######################################################################
1.146     matthew   854: sub get_persistent_form_data {
                    855:     my $filename = shift;
1.147     matthew   856:     return 0 if (! -e $filename);
1.146     matthew   857:     return undef if (! tie(%persistent_db,'GDBM_File',$filename,
1.148     matthew   858:                            &GDBM_READER(),0640));
1.146     matthew   859:     #
                    860:     # These make sure we do not get array references printed out as 'values'.
1.161     matthew   861:     my %arrays_allowed = ('form.domains'=>1);
1.146     matthew   862:     #
                    863:     # Loop through the keys, looking for 'form.'
                    864:     foreach my $name (keys(%persistent_db)) {
                    865:         next if ($name !~ /^form./);
1.182     matthew   866:         # Kludgification begins!
                    867:         if ($name eq 'form.domains' && 
                    868:             $ENV{'form.searchmode'} eq 'basic' &&
                    869:             $ENV{'form.phase'} ne 'disp_basic') {
                    870:             next;
                    871:         }
                    872:         # End kludge (hopefully)
1.152     matthew   873:         next if (exists($ENV{$name}));
1.146     matthew   874:         my @values = map { 
                    875:             &Apache::lonnet::unescape($_);
                    876:         } split(',',$persistent_db{$name});
                    877:         next if (@values <1);
1.152     matthew   878:         if ($arrays_allowed{$name}) {
                    879:             $ENV{$name} = [@values];
1.146     matthew   880:         } else {
1.152     matthew   881:             $ENV{$name} = $values[0] if ($values[0]);
1.146     matthew   882:         }
                    883:     }
                    884:     untie (%persistent_db);
                    885:     return 1;
                    886: }
1.181     matthew   887: 
1.146     matthew   888: ######################################################################
                    889: ######################################################################
                    890: 
                    891: =pod 
                    892: 
                    893: =item &get_persistent_data
                    894: 
                    895: Inputs: filename of database, ref to array of values to recover.
                    896: 
                    897: Outputs: array of values.  Returns undef on error.
                    898: 
                    899: This function is the reverse of &make_persistent();
                    900: Retrieve persistent data from %persistent_db.  Retrieved items will have their
                    901: values unescaped.  If the item contains commas (before unescaping), the
                    902: returned value will be an array pointer. 
                    903: 
                    904: =cut
                    905: 
                    906: ######################################################################
                    907: ######################################################################
                    908: sub get_persistent_data {
                    909:     my $filename = shift;
                    910:     my @Vars = @{shift()};
                    911:     my @Values;   # Return array
                    912:     return undef if (! -e $filename);
                    913:     return undef if (! tie(%persistent_db,'GDBM_File',$filename,
1.148     matthew   914:                            &GDBM_READER(),0640));
1.146     matthew   915:     foreach my $name (@Vars) {
                    916:         if (! exists($persistent_db{$name})) {
                    917:             push @Values, undef;
                    918:             next;
                    919:         }
                    920:         my @values = map { 
                    921:             &Apache::lonnet::unescape($_);
                    922:         } split(',',$persistent_db{$name});
1.152     matthew   923:         if (@values <= 1) {
1.146     matthew   924:             push @Values,$values[0];
1.145     matthew   925:         } else {
1.146     matthew   926:             push @Values,\@values;
1.145     matthew   927:         }
                    928:     }
1.146     matthew   929:     untie (%persistent_db);
                    930:     return @Values;
1.145     matthew   931: }
                    932: 
                    933: ######################################################################
                    934: ######################################################################
                    935: 
                    936: =pod 
                    937: 
1.121     matthew   938: =item &make_persistent() 
                    939: 
1.146     matthew   940: Inputs: Hash of values to save, filename of persistent database.
                    941: 
                    942: Store variables away to the %persistent_db.
1.145     matthew   943: Values will be escaped.  Values that are array pointers will have their
                    944: elements escaped and concatenated in a comma seperated string.  
1.122     matthew   945: 
1.121     matthew   946: =cut
                    947: 
                    948: ######################################################################
                    949: ######################################################################
1.98      harris41  950: sub make_persistent {
1.133     matthew   951:     my %save = %{shift()};
1.146     matthew   952:     my $filename = shift;
                    953:     return undef if (! tie(%persistent_db,'GDBM_File',
1.148     matthew   954:                            $filename,&GDBM_WRCREAT(),0640));
1.146     matthew   955:     foreach my $name (keys(%save)) {
1.145     matthew   956:         my @values = (ref($save{$name}) ? @{$save{$name}} : ($save{$name}));
                    957:         # We handle array references, but not recursively.
                    958:         my $store = join(',', map { &Apache::lonnet::escape($_); } @values );
                    959:         $persistent_db{$name} = $store;
1.109     harris41  960:     }
1.146     matthew   961:     untie(%persistent_db);
                    962:     return 1;
                    963: }
                    964: 
                    965: ######################################################################
                    966: ######################################################################
                    967: 
                    968: =pod 
                    969: 
                    970: =item &make_form_data_persistent() 
                    971: 
                    972: Inputs: filename of persistent database.
                    973: 
                    974: Store most form variables away to the %persistent_db.
                    975: Values will be escaped.  Values that are array pointers will have their
                    976: elements escaped and concatenated in a comma seperated string.  
                    977: 
                    978: =cut
                    979: 
                    980: ######################################################################
                    981: ######################################################################
                    982: sub make_form_data_persistent {
                    983:     my $r = shift;
                    984:     my $filename = shift;
                    985:     my %save;
                    986:     foreach (keys(%ENV)) {
1.150     matthew   987:         next if (!/^form/ || /submit/);
1.146     matthew   988:         $save{$_} = $ENV{$_};
                    989:     }
1.152     matthew   990:     return &make_persistent(\%save,$filename);
1.98      harris41  991: }
                    992: 
1.122     matthew   993: ######################################################################
1.142     matthew   994: #                HTML form building functions                        #  
1.122     matthew   995: ######################################################################
                    996: 
                    997: =pod 
                    998: 
                    999: =item HTML form building functions
                   1000: 
                   1001: =over 4
                   1002: 
1.142     matthew  1003: =cut
                   1004: 
                   1005: ###############################################
                   1006: ###############################################
                   1007: 
                   1008: =pod
                   1009: 
1.122     matthew  1010: =item &simpletextfield() 
                   1011: 
                   1012: Inputs: $name,$value,$size
                   1013: 
                   1014: Returns a text input field with the given name, value, and size.  
                   1015: If size is not specified, a value of 20 is used.
                   1016: 
1.142     matthew  1017: =cut
                   1018: 
                   1019: ###############################################
                   1020: ###############################################
                   1021: 
                   1022: sub simpletextfield {
                   1023:     my ($name,$value,$size)=@_;
                   1024:     $size = 20 if (! defined($size));
                   1025:     return '<input type="text" name="'.$name.
                   1026:         '" size="'.$size.'" value="'.$value.'" />';
                   1027: }
                   1028: 
                   1029: ###############################################
                   1030: ###############################################
                   1031: 
                   1032: =pod
                   1033: 
1.122     matthew  1034: =item &simplecheckbox()
                   1035: 
                   1036: Inputs: $name,$value
                   1037: 
                   1038: Returns a simple check box with the given $name.
                   1039: If $value eq 'on' the box is checked.
                   1040: 
1.142     matthew  1041: =cut
                   1042: 
                   1043: ###############################################
                   1044: ###############################################
1.122     matthew  1045: 
1.180     matthew  1046: sub simplecheckbox{
                   1047:     my ($name,$value,$checked)=@_;
                   1048:     $checked="checked" if ($value eq 'on');
                   1049:     return '<input type="checkbox" name="'.$name.'" value="'.$value.'" '.
                   1050:         $checked.' />';
1.142     matthew  1051: }
1.122     matthew  1052: 
1.142     matthew  1053: ###############################################
                   1054: ###############################################
1.122     matthew  1055: 
1.142     matthew  1056: =pod
1.122     matthew  1057: 
1.142     matthew  1058: =item &fieldtitle()
1.126     matthew  1059: 
1.142     matthew  1060: Input: $title
1.122     matthew  1061: 
1.142     matthew  1062: Returns a scalar with html which will display $title as a search
                   1063: field heading.
1.129     matthew  1064: 
1.142     matthew  1065: =cut
1.129     matthew  1066: 
1.142     matthew  1067: ###############################################
                   1068: ###############################################
1.129     matthew  1069: 
1.142     matthew  1070: sub fieldtitle {
1.187     www      1071:     my $title = uc(&mt(shift()));
1.142     matthew  1072:     return '<font color="#800000" face="helvetica"><b>'.$title.
                   1073:         ':&nbsp;</b></font>';
                   1074: }
1.129     matthew  1075: 
1.142     matthew  1076: ###############################################
                   1077: ###############################################
1.129     matthew  1078: 
1.142     matthew  1079: =pod
1.129     matthew  1080: 
1.142     matthew  1081: =item &searchphrasefield()
1.129     matthew  1082: 
1.142     matthew  1083: Inputs: $title,$name,$value
1.129     matthew  1084: 
1.142     matthew  1085: Returns html for a title line and an input field for entering search terms.
                   1086: The entry field (which is where the $name and $value are used) is a 50 column 
                   1087: simpletextfield.  The html returned is for a row in a three column table.
1.129     matthew  1088: 
1.142     matthew  1089: =cut
1.129     matthew  1090: 
1.142     matthew  1091: ###############################################
                   1092: ###############################################
                   1093:     
                   1094: sub searchphrasefield {
                   1095:     my ($title,$name,$value)=@_;
                   1096:     return '<tr><td>'.&fieldtitle($title).'</td><td>'.
                   1097:         &simpletextfield($name,$value,50)."</td><td>&nbsp;</td></tr>\n";
                   1098: }
1.129     matthew  1099: 
1.142     matthew  1100: ###############################################
                   1101: ###############################################
1.129     matthew  1102: 
1.142     matthew  1103: =pod
1.129     matthew  1104: 
1.142     matthew  1105: =item &searchphrasefield_with_related()
1.129     matthew  1106: 
1.142     matthew  1107: Inputs: $title,$name,$value
1.129     matthew  1108: 
1.142     matthew  1109: Returns html for a title line and an input field for entering search terms
                   1110: and a check box for 'related words'.  The entry field (which is where the 
                   1111: $name and $value are used) is a 50 column simpletextfield.  The name of
                   1112: the related words checkbox is "$name_related".
1.129     matthew  1113: 
1.142     matthew  1114: =cut
1.129     matthew  1115: 
1.142     matthew  1116: ###############################################
                   1117: ###############################################
                   1118:     
                   1119: sub searchphrasefield_with_related {
                   1120:     my ($title,$name,$value)=@_;
                   1121:     return '<tr><td>'.&fieldtitle($title).'</td><td>'.
                   1122:         &simpletextfield($name,$value,50).'</td><td align="center">&nbsp;'.
                   1123:             &simplecheckbox($name.'_related',$ENV{'form.'.$name.'_related'}).
                   1124:                 "&nbsp;</td></tr>\n";
                   1125: }
1.126     matthew  1126: 
1.142     matthew  1127: ###############################################
                   1128: ###############################################
1.122     matthew  1129: 
1.142     matthew  1130: =pod
1.122     matthew  1131: 
1.142     matthew  1132: =item &dateboxes()
1.8       harris41 1133: 
1.142     matthew  1134: Returns html selection form elements for the specification of 
                   1135: the day, month, and year.
1.11      harris41 1136: 
1.142     matthew  1137: =cut
1.11      harris41 1138: 
1.142     matthew  1139: ###############################################
                   1140: ###############################################
1.3       harris41 1141: 
1.8       harris41 1142: sub dateboxes {
1.11      harris41 1143:     my ($name,$defaultmonth,$defaultday,$defaultyear,
                   1144: 	$currentmonth,$currentday,$currentyear)=@_;
                   1145:     ($defaultmonth,$defaultday,$defaultyear)=('','','');
1.117     matthew  1146:     #
                   1147:     # Day
                   1148:     my $day=<<END;
                   1149: <select name="${name}_day">
                   1150: <option value='$defaultday'> </option>
                   1151: END
                   1152:     for (my $i = 1; $i<=31; $i++) {
                   1153: 	$day.="<option value=\"$i\">$i</option>\n";
                   1154:     }
                   1155:     $day.="</select>\n";
                   1156:     $day=~s/(\"$currentday\")/$1 SELECTED/ if length($currentday);
                   1157:     #
                   1158:     # Month
1.11      harris41 1159:     my $month=<<END;
1.8       harris41 1160: <select name="${name}_month">
1.11      harris41 1161: <option value='$defaultmonth'> </option>
                   1162: END
1.117     matthew  1163:     my $i = 1;
                   1164:     foreach (qw/January February March April May June 
                   1165: 	     July August September October November December /){
1.187     www      1166: 	$month .="<option value=\"$i\">".&mt($_)."</option>\n";
1.117     matthew  1167: 	$i++;
                   1168:     }
                   1169:     $month.="</select>\n";
1.11      harris41 1170:     $month=~s/(\"$currentmonth\")/$1 SELECTED/ if length($currentmonth);
1.117     matthew  1171:     #
                   1172:     # Year (obviously)
1.11      harris41 1173:     my $year=<<END;
1.8       harris41 1174: <select name="${name}_year">
1.11      harris41 1175: <option value='$defaultyear'> </option>
1.3       harris41 1176: END
1.117     matthew  1177:     my $maxyear = 2051; 
                   1178:     for (my $i = 1976; $i<=$maxyear; $i++) {
                   1179: 	$year.="<option value=\"$i\">$i</option>\n";
                   1180:     }
                   1181:     $year.="</select>\n";
1.11      harris41 1182:     $year=~s/(\"$currentyear\")/$1 SELECTED/ if length($currentyear);
                   1183:     return "$month$day$year";
1.3       harris41 1184: }
                   1185: 
1.142     matthew  1186: ###############################################
                   1187: ###############################################
                   1188: 
                   1189: =pod
                   1190: 
                   1191: =item &selectbox()
                   1192: 
                   1193: Returns a scalar containing an html <select> form.  
                   1194: 
                   1195: Inputs: 
                   1196: 
                   1197: =over 4
                   1198: 
                   1199: =item $title 
                   1200: 
                   1201: Printed above the select box, in uppercase.  If undefined, only a select
                   1202: box will be returned, with no additional html.
                   1203: 
                   1204: =item $name 
                   1205: 
                   1206: The name element of the <select> tag.
                   1207: 
                   1208: =item $default 
                   1209: 
                   1210: The default value of the form.  Can be $anyvalue, or in @idlist.
                   1211: 
                   1212: =item $anyvalue 
                   1213: 
                   1214: The <option value="..."> used to indicate a default of 
                   1215: none of the values.  Can be undef.
                   1216: 
                   1217: =item $anytag 
                   1218: 
                   1219: The text associate with $anyvalue above.
                   1220: 
                   1221: =item $functionref 
                   1222: 
                   1223: Each element in @idlist will be passed as a parameter 
                   1224: to the function referenced here.  The return value of the function should
                   1225: be a scalar description of the items.  If this value is undefined the 
                   1226: description of each item in @idlist will be the item name.
                   1227: 
                   1228: =item @idlist 
                   1229: 
                   1230: The items to be selected from.  One of these or $anyvalue will be the 
                   1231: value returned by the form element, $ENV{form.$name}.
                   1232: 
                   1233: =back
                   1234: 
                   1235: =cut
                   1236: 
                   1237: ###############################################
                   1238: 
1.3       harris41 1239: sub selectbox {
1.129     matthew  1240:     my ($title,$name,$default,$anyvalue,$anytag,$functionref,@idlist)=@_;
                   1241:     if (! defined($functionref)) { $functionref = sub { $_[0]}; }
1.139     matthew  1242:     my $selout='';
1.186     www      1243:     $title=&mt($title);
1.139     matthew  1244:     if (defined($title)) {
                   1245:         my $uctitle=uc($title);
                   1246:         $selout="\n".'<p><font color="#800000" face="helvetica">'.
                   1247:             '<b>'.$uctitle.': </b></font>';
                   1248:     }
                   1249:     $selout .= '<select name="'.$name.'">';
                   1250:     unshift @idlist,$anyvalue if (defined($anyvalue));
                   1251:     foreach (@idlist) {
1.122     matthew  1252:         $selout.='<option value="'.$_.'"';
1.129     matthew  1253:         if ($_ eq $default and !/^any$/) {
1.187     www      1254: 	    $selout.=' selected >'.&mt(&{$functionref}($_)).'</option>';
1.111     harris41 1255: 	}
1.129     matthew  1256: 	elsif ($_ eq $default and /^$anyvalue$/) {
1.187     www      1257: 	    $selout.=' selected >'.&mt($anytag).'</option>';
1.111     harris41 1258: 	}
1.187     www      1259:         else {$selout.='>'.&mt(&{$functionref}($_)).'</option>';}
1.109     harris41 1260:     }
1.139     matthew  1261:     return $selout.'</select>'.(defined($title)?'</p>':' ');
1.6       harris41 1262: }
                   1263: 
1.122     matthew  1264: ######################################################################
1.142     matthew  1265: #                End of HTML form building functions                 #  
                   1266: ######################################################################
                   1267: 
                   1268: =pod
                   1269: 
                   1270: =back 
                   1271: 
                   1272: =cut
                   1273: 
                   1274: 
                   1275: ######################################################################
1.122     matthew  1276: ######################################################################
                   1277: 
                   1278: =pod 
                   1279: 
1.134     matthew  1280: =item &parse_advanced_search()
                   1281: 
                   1282: Parse advanced search form and return the following:
                   1283: 
                   1284: =over 4
                   1285: 
                   1286: =item $query Scalar containing an SQL query.
1.126     matthew  1287: 
1.134     matthew  1288: =item $customquery Scalar containing a custom query.
                   1289: 
                   1290: =item $customshow Scalar containing commands to show custom metadata.
                   1291: 
                   1292: =item $libraries_to_query Reference to array of domains to search.
                   1293: 
                   1294: =back
1.122     matthew  1295: 
                   1296: =cut
                   1297: 
                   1298: ######################################################################
                   1299: ######################################################################
1.134     matthew  1300: sub parse_advanced_search {
1.145     matthew  1301:     my ($r,$closebutton)=@_;
1.32      harris41 1302:     my $fillflag=0;
1.143     matthew  1303:     my $pretty_search_string = "<br />\n";
1.64      harris41 1304:     # Clean up fields for safety
                   1305:     for my $field ('title','author','subject','keywords','url','version',
                   1306: 		   'creationdatestart_month','creationdatestart_day',
                   1307: 		   'creationdatestart_year','creationdateend_month',
                   1308: 		   'creationdateend_day','creationdateend_year',
                   1309: 		   'lastrevisiondatestart_month','lastrevisiondatestart_day',
                   1310: 		   'lastrevisiondatestart_year','lastrevisiondateend_month',
                   1311: 		   'lastrevisiondateend_day','lastrevisiondateend_year',
1.161     matthew  1312: 		   'notes','abstract','extension','language','owner',
1.131     matthew  1313: 		   'custommetadata','customshow','category') {
1.101     harris41 1314: 	$ENV{"form.$field"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
1.64      harris41 1315:     }
1.117     matthew  1316:     foreach ('mode','form','element') {
                   1317: 	# is this required?  Hmmm.
                   1318: 	next unless (exists($ENV{"form.$_"}));
                   1319: 	$ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"});
                   1320: 	$ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
                   1321:     }
1.131     matthew  1322:     # Preprocess the category form element.
1.161     matthew  1323:     $ENV{'form.category'} = 'any' if (! defined($ENV{'form.category'}) ||
                   1324:                                       ref($ENV{'form.category'}));
                   1325:     #
1.90      harris41 1326:     # Check to see if enough information was filled in
1.32      harris41 1327:     for my $field ('title','author','subject','keywords','url','version',
1.161     matthew  1328: 		   'notes','abstract','category','extension','language',
                   1329:                    'owner','custommetadata') {
1.40      harris41 1330: 	if (&filled($ENV{"form.$field"})) {
1.32      harris41 1331: 	    $fillflag++;
                   1332: 	}
                   1333:     }
                   1334:     unless ($fillflag) {
1.151     matthew  1335: 	&output_blank_field_error($r,$closebutton,'phase=disp_adv');
1.134     matthew  1336: 	return ;
1.32      harris41 1337:     }
1.90      harris41 1338:     # Turn the form input into a SQL-based query
1.39      harris41 1339:     my $query='';
1.45      harris41 1340:     my @queries;
1.143     matthew  1341:     my $font = '<font color="#800000" face="helvetica">';
1.90      harris41 1342:     # Evaluate logical expression AND/OR/NOT phrase fields.
1.58      harris41 1343:     foreach my $field ('title','author','subject','notes','abstract','url',
1.161     matthew  1344: 		       'keywords','version','owner') {
1.44      harris41 1345: 	if ($ENV{'form.'.$field}) {
1.142     matthew  1346:             my $searchphrase = $ENV{'form.'.$field};
1.143     matthew  1347:             $pretty_search_string .= $font."$field</font> contains <b>".
                   1348:                 $searchphrase."</b>";
1.142     matthew  1349:             if ($ENV{'form.'.$field.'_related'}) {
1.143     matthew  1350:                 my @New_Words;
                   1351:                 ($searchphrase,@New_Words) = &related_version($searchphrase);
                   1352:                 if (@New_Words) {
                   1353:                     $pretty_search_string .= " with related words: ".
                   1354:                         "<b>@New_Words</b>.";
                   1355:                 } else {
                   1356:                     $pretty_search_string .= " with no related words.";
                   1357:                 }
1.142     matthew  1358:             }
1.143     matthew  1359:             $pretty_search_string .= "<br />\n";
1.142     matthew  1360: 	    push @queries,&build_SQL_query($field,$searchphrase);
1.131     matthew  1361:         }
1.44      harris41 1362:     }
1.161     matthew  1363:     #
                   1364:     # Make the 'mime' from 'form.category' and 'form.extension'
                   1365:     #
                   1366:     my $searchphrase;
                   1367:     if (exists($ENV{'form.category'})    && 
                   1368:         $ENV{'form.category'} !~ /^\s*$/ &&
                   1369:         $ENV{'form.category'} ne 'any')     {
                   1370:         my @extensions = &Apache::loncommon::filecategorytypes
                   1371:                                                    ($ENV{'form.category'});
                   1372:         if (scalar(@extensions) > 0) {
                   1373:             $searchphrase = join(' OR ',@extensions);
                   1374:         }
                   1375:     }
                   1376:     if (exists($ENV{'form.extension'}) && $ENV{'form.extension'} !~ /^\s*$/) {
                   1377:         $searchphrase .= ' OR ' if (defined($searchphrase));
                   1378:         my @extensions = split(/,/,$ENV{'form.extension'});
                   1379:         $searchphrase .= join(' OR ',@extensions);
                   1380:     }
                   1381:     if (defined($searchphrase)) {
                   1382:         push @queries,&build_SQL_query('mime',$searchphrase);
                   1383:         $pretty_search_string .=$font.'mime</font> contains <b>'.
                   1384:             $searchphrase.'</b><br />';
1.135     matthew  1385:     }
1.161     matthew  1386:     #####
1.90      harris41 1387:     # Evaluate option lists
1.58      harris41 1388:     if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') {
1.90      harris41 1389: 	push @queries,"(language like \"$ENV{'form.language'}\")";
1.143     matthew  1390:         $pretty_search_string.=$font."language</font>= ".
                   1391:             &Apache::loncommon::languagedescription($ENV{'form.language'}).
                   1392:                 "<br />\n";
1.58      harris41 1393:     }
                   1394:     if ($ENV{'form.copyright'} and $ENV{'form.copyright'} ne 'any') {
1.90      harris41 1395: 	push @queries,"(copyright like \"$ENV{'form.copyright'}\")";
1.143     matthew  1396:         $pretty_search_string.=$font."copyright</font> = ".
                   1397:             &Apache::loncommon::copyrightdescription($ENV{'form.copyright'}).
                   1398:                 "<br \>\n";
1.58      harris41 1399:     }
1.143     matthew  1400:     #
1.90      harris41 1401:     # Evaluate date windows
1.60      harris41 1402:     my $datequery=&build_date_queries(
                   1403: 			$ENV{'form.creationdatestart_month'},
                   1404: 			$ENV{'form.creationdatestart_day'},
                   1405: 			$ENV{'form.creationdatestart_year'},
                   1406: 			$ENV{'form.creationdateend_month'},
                   1407: 			$ENV{'form.creationdateend_day'},
                   1408: 			$ENV{'form.creationdateend_year'},
                   1409: 			$ENV{'form.lastrevisiondatestart_month'},
                   1410: 			$ENV{'form.lastrevisiondatestart_day'},
                   1411: 			$ENV{'form.lastrevisiondatestart_year'},
                   1412: 			$ENV{'form.lastrevisiondateend_month'},
                   1413: 			$ENV{'form.lastrevisiondateend_day'},
                   1414: 			$ENV{'form.lastrevisiondateend_year'},
                   1415: 			);
1.90      harris41 1416:     # Test to see if date windows are legitimate
1.61      harris41 1417:     if ($datequery=~/^Incorrect/) {
1.145     matthew  1418: 	&output_date_error($r,$datequery,$closebutton);
1.134     matthew  1419: 	return ;
1.143     matthew  1420:     } elsif ($datequery) {
                   1421:         # Here is where you would set up pretty_search_string to output
                   1422:         # date query information.
1.60      harris41 1423: 	push @queries,$datequery;
                   1424:     }
1.90      harris41 1425:     # Process form information for custom metadata querying
1.134     matthew  1426:     my $customquery=undef;
1.152     matthew  1427: #    if ($ENV{'form.custommetadata'}) {
                   1428: #        $pretty_search_string .=$font."Custom Metadata Search</font>: <b>".
                   1429: #            $ENV{'form.custommetadata'}."</b><br />\n";
                   1430: #	$customquery=&build_custommetadata_query('custommetadata',
                   1431: #				      $ENV{'form.custommetadata'});
                   1432: #    }
1.134     matthew  1433:     my $customshow=undef;
1.152     matthew  1434: #    if ($ENV{'form.customshow'}) {
                   1435: #        $pretty_search_string .=$font."Custom Metadata Display</font>: <b>".
                   1436: #            $ENV{'form.customshow'}."</b><br />\n";
                   1437: #	$customshow=$ENV{'form.customshow'};
                   1438: #	$customshow=~s/[^\w\s]//g;
                   1439: #	my @fields=split(/\s+/,$customshow);
                   1440: #	$customshow=join(" ",@fields);
                   1441: #    }
1.133     matthew  1442:     ## ---------------------------------------------------------------
1.132     matthew  1443:     ## Deal with restrictions to given domains
                   1444:     ## 
1.180     matthew  1445:     my ($libraries_to_query,$pretty_domains_string) = 
                   1446:         &parse_domain_restrictions();
                   1447:     $pretty_search_string .= $pretty_domains_string."<br />\n";
                   1448:     #
                   1449:     if (@queries) {
                   1450: 	$query=join(" AND ",@queries);
                   1451: 	$query="select * from metadata where $query";
                   1452:     } elsif ($customquery) {
                   1453:         $query = '';
                   1454:     }
                   1455:     return ($query,$customquery,$customshow,$libraries_to_query,
                   1456:             $pretty_search_string);
                   1457: }
                   1458: 
                   1459: sub parse_domain_restrictions {
1.132     matthew  1460:     my $libraries_to_query = undef;
                   1461:     # $ENV{'form.domains'} can be either a scalar or an array reference.
                   1462:     # We need an array.
1.180     matthew  1463:     if (! exists($ENV{'form.domains'})) {
                   1464:         return (undef,'');
                   1465:     }
                   1466:     my @allowed_domains;
                   1467:     if (ref($ENV{'form.domains'})) {
                   1468:         @allowed_domains =  @{$ENV{'form.domains'}};
                   1469:     } else {
                   1470:         @allowed_domains = ($ENV{'form.domains'});
                   1471:     }
1.132     matthew  1472:     my %domain_hash = ();
1.143     matthew  1473:     my $pretty_domains_string;
1.132     matthew  1474:     foreach (@allowed_domains) {
                   1475:         $domain_hash{$_}++;
                   1476:     }
1.143     matthew  1477:     if ($domain_hash{'any'}) {
1.152     matthew  1478:         $pretty_domains_string = "In all LON-CAPA domains.";
1.143     matthew  1479:     } else {
                   1480:         if (@allowed_domains > 1) {
1.152     matthew  1481:             $pretty_domains_string = "In LON-CAPA domains:";
1.143     matthew  1482:         } else {
1.152     matthew  1483:             $pretty_domains_string = "In LON-CAPA domain ";
1.143     matthew  1484:         }
                   1485:         foreach (sort @allowed_domains) {
1.152     matthew  1486:             $pretty_domains_string .= "<b>".$_."</b> ";
1.132     matthew  1487:         }
1.143     matthew  1488:         foreach (keys(%Apache::lonnet::libserv)) {
                   1489:             if (exists($domain_hash{$Apache::lonnet::hostdom{$_}})) {
                   1490:                 push @$libraries_to_query,$_;
                   1491:             }
1.132     matthew  1492:         }
                   1493:     }
1.180     matthew  1494:     return ($libraries_to_query,$pretty_domains_string);
1.18      harris41 1495: }
                   1496: 
1.122     matthew  1497: ######################################################################
                   1498: ######################################################################
                   1499: 
                   1500: =pod 
                   1501: 
1.134     matthew  1502: =item &parse_basic_search() 
1.122     matthew  1503: 
1.134     matthew  1504: Parse the basic search form and return a scalar containing an sql query.
1.126     matthew  1505: 
1.122     matthew  1506: =cut
                   1507: 
                   1508: ######################################################################
                   1509: ######################################################################
1.134     matthew  1510: sub parse_basic_search {
1.145     matthew  1511:     my ($r,$closebutton)=@_;
1.64      harris41 1512:     # Clean up fields for safety
                   1513:     for my $field ('basicexp') {
                   1514: 	$ENV{"form.$field"}=~s/[^\w\s\(\)\-]//g;
                   1515:     }
1.117     matthew  1516:     foreach ('mode','form','element') {
                   1517: 	# is this required?  Hmmm.
                   1518: 	next unless (exists($ENV{"form.$_"}));
                   1519: 	$ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"});
                   1520: 	$ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
                   1521:     }
1.180     matthew  1522:     my ($libraries_to_query,$pretty_domains_string) = 
                   1523:         &parse_domain_restrictions();
1.90      harris41 1524:     # Check to see if enough is filled in
1.26      harris41 1525:     unless (&filled($ENV{'form.basicexp'})) {
1.151     matthew  1526: 	&output_blank_field_error($r,$closebutton,'phase=disp_basic');
1.24      harris41 1527: 	return OK;
                   1528:     }
1.143     matthew  1529:     my $pretty_search_string = '<b>'.$ENV{'form.basicexp'}.'</b>';
1.142     matthew  1530:     my $search_string = $ENV{'form.basicexp'};
1.141     matthew  1531:     if ($ENV{'form.related'}) {
1.143     matthew  1532:         my @New_Words;
                   1533:         ($search_string,@New_Words) = &related_version($ENV{'form.basicexp'});
                   1534:         if (@New_Words) {
                   1535:             $pretty_search_string .= " with related words: <b>@New_Words</b>.";
                   1536:         } else {
                   1537:             $pretty_search_string .= " with no related words.";
                   1538:         }
1.141     matthew  1539:     }
1.90      harris41 1540:     # Build SQL query string based on form page
1.39      harris41 1541:     my $query='';
1.178     matthew  1542:     my $concatarg=join(',',
1.124     matthew  1543: 		       ('title', 'author', 'subject', 'notes', 'abstract',
                   1544:                         'keywords'));
1.95      harris41 1545:     $concatarg='title' if $ENV{'form.titleonly'};
1.178     matthew  1546:     $query=&build_SQL_query('concat_ws(" ",'.$concatarg.')',$search_string);
1.180     matthew  1547:     if (defined($pretty_domains_string) && $pretty_domains_string ne '') {
                   1548:         $pretty_search_string .= ' '.$pretty_domains_string;
                   1549:     }
1.143     matthew  1550:     $pretty_search_string .= "<br />\n";
1.183     matthew  1551:     my $final_query = 'SELECT * FROM metadata WHERE '.$query;
                   1552: #    &Apache::lonnet::logthis($final_query);
                   1553:     return ($final_query,$pretty_search_string,
1.180     matthew  1554:             $libraries_to_query);
1.22      harris41 1555: }
                   1556: 
1.122     matthew  1557: 
                   1558: ######################################################################
                   1559: ######################################################################
                   1560: 
                   1561: =pod 
                   1562: 
1.142     matthew  1563: =item &related_version
                   1564: 
                   1565: Modifies an input string to include related words.  Words in the string
                   1566: are replaced with parenthesized lists of 'OR'd words.  For example
                   1567: "torque" is replaced with "(torque OR word1 OR word2 OR ...)".  
                   1568: 
                   1569: Note: Using this twice on a string is probably silly.
                   1570: 
                   1571: =cut
                   1572: 
                   1573: ######################################################################
                   1574: ######################################################################
                   1575: sub related_version {
                   1576:     my $search_string = shift;
                   1577:     my $result = $search_string;
1.143     matthew  1578:     my %New_Words = ();
1.142     matthew  1579:     while ($search_string =~ /(\w+)/cg) {
                   1580:         my $word = $1;
                   1581:         next if (lc($word) =~ /\b(or|and|not)\b/);
                   1582:         my @Words = &Apache::loncommon::get_related_words($word);
1.143     matthew  1583:         @Words = ($#Words>4? @Words[0..4] : @Words);
                   1584:         foreach (@Words) { $New_Words{$_}++;}
                   1585:         my $replacement = join " OR ", ($word,@Words);
1.142     matthew  1586:         $result =~ s/(\b)$word(\b)/$1($replacement)$2/g;
                   1587:     }
1.143     matthew  1588:     return $result,sort(keys(%New_Words));
1.142     matthew  1589: }
                   1590: 
                   1591: ######################################################################
                   1592: ######################################################################
                   1593: 
                   1594: =pod 
                   1595: 
1.122     matthew  1596: =item &build_SQL_query() 
                   1597: 
1.126     matthew  1598: Builds a SQL query string from a logical expression with AND/OR keywords
                   1599: using Text::Query and &recursive_SQL_query_builder()
                   1600: 
1.122     matthew  1601: =cut
                   1602: 
                   1603: ######################################################################
                   1604: ######################################################################
1.98      harris41 1605: sub build_SQL_query {
                   1606:     my ($field_name,$logic_statement)=@_;
                   1607:     my $q=new Text::Query('abc',
                   1608: 			  -parse => 'Text::Query::ParseAdvanced',
                   1609: 			  -build => 'Text::Query::Build');
                   1610:     $q->prepare($logic_statement);
                   1611:     my $matchexp=${$q}{'matchexp'}; chomp $matchexp;
                   1612:     my $sql_query=&recursive_SQL_query_build($field_name,$matchexp);
                   1613:     return $sql_query;
                   1614: }
                   1615: 
1.122     matthew  1616: ######################################################################
                   1617: ######################################################################
                   1618: 
                   1619: =pod 
                   1620: 
                   1621: =item &build_custommetadata_query() 
                   1622: 
1.126     matthew  1623: Constructs a custom metadata query using a rather heinous regular
                   1624: expression.
                   1625: 
1.122     matthew  1626: =cut
                   1627: 
                   1628: ######################################################################
                   1629: ######################################################################
1.98      harris41 1630: sub build_custommetadata_query {
                   1631:     my ($field_name,$logic_statement)=@_;
                   1632:     my $q=new Text::Query('abc',
                   1633: 			  -parse => 'Text::Query::ParseAdvanced',
                   1634: 			  -build => 'Text::Query::BuildAdvancedString');
                   1635:     $q->prepare($logic_statement);
                   1636:     my $matchexp=${$q}{'-parse'}{'-build'}{'matchstring'};
                   1637:     # quick fix to change literal into xml tag-matching
                   1638:     # will eventually have to write a separate builder module
1.122     matthew  1639:     # wordone=wordtwo becomes\<wordone\>[^\<] *wordtwo[^\<]*\<\/wordone\>
                   1640:     $matchexp =~ s/(\w+)\\=([\w\\\+]+)?# wordone=wordtwo is changed to 
                   1641:                  /\\<$1\\>?#           \<wordone\>
                   1642:                    \[\^\\<\]?#        [^\<]         
                   1643:                    \*$2\[\^\\<\]?#           *wordtwo[^\<]
                   1644:                    \*\\<\\\/$1\\>?#                        *\<\/wordone\>
                   1645:                    /g;
1.98      harris41 1646:     return $matchexp;
                   1647: }
                   1648: 
1.122     matthew  1649: ######################################################################
                   1650: ######################################################################
                   1651: 
                   1652: =pod 
                   1653: 
                   1654: =item &recursive_SQL_query_build() 
                   1655: 
1.126     matthew  1656: Recursively constructs an SQL query.  Takes as input $dkey and $pattern.
                   1657: 
1.122     matthew  1658: =cut
                   1659: 
                   1660: ######################################################################
                   1661: ######################################################################
1.98      harris41 1662: sub recursive_SQL_query_build {
                   1663:     my ($dkey,$pattern)=@_;
                   1664:     my @matches=($pattern=~/(\[[^\]|\[]*\])/g);
                   1665:     return $pattern unless @matches;
                   1666:     foreach my $match (@matches) {
1.173     matthew  1667:         $match=~/\[ (\w+)\s(.*) \]/;
                   1668:         my ($key,$value)=($1,$2);
                   1669:         my $replacement='';
                   1670:         if ($key eq 'literal') {
1.178     matthew  1671:             $replacement="($dkey LIKE \"\%$value\%\")";
                   1672:         } elsif (lc($key) eq 'not') {
                   1673:             $value=~s/LIKE/NOT LIKE/;
1.173     matthew  1674: #          $replacement="($dkey not like $value)";
                   1675:             $replacement="$value";
                   1676:         } elsif ($key eq 'and') {
                   1677:             $value=~/(.*[\"|\)]) ([|\(|\^].*)/;
                   1678:             $replacement="($1 AND $2)";
                   1679: 	} elsif ($key eq 'or') {
                   1680:             $value=~/(.*[\"|\)]) ([|\(|\^].*)/;
                   1681:             $replacement="($1 OR $2)";
1.98      harris41 1682: 	}
                   1683: 	substr($pattern,
1.173     matthew  1684:                index($pattern,$match),
                   1685:                length($match),
                   1686:                $replacement);
1.98      harris41 1687:     }
                   1688:     &recursive_SQL_query_build($dkey,$pattern);
                   1689: }
1.22      harris41 1690: 
1.122     matthew  1691: ######################################################################
                   1692: ######################################################################
                   1693: 
                   1694: =pod 
                   1695: 
                   1696: =item &build_date_queries() 
                   1697: 
1.126     matthew  1698: Builds a SQL logic query to check time/date entries.
                   1699: Also reports errors (check for /^Incorrect/).
                   1700: 
1.122     matthew  1701: =cut
                   1702: 
                   1703: ######################################################################
                   1704: ######################################################################
1.98      harris41 1705: sub build_date_queries {
                   1706:     my ($cmonth1,$cday1,$cyear1,$cmonth2,$cday2,$cyear2,
                   1707: 	$lmonth1,$lday1,$lyear1,$lmonth2,$lday2,$lyear2)=@_;
                   1708:     my @queries;
                   1709:     if ($cmonth1 or $cday1 or $cyear1 or $cmonth2 or $cday2 or $cyear2) {
                   1710: 	unless ($cmonth1 and $cday1 and $cyear1 and
                   1711: 		$cmonth2 and $cday2 and $cyear2) {
                   1712: 	    return "Incorrect entry for the creation date.  You must specify ".
                   1713: 		   "a starting month, day, and year and an ending month, ".
                   1714: 		   "day, and year.";
                   1715: 	}
                   1716: 	my $cnumeric1=sprintf("%d%2d%2d",$cyear1,$cmonth1,$cday1);
                   1717: 	$cnumeric1+=0;
                   1718: 	my $cnumeric2=sprintf("%d%2d%2d",$cyear2,$cmonth2,$cday2);
                   1719: 	$cnumeric2+=0;
                   1720: 	if ($cnumeric1>$cnumeric2) {
                   1721: 	    return "Incorrect entry for the creation date.  The starting ".
                   1722: 		   "date must occur before the ending date.";
                   1723: 	}
                   1724: 	my $cquery="(creationdate BETWEEN '$cyear1-$cmonth1-$cday1' AND '".
                   1725: 	           "$cyear2-$cmonth2-$cday2 23:59:59')";
                   1726: 	push @queries,$cquery;
                   1727:     }
                   1728:     if ($lmonth1 or $lday1 or $lyear1 or $lmonth2 or $lday2 or $lyear2) {
                   1729: 	unless ($lmonth1 and $lday1 and $lyear1 and
                   1730: 		$lmonth2 and $lday2 and $lyear2) {
                   1731: 	    return "Incorrect entry for the last revision date.  You must ".
                   1732: 		   "specify a starting month, day, and year and an ending ".
                   1733: 		   "month, day, and year.";
                   1734: 	}
                   1735: 	my $lnumeric1=sprintf("%d%2d%2d",$lyear1,$lmonth1,$lday1);
                   1736: 	$lnumeric1+=0;
                   1737: 	my $lnumeric2=sprintf("%d%2d%2d",$lyear2,$lmonth2,$lday2);
                   1738: 	$lnumeric2+=0;
                   1739: 	if ($lnumeric1>$lnumeric2) {
                   1740: 	    return "Incorrect entry for the last revision date.  The ".
                   1741: 		   "starting date must occur before the ending date.";
                   1742: 	}
                   1743: 	my $lquery="(lastrevisiondate BETWEEN '$lyear1-$lmonth1-$lday1' AND '".
                   1744: 	           "$lyear2-$lmonth2-$lday2 23:59:59')";
                   1745: 	push @queries,$lquery;
                   1746:     }
                   1747:     if (@queries) {
                   1748: 	return join(" AND ",@queries);
                   1749:     }
                   1750:     return '';
1.18      harris41 1751: }
1.6       harris41 1752: 
1.122     matthew  1753: ######################################################################
                   1754: ######################################################################
                   1755: 
1.144     matthew  1756: =pod
                   1757: 
                   1758: =item &copyright_check()
                   1759: 
                   1760: =cut
                   1761: 
                   1762: ######################################################################
                   1763: ######################################################################
                   1764: sub copyright_check {
                   1765:     my $Metadata = shift;
                   1766:     # Check copyright tags and skip results the user cannot use
                   1767:     my (undef,undef,$resdom,$resname) = split('/',
                   1768:                                               $Metadata->{'url'});
                   1769:     # Check for priv
                   1770:     if (($Metadata->{'copyright'} eq 'priv') && 
                   1771:         (($ENV{'user.name'} ne $resname) &&
                   1772:          ($ENV{'user.domain'} ne $resdom))) {
                   1773:         return 0;
                   1774:     }
                   1775:     # Check for domain
                   1776:     if (($Metadata->{'copyright'} eq 'domain') &&
                   1777:         ($ENV{'user.domain'} ne $resdom)) {
                   1778:         return 0;
                   1779:     }
                   1780:     return 1;
                   1781: }
                   1782: 
1.151     matthew  1783: 
                   1784: ######################################################################
                   1785: ######################################################################
                   1786: 
                   1787: =pod
                   1788: 
                   1789: =item &ensure_db_and_table
                   1790: 
                   1791: Ensure we can get lonmysql to connect to the database and the table we
                   1792: need exists.
                   1793: 
                   1794: Inputs: $r, table id
                   1795: 
                   1796: Returns: undef on error, 1 if the table exists.
                   1797: 
                   1798: =cut
                   1799: 
                   1800: ######################################################################
                   1801: ######################################################################
                   1802: sub ensure_db_and_table {
                   1803:     my ($r,$table) = @_;
                   1804:     ##
                   1805:     ## Sanity check the table id.
                   1806:     ##
                   1807:     if (! defined($table) || $table eq '' || $table =~ /\D/ ) {
                   1808:         $r->print("Unable to retrieve search results.  ".
                   1809:                   "Unable to determine the table results were stored in.  ".
                   1810:                   "</body></html>");
                   1811:         return undef;
                   1812:     }
                   1813:     ##
                   1814:     ## Make sure we can connect and the table exists.
                   1815:     ##
                   1816:     my $connection_result = &Apache::lonmysql::connect_to_db();
                   1817:     if (!defined($connection_result)) {
                   1818:         $r->print("Unable to connect to the MySQL database where your results".
                   1819:                   " are stored. </body></html>");
                   1820:         &Apache::lonnet::logthis("lonsearchcat: unable to get lonmysql to".
                   1821:                                  " connect to database.");
                   1822:         &Apache::lonnet::logthis(&Apache::lonmysql::get_error());
                   1823:         return undef;
                   1824:     }
                   1825:     my $table_check = &Apache::lonmysql::check_table($table);
                   1826:     if (! defined($table_check)) {
                   1827:         $r->print("A MySQL error has occurred.</form></body></html>");
                   1828:         &Apache::lonnet::logthis("lonmysql was unable to determine the status".
                   1829:                                  " of table ".$table);
                   1830:         return undef;
                   1831:     } elsif (! $table_check) {
                   1832:         $r->print("The table of results could not be found.");
                   1833:         &Apache::lonnet::logthis("The user requested a table, ".$table.
                   1834:                                  ", that could not be found.");
                   1835:         return undef;
                   1836:     }
                   1837:     return 1;
                   1838: }
                   1839: 
                   1840: ######################################################################
                   1841: ######################################################################
                   1842: 
                   1843: =pod
                   1844: 
                   1845: =item &print_sort_form
                   1846: 
                   1847: =cut
                   1848: 
                   1849: ######################################################################
                   1850: ######################################################################
                   1851: sub print_sort_form {
                   1852:     my ($r,$pretty_query_string) = @_;
                   1853:     ##
1.187     www      1854:     my %SortableFields=&Apache::lonlocal::texthash( 
                   1855:          id        => 'Default',
1.151     matthew  1856:          title     => 'Title',
                   1857:          author    => 'Author',
                   1858:          subject   => 'Subject',
                   1859:          url       => 'URL',
                   1860:          version   => 'Version Number',
                   1861:          mime      => 'Mime type',
                   1862:          lang      => 'Language',
                   1863:          owner     => 'Owner/Publisher',
                   1864:          copyright => 'Copyright',
                   1865:          hostname  => 'Host',
                   1866:          creationdate     => 'Creation Date',
1.187     www      1867:          lastrevisiondate => 'Revision Date'
1.151     matthew  1868:      );
                   1869:     ##
                   1870:     my $table = $ENV{'form.table'};
                   1871:     return if (! &ensure_db_and_table($r,$table));
                   1872:     ##
                   1873:     ## Get the number of results 
                   1874:     ##
                   1875:     my $total_results = &Apache::lonmysql::number_of_rows($table);
                   1876:     if (! defined($total_results)) {
                   1877:         $r->print("A MySQL error has occurred.</form></body></html>");
                   1878:         &Apache::lonnet::logthis("lonmysql was unable to determine the number".
                   1879:                                  " of rows in table ".$table);
                   1880:         &Apache::lonnet::logthis(&Apache::lonmysql::get_error());
                   1881:         return;
                   1882:     }
                   1883:     my $result;
                   1884:     $result.=<<END;
                   1885: <html>
                   1886: <head>
                   1887: <script>
                   1888:     function change_sort() {
                   1889:         var newloc = "/adm/searchcat?phase=results";
                   1890:         newloc += "&persistent_db_id=$ENV{'form.persistent_db_id'}";
                   1891:         newloc += "&sortby=";
                   1892:         newloc += document.forms.statusform.elements.sortby.value;
                   1893:         parent.resultsframe.location= newloc;
                   1894:     }
                   1895: </script>
                   1896: <title>Results</title>
                   1897: </head>
1.155     matthew  1898: $bodytag
1.151     matthew  1899: <form name="statusform" action="" method="post">
1.153     matthew  1900: <input type="hidden" name="Queue" value="" />
1.151     matthew  1901: END
                   1902: 
                   1903: #<h2>Sort Results</h2>
                   1904: #Sort by: <select size="1" name="sortby" onchange="javascript:change_sort();">
                   1905: #    $ENV{'form.sortby'} = 'id' if (! defined($ENV{'form.sortby'}));
                   1906: #    foreach (keys(%SortableFields)) {
                   1907: #        $result.="<option name=\"$_\"";
                   1908: #        if ($_ eq $ENV{'form.sortby'}) {
                   1909: #            $result.=" selected ";
                   1910: #        }
                   1911: #        $result.=" >$SortableFields{$_}</option>\n";
                   1912: #    }
                   1913: #    $result.="</select>\n";
                   1914:     my $revise = &revise_button();
                   1915:     $result.=<<END;
                   1916: <p>
                   1917: There are $total_results matches to your query. $revise
                   1918: </p><p>
                   1919: Search:$pretty_query_string
                   1920: </p>
                   1921: </form>
                   1922: </body>
                   1923: </html>
                   1924: END
                   1925:     $r->print($result);
                   1926:     return;
                   1927: }
                   1928: 
1.144     matthew  1929: #####################################################################
                   1930: #####################################################################
                   1931: 
                   1932: =pod
                   1933: 
                   1934: =item MySQL Table Description
                   1935: 
                   1936: MySQL table creation requires a precise description of the data to be
                   1937: stored.  The use of the correct types to hold data is vital to efficient
                   1938: storage and quick retrieval of records.  The columns must be described in
                   1939: the following format:
                   1940: 
                   1941: =cut
                   1942: 
1.170     matthew  1943: #####################################################################
                   1944: #####################################################################
                   1945: 
                   1946: my @Datatypes = 
                   1947:     ( { name => 'id', 
                   1948:         type => 'MEDIUMINT',
                   1949:         restrictions => 'UNSIGNED NOT NULL',
                   1950:         primary_key  => 'yes',
                   1951:         auto_inc     => 'yes' },
                   1952:       { name => 'title',     type=>'TEXT'},
                   1953:       { name => 'author',    type=>'TEXT'},
                   1954:       { name => 'subject',   type=>'TEXT'},
                   1955:       { name => 'url',       type=>'TEXT', restrictions => 'NOT NULL' },
                   1956:       { name => 'keywords',  type=>'TEXT'},
                   1957:       { name => 'version',   type=>'TEXT'},
                   1958:       { name => 'notes',     type=>'TEXT'},
                   1959:       { name => 'abstract',  type=>'TEXT'},
                   1960:       { name => 'mime',      type=>'TEXT'},
                   1961:       { name => 'lang',      type=>'TEXT'},
                   1962:       { name => 'owner',     type=>'TEXT'},
                   1963:       { name => 'copyright', type=>'TEXT'},
                   1964:       { name => 'hostname',  type=>'TEXT'},
1.144     matthew  1965:       #--------------------------------------------------
1.170     matthew  1966:       { name => 'creationdate',     type=>'DATETIME'},
                   1967:       { name => 'lastrevisiondate', type=>'DATETIME'},
1.144     matthew  1968:       #--------------------------------------------------
                   1969:       );
                   1970: 
1.147     matthew  1971: my @Fullindicies = 
1.151     matthew  1972:     qw/title/;
                   1973: #    qw/title author subject abstract mime language owner copyright/;
1.147     matthew  1974:     
1.144     matthew  1975: ######################################################################
                   1976: ######################################################################
                   1977: 
                   1978: =pod
                   1979: 
1.146     matthew  1980: =item &create_results_table()
                   1981: 
                   1982: Creates the table of search results by calling lonmysql.  Stores the
                   1983: table id in $ENV{'form.table'}
                   1984: 
                   1985: Inputs: none.
                   1986: 
                   1987: Returns: the identifier of the table on success, undef on error.
                   1988: 
                   1989: =cut
                   1990: 
                   1991: ######################################################################
                   1992: ######################################################################
                   1993: sub create_results_table {
                   1994:     my $table = &Apache::lonmysql::create_table
1.170     matthew  1995:         ( { columns => \@Datatypes,
1.172     matthew  1996:             FULLTEXT => [{'columns' => \@Fullindicies},],
1.146     matthew  1997:         } );
                   1998:     if (defined($table)) {
                   1999:         $ENV{'form.table'} = $table;
                   2000:         return $table;
                   2001:     } 
                   2002:     return undef; # Error...
                   2003: }
1.148     matthew  2004: 
1.146     matthew  2005: ######################################################################
                   2006: ######################################################################
                   2007: 
                   2008: =pod
                   2009: 
1.150     matthew  2010: =item Search Status update functions
1.144     matthew  2011: 
1.150     matthew  2012: Each of the following functions changes the values of one of the
                   2013: input fields used to display the search status to the user.  The names
                   2014: should be explanatory.
1.144     matthew  2015: 
1.150     matthew  2016: Inputs: Apache request handler ($r), text to display.
1.148     matthew  2017: 
1.150     matthew  2018: Returns: Nothing.
1.148     matthew  2019: 
                   2020: =over 4
                   2021: 
                   2022: =item &update_count_status()
                   2023: 
1.150     matthew  2024: =item &update_status()
1.148     matthew  2025: 
1.150     matthew  2026: =item &update_seconds()
1.148     matthew  2027: 
                   2028: =back
                   2029: 
                   2030: =cut
                   2031: 
                   2032: ######################################################################
                   2033: ######################################################################
                   2034: sub update_count_status {
                   2035:     my ($r,$text) = @_;
                   2036:     $text =~ s/\'/\\\'/g;
                   2037:     $r->print
                   2038:         ("<script>document.statusform.count.value = ' $text'</script>\n");
                   2039:     $r->rflush();
                   2040: }
                   2041: 
1.150     matthew  2042: sub update_status {
1.148     matthew  2043:     my ($r,$text) = @_;
                   2044:     $text =~ s/\'/\\\'/g;
                   2045:     $r->print
1.150     matthew  2046:         ("<script>document.statusform.status.value = ' $text'</script>\n");
1.148     matthew  2047:     $r->rflush();
                   2048: }
                   2049: 
1.150     matthew  2050: sub update_seconds {
1.148     matthew  2051:     my ($r,$text) = @_;
                   2052:     $text =~ s/\'/\\\'/g;
                   2053:     $r->print
1.150     matthew  2054:         ("<script>document.statusform.seconds.value = ' $text'</script>\n");
1.148     matthew  2055:     $r->rflush();
                   2056: }
                   2057: 
                   2058: ######################################################################
                   2059: ######################################################################
                   2060: 
                   2061: =pod
                   2062: 
1.151     matthew  2063: =item &revise_button
                   2064: 
                   2065: Inputs: None
                   2066: 
                   2067: Returns: html string for a 'revise search' button.
                   2068: 
                   2069: =cut
                   2070: 
                   2071: ######################################################################
                   2072: ######################################################################
                   2073: sub revise_button {
                   2074:     my $revise_phase = 'disp_basic';
                   2075:     $revise_phase = 'disp_adv' if ($ENV{'form.searchmode'} eq 'advanced');
                   2076:     my $newloc = '/adm/searchcat'.
                   2077:         '?persistent_db_id='.$ENV{'form.persistent_db_id'}.
1.158     matthew  2078:             '&cleargroupsort=1'.
1.151     matthew  2079:             '&phase='.$revise_phase;
                   2080:     my $result = qq{<input type="button" value="Revise search" name="revise"} .
                   2081:         qq{ onClick="parent.location='$newloc';" /> };
                   2082:     return $result;
                   2083: }
                   2084: 
                   2085: ######################################################################
                   2086: ######################################################################
                   2087: 
                   2088: =pod
                   2089: 
1.144     matthew  2090: =item &run_search 
                   2091: 
                   2092: =cut
                   2093: 
                   2094: ######################################################################
                   2095: ######################################################################
                   2096: sub run_search {
1.146     matthew  2097:     my ($r,$query,$customquery,$customshow,$serverlist,$pretty_string) = @_;
1.150     matthew  2098:     my $connection = $r->connection;
1.144     matthew  2099:     #
1.145     matthew  2100:     # Timing variables
                   2101:     #
                   2102:     my $starttime = time;
1.151     matthew  2103:     my $max_time  = 30;  # seconds for the search to complete
1.145     matthew  2104:     #
1.146     matthew  2105:     # Print run_search header
                   2106:     #
1.151     matthew  2107:     $r->print(<<END);
                   2108: <html>
                   2109: <head><title>Search Status</title></head>
1.155     matthew  2110: $bodytag
1.151     matthew  2111: <form name="statusform" action="" method="post">
                   2112: <input type="hidden" name="Queue" value="" />
                   2113: END
                   2114:     # Check to see if $pretty_string has more than one carriage return.
                   2115:     # Assume \n s are following <br /> s and truncate the value.
                   2116:     # (there is probably a better way)...
1.152     matthew  2117:     my @Lines = split /<br \/>/,$pretty_string;
                   2118:     if (@Lines > 2) {
                   2119:         $pretty_string = join '<br \>',(@Lines[0..2],'....<br />');
1.151     matthew  2120:     }
1.187     www      2121:     $r->print(&mt("Search").": ".$pretty_string);
1.146     matthew  2122:     $r->rflush();
                   2123:     #
1.145     matthew  2124:     # Determine the servers we need to contact.
                   2125:     #
1.144     matthew  2126:     my @Servers_to_contact;
                   2127:     if (defined($serverlist)) {
1.152     matthew  2128:         if (ref($serverlist) eq 'ARRAY') {
                   2129:             @Servers_to_contact = @$serverlist;
                   2130:         } else {
                   2131:             @Servers_to_contact = ($serverlist);
                   2132:         }
1.144     matthew  2133:     } else {
                   2134:         @Servers_to_contact = sort(keys(%Apache::lonnet::libserv));
                   2135:     }
                   2136:     my %Server_status;
1.146     matthew  2137:     my $table =$ENV{'form.table'};
1.150     matthew  2138:     if (! defined($table) || $table eq '' || $table =~ /\D/ ) {
1.147     matthew  2139:         $r->print("Unable to determine table id to store search results in.".
1.148     matthew  2140:                   "The search has been aborted.</body></html>");
1.147     matthew  2141:         return;
                   2142:     }
                   2143:     my $table_status = &Apache::lonmysql::check_table($table);
                   2144:     if (! defined($table_status)) {
                   2145:         $r->print("Unable to determine status of table.</body></html>");
                   2146:         &Apache::lonnet::logthis("Bogus table id of $table for ".
                   2147:                                  "$ENV{'user.name'} @ $ENV{'user.domain'}");
                   2148:         &Apache::lonnet::logthis("lonmysql error = ".
1.144     matthew  2149:                                  &Apache::lonmysql::get_error());
1.147     matthew  2150:         return;
                   2151:     }
                   2152:     if (! $table_status) {
                   2153:         $r->print("The table id,$table, we tried to use is invalid.".
1.148     matthew  2154:                   "The search has been aborted.</body></html>");
1.144     matthew  2155:         return;
                   2156:     }
1.145     matthew  2157:     ##
1.146     matthew  2158:     ## Prepare for the big loop.
                   2159:     ##
1.144     matthew  2160:     my $hitcountsum;
                   2161:     my $server; 
                   2162:     my $status;
1.151     matthew  2163:     my $revise = &revise_button();
1.148     matthew  2164:     $r->print(<<END);
                   2165: <table>
1.151     matthew  2166: <tr><th>Status</th><th>Total Matches</th><th>Time Remaining</th><th></th></tr>
1.148     matthew  2167: <tr>
1.150     matthew  2168: <td><input type="text" name="status"  value="" size="30" /></td>
                   2169: <td><input type="text" name="count"   value="" size="10" /></td>
                   2170: <td><input type="text" name="seconds" value="" size="8" /></td>
1.151     matthew  2171: <td>$revise</td>
1.148     matthew  2172: </tr>
                   2173: </table>
                   2174: </form>
                   2175: END
                   2176:     $r->rflush();
1.150     matthew  2177:     my $time_remaining = $max_time - (time - $starttime) ;
                   2178:     my $last_time = $time_remaining;
                   2179:     &update_seconds($r,$time_remaining);
1.178     matthew  2180:     &update_status($r,'contacting '.$Servers_to_contact[0]);
1.159     matthew  2181:     while (($time_remaining > 0) &&
1.144     matthew  2182:            ((@Servers_to_contact) || keys(%Server_status))) {
                   2183:         # Send out a search request if it needs to be done.
                   2184:         if (@Servers_to_contact) {
                   2185:             # Contact one server
                   2186:             my $server = shift(@Servers_to_contact);
1.189     www      2187:             &update_status($r,&mt('contacting').' '.$server);
1.144     matthew  2188:             my $reply=&Apache::lonnet::metadata_query($query,$customquery,
                   2189:                                                       $customshow,[$server]);
                   2190:             ($server) = keys(%$reply);
                   2191:             $Server_status{$server} = $reply->{$server};
                   2192:         } else {
1.150     matthew  2193:             # wait a sec. to give time for files to be written
                   2194:             # This sleep statement is here instead of outside the else 
                   2195:             # block because we do not want to pause if we have servers
                   2196:             # left to contact.  
1.183     matthew  2197:             if (scalar (keys(%Server_status))) {
                   2198:                 &update_status($r,
1.189     www      2199:                        &mt('waiting on').' '.(join(' ',keys(%Server_status))));
1.183     matthew  2200:             }
1.150     matthew  2201:             sleep(1)1.144     matthew  2202:         }
1.159     matthew  2203:         #
                   2204:         #
                   2205:         # Loop through the servers we have contacted but do not
                   2206:         # have results from yet, looking for results.
1.144     matthew  2207:         while (my ($server,$status) = each(%Server_status)) {
1.150     matthew  2208:             last if ($connection->aborted());
1.144     matthew  2209:             if ($status eq 'con_lost') {
                   2210:                 delete ($Server_status{$server});
                   2211:                 next;
                   2212:             }
                   2213:             $status=~/^([\.\w]+)$/; 
                   2214:        	    my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$1;
                   2215:             if (-e $datafile && ! -e "$datafile.end") {
1.189     www      2216:                 &update_status($r,&mt('Receiving results from').' '.$server);
1.144     matthew  2217:                 next;
                   2218:             }
1.150     matthew  2219:             last if ($connection->aborted());
1.144     matthew  2220:             if (-e "$datafile.end") {
1.189     www      2221:                 &update_status($r,&mt('Reading results from').' '.$server);
1.144     matthew  2222:                 if (-z "$datafile") {
                   2223:                     delete($Server_status{$server});
                   2224:                     next;
                   2225:                 }
                   2226:                 my $fh;
                   2227:                 if (!($fh=Apache::File->new($datafile))) { 
1.146     matthew  2228:                     $r->print("Unable to open search results file for ".
1.145     matthew  2229:                                   "server $server.  Omitting from search");
1.150     matthew  2230:                     delete($Server_status{$server}); 
                   2231:                    next;
1.144     matthew  2232:                 }
                   2233:                 # Read in the whole file.
                   2234:                 while (my $result = <$fh>) {
1.150     matthew  2235:                     last if ($connection->aborted());
1.144     matthew  2236:                     # handle custom fields?  Someday we will!
                   2237:                     chomp($result);
                   2238:                     next unless $result;
                   2239:                     # Parse the result.
                   2240:                     my %Fields = &parse_raw_result($result,$server);
                   2241:                     $Fields{'hostname'} = $server;
                   2242:                     next if (! &copyright_check(\%Fields));
                   2243:                     # Store the result in the mysql database
                   2244:                     my $result = &Apache::lonmysql::store_row($table,\%Fields);
                   2245:                     if (! defined($result)) {
1.146     matthew  2246:                         $r->print(&Apache::lonmysql::get_error());
1.144     matthew  2247:                     }
1.146     matthew  2248:                     # $r->print(&Apache::lonmysql::get_debug());
1.144     matthew  2249:                     $hitcountsum ++;
1.150     matthew  2250:                     $time_remaining = $max_time - (time - $starttime) ;
                   2251:                     if ($last_time - $time_remaining > 0) {
                   2252:                         &update_seconds($r,$time_remaining);
                   2253:                         $last_time = $time_remaining;
                   2254:                     }
                   2255:                     if ($hitcountsum % 50 == 0) {
                   2256:                         &update_count_status($r,$hitcountsum);
                   2257:                     }
1.144     matthew  2258:                 } # End of foreach (@results)
                   2259:                 $fh->close();
                   2260:                 # $server is only deleted if the results file has been 
                   2261:                 # found and (successfully) opened.  This may be a bad idea.
                   2262:                 delete($Server_status{$server});
                   2263:             }
1.150     matthew  2264:             last if ($connection->aborted());
1.148     matthew  2265:             &update_count_status($r,$hitcountsum);
1.144     matthew  2266:         }
1.150     matthew  2267:         last if ($connection->aborted());
1.144     matthew  2268:         # Finished looping through the servers
1.159     matthew  2269:         $starttime = time if (@Servers_to_contact);
1.150     matthew  2270:         $time_remaining = $max_time - (time - $starttime) ;
                   2271:         if ($last_time - $time_remaining > 0) {
                   2272:             $last_time = $time_remaining;
                   2273:             &update_seconds($r,$time_remaining);
                   2274:         }
1.144     matthew  2275:     }
1.189     www      2276:     &update_status($r,&mt('Search Complete').$server);
1.151     matthew  2277:     &update_seconds($r,0);
1.144     matthew  2278:     &Apache::lonmysql::disconnect_from_db();
                   2279:     # We have run out of time or run out of servers to talk to and
                   2280:     # results to get.  
1.146     matthew  2281:     $r->print("</body></html>");
1.153     matthew  2282:     if ($ENV{'form.catalogmode'} ne 'groupsearch') {
                   2283:         $r->print("<script>".
                   2284:                       "window.location='/adm/searchcat?".
                   2285:                       "phase=sort&".
                   2286:                       "persistent_db_id=$ENV{'form.persistent_db_id'}';".
                   2287:                   "</script>");
                   2288:     }
1.144     matthew  2289:     return;
                   2290: }
                   2291: 
                   2292: ######################################################################
                   2293: ######################################################################
                   2294: =pod
                   2295: 
1.146     matthew  2296: =item &prev_next_buttons
1.144     matthew  2297: 
                   2298: =cut
                   2299: 
                   2300: ######################################################################
                   2301: ######################################################################
1.146     matthew  2302: sub prev_next_buttons {
1.145     matthew  2303:     my ($current_min,$show,$total,$parms) = @_;
                   2304:     return '' if ($show eq 'all'); # No links if you get them all at once.
                   2305:     my $links;
                   2306:     ##
                   2307:     ## Prev
                   2308:     my $prev_min = $current_min - $show;
1.151     matthew  2309:     $prev_min = 1 if $prev_min < 1;
1.145     matthew  2310:     if ($prev_min < $current_min) {
                   2311:         $links .= qq{
1.146     matthew  2312: <a href="/adm/searchcat?$parms&start=$prev_min&show=$show">prev</a>
1.145     matthew  2313: };    
1.146     matthew  2314:     } else {
                   2315:         $links .= 'prev';
1.145     matthew  2316:     }
                   2317:     ##
                   2318:     ## Pages.... Someday.
                   2319:     ##
1.146     matthew  2320:     $links .= qq{ &nbsp;
                   2321: <a href="/adm/searchcat?$parms&start=$current_min&$show=$show">reload</a>
                   2322: };
1.145     matthew  2323:     ##
                   2324:     ## Next
                   2325:     my $next_min = $current_min + $show;
1.146     matthew  2326:     $next_min = $current_min if ($next_min > $total);
1.145     matthew  2327:     if ($next_min != $current_min) {
1.146     matthew  2328:         $links .= qq{ &nbsp;
                   2329: <a href="/adm/searchcat?$parms&start=$next_min&show=$show">next</a>
1.145     matthew  2330: };    
1.146     matthew  2331:     } else {
                   2332:         $links .= '&nbsp;next';
1.144     matthew  2333:     }
1.145     matthew  2334:     return $links;
1.144     matthew  2335: }
                   2336: ######################################################################
                   2337: ######################################################################
                   2338: 
                   2339: =pod
                   2340: 
                   2341: =item &display_results
                   2342: 
                   2343: =cut
                   2344: 
                   2345: ######################################################################
                   2346: ######################################################################
                   2347: sub display_results {
1.150     matthew  2348:     my ($r,$importbutton,$closebutton) = @_;
                   2349:     my $connection = $r->connection;
                   2350:     $r->print(&search_results_header($importbutton,$closebutton));
1.144     matthew  2351:     ##
                   2352:     ## Set viewing function
                   2353:     ##
                   2354:     my $viewfunction = $Views{$ENV{'form.viewselect'}};
                   2355:     if (!defined($viewfunction)) {
                   2356:         $r->print("Internal Error - Bad view selected.\n");
                   2357:         $r->rflush();
                   2358:         return;
                   2359:     }
                   2360:     ##
1.158     matthew  2361:     ## $checkbox_num is a count of the number of checkboxes output on the 
                   2362:     ## page this is used only during catalogmode=groupsearch.
                   2363:     my $checkbox_num = 0;
                   2364:     ##
1.144     matthew  2365:     ## Get the catalog controls setup
                   2366:     ##
1.146     matthew  2367:     my $action = "/adm/searchcat?phase=results";
                   2368:     ##
1.147     matthew  2369:     ## Deal with groupsearch
1.146     matthew  2370:     ##
                   2371:     if ($ENV{'form.catalogmode'} eq 'groupsearch') {
                   2372:         if (! tie(%groupsearch_db,'GDBM_File',$diropendb,
1.148     matthew  2373:                   &GDBM_WRCREAT(),0640)) {
1.150     matthew  2374:             $r->print('Unable to store import results.</form></body></html>');
1.146     matthew  2375:             $r->rflush();
                   2376:             return;
                   2377:         } 
1.144     matthew  2378:     }
1.145     matthew  2379:     ##
                   2380:     ## Prepare the table for querying
                   2381:     ##
1.144     matthew  2382:     my $table = $ENV{'form.table'};
1.151     matthew  2383:     return if (! &ensure_db_and_table($r,$table));
1.145     matthew  2384:     ##
                   2385:     ## Get the number of results 
                   2386:     ##
                   2387:     my $total_results = &Apache::lonmysql::number_of_rows($table);
                   2388:     if (! defined($total_results)) {
1.150     matthew  2389:         $r->print("A MySQL error has occurred.</form></body></html>");
1.145     matthew  2390:         &Apache::lonnet::logthis("lonmysql was unable to determine the number".
                   2391:                                  " of rows in table ".$table);
                   2392:         &Apache::lonnet::logthis(&Apache::lonmysql::get_error());
                   2393:         return;
                   2394:     }
                   2395:     ##
                   2396:     ## Determine how many results we need to get
                   2397:     ##
1.151     matthew  2398:     $ENV{'form.start'} = 1      if (! exists($ENV{'form.start'}));
                   2399:     $ENV{'form.show'}  = 'all'  if (! exists($ENV{'form.show'}));
1.146     matthew  2400:     my $min = $ENV{'form.start'};
1.145     matthew  2401:     my $max;
                   2402:     if ($ENV{'form.show'} eq 'all') {
                   2403:         $max = $total_results ;
                   2404:     } else {
1.151     matthew  2405:         $max = $min + $ENV{'form.show'} - 1;
1.146     matthew  2406:         $max = $total_results if ($max > $total_results);
1.145     matthew  2407:     }
                   2408:     ##
                   2409:     ## Output links (if necessary) for 'prev' and 'next' pages.
                   2410:     ##
1.146     matthew  2411:     $r->print
1.148     matthew  2412:         ('<center>'.
1.146     matthew  2413:          &prev_next_buttons($min,$ENV{'form.show'},$total_results,
                   2414:                             "table=".$ENV{'form.table'}.
                   2415:                             "&phase=results".
                   2416:                             "&persistent_db_id=".$ENV{'form.persistent_db_id'})
1.148     matthew  2417:          ."</center>\n"
1.146     matthew  2418:          );
1.150     matthew  2419:     if ($total_results == 0) {
1.181     matthew  2420:         $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="1">'.
1.187     www      2421:                   '<h3>'.&mt('There are currently no results').'.</h3>'.
1.150     matthew  2422:                   "</form></body></html>");
                   2423:         return;
                   2424:     } else {
                   2425:         $r->print
                   2426:             ("<center>Results $min to $max out of $total_results</center>\n");
                   2427:     }
1.145     matthew  2428:     ##
                   2429:     ## Get results from MySQL table
                   2430:     ##
                   2431:     my @Results = &Apache::lonmysql::get_rows($table,
1.151     matthew  2432:                                               'id>='.$min.' AND id<='.$max);
1.145     matthew  2433:     ##
                   2434:     ## Loop through the results and output them.
                   2435:     ##
1.144     matthew  2436:     foreach my $row (@Results) {
1.150     matthew  2437:         if ($connection->aborted()) {
1.162     www      2438:             &cleanup();
1.150     matthew  2439:             return;
                   2440:         }
1.144     matthew  2441:         my %Fields = %{&parse_row(@$row)};
1.145     matthew  2442:         my $output="<p>\n";
1.158     matthew  2443:         my $prefix=&catalogmode_output($Fields{'title'},$Fields{'url'},
                   2444:                                        $Fields{'id'},$checkbox_num++);
1.144     matthew  2445:         # Render the result into html
1.150     matthew  2446:         $output.= &$viewfunction($prefix,%Fields);
1.145     matthew  2447:         # Print them out as they come in.
1.144     matthew  2448:         $r->print($output);
                   2449:         $r->rflush();
                   2450:     }
                   2451:     if (@Results < 1) {
1.187     www      2452:         $r->print(&mt("There were no results matching your query"));
1.147     matthew  2453:     } else {
                   2454:         $r->print
1.148     matthew  2455:             ('<center>'.
1.147     matthew  2456:              &prev_next_buttons($min,$ENV{'form.show'},$total_results,
                   2457:                                 "table=".$ENV{'form.table'}.
                   2458:                                 "&phase=results".
                   2459:                                 "&persistent_db_id=".
                   2460:                                 $ENV{'form.persistent_db_id'})
1.148     matthew  2461:              ."</center>\n"
1.147     matthew  2462:              );
1.144     matthew  2463:     }
1.150     matthew  2464:     $r->print("</form></body></html>");
1.144     matthew  2465:     $r->rflush();
1.150     matthew  2466:     untie %groupsearch_db if (tied(%groupsearch_db));
1.144     matthew  2467:     return;
                   2468: }
                   2469: 
                   2470: ######################################################################
                   2471: ######################################################################
                   2472: 
                   2473: =pod
                   2474: 
1.158     matthew  2475: =item &catalogmode_output($title,$url,$fnum,$checkbox_num)
1.145     matthew  2476: 
                   2477: Returns html needed for the various catalog modes.  Gets inputs from
1.158     matthew  2478: $ENV{'form.catalogmode'}.  Stores data in %groupsearch_db.
1.145     matthew  2479: 
                   2480: =cut
                   2481: 
                   2482: ######################################################################
                   2483: ######################################################################
                   2484: sub catalogmode_output {
                   2485:     my $output = '';
1.158     matthew  2486:     my ($title,$url,$fnum,$checkbox_num) = @_;
1.145     matthew  2487:     if ($ENV{'form.catalogmode'} eq 'interactive') {
1.150     matthew  2488:         $title=~ s/\'/\\\'/g;
1.145     matthew  2489:         if ($ENV{'form.catalogmode'} eq 'interactive') {
                   2490:             $output.=<<END 
                   2491: <font size='-1'><INPUT TYPE="button" NAME="returnvalues" VALUE="SELECT"
                   2492: onClick="javascript:select_data('$title','$url')">
                   2493: </font>
                   2494: END
                   2495:         }
1.150     matthew  2496:     } elsif ($ENV{'form.catalogmode'} eq 'groupsearch') {
1.145     matthew  2497:         $groupsearch_db{"pre_${fnum}_link"}=$url;
                   2498:         $groupsearch_db{"pre_${fnum}_title"}=$title;
                   2499:         $output.=<<END;
                   2500: <font size='-1'>
                   2501: <input type="checkbox" name="returnvalues" value="SELECT"
1.158     matthew  2502: onClick="javascript:queue($checkbox_num,$fnum)" />
1.145     matthew  2503: </font>
                   2504: END
                   2505:     }
                   2506:     return $output;
                   2507: }
                   2508: ######################################################################
                   2509: ######################################################################
                   2510: 
                   2511: =pod
                   2512: 
1.144     matthew  2513: =item &parse_row
                   2514: 
                   2515: Parse a row returned from the database.
                   2516: 
                   2517: =cut
                   2518: 
                   2519: ######################################################################
                   2520: ######################################################################
                   2521: sub parse_row {
                   2522:     my @Row = @_;
                   2523:     my %Fields;
                   2524:     for (my $i=0;$i<=$#Row;$i++) {
1.170     matthew  2525:         $Fields{$Datatypes[$i]->{'name'}}=&Apache::lonnet::unescape($Row[$i]);
1.144     matthew  2526:     }
                   2527:     $Fields{'language'} = 
                   2528:         &Apache::loncommon::languagedescription($Fields{'lang'});
                   2529:     $Fields{'copyrighttag'} =
                   2530:         &Apache::loncommon::copyrightdescription($Fields{'copyright'});
                   2531:     $Fields{'mimetag'} =
                   2532:         &Apache::loncommon::filedescription($Fields{'mime'});
                   2533:     return \%Fields;
                   2534: }
1.126     matthew  2535: 
                   2536: ###########################################################
                   2537: ###########################################################
                   2538: 
                   2539: =pod
                   2540: 
                   2541: =item &parse_raw_result()
                   2542: 
                   2543: Takes a line from the file of results and parse it.  Returns a hash 
                   2544: with keys for the following fields:
                   2545: 'title', 'author', 'subject', 'url', 'keywords', 'version', 'notes', 
                   2546: 'abstract', 'mime', 'lang', 'owner', 'copyright', 'creationdate', 
                   2547: 'lastrevisiondate'.
                   2548: 
                   2549: In addition, the following tags are set by calling the appropriate 
                   2550: lonnet function: 'language', 'cprtag', 'mimetag'.
                   2551: 
                   2552: The 'title' field is set to "Untitled" if the title field is blank.
                   2553: 
                   2554: 'abstract' and 'keywords' are truncated to 200 characters.
                   2555: 
                   2556: =cut
                   2557: 
                   2558: ###########################################################
                   2559: ###########################################################
                   2560: sub parse_raw_result {
                   2561:     my ($result,$hostname) = @_;
                   2562:     # Check for a comma - if it is there then we do not need to unescape the
                   2563:     # string.  There seems to be some kind of problem with some items in
                   2564:     # the database - the entire string gets sent out unescaped...?
                   2565:     unless ($result =~ /,/) {
                   2566:         $result = &Apache::lonnet::unescape($result);
                   2567:     }
                   2568:     my @fields=map {
                   2569:         &Apache::lonnet::unescape($_);
                   2570:     } (split(/\,/,$result));
                   2571:     my ($title,$author,$subject,$url,$keywords,$version,
                   2572:         $notes,$abstract,$mime,$lang,
                   2573:         $creationdate,$lastrevisiondate,$owner,$copyright)=@fields;
                   2574:     my %Fields = 
                   2575:         ( title     => &Apache::lonnet::unescape($title),
                   2576:           author    => &Apache::lonnet::unescape($author),
                   2577:           subject   => &Apache::lonnet::unescape($subject),
                   2578:           url       => &Apache::lonnet::unescape($url),
                   2579:           keywords  => &Apache::lonnet::unescape($keywords),
                   2580:           version   => &Apache::lonnet::unescape($version),
                   2581:           notes     => &Apache::lonnet::unescape($notes),
                   2582:           abstract  => &Apache::lonnet::unescape($abstract),
                   2583:           mime      => &Apache::lonnet::unescape($mime),
                   2584:           lang      => &Apache::lonnet::unescape($lang),
                   2585:           owner     => &Apache::lonnet::unescape($owner),
                   2586:           copyright => &Apache::lonnet::unescape($copyright),
                   2587:           creationdate     => &Apache::lonnet::unescape($creationdate),
                   2588:           lastrevisiondate => &Apache::lonnet::unescape($lastrevisiondate)
                   2589:         );
                   2590:     $Fields{'language'} = 
                   2591:         &Apache::loncommon::languagedescription($Fields{'lang'});
                   2592:     $Fields{'copyrighttag'} =
                   2593:         &Apache::loncommon::copyrightdescription($Fields{'copyright'});
                   2594:     $Fields{'mimetag'} =
                   2595:         &Apache::loncommon::filedescription($Fields{'mime'});
1.134     matthew  2596:     if ($Fields{'author'}=~/^(\s*|error)$/) {
                   2597:         $Fields{'author'}="Unknown Author";
                   2598:     }
1.126     matthew  2599:     # Put spaces in the keyword list, if needed.
                   2600:     $Fields{'keywords'}=~ s/,([A-z])/, $1/g; 
                   2601:     if ($Fields{'title'}=~ /^\s*$/ ) { 
                   2602:         $Fields{'title'}='Untitled'; 
                   2603:     }
                   2604:     unless ($ENV{'user.adv'}) {
1.144     matthew  2605:         # What is this anyway?
1.126     matthew  2606:         $Fields{'keywords'} = '- not displayed -';
                   2607:         $Fields{'notes'}    = '- not displayed -';
                   2608:         $Fields{'abstract'} = '- not displayed -';
                   2609:         $Fields{'subject'}  = '- not displayed -';
                   2610:     }
                   2611:     if (length($Fields{'abstract'})>200) {
                   2612:         $Fields{'abstract'} = 
                   2613:             substr($Fields{'abstract'},0,200).'...';
                   2614:     }
                   2615:     if (length($Fields{'keywords'})>200) {
                   2616:         $Fields{'keywords'} =
                   2617:             substr($Fields{'keywords'},0,200).'...';
                   2618:     }
                   2619:     return %Fields;
                   2620: }
                   2621: 
                   2622: ###########################################################
                   2623: ###########################################################
                   2624: 
                   2625: =pod
                   2626: 
                   2627: =item &handle_custom_fields()
                   2628: 
                   2629: =cut
                   2630: 
                   2631: ###########################################################
                   2632: ###########################################################
                   2633: sub handle_custom_fields {
                   2634:     my @results = @{shift()};
                   2635:     my $customshow='';
                   2636:     my $extrashow='';
                   2637:     my @customfields;
                   2638:     if ($ENV{'form.customshow'}) {
                   2639:         $customshow=$ENV{'form.customshow'};
                   2640:         $customshow=~s/[^\w\s]//g;
                   2641:         my @fields=map {
                   2642:             "<font color=\"#008000\">$_:</font><!-- $_ -->";
                   2643:         } split(/\s+/,$customshow);
                   2644:         @customfields=split(/\s+/,$customshow);
                   2645:         if ($customshow) {
                   2646:             $extrashow="<ul><li>".join("</li><li>",@fields)."</li></ul>\n";
                   2647:         }
                   2648:     }
                   2649:     my $customdata='';
                   2650:     my %customhash;
                   2651:     foreach my $result (@results) {
                   2652:         if ($result=~/^(custom\=.*)$/) { # grab all custom metadata
                   2653:             my $tmp=$result;
                   2654:             $tmp=~s/^custom\=//;
                   2655:             my ($k,$v)=map {&Apache::lonnet::unescape($_);
                   2656:                         } split(/\,/,$tmp);
                   2657:             $customhash{$k}=$v;
                   2658:         }
                   2659:     }
                   2660:     return ($extrashow,\@customfields,\%customhash);
1.41      harris41 2661: }
                   2662: 
1.122     matthew  2663: ######################################################################
                   2664: ######################################################################
                   2665: 
1.125     matthew  2666: =pod
                   2667: 
                   2668: =item &search_results_header
                   2669: 
1.130     matthew  2670: Output the proper html headers and javascript code to deal with different 
                   2671: calling modes.
                   2672: 
                   2673: Takes most inputs directly from %ENV, except $mode.  
                   2674: 
                   2675: =over 4
                   2676: 
                   2677: =item $mode is either (at this writing) 'Basic' or 'Advanced'
                   2678: 
                   2679: =back
1.126     matthew  2680: 
1.130     matthew  2681: The following environment variables are checked:
1.126     matthew  2682: 
                   2683: =over 4
                   2684: 
                   2685: =item 'form.catalogmode' 
                   2686: 
                   2687: Checked for 'interactive' and 'groupsearch'.
                   2688: 
                   2689: =item 'form.mode'
                   2690: 
                   2691: Checked for existance & 'edit' mode.
                   2692: 
                   2693: =item 'form.form'
                   2694: 
1.191     albertel 2695: Contains the name of the form that has the input fields to set
                   2696: 
1.126     matthew  2697: =item 'form.element'
                   2698: 
1.191     albertel 2699: the name of the input field to put the URL into
                   2700: 
                   2701: =item 'form.titleelement'
                   2702: 
                   2703: the name of the input field to put the title into
                   2704: 
1.126     matthew  2705: =back
                   2706: 
1.125     matthew  2707: =cut
                   2708: 
                   2709: ######################################################################
                   2710: ######################################################################
                   2711: sub search_results_header {
1.150     matthew  2712:     my ($importbutton,$closebutton) = @_;
1.125     matthew  2713:     my $result = '';
                   2714:     # output beginning of search page
                   2715:     # conditional output of script functions dependent on the mode in
                   2716:     # which the search was invoked
                   2717:     if ($ENV{'form.catalogmode'} eq 'interactive'){
                   2718: 	if (! exists($ENV{'form.mode'}) || $ENV{'form.mode'} ne 'edit') {
                   2719:             $result.=<<SCRIPT;
                   2720: <script type="text/javascript">
                   2721:     function select_data(title,url) {
                   2722: 	changeTitle(title);
                   2723: 	changeURL(url);
1.150     matthew  2724: 	parent.close();
1.125     matthew  2725:     }
                   2726:     function changeTitle(val) {
1.153     matthew  2727: 	if (parent.opener.inf.document.forms.resinfo.elements.t) {
                   2728: 	    parent.opener.inf.document.forms.resinfo.elements.t.value=val;
1.125     matthew  2729: 	}
                   2730:     }
                   2731:     function changeURL(val) {
1.153     matthew  2732: 	if (parent.opener.inf.document.forms.resinfo.elements.u) {
                   2733: 	    parent.opener.inf.document.forms.resinfo.elements.u.value=val;
1.125     matthew  2734: 	}
                   2735:     }
                   2736: </script>
                   2737: SCRIPT
                   2738:         } elsif ($ENV{'form.mode'} eq 'edit') {
                   2739:             my $form = $ENV{'form.form'};
                   2740:             my $element = $ENV{'form.element'};
1.191     albertel 2741:             my $titleelement = $ENV{'form.titleelement'};
                   2742: 	    my $changetitle;
                   2743: 	    if (!$titleelement) {
                   2744: 		$changetitle='function changeTitle(val) {}';
                   2745: 	    } else {
                   2746: 		    $changetitle=<<END;
                   2747: function changeTitle(val) {
                   2748:     if (parent.targetwin.document) {
                   2749:         parent.targetwin.document.forms["$form"].elements["$titleelement"].value=val;
                   2750:     } else {
                   2751: 	var url = 'forms[\"$form\"].elements[\"$titleelement\"].value';
                   2752:         alert("Unable to transfer data to "+url);
                   2753:     }
                   2754: }
                   2755: END
                   2756:             }
                   2757: 
1.125     matthew  2758:             $result.=<<SCRIPT;
                   2759: <script type="text/javascript">
                   2760: function select_data(title,url) {
                   2761:     changeURL(url);
1.191     albertel 2762:     changeTitle(title);
1.150     matthew  2763:     parent.close();
1.125     matthew  2764: }
1.191     albertel 2765: $changetitle
1.125     matthew  2766: function changeURL(val) {
1.150     matthew  2767:     if (parent.targetwin.document) {
                   2768:         parent.targetwin.document.forms["$form"].elements["$element"].value=val;
1.125     matthew  2769:     } else {
                   2770: 	var url = 'forms[\"$form\"].elements[\"$element\"].value';
                   2771:         alert("Unable to transfer data to "+url);
                   2772:     }
                   2773: }
                   2774: </script>
                   2775: SCRIPT
                   2776:         }
                   2777:     }
                   2778:     $result.=<<SCRIPT if $ENV{'form.catalogmode'} eq 'groupsearch';
                   2779: <script type="text/javascript">
1.158     matthew  2780:     function queue(checkbox_num,val) {
1.185     matthew  2781:         if (document.forms.results.returnvalues.length != "undefined" &&
                   2782:             typeof(document.forms.results.returnvalues.length) == "number") {
                   2783:             if (document.forms.results.returnvalues[checkbox_num].checked) {
                   2784:                 parent.statusframe.document.forms.statusform.elements.Queue.value +='1a'+val+'b';
                   2785:             } else {
                   2786:                 parent.statusframe.document.forms.statusform.elements.Queue.value +='0a'+val+'b';
                   2787:             }
1.150     matthew  2788:         } else {
1.185     matthew  2789:             if (document.forms.results.returnvalues.checked) {
                   2790:                 parent.statusframe.document.forms.statusform.elements.Queue.value +='1a'+val+'b';
                   2791:             } else {
                   2792:                 parent.statusframe.document.forms.statusform.elements.Queue.value +='0a'+val+'b';
                   2793:             }
1.150     matthew  2794:         }
1.125     matthew  2795:     }
                   2796:     function select_group() {
1.150     matthew  2797: 	parent.window.location=
1.125     matthew  2798:     "/adm/groupsort?mode=$ENV{'form.mode'}&catalogmode=groupsearch&acts="+
1.150     matthew  2799: 	    parent.statusframe.document.forms.statusform.elements.Queue.value;
1.125     matthew  2800:     }
                   2801: </script>
                   2802: SCRIPT
1.130     matthew  2803:     $result.=<<END;
                   2804: </head>
1.155     matthew  2805: $bodytag
1.150     matthew  2806: <form name="results" method="post" action="" >
                   2807: <input type="hidden" name="Queue" value="" />
                   2808: $importbutton
1.130     matthew  2809: END
1.125     matthew  2810:     return $result;
                   2811: }
                   2812: 
                   2813: ######################################################################
                   2814: ######################################################################
1.146     matthew  2815: sub search_status_header {
                   2816:     return <<ENDSTATUS;
                   2817: <html><head><title>Search Status</title></head>
1.155     matthew  2818: $bodytag
1.146     matthew  2819: <h3>Search Status</h3>
                   2820: Sending search request to LON-CAPA servers.<br />
                   2821: ENDSTATUS
                   2822: }
                   2823: 
1.150     matthew  2824: sub results_link {
                   2825:     my $basic_link   = "/adm/searchcat?"."&table=".$ENV{'form.table'}.
                   2826:         "&persistent_db_id=".$ENV{'form.persistent_db_id'};
                   2827:     my $results_link = $basic_link."&phase=results".
1.151     matthew  2828:         "&pause=1"."&start=1";
1.150     matthew  2829:     return $results_link;
                   2830: }
                   2831: 
1.146     matthew  2832: ######################################################################
                   2833: ######################################################################
                   2834: sub print_frames_interface {
                   2835:     my $r = shift;
                   2836:     my $basic_link = "/adm/searchcat?"."&table=".$ENV{'form.table'}.
                   2837:         "&persistent_db_id=".$ENV{'form.persistent_db_id'};
                   2838:     my $run_search_link = $basic_link."&phase=run_search";
1.150     matthew  2839:     my $results_link = &results_link();
1.146     matthew  2840:     my $result = <<"ENDFRAMES";
                   2841: <html>
                   2842: <head>
1.150     matthew  2843: <script>
                   2844: var targetwin = opener;
1.158     matthew  2845: var queue = '';
1.150     matthew  2846: </script>
1.146     matthew  2847: <title>LON-CAPA Digital Library Search Results</title>
                   2848: </head>
1.176     www      2849: <frameset rows="150,*">
1.146     matthew  2850:     <frame name="statusframe"  src="$run_search_link">
                   2851:     <frame name="resultsframe" src="$results_link">
                   2852: </frameset>
                   2853: </html>
                   2854: ENDFRAMES
                   2855: 
                   2856:     $r->print($result);
                   2857:     return;
                   2858: }
                   2859: 
                   2860: ######################################################################
                   2861: ######################################################################
1.125     matthew  2862: 
1.122     matthew  2863: =pod 
                   2864: 
                   2865: =item Metadata Viewing Functions
                   2866: 
                   2867: Output is a HTML-ified string.
                   2868: Input arguments are title, author, subject, url, keywords, version,
                   2869: notes, short abstract, mime, language, creation date,
1.126     matthew  2870: last revision date, owner, copyright, hostname, and
1.122     matthew  2871: extra custom metadata to show.
                   2872: 
                   2873: =over 4
                   2874: 
                   2875: =item &detailed_citation_view() 
                   2876: 
                   2877: =cut
                   2878: 
                   2879: ######################################################################
                   2880: ######################################################################
1.50      harris41 2881: sub detailed_citation_view {
1.150     matthew  2882:     my ($prefix,%values) = @_;
1.192     albertel 2883:     my $icon=&Apache::loncommon::icon($values{'url'});
1.50      harris41 2884:     my $result=<<END;
1.192     albertel 2885: <b>$prefix<img src="$icon" /><a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
1.150     matthew  2886:     target='search_preview'>$values{'title'}</a></b>
1.56      harris41 2887: <p>
1.130     matthew  2888: <b>$values{'author'}</b>, <i>$values{'owner'}</i><br />
                   2889: 
                   2890: <b>Subject:       </b> $values{'subject'}<br />
                   2891: <b>Keyword(s):    </b> $values{'keywords'}<br />
                   2892: <b>Notes:         </b> $values{'notes'}<br />
                   2893: <b>MIME Type:     </b> $values{'mimetag'}<br />
                   2894: <b>Language:      </b> $values{'language'}<br />
                   2895: <b>Copyright/Distribution:</b> $values{'cprtag'}<br />
1.78      harris41 2896: </p>
1.126     matthew  2897: $values{'extrashow'}
1.78      harris41 2898: <p>
1.126     matthew  2899: $values{'shortabstract'}
1.50      harris41 2900: </p>
1.150     matthew  2901: <hr align='left' width='200' noshade />
1.50      harris41 2902: END
                   2903:     return $result;
                   2904: }
                   2905: 
1.122     matthew  2906: ######################################################################
                   2907: ######################################################################
                   2908: 
                   2909: =pod 
                   2910: 
                   2911: =item &summary_view() 
                   2912: 
                   2913: =cut
                   2914: ######################################################################
                   2915: ######################################################################
1.50      harris41 2916: sub summary_view {
1.150     matthew  2917:     my ($prefix,%values) = @_;
1.192     albertel 2918:     my $icon=&Apache::loncommon::icon($values{'url'});
1.50      harris41 2919:     my $result=<<END;
1.192     albertel 2920: $prefix<img src="$icon" /><a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
1.126     matthew  2921:    target='search_preview'>$values{'author'}</a><br />
                   2922: $values{'title'}<br />
                   2923: $values{'owner'} -- $values{'lastrevisiondate'}<br />
                   2924: $values{'copyrighttag'}<br />
                   2925: $values{'extrashow'}
1.50      harris41 2926: </p>
1.150     matthew  2927: <hr align='left' width='200' noshade />
1.50      harris41 2928: END
                   2929:     return $result;
                   2930: }
                   2931: 
1.122     matthew  2932: ######################################################################
                   2933: ######################################################################
                   2934: 
                   2935: =pod 
                   2936: 
1.150     matthew  2937: =item &compact_view() 
                   2938: 
                   2939: =cut
                   2940: 
                   2941: ######################################################################
                   2942: ######################################################################
                   2943: sub compact_view {
                   2944:     my ($prefix,%values) = @_;
1.192     albertel 2945:     my $icon=&Apache::loncommon::icon($values{'url'});
1.150     matthew  2946:     my $result=<<END;
1.192     albertel 2947: $prefix <img src="$icon" /> <a href="http://$ENV{'HTTP_HOST'}$values{'url'}"  target='search_preview'>
1.150     matthew  2948: $values{'title'}</a>
                   2949: <b>$values{'author'}</b><br />
                   2950: END
                   2951:     return $result;
                   2952: }
                   2953: 
                   2954: 
                   2955: ######################################################################
                   2956: ######################################################################
                   2957: 
                   2958: =pod 
                   2959: 
1.122     matthew  2960: =item &fielded_format_view() 
                   2961: 
                   2962: =cut
                   2963: 
                   2964: ######################################################################
                   2965: ######################################################################
1.50      harris41 2966: sub fielded_format_view {
1.150     matthew  2967:     my ($prefix,%values) = @_;
1.192     albertel 2968:     my $icon=&Apache::loncommon::icon($values{'url'});
1.50      harris41 2969:     my $result=<<END;
1.192     albertel 2970: $prefix <img src="$icon" />
1.126     matthew  2971: <b>URL: </b> <a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
                   2972:               target='search_preview'>$values{'url'}</a>
1.56      harris41 2973: <br />
1.126     matthew  2974: <b>Title:</b> $values{'title'}<br />
                   2975: <b>Author(s):</b> $values{'author'}<br />
                   2976: <b>Subject:</b> $values{'subject'}<br />
                   2977: <b>Keyword(s):</b> $values{'keywords'}<br />
                   2978: <b>Notes:</b> $values{'notes'}<br />
                   2979: <b>MIME Type:</b> $values{'mimetag'}<br />
                   2980: <b>Language:</b> $values{'language'}<br />
                   2981: <b>Creation Date:</b> $values{'creationdate'}<br />
                   2982: <b>Last Revision Date:</b> $values{'lastrevisiondate'}<br />
                   2983: <b>Publisher/Owner:</b> $values{'owner'}<br />
                   2984: <b>Copyright/Distribution:</b> $values{'copyrighttag'}<br />
                   2985: <b>Repository Location:</b> $values{'hostname'}<br />
                   2986: <b>Abstract:</b> $values{'shortabstract'}<br />
                   2987: $values{'extrashow'}
1.50      harris41 2988: </p>
1.150     matthew  2989: <hr align='left' width='200' noshade />
1.50      harris41 2990: END
                   2991:     return $result;
                   2992: }
                   2993: 
1.122     matthew  2994: ######################################################################
                   2995: ######################################################################
                   2996: 
                   2997: =pod 
                   2998: 
                   2999: =item &xml_sgml_view() 
                   3000: 
                   3001: =back 
                   3002: 
                   3003: =cut
                   3004: 
                   3005: ######################################################################
                   3006: ######################################################################
1.50      harris41 3007: sub xml_sgml_view {
1.150     matthew  3008:     my ($prefix,%values) = @_;
1.50      harris41 3009:     my $result=<<END;
1.150     matthew  3010: $prefix
1.56      harris41 3011: <pre>
                   3012: &lt;LonCapaResource&gt;
1.126     matthew  3013: &lt;url&gt;$values{'url'}&lt;/url&gt;
                   3014: &lt;title&gt;$values{'title'}&lt;/title&gt;
                   3015: &lt;author&gt;$values{'author'}&lt;/author&gt;
                   3016: &lt;subject&gt;$values{'subject'}&lt;/subject&gt;
                   3017: &lt;keywords&gt;$values{'keywords'}&lt;/keywords&gt;
                   3018: &lt;notes&gt;$values{'notes'}&lt;/notes&gt;
1.56      harris41 3019: &lt;mimeInfo&gt;
1.126     matthew  3020: &lt;mime&gt;$values{'mime'}&lt;/mime&gt;
                   3021: &lt;mimetag&gt;$values{'mimetag'}&lt;/mimetag&gt;
1.56      harris41 3022: &lt;/mimeInfo&gt;
                   3023: &lt;languageInfo&gt;
1.126     matthew  3024: &lt;language&gt;$values{'lang'}&lt;/language&gt;
                   3025: &lt;languagetag&gt;$values{'language'}&lt;/languagetag&gt;
1.56      harris41 3026: &lt;/languageInfo&gt;
1.126     matthew  3027: &lt;creationdate&gt;$values{'creationdate'}&lt;/creationdate&gt;
                   3028: &lt;lastrevisiondate&gt;$values{'lastrevisiondate'}&lt;/lastrevisiondate&gt;
                   3029: &lt;owner&gt;$values{'owner'}&lt;/owner&gt;
1.56      harris41 3030: &lt;copyrightInfo&gt;
1.126     matthew  3031: &lt;copyright&gt;$values{'copyright'}&lt;/copyright&gt;
                   3032: &lt;copyrighttag&gt;$values{'copyrighttag'}&lt;/copyrighttag&gt;
1.56      harris41 3033: &lt;/copyrightInfo&gt;
1.126     matthew  3034: &lt;repositoryLocation&gt;$values{'hostname'}&lt;/repositoryLocation&gt;
                   3035: &lt;shortabstract&gt;$values{'shortabstract'}&lt;/shortabstract&gt;
1.57      harris41 3036: &lt;/LonCapaResource&gt;
1.56      harris41 3037: </pre>
1.126     matthew  3038: $values{'extrashow'}
1.150     matthew  3039: <hr align='left' width='200' noshade />
1.50      harris41 3040: END
                   3041:     return $result;
1.60      harris41 3042: }
                   3043: 
1.122     matthew  3044: ######################################################################
                   3045: ######################################################################
                   3046: 
                   3047: =pod 
                   3048: 
                   3049: =item &filled() see if field is filled.
                   3050: 
                   3051: =cut
                   3052: 
                   3053: ######################################################################
                   3054: ######################################################################
1.98      harris41 3055: sub filled {
                   3056:     my ($field)=@_;
                   3057:     if ($field=~/\S/ && $field ne 'any') {
                   3058: 	return 1;
1.61      harris41 3059:     }
1.98      harris41 3060:     else {
                   3061: 	return 0;
1.61      harris41 3062:     }
1.60      harris41 3063: }
                   3064: 
1.122     matthew  3065: ######################################################################
                   3066: ######################################################################
                   3067: 
                   3068: =pod 
                   3069: 
                   3070: =item &output_blank_field_error()
                   3071: 
1.151     matthew  3072: Output a complete page that indicates the user has not filled in enough
                   3073: information to do a search.
                   3074: 
                   3075: Inputs: $r (Apache request handle), $closebutton, $parms.
                   3076: 
                   3077: Returns: nothing
                   3078: 
                   3079: $parms is extra information to include in the 'Revise search request' link.
                   3080: 
1.122     matthew  3081: =cut
                   3082: 
                   3083: ######################################################################
                   3084: ######################################################################
1.98      harris41 3085: sub output_blank_field_error {
1.151     matthew  3086:     my ($r,$closebutton,$parms)=@_;
1.98      harris41 3087:     # make query information persistent to allow for subsequent revision
                   3088:     $r->print(<<BEGINNING);
                   3089: <html>
                   3090: <head>
                   3091: <title>The LearningOnline Network with CAPA</title>
                   3092: BEGINNING
                   3093:     $r->print(<<RESULTS);
                   3094: </head>
1.155     matthew  3095: $bodytag
1.98      harris41 3096: <img align='right' src='/adm/lonIcons/lonlogos.gif' />
                   3097: <h1>Search Catalog</h1>
                   3098: <form method="post" action="/adm/searchcat">
1.145     matthew  3099: $hidden_fields
1.151     matthew  3100: <a href="/adm/searchcat?$parms&persistent_db_id=$ENV{'form.persistent_db_id'}"
1.146     matthew  3101: >Revise search request</a>&nbsp;
1.98      harris41 3102: $closebutton
                   3103: <hr />
1.151     matthew  3104: <h3>Unactionable search query.</h3>
1.98      harris41 3105: <p>
1.151     matthew  3106: You did not fill in enough information for the search to be started.
                   3107: You need to fill in relevant fields on the search page in order 
                   3108: for a query to be processed.
1.98      harris41 3109: </p>
                   3110: </body>
                   3111: </html>
                   3112: RESULTS
                   3113: }
                   3114: 
1.122     matthew  3115: ######################################################################
                   3116: ######################################################################
                   3117: 
                   3118: =pod 
                   3119: 
                   3120: =item &output_date_error()
                   3121: 
                   3122: Output a full html page with an error message.
                   3123: 
1.145     matthew  3124: Inputs: 
                   3125: 
                   3126:     $r, the request pointer.
                   3127:     $message, the error message for the user.
                   3128:     $closebutton, the specialized close button needed for groupsearch.
                   3129: 
1.122     matthew  3130: =cut
                   3131: 
                   3132: ######################################################################
                   3133: ######################################################################
1.60      harris41 3134: sub output_date_error {
1.145     matthew  3135:     my ($r,$message,$closebutton)=@_;
1.60      harris41 3136:     # make query information persistent to allow for subsequent revision
1.122     matthew  3137:     $r->print(<<RESULTS);
1.60      harris41 3138: <html>
                   3139: <head>
                   3140: <title>The LearningOnline Network with CAPA</title>
                   3141: </head>
1.155     matthew  3142: $bodytag
1.98      harris41 3143: <img align='right' src='/adm/lonIcons/lonlogos.gif' />
1.60      harris41 3144: <h1>Search Catalog</h1>
                   3145: <form method="post" action="/adm/searchcat">
1.145     matthew  3146: $hidden_fields
1.60      harris41 3147: <input type='button' value='Revise search request'
1.98      harris41 3148: onClick='this.form.submit();' />
1.60      harris41 3149: $closebutton
1.98      harris41 3150: <hr />
1.151     matthew  3151: <h3>Error</h3>
1.60      harris41 3152: <p>
                   3153: $message
                   3154: </p>
                   3155: </body>
                   3156: </html>
                   3157: RESULTS
1.101     harris41 3158: }
                   3159: 
1.122     matthew  3160: ######################################################################
                   3161: ######################################################################
                   3162: 
                   3163: =pod 
                   3164: 
                   3165: =item &start_fresh_session()
                   3166: 
1.142     matthew  3167: Cleans the global %groupsearch_db by removing all fields which begin with
1.122     matthew  3168: 'pre_' or 'store'.
                   3169: 
                   3170: =cut
                   3171: 
                   3172: ######################################################################
                   3173: ######################################################################
1.101     harris41 3174: sub start_fresh_session {
1.142     matthew  3175:     delete $groupsearch_db{'mode_catalog'};
                   3176:     foreach (keys %groupsearch_db) {
1.101     harris41 3177:         if ($_ =~ /^pre_/) {
1.142     matthew  3178:             delete $groupsearch_db{$_};
1.101     harris41 3179:         }
                   3180:         if ($_ =~ /^store/) {
1.142     matthew  3181: 	    delete $groupsearch_db{$_};
1.101     harris41 3182: 	}
1.109     harris41 3183:     }
1.3       harris41 3184: }
1.1       www      3185: 
                   3186: 1;
1.162     www      3187: 
                   3188: sub cleanup {
1.163     www      3189:     if (tied(%groupsearch_db)) {
                   3190:         unless (untie(%groupsearch_db)) {
                   3191: 	  &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db');
                   3192:         }
                   3193:     }
1.167     www      3194:     &untiehash();
1.162     www      3195:     &Apache::lonmysql::disconnect_from_db();
                   3196: }
1.98      harris41 3197: 
1.1       www      3198: __END__
1.105     harris41 3199: 
1.121     matthew  3200: =pod
1.105     harris41 3201: 
1.121     matthew  3202: =back 
1.105     harris41 3203: 
                   3204: =cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.