File:  [LON-CAPA] / loncom / interface / coursecatalog.pm
Revision 1.4: download - view: text, annotated - select for diffs
Wed Sep 13 21:35:46 2006 UTC (17 years, 8 months ago) by albertel
Branches: MAIN
CVS tags: HEAD
- style

    1: #
    2: # Copyright Michigan State University Board of Trustees
    3: #
    4: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    5: #
    6: # LON-CAPA is free software; you can redistribute it and/or modify
    7: # it under the terms of the GNU General Public License as published by
    8: # the Free Software Foundation; either version 2 of the License, or
    9: # (at your option) any later version.
   10: #
   11: # LON-CAPA is distributed in the hope that it will be useful,
   12: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   13: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14: # GNU General Public License for more details.
   15: #
   16: # You should have received a copy of the GNU General Public License
   17: # along with LON-CAPA; if not, write to the Free Software
   18: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19: #
   20: # /home/httpd/html/adm/gpl.txt
   21: #
   22: # http://www.lon-capa.org/
   23: #
   24: 
   25: package Apache::coursecatalog;
   26: 
   27: use strict;
   28: use lib qw(/home/httpd/lib/perl);
   29: use Apache::Constants qw(:common);
   30: use Apache::loncommon;
   31: use Apache::lonnet;
   32: use Apache::lonlocal;
   33: use Apache::lonsupportreq;
   34: use Apache::lonacc;
   35: use lib '/home/httpd/lib/perl/';
   36: use LONCAPA;
   37: 
   38: sub handler {
   39:     my ($r) = @_;
   40:     &Apache::loncommon::content_type($r,'text/html');
   41:     $r->send_http_header;
   42:     if ($r->header_only) {
   43:         return OK;
   44:     }
   45:     &Apache::lonacc::get_posted_cgi($r);
   46:     &Apache::lonlocal::get_language_handle($r);
   47:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['sortby']);
   48:     my $codedom = $Apache::lonnet::perlvar{'lonDefDomain'};
   49:     my $ccode = '';
   50:     my %coursecodes = ();
   51:     my %codes = ();
   52:     my @codetitles = ();
   53:     my %cat_titles = ();
   54:     my %cat_order = ();
   55:     my %idlist = ();
   56:     my %idnums = ();
   57:     my %idlist_titles = ();
   58:     my $caller = 'global';
   59:     my $format_reply;
   60:     my $totcodes = 0;
   61:     my $jscript = '';
   62:     my $formname = 'coursecatalog';
   63:     $totcodes = &Apache::lonsupportreq::retrieve_instcodes(\%coursecodes,$codedom,$totcodes);
   64:     if ($totcodes > 0) {
   65:         if ($ccode eq '') {
   66:             $format_reply = &Apache::lonnet::auto_instcode_format($caller,$codedom,\%coursecodes,\%codes,\@codetitles,\%cat_titles,\%cat_order);
   67:             if ($format_reply eq 'ok') {
   68:                 my $numtypes = @codetitles;
   69:                 &Apache::lonsupportreq::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles);
   70:                 &Apache::lonsupportreq::javascript_code_selections($formname,$numtypes,\%cat_titles,\$jscript,\%idlist,\%idnums,\%idlist_titles,\@codetitles);
   71:             }
   72:         }
   73:         if ($env{'form.state'} eq 'listing') {
   74:             $jscript .= '
   75: function setElements() {
   76: ';
   77:             for (my $i=0; $i<@codetitles; $i++) {
   78:                 if ($env{'form.'.$codetitles[$i]} != -1) {
   79:                     $jscript .= '
   80:     for (var j=0; j<document.'.$formname.'.'.$codetitles[$i].'.length; j++) {
   81:         if (document.'.$formname.'.'.$codetitles[$i].'[j].value == "'.$env{'form.'.$codetitles[$i]}.'") {
   82:             document.'.$formname.'.'.$codetitles[$i].'.selectedIndex = j;
   83:         }
   84:     }
   85: ';
   86:                     $jscript .= '  courseSet('."'$codetitles[$i]'".');'."\n";
   87:                 } else {
   88:                     last;
   89:                 }
   90:             }
   91:             $jscript .= '}';
   92:             $jscript .= qq|
   93: function changeSort(caller) {
   94:     document.coursecatalog.sortby.value = caller;
   95:     document.coursecatalog.submit();
   96: }\n|;
   97:         }
   98:         my $js = '<script type"text/javascript">'."\n$jscript\n".
   99:                  '</script>';
  100:         my %add_entries = (topmargin    => "0",
  101:                            marginheight => "0",
  102:                            onLoad       =>"setElements()",);
  103:         my $start_page =
  104:             &Apache::loncommon::start_page('Course Catalog',$js,
  105:                                            { 
  106:                                              'add_entries' => \%add_entries,
  107:                                              'no_inline_link'   => 1,});
  108:         $r->print($start_page);
  109: 
  110:         my $numtitles = @codetitles;
  111:         my $domdesc = $Apache::lonnet::domaindescription{$codedom};
  112:         $r->print('<h3>'.&mt('Display information about official [_1] classes for which LON-CAPA courses have been created:',$domdesc).'</h3>');
  113:         $r->print(&mt('<b>Choose which course(s) to list.</b><br />'));
  114:         $r->print('<form name="coursecatalog" method="post">'); 
  115:         if ($numtitles > 0) {
  116:             my $lasttitle = $numtitles;
  117:             if ($numtitles > 4) {
  118:                 $lasttitle = 4;
  119:             }
  120:             $r->print('<table><tr><td>'.$codetitles[0].'<br />'."\n".
  121:                   '<select name="'.$codetitles[0].'" onChange="courseSet('."'$codetitles[0]'".')">'."\n".
  122:                   ' <option value="-1" />Select'."\n");
  123:             my @items = ();
  124:             my @longitems = ();
  125:             if ($idlist{$codetitles[0]} =~ /","/) {
  126:                 @items = split(/","/,$idlist{$codetitles[0]});
  127:             } else {
  128:                 $items[0] = $idlist{$codetitles[0]};
  129:             }
  130:             if (defined($idlist_titles{$codetitles[0]})) {
  131:                 if ($idlist_titles{$codetitles[0]} =~ /","/) {
  132:                     @longitems = split(/","/,$idlist_titles{$codetitles[0]});
  133:                 } else {
  134:                     $longitems[0] = $idlist_titles{$codetitles[0]};
  135:                 }
  136:                 for (my $i=0; $i<@longitems; $i++) {
  137:                     if ($longitems[$i] eq '') {
  138:                         $longitems[$i] = $items[$i];
  139:                     }
  140:                 }
  141:             } else {
  142:                 @longitems = @items;
  143:             }
  144:             for (my $i=0; $i<@items; $i++) {
  145:                 $r->print(' <option value="'.$items[$i].'">'.$longitems[$i].'</option>');
  146:             }
  147:             $r->print('</select></td>');
  148:             for (my $i=1; $i<$numtitles; $i++) {
  149:                 $r->print('<td>'.$codetitles[$i].'<br />'."\n".
  150:                  '<select name="'.$codetitles[$i].'" onChange="courseSet('."'$codetitles[$i]'".')">'."\n".
  151:                  '<option value="-1">&lt;-Pick '.$codetitles[$i-1].'</option>'."\n".
  152:                  '</select>'."\n".
  153:                  '</td>'
  154:                 );
  155:             }
  156:             $r->print('</tr></table>');
  157:             if ($numtitles > 4) {
  158:                 $r->print('<br /><br />'.$codetitles[$numtitles].'<br />'."\n".
  159:                     '<select name="'.$codetitles[$numtitles].
  160:                     '" onChange="courseSet('."'$codetitles[$numtitles]'".')">'."\n".
  161:                     '<option value="-1">&lt;-Pick '.$codetitles[$numtitles-1].
  162:                     '</option>'."\n".'</select>'."\n");
  163:             }
  164:         }
  165:         $r->print('<br /><input type="hidden" name="state" value="listing" /><input type="hidden" name="sortby" value="" /><input type="submit" name="catalogfilter" value="'.&mt('Display courses').'" /></form>');
  166:     }
  167:     if ($env{'form.state'} eq 'listing') {
  168:         $r->print('<br /><br />'.&print_course_listing($codedom));
  169:     }
  170:     $r->print(&Apache::loncommon::end_page());
  171: }
  172: 
  173: sub print_course_listing {
  174:     my ($domain) = @_;
  175:     my $output;
  176:     my $year = $env{'form.Year'};
  177:     my $sem = $env{'form.Semester'};
  178:     my $dept = $env{'form.Department'};
  179:     my $coursenum = $env{'form.Number'};
  180:     my $instcode;
  181:     if ($sem != -1) {
  182:         $instcode .= $sem; 
  183:     }
  184:     if ($year != -1) {
  185:         $instcode .= $year; 
  186:     }
  187:     if ($dept != -1) {
  188:         $instcode .= $dept;
  189:     }
  190:     if ($coursenum != -1) {
  191:         $instcode .= $coursenum; 
  192:     }
  193:     my %courses = &Apache::lonnet::courseiddump($domain,'.',1,$instcode,'.','.',
  194:                                                 undef,undef,'Course');
  195:     if (keys(%courses) == 0) {
  196:         $output = &mt('No courses match the criteria you selected.');
  197:         return $output;
  198:     }
  199:     $output = &mt('<b>Note for students:</b> If you are officially enrolled in a course but there is no student role for the course in your LON-CAPA roles screen, check the default access dates and/or auto-enrollment settings for the course below.  Your roles screen displays only currently accessible roles.<br /><br />');
  200:     $output .= &Apache::loncommon::start_data_table().
  201:               &Apache::loncommon::start_data_table_header_row().
  202:               '<th><a href="javascript:changeSort('."'code'".')">'.&mt('Code').'</a></th>'.
  203:               '<th>'.&mt('Sections').'</th>'.
  204:               '<th>'.&mt('Crosslisted').'</th>'.
  205:               '<th><a href="javascript:changeSort('."'title'".')">'.&mt('Title').'</a></th>'.
  206:               '<th><a href="javascript:changeSort('."'owner'".')">'.&mt('Owner').'</a></th>'.
  207:               '<th>'.&mt('Student Status').'</th>'.
  208:               '<th>'.&mt('Default Access Dates').'</th>'.
  209:               '<th>'.&mt('Auto-enrollment').'</th>'.
  210:               &Apache::loncommon::end_data_table_header_row();
  211:     my %courseinfo;
  212:     foreach my $course (keys(%courses)) {
  213:         my $descr;
  214:         if ($courses{$course} =~ m/^([^:]*):/i) {
  215:             $descr = &unescape($1);
  216:         } else {
  217:             $descr = &unescape($courses{$course});
  218:         }
  219:         my $cleandesc=&HTML::Entities::encode($descr,'<>&"');
  220:         $cleandesc=~s/'/\\'/g;
  221:         my ($cdom,$cnum)=split(/\_/,$course);
  222:        
  223:         my ($desc,$instcode,$owner,$ttype) = split(/:/,$courses{$course});
  224:         $owner = &unescape($owner);
  225:         my ($ownername,$ownerdom);
  226:         if ($owner =~ /:/) {
  227:             ($ownername,$ownerdom) = split(/:/,$owner);
  228:         } else {
  229:             $ownername = $owner;
  230:             if ($owner ne '') {
  231:                 $ownerdom = $cdom;
  232:             }
  233:         }
  234:         my %ownernames;
  235:         if ($ownername ne '' && $ownerdom ne '') {
  236:             %ownernames = &Apache::loncommon::getnames($ownername,$ownerdom);
  237:         }
  238:         $courseinfo{$course}{'cdom'} = $cdom;
  239:         $courseinfo{$course}{'cnum'} = $cnum;
  240:         $courseinfo{$course}{'code'} = $instcode;
  241:         $courseinfo{$course}{'ownerlastname'} = $ownernames{'lastname'};
  242:         $courseinfo{$course}{'title'} = $cleandesc;
  243:         $courseinfo{$course}{'owner'} = $owner; 
  244:     }
  245:     my %Sortby;
  246:     foreach my $course (sort(keys(%courses))) {
  247:         if ($env{'form.sortby'} eq 'code') {
  248:             push(@{$Sortby{$courseinfo{$course}{'code'}}},$course);
  249:         } elsif ($env{'form.sortby'} eq 'owner') {
  250:             push(@{$Sortby{$courseinfo{$course}{'ownerlastname'}}},$course);
  251:         } else {
  252:             push(@{$Sortby{$courseinfo{$course}{'title'}}},$course);
  253:         }
  254:     }
  255:     my @sorted_courses;
  256:     if (($env{'form.sortby'} eq 'code') || ($env{'form.sortby'} eq 'owner')) {
  257:         @sorted_courses = sort(keys(%Sortby));
  258:     } else {
  259:         @sorted_courses = sort { lc($a) cmp lc($b) } (keys(%Sortby));
  260:     }
  261:     foreach my $item (@sorted_courses) {
  262:         foreach my $course (@{$Sortby{$item}}) {
  263:             $output.=&Apache::loncommon::start_data_table_row(); 
  264:             $output.=&courseinfo_row($courseinfo{$course});
  265:             $output.=&Apache::loncommon::end_data_table_row();
  266:         }
  267:     }
  268:     $output .= &Apache::loncommon::end_data_table();
  269:     return $output;
  270: }
  271: 
  272: sub courseinfo_row {
  273:     my ($info) = @_;
  274:     my ($cdom,$cnum,$title,$ownerlast,$code,$owner,$output);
  275:     if (ref($info) eq 'HASH') {
  276:         $cdom = $info->{'cdom'};
  277:         $cnum = $info->{'cnum'};
  278:         $title = $info->{'title'};
  279:         $ownerlast = $info->{'ownerlastname'};
  280:         $code = $info->{'code'};
  281:         $owner = $info->{'owner'};
  282:     } else {
  283:         $output = '<td colspan="8">'.&mt('No information available for [_1].',
  284:                                          $code).'</td>';
  285:         return $output;
  286:     }
  287:     my %coursehash = &Apache::lonnet::dump('environment',$cdom,$cnum);
  288:     my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cnum);
  289:     my %idx;
  290:     my @classids;
  291:     my @crosslistings;
  292:     $idx{'status'} = &Apache::loncoursedata::CL_STATUS();
  293:     my %status_title = &Apache::lonlocal::texthash(
  294:                            Expired => 'Previous access',
  295:                            Active => 'Current access',
  296:                            Future => 'Future access',
  297:                        );
  298:     my %student_count = (
  299:                            Expired => 0,
  300:                            Active => 0,
  301:                            Future => 0,
  302:                        );
  303:     while (my ($student,$data) = each(%$classlist)) {
  304:         $student_count{$data->[$idx{'status'}]} ++;
  305:     }
  306:     my $seclist = &identify_sections($coursehash{'internal.sectionnums'});
  307:     my $xlist_items = &identify_sections($coursehash{'internal.crosslistings'});
  308:     my $countslist;
  309:     my $startaccess = '';
  310:     my $endaccess = '';
  311:     my $now;
  312:     my ($accessdates,$autoenrolldates,$showsyllabus);
  313:     if ( defined($coursehash{'default_enrollment_start_date'}) ) {
  314:         $startaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_start_date'});
  315:     }
  316:     if ( defined($coursehash{'default_enrollment_end_date'}) ) {
  317:         $endaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_end_date'});
  318:         if ($coursehash{'default_enrollment_end_date'} == 0) {
  319:             $endaccess = "No ending date";
  320:         }
  321:     }
  322:     if ($startaccess) {
  323:         $accessdates .= &mt('From: ').$startaccess.'<br />';
  324:     }
  325:     if ($endaccess) {
  326:         $accessdates .= &mt('To: ').$endaccess.'<br />';
  327:     }
  328:     $autoenrolldates = &mt('Not enabled');
  329:     if (defined($coursehash{'internal.autoadds'}) && $coursehash{'internal.autoadds'} == 1) {
  330:         my ($autostart,$autoend);
  331:         if ( defined($coursehash{'internal.autostart'}) ) {
  332:             $autostart = &Apache::lonlocal::locallocaltime($coursehash{'internal.autostart'});
  333:         }
  334:         if ( defined($coursehash{'internal.autoend'}) ) {
  335:             $autoend = &Apache::lonlocal::locallocaltime($coursehash{'internal.autoend'});
  336:         }
  337:         if ($coursehash{'internal.autostart'} > $now) {
  338:             if ($coursehash{'internal.autoend'} && $coursehash{'internal.autoend'} < $now) {
  339:                 $autoenrolldates = &mt('Not enabled');
  340:             } else {
  341:                 my $valid_classes = &get_valid_classes($seclist,$xlist_items,
  342:                                                        $code,$owner,$cdom,$cnum);
  343:                 if ($valid_classes ne '') {
  344:                     $autoenrolldates = &mt('Not enabled<br />Starts: ').
  345:                                        $autostart.'<br />'.$valid_classes;
  346:                 }
  347:             }
  348:         } else {
  349:             if ($coursehash{'internal.autoend'} && $coursehash{'internal.autoend'} < $now) {
  350:                 $autoenrolldates = &mt('Not enabled<br />Ended: ').$autoend;
  351:             } else {
  352:                 my $valid_classes = &get_valid_classes($seclist,$xlist_items,
  353:                                                        $code,$owner,$cdom,$cnum);
  354:                 if ($valid_classes ne '') {
  355:                     $autoenrolldates = &mt('Currently enabled<br />').
  356:                                        $valid_classes;
  357:                 }
  358:             }
  359:         }
  360:     }
  361:     if (defined($coursehash{'showsyllabus'})) {
  362:         $showsyllabus = $coursehash{'showsyllabus'};
  363:     } 
  364:     foreach my $status ('Active','Future','Expired') {
  365:         $countslist .= '<nobr>'.$status_title{$status}.': '.
  366:                        $student_count{$status}.'</nobr><br />';
  367:     }
  368:     if ($xlist_items eq '') {
  369:         $xlist_items = &mt('No');
  370:     }
  371:     $output = '<td>'.$coursehash{'internal.coursecode'}.'</td>'.
  372:               '<td>'.$seclist.'</td>'.
  373:               '<td>'.$xlist_items.'</td>'.
  374:               '<td>'.$title.'&nbsp;<font size="-2">';
  375:     if ($showsyllabus) {
  376:         $output .= &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$cnum,$cdom);
  377:     }
  378:     $output .= '</font></td>'.
  379:                '<td>'.$ownerlast.'</td>'.
  380:                '<td>'.$countslist.'</td>'.
  381:                '<td>'.$accessdates.'</td>'.
  382:                '<td>'.$autoenrolldates.'</td>'; 
  383:     return $output;
  384: }
  385: 
  386: sub identify_sections {
  387:     my ($seclist) = @_;
  388:     my @secnums;
  389:     if ($seclist =~ /,/) {
  390:         my @sections = split(/,/,$seclist);
  391:         foreach my $sec (@sections) {
  392:             $sec =~ s/:[^:]*$//;
  393:             push(@secnums,$sec);
  394:         }
  395:     } else {
  396:         if ($seclist =~ m/^([^:]+):/) {
  397:             my $sec = $1;
  398:             if (!grep(/^\Q$sec\E$/,@secnums)) {
  399:                 push(@secnums,$sec);
  400:             }
  401:         }
  402:     }
  403:     @secnums = sort {$a <=> $b} @secnums;
  404:     my $seclist = join(', ',@secnums);
  405:     return $seclist;
  406: }
  407: 
  408: sub get_valid_classes {
  409:     my ($seclist,$xlist_items,$crscode,$owner,$cdom,$cnum) = @_;
  410:     my $response;
  411:     my %validations;
  412:     @{$validations{'sections'}} = ();
  413:     @{$validations{'xlists'}} = ();
  414:     my $totalitems = 0;
  415:     if ($seclist) {
  416:         foreach my $sec (split(',',$seclist)) {
  417:             my $class = $crscode.$sec;
  418:             if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owner,
  419: 							 $class) eq 'ok') {
  420:                 if (!grep(/^\Q$sec$\E/,@{$validations{'sections'}})) {
  421:                     push(@{$validations{'sections'}},$sec);
  422:                     $totalitems ++;
  423:                 }
  424:             }
  425:         }
  426:     }
  427:     if ($xlist_items) {
  428:         foreach my $item (split(',',$xlist_items)) {
  429:             if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owner,
  430: 							 $item) eq 'ok') {
  431:                 if (!grep(/^\Q$item$\E/,@{$validations{'xlists'}})) {
  432:                     push(@{$validations{'xlists'}},$item);
  433:                     $totalitems ++;
  434:                 }
  435:             }
  436:         }
  437:     }
  438:     if ($totalitems > 0) {
  439:         if (@{$validations{'sections'}}) {
  440:             $response = &mt('Sections: ').
  441:                         join(',',@{$validations{'sections'}}).'<br />';
  442:         }
  443:         if (@{$validations{'xlists'}}) {
  444:             $response .= &mt('Courses: ').
  445:                         join(',',@{$validations{'xlists'}});
  446:         }
  447:     }
  448:     return $response;
  449: }
  450: 
  451: 
  452: 1;
  453: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>