File:  [LON-CAPA] / loncom / interface / coursecatalog.pm
Revision 1.5: download - view: text, annotated - select for diffs
Mon Sep 25 00:16:56 2006 UTC (17 years, 8 months ago) by raeburn
Branches: MAIN
CVS tags: HEAD
Need to return status code from the handler.  Also provide appropriate message when no courses have been assigned institutional codes.

    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:     my $domdesc = $Apache::lonnet::domaindescription{$codedom};
   64:     $totcodes = &Apache::lonsupportreq::retrieve_instcodes(\%coursecodes,$codedom,$totcodes);
   65:     if ($totcodes > 0) {
   66:         if ($ccode eq '') {
   67:             $format_reply = &Apache::lonnet::auto_instcode_format($caller,$codedom,\%coursecodes,\%codes,\@codetitles,\%cat_titles,\%cat_order);
   68:             if ($format_reply eq 'ok') {
   69:                 my $numtypes = @codetitles;
   70:                 &Apache::lonsupportreq::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles);
   71:                 &Apache::lonsupportreq::javascript_code_selections($formname,$numtypes,\%cat_titles,\$jscript,\%idlist,\%idnums,\%idlist_titles,\@codetitles);
   72:             }
   73:         }
   74:         if ($env{'form.state'} eq 'listing') {
   75:             $jscript .= '
   76: function setElements() {
   77: ';
   78:             for (my $i=0; $i<@codetitles; $i++) {
   79:                 if ($env{'form.'.$codetitles[$i]} != -1) {
   80:                     $jscript .= '
   81:     for (var j=0; j<document.'.$formname.'.'.$codetitles[$i].'.length; j++) {
   82:         if (document.'.$formname.'.'.$codetitles[$i].'[j].value == "'.$env{'form.'.$codetitles[$i]}.'") {
   83:             document.'.$formname.'.'.$codetitles[$i].'.selectedIndex = j;
   84:         }
   85:     }
   86: ';
   87:                     $jscript .= '  courseSet('."'$codetitles[$i]'".');'."\n";
   88:                 } else {
   89:                     last;
   90:                 }
   91:             }
   92:             $jscript .= '}';
   93:             $jscript .= qq|
   94: function changeSort(caller) {
   95:     document.coursecatalog.sortby.value = caller;
   96:     document.coursecatalog.submit();
   97: }\n|;
   98:         }
   99:         my $js = '<script type"text/javascript">'."\n$jscript\n".
  100:                  '</script>';
  101:         my %add_entries = (topmargin    => "0",
  102:                            marginheight => "0",
  103:                            onLoad       =>"setElements()",);
  104:         my $start_page =
  105:             &Apache::loncommon::start_page('Course Catalog',$js,
  106:                                            { 
  107:                                              'add_entries' => \%add_entries,
  108:                                              'no_inline_link'   => 1,});
  109:         $r->print($start_page);
  110: 
  111:         my $numtitles = @codetitles;
  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:     } else {
  167:         $r->print(&Apache::loncommon::start_page('Course Catalog','',
  168:                   {
  169:                    'no_inline_link'   => 1,}));
  170:         $r->print('<br />'.&mt('No official courses to display for [_1].',$domdesc));
  171:     }
  172:     if ($env{'form.state'} eq 'listing') {
  173:         $r->print('<br /><br />'.&print_course_listing($codedom));
  174:     }
  175:     $r->print(&Apache::loncommon::end_page());
  176:     return OK;
  177: }
  178: 
  179: sub print_course_listing {
  180:     my ($domain) = @_;
  181:     my $output;
  182:     my $year = $env{'form.Year'};
  183:     my $sem = $env{'form.Semester'};
  184:     my $dept = $env{'form.Department'};
  185:     my $coursenum = $env{'form.Number'};
  186:     my $instcode;
  187:     if ($sem != -1) {
  188:         $instcode .= $sem; 
  189:     }
  190:     if ($year != -1) {
  191:         $instcode .= $year; 
  192:     }
  193:     if ($dept != -1) {
  194:         $instcode .= $dept;
  195:     }
  196:     if ($coursenum != -1) {
  197:         $instcode .= $coursenum; 
  198:     }
  199:     my %courses = &Apache::lonnet::courseiddump($domain,'.',1,$instcode,'.','.',
  200:                                                 undef,undef,'Course');
  201:     if (keys(%courses) == 0) {
  202:         $output = &mt('No courses match the criteria you selected.');
  203:         return $output;
  204:     }
  205:     $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 />');
  206:     $output .= &Apache::loncommon::start_data_table().
  207:               &Apache::loncommon::start_data_table_header_row().
  208:               '<th><a href="javascript:changeSort('."'code'".')">'.&mt('Code').'</a></th>'.
  209:               '<th>'.&mt('Sections').'</th>'.
  210:               '<th>'.&mt('Crosslisted').'</th>'.
  211:               '<th><a href="javascript:changeSort('."'title'".')">'.&mt('Title').'</a></th>'.
  212:               '<th><a href="javascript:changeSort('."'owner'".')">'.&mt('Owner').'</a></th>'.
  213:               '<th>'.&mt('Student Status').'</th>'.
  214:               '<th>'.&mt('Default Access Dates').'</th>'.
  215:               '<th>'.&mt('Auto-enrollment').'</th>'.
  216:               &Apache::loncommon::end_data_table_header_row();
  217:     my %courseinfo;
  218:     foreach my $course (keys(%courses)) {
  219:         my $descr;
  220:         if ($courses{$course} =~ m/^([^:]*):/i) {
  221:             $descr = &unescape($1);
  222:         } else {
  223:             $descr = &unescape($courses{$course});
  224:         }
  225:         my $cleandesc=&HTML::Entities::encode($descr,'<>&"');
  226:         $cleandesc=~s/'/\\'/g;
  227:         my ($cdom,$cnum)=split(/\_/,$course);
  228:        
  229:         my ($desc,$instcode,$owner,$ttype) = split(/:/,$courses{$course});
  230:         $owner = &unescape($owner);
  231:         my ($ownername,$ownerdom);
  232:         if ($owner =~ /:/) {
  233:             ($ownername,$ownerdom) = split(/:/,$owner);
  234:         } else {
  235:             $ownername = $owner;
  236:             if ($owner ne '') {
  237:                 $ownerdom = $cdom;
  238:             }
  239:         }
  240:         my %ownernames;
  241:         if ($ownername ne '' && $ownerdom ne '') {
  242:             %ownernames = &Apache::loncommon::getnames($ownername,$ownerdom);
  243:         }
  244:         $courseinfo{$course}{'cdom'} = $cdom;
  245:         $courseinfo{$course}{'cnum'} = $cnum;
  246:         $courseinfo{$course}{'code'} = $instcode;
  247:         $courseinfo{$course}{'ownerlastname'} = $ownernames{'lastname'};
  248:         $courseinfo{$course}{'title'} = $cleandesc;
  249:         $courseinfo{$course}{'owner'} = $owner; 
  250:     }
  251:     my %Sortby;
  252:     foreach my $course (sort(keys(%courses))) {
  253:         if ($env{'form.sortby'} eq 'code') {
  254:             push(@{$Sortby{$courseinfo{$course}{'code'}}},$course);
  255:         } elsif ($env{'form.sortby'} eq 'owner') {
  256:             push(@{$Sortby{$courseinfo{$course}{'ownerlastname'}}},$course);
  257:         } else {
  258:             push(@{$Sortby{$courseinfo{$course}{'title'}}},$course);
  259:         }
  260:     }
  261:     my @sorted_courses;
  262:     if (($env{'form.sortby'} eq 'code') || ($env{'form.sortby'} eq 'owner')) {
  263:         @sorted_courses = sort(keys(%Sortby));
  264:     } else {
  265:         @sorted_courses = sort { lc($a) cmp lc($b) } (keys(%Sortby));
  266:     }
  267:     foreach my $item (@sorted_courses) {
  268:         foreach my $course (@{$Sortby{$item}}) {
  269:             $output.=&Apache::loncommon::start_data_table_row(); 
  270:             $output.=&courseinfo_row($courseinfo{$course});
  271:             $output.=&Apache::loncommon::end_data_table_row();
  272:         }
  273:     }
  274:     $output .= &Apache::loncommon::end_data_table();
  275:     return $output;
  276: }
  277: 
  278: sub courseinfo_row {
  279:     my ($info) = @_;
  280:     my ($cdom,$cnum,$title,$ownerlast,$code,$owner,$output);
  281:     if (ref($info) eq 'HASH') {
  282:         $cdom = $info->{'cdom'};
  283:         $cnum = $info->{'cnum'};
  284:         $title = $info->{'title'};
  285:         $ownerlast = $info->{'ownerlastname'};
  286:         $code = $info->{'code'};
  287:         $owner = $info->{'owner'};
  288:     } else {
  289:         $output = '<td colspan="8">'.&mt('No information available for [_1].',
  290:                                          $code).'</td>';
  291:         return $output;
  292:     }
  293:     my %coursehash = &Apache::lonnet::dump('environment',$cdom,$cnum);
  294:     my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cnum);
  295:     my %idx;
  296:     my @classids;
  297:     my @crosslistings;
  298:     $idx{'status'} = &Apache::loncoursedata::CL_STATUS();
  299:     my %status_title = &Apache::lonlocal::texthash(
  300:                            Expired => 'Previous access',
  301:                            Active => 'Current access',
  302:                            Future => 'Future access',
  303:                        );
  304:     my %student_count = (
  305:                            Expired => 0,
  306:                            Active => 0,
  307:                            Future => 0,
  308:                        );
  309:     while (my ($student,$data) = each(%$classlist)) {
  310:         $student_count{$data->[$idx{'status'}]} ++;
  311:     }
  312:     my $seclist = &identify_sections($coursehash{'internal.sectionnums'});
  313:     my $xlist_items = &identify_sections($coursehash{'internal.crosslistings'});
  314:     my $countslist;
  315:     my $startaccess = '';
  316:     my $endaccess = '';
  317:     my $now;
  318:     my ($accessdates,$autoenrolldates,$showsyllabus);
  319:     if ( defined($coursehash{'default_enrollment_start_date'}) ) {
  320:         $startaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_start_date'});
  321:     }
  322:     if ( defined($coursehash{'default_enrollment_end_date'}) ) {
  323:         $endaccess = &Apache::lonlocal::locallocaltime($coursehash{'default_enrollment_end_date'});
  324:         if ($coursehash{'default_enrollment_end_date'} == 0) {
  325:             $endaccess = "No ending date";
  326:         }
  327:     }
  328:     if ($startaccess) {
  329:         $accessdates .= &mt('From: ').$startaccess.'<br />';
  330:     }
  331:     if ($endaccess) {
  332:         $accessdates .= &mt('To: ').$endaccess.'<br />';
  333:     }
  334:     $autoenrolldates = &mt('Not enabled');
  335:     if (defined($coursehash{'internal.autoadds'}) && $coursehash{'internal.autoadds'} == 1) {
  336:         my ($autostart,$autoend);
  337:         if ( defined($coursehash{'internal.autostart'}) ) {
  338:             $autostart = &Apache::lonlocal::locallocaltime($coursehash{'internal.autostart'});
  339:         }
  340:         if ( defined($coursehash{'internal.autoend'}) ) {
  341:             $autoend = &Apache::lonlocal::locallocaltime($coursehash{'internal.autoend'});
  342:         }
  343:         if ($coursehash{'internal.autostart'} > $now) {
  344:             if ($coursehash{'internal.autoend'} && $coursehash{'internal.autoend'} < $now) {
  345:                 $autoenrolldates = &mt('Not enabled');
  346:             } else {
  347:                 my $valid_classes = &get_valid_classes($seclist,$xlist_items,
  348:                                                        $code,$owner,$cdom,$cnum);
  349:                 if ($valid_classes ne '') {
  350:                     $autoenrolldates = &mt('Not enabled<br />Starts: ').
  351:                                        $autostart.'<br />'.$valid_classes;
  352:                 }
  353:             }
  354:         } else {
  355:             if ($coursehash{'internal.autoend'} && $coursehash{'internal.autoend'} < $now) {
  356:                 $autoenrolldates = &mt('Not enabled<br />Ended: ').$autoend;
  357:             } else {
  358:                 my $valid_classes = &get_valid_classes($seclist,$xlist_items,
  359:                                                        $code,$owner,$cdom,$cnum);
  360:                 if ($valid_classes ne '') {
  361:                     $autoenrolldates = &mt('Currently enabled<br />').
  362:                                        $valid_classes;
  363:                 }
  364:             }
  365:         }
  366:     }
  367:     if (defined($coursehash{'showsyllabus'})) {
  368:         $showsyllabus = $coursehash{'showsyllabus'};
  369:     } 
  370:     foreach my $status ('Active','Future','Expired') {
  371:         $countslist .= '<nobr>'.$status_title{$status}.': '.
  372:                        $student_count{$status}.'</nobr><br />';
  373:     }
  374:     if ($xlist_items eq '') {
  375:         $xlist_items = &mt('No');
  376:     }
  377:     $output = '<td>'.$coursehash{'internal.coursecode'}.'</td>'.
  378:               '<td>'.$seclist.'</td>'.
  379:               '<td>'.$xlist_items.'</td>'.
  380:               '<td>'.$title.'&nbsp;<font size="-2">';
  381:     if ($showsyllabus) {
  382:         $output .= &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$cnum,$cdom);
  383:     }
  384:     $output .= '</font></td>'.
  385:                '<td>'.$ownerlast.'</td>'.
  386:                '<td>'.$countslist.'</td>'.
  387:                '<td>'.$accessdates.'</td>'.
  388:                '<td>'.$autoenrolldates.'</td>'; 
  389:     return $output;
  390: }
  391: 
  392: sub identify_sections {
  393:     my ($seclist) = @_;
  394:     my @secnums;
  395:     if ($seclist =~ /,/) {
  396:         my @sections = split(/,/,$seclist);
  397:         foreach my $sec (@sections) {
  398:             $sec =~ s/:[^:]*$//;
  399:             push(@secnums,$sec);
  400:         }
  401:     } else {
  402:         if ($seclist =~ m/^([^:]+):/) {
  403:             my $sec = $1;
  404:             if (!grep(/^\Q$sec\E$/,@secnums)) {
  405:                 push(@secnums,$sec);
  406:             }
  407:         }
  408:     }
  409:     @secnums = sort {$a <=> $b} @secnums;
  410:     my $seclist = join(', ',@secnums);
  411:     return $seclist;
  412: }
  413: 
  414: sub get_valid_classes {
  415:     my ($seclist,$xlist_items,$crscode,$owner,$cdom,$cnum) = @_;
  416:     my $response;
  417:     my %validations;
  418:     @{$validations{'sections'}} = ();
  419:     @{$validations{'xlists'}} = ();
  420:     my $totalitems = 0;
  421:     if ($seclist) {
  422:         foreach my $sec (split(',',$seclist)) {
  423:             my $class = $crscode.$sec;
  424:             if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owner,
  425: 							 $class) eq 'ok') {
  426:                 if (!grep(/^\Q$sec$\E/,@{$validations{'sections'}})) {
  427:                     push(@{$validations{'sections'}},$sec);
  428:                     $totalitems ++;
  429:                 }
  430:             }
  431:         }
  432:     }
  433:     if ($xlist_items) {
  434:         foreach my $item (split(',',$xlist_items)) {
  435:             if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owner,
  436: 							 $item) eq 'ok') {
  437:                 if (!grep(/^\Q$item$\E/,@{$validations{'xlists'}})) {
  438:                     push(@{$validations{'xlists'}},$item);
  439:                     $totalitems ++;
  440:                 }
  441:             }
  442:         }
  443:     }
  444:     if ($totalitems > 0) {
  445:         if (@{$validations{'sections'}}) {
  446:             $response = &mt('Sections: ').
  447:                         join(',',@{$validations{'sections'}}).'<br />';
  448:         }
  449:         if (@{$validations{'xlists'}}) {
  450:             $response .= &mt('Courses: ').
  451:                         join(',',@{$validations{'xlists'}});
  452:         }
  453:     }
  454:     return $response;
  455: }
  456: 
  457: 
  458: 1;
  459: 

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