Annotation of loncom/interface/lonsearchcourse.pm, revision 1.1
1.1 ! www 1: # The LearningOnline Network with CAPA
! 2: # Search Course
! 3: #
! 4: # $Id: lonsearchcat.pm,v 1.326 2010/08/25 12:38:45 wenzelju Exp $
! 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.
! 14: #
! 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/
! 27: #
! 28: ###############################################################################
! 29: ###############################################################################
! 30:
! 31: package Apache::lonsearchcourse;
! 32:
! 33: use strict;
! 34: use Apache::Constants qw(:common :http);
! 35: use Apache::lonnet;
! 36: use GDBM_File;
! 37: use Apache::loncommon();
! 38: use Apache::lonmeta;
! 39: use Apache::lonhtmlcommon;
! 40: use Apache::lonlocal;
! 41: use LONCAPA::lonmetadata();
! 42: use HTML::Entities();
! 43: use Apache::lonnavmaps;
! 44: use Apache::londocs();
! 45: use Apache::lonindexer();
! 46: use LONCAPA;
! 47:
! 48: # Variables For course search
! 49: my %alreadyseen;
! 50: my %hash;
! 51: my $totalfound;
! 52:
! 53:
! 54: sub menu {
! 55: my $scrout='';
! 56: if ($env{'request.course.id'}) {
! 57: my %lt=&Apache::lonlocal::texthash('srch' => 'Search',
! 58: 'header' => 'Course Search',
! 59: 'note' => 'Enter terms or phrases, then press "Search" below',
! 60: 'use' => 'use related words',
! 61: 'full' =>'fulltext search (time consuming)',
! 62: 'disc' => 'search discussion postings (resources and discussion boards)',
! 63: );
! 64: $scrout.=(<<ENDCOURSESEARCH);
! 65: <form name="loncapa_search" method="post" action="/adm/searchcourse">
! 66: <center>
! 67: <hr />
! 68: <h1>$lt{'header'}</h1>
! 69: <input type="hidden" name="phase" value="results" />
! 70: <p>
! 71: $lt{'note'}.
! 72: </p>
! 73: <table>
! 74: <tr><td>
! 75: ENDCOURSESEARCH
! 76: $scrout.=' '.
! 77: &Apache::lonhtmlcommon::textbox('courseexp',
! 78: $env{'form.courseexp'},40);
! 79: my $crscheckbox =
! 80: &Apache::lonhtmlcommon::checkbox('crsfulltext',
! 81: $env{'form.crsfulltext'});
! 82: my $relcheckbox =
! 83: &Apache::lonhtmlcommon::checkbox('crsrelated',
! 84: $env{'form.crsrelated'});
! 85: my $discheckbox =
! 86: &Apache::lonhtmlcommon::checkbox('crsdiscuss',
! 87: $env{'form.crsrelated'});
! 88: $scrout.=(<<ENDENDCOURSE);
! 89: </td></tr>
! 90: <tr><td><label>$relcheckbox $lt{'use'}</label></td><td></td></tr>
! 91: <tr><td><label>$crscheckbox $lt{'full'}</label></td><td></td></tr>
! 92: <tr><td><label>$discheckbox $lt{'disc'}</label></td><td></td></tr>
! 93: </table>
! 94: <p>
! 95: <input type="submit" name="coursesubmit" value='$lt{'srch'}' />
! 96: </p>
! 97: </center>
! 98: </form>
! 99: ENDENDCOURSE
! 100: }
! 101: return $scrout;
! 102: }
! 103:
! 104: sub make_symb {
! 105: my ($id)=@_;
! 106: my ($mapid,$resid)=split(/\./,$id);
! 107: my $map=$hash{'map_id_'.$mapid};
! 108: my $res=$hash{'src_'.$id};
! 109: my $symb=&Apache::lonnet::encode_symb($map,$resid,$res);
! 110: return $symb;
! 111: }
! 112:
! 113: sub related_version {
! 114: my ($word) = @_;
! 115: return (undef) if (lc($word) =~ /\b(or|and|not)\b/);
! 116: my @Words = &Apache::loncommon::get_related_words($word);
! 117: # Only use 4 related words
! 118: @Words = ($#Words>4? @Words[0..4] : @Words);
! 119: my $result = join " OR ", ($word,@Words);
! 120: return $result,sort(@Words);
! 121: }
! 122:
! 123: sub course_search {
! 124: my $r=shift;
! 125: my $pretty_search_string = '<b>'.$env{'form.courseexp'}.'</b>';
! 126: my $search_string = $env{'form.courseexp'};
! 127: my @New_Words;
! 128: undef(%alreadyseen);
! 129: if ($env{'form.crsrelated'}) {
! 130: ($search_string,@New_Words) = &related_version($env{'form.courseexp'});
! 131: if (@New_Words) {
! 132: $pretty_search_string .= ' '.&mt("with related words").": <b>@New_Words</b>.";
! 133: } else {
! 134: $pretty_search_string .= ' '.&mt('with no related words').".";
! 135: }
! 136: }
! 137: my $fulltext=$env{'form.crsfulltext'};
! 138: my $discuss=$env{'form.crsdiscuss'};
! 139: my @allwords=($search_string,@New_Words);
! 140: $totalfound=0;
! 141:
! 142: $r->print(
! 143: '<hr /><center><font size="+2" face="arial">'.
! 144: $pretty_search_string.'</font></center>'.
! 145: '<hr /><b>'.&mt('Course content').':</b><br />');
! 146: $r->rflush();
! 147: # ======================================================= Go through the course
! 148: my $c=$r->connection;
! 149: if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
! 150: &GDBM_READER(),0640)) {
! 151: foreach (sort(keys(%hash))) {
! 152: if ($c->aborted()) { last; }
! 153: if (($_=~/^src\_(.+)$/)) {
! 154: if ($hash{'randomout_'.$1} & !$env{'request.role.adv'}) {
! 155: next;
! 156: }
! 157: my $symb=&make_symb($1);
! 158: &checkonthis($r,$1,$hash{$_},0,&Apache::lonnet::gettitle($symb),
! 159: $fulltext,$symb,@allwords);
! 160: }
! 161: }
! 162: untie(%hash);
! 163: }
! 164: unless ($totalfound) {
! 165: $r->print('<p class="LC_info">'.&mt('No matches found in resources.').'</p>');
! 166: }
! 167:
! 168: # Check discussions if requested
! 169: if ($discuss) {
! 170: my $totaldiscussions = 0;
! 171: $r->print('<br /><br /><b>'.&mt('Discussion postings').':</b><br />');
! 172: my $navmap = Apache::lonnavmaps::navmap->new();
! 173: if (defined($navmap)) {
! 174: my @allres=$navmap->retrieveResources();
! 175: my %discussiontime = &Apache::lonnet::dump('discussiontimes',
! 176: $env{'course.'.$env{'request.course.id'}.'.domain'},
! 177: $env{'course.'.$env{'request.course.id'}.'.num'});
! 178: foreach my $resource (@allres) {
! 179: my $result = '';
! 180: my $applies = 0;
! 181: my $symb = $resource->symb();
! 182: my $ressymb = $symb;
! 183: if ($symb =~ m#(___adm/$LONCAPA::domain_re/$LONCAPA::username_re)/(\d+)/bulletinboard$#) {
! 184: $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard';
! 185: unless ($ressymb =~ m#bulletin___\d+___adm/wrapper#) {
! 186: $ressymb=~s#(bulletin___\d+___)#$1adm/wrapper/#;
! 187: }
! 188: }
! 189: if (defined($discussiontime{$ressymb})) {
! 190: my %contrib = &Apache::lonnet::restore($ressymb,$env{'request.course.id'},
! 191: $env{'course.'.$env{'request.course.id'}.'.domain'},
! 192: $env{'course.'.$env{'request.course.id'}.'.num'});
! 193: if ($contrib{'version'}) {
! 194: for (my $id=1;$id<=$contrib{'version'};$id++) {
! 195: unless (($contrib{'hidden'}=~/\.$id\./) || ($contrib{'deleted'}=~/\.$id\./)) {
! 196: if ($contrib{$id.':subject'}) {
! 197: $result .= $contrib{$id.':subject'};
! 198: }
! 199: if ($contrib{$id.':message'}) {
! 200: $result .= $contrib{$id.':message'};
! 201: }
! 202: if ($contrib{$id,':attachmenturl'}) {
! 203: if ($contrib{$id,':attachmenturl'} =~ m-/([^/]+)$-) {
! 204: $result .= $1;
! 205: }
! 206: }
! 207: $applies = &checkwords($result,$applies,@allwords);
! 208: }
! 209: }
! 210: }
! 211: }
! 212: # Does this discussion apply?
! 213: if ($applies) {
! 214: my ($map,$ind,$url)=&Apache::lonnet::decode_symb($ressymb);
! 215: my $disctype = &mt('resource');
! 216: if ($url =~ m#/bulletinboard$#) {
! 217: if ($url =~m#^adm/wrapper/adm/.*/bulletinboard$#) {
! 218: $url =~s#^adm/wrapper##;
! 219: }
! 220: $disctype = &mt('discussion board');
! 221: } else {
! 222: $url = '/res/'.$url;
! 223: }
! 224: if ($url =~ /\?/) {
! 225: $url .= '&symb=';
! 226: } else {
! 227: $url .= '?symb=';
! 228: }
! 229: $url .= &escape($resource->symb());
! 230: my $title = $resource->compTitle();
! 231: $r->print('<br /><a href="'.$url.'" target="cat">'.
! 232: ($title?$title:$url).'</a> - '.
! 233: $disctype.'<br />');
! 234: $totaldiscussions++;
! 235: } else {
! 236: $r->print(' .');
! 237: }
! 238: }
! 239: unless ($totaldiscussions) {
! 240: $r->print('<p class="LC_info">'.&mt('No matches found in postings.').'</p>');
! 241: }
! 242: } else {
! 243: $r->print('<div class="LC_error">'.&mt('An error occurred retrieving information about resources in the course.').'<br />'.&mt('It is recommended that you [_1]re-initialize the course[_2] and then try your search again.','<a href="/adm/roles">','</a>').'</div>');
! 244: }
! 245: }
! 246:
! 247: # =================================================== Done going through course
! 248: $r->print(&Apache::loncommon::end_page());
! 249: }
! 250:
! 251: # =============================== This pulls up a resource and its dependencies
! 252:
! 253: sub checkonthis {
! 254: my ($r,$id,$url,$level,$title,$fulltext,$symb,@allwords)=@_;
! 255: $alreadyseen{$id}=1;
! 256: if (&Apache::loncommon::connection_aborted($r)) { return; }
! 257: $r->rflush();
! 258:
! 259: my $result=$title.' ';
! 260: if ($env{'request.role.adv'} || !$hash{'encrypted_'.$id}) {
! 261: $result.=&Apache::lonnet::metadata($url,'title').' '.
! 262: &Apache::lonnet::metadata($url,'subject').' '.
! 263: &Apache::lonnet::metadata($url,'abstract').' '.
! 264: &Apache::lonnet::metadata($url,'keywords');
! 265: }
! 266: my ($extension)=($url=~/\.(\w+)$/);
! 267: if (&Apache::loncommon::fileembstyle($extension) eq 'ssi' &&
! 268: ($url) && ($fulltext)) {
! 269: $result.=&Apache::lonnet::ssi_body($url.'?symb='.&escape($symb));
! 270: }
! 271: $result=~s/\s+/ /gs;
! 272: my $applies = 0;
! 273: $applies = &checkwords($result,$applies,@allwords);
! 274: # Does this resource apply?
! 275: if ($applies) {
! 276: $r->print('<br />');
! 277: for (my $i=0;$i<=$level*5;$i++) {
! 278: $r->print(' ');
! 279: }
! 280: my $href=$url;
! 281: if ($hash{'encrypted_'.$id} && !$env{'request.role.adv'}) {
! 282: $href=&Apache::lonenc::encrypted($href)
! 283: .'?symb='.&Apache::lonenc::encrypted($symb);
! 284: } else {
! 285: $href.='?symb='.&escape($symb);
! 286: }
! 287: $r->print('<a href="'.$href.'" target="cat">'.($title?$title:$url).
! 288: '</a><br />');
! 289: $totalfound++;
! 290: } elsif ($fulltext) {
! 291: $r->print(' .');
! 292: }
! 293: $r->rflush();
! 294: # Check also the dependencies of this one
! 295: my $dependencies=
! 296: &Apache::lonnet::metadata($url,'dependencies');
! 297: foreach (split(/\,/,$dependencies)) {
! 298: if (($_=~/^\/res\//) && (!$alreadyseen{$id})) {
! 299: &checkonthis($r,$id,$_,$level+1,'',$fulltext,undef,@allwords);
! 300: }
! 301: }
! 302: }
! 303:
! 304: sub checkwords {
! 305: my ($result,$applies,@allwords) = @_;
! 306: foreach (@allwords) {
! 307: if ($_=~/\w/) {
! 308: if ($result=~/$_/si) {
! 309: $applies++;
! 310: }
! 311: }
! 312: }
! 313: return $applies;
! 314: }
! 315:
! 316: sub untiehash {
! 317: if (tied(%hash)) {
! 318: untie(%hash);
! 319: }
! 320: }
! 321:
! 322: sub handler {
! 323: my $r = shift;
! 324: &Apache::loncommon::content_type($r,'text/html');
! 325: $r->send_http_header;
! 326: if ($r->header_only) { return OK; }
! 327:
! 328: my $crstype = &Apache::loncommon::course_type();
! 329: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['phase']);
! 330: &Apache::lonhtmlcommon::clear_breadcrumbs();
! 331: $r->print(&Apache::loncommon::start_page("$crstype Search"));
! 332: $r->print(&Apache::lonhtmlcommon::breadcrumbs("$crstype Search"));
! 333: &Apache::londocs::startContentScreen($r,'coursesearch');
! 334: if ($env{'form.phase'} eq 'results') {
! 335: &course_search($r);
! 336: } else {
! 337: $r->print(&menu());
! 338: }
! 339: &Apache::londocs::endContentScreen($r);
! 340: $r->print(&Apache::loncommon::end_page());
! 341: return OK;
! 342: }
! 343:
! 344: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>