[LON-CAPA-cvs] cvs: loncom / lond /interface coursecatalog.pm courseclassifier.pm lonmodifycourse.pm lonpickcourse.pm /lonnet/perl lonnet.pm

raeburn lon-capa-cvs-allow@mail.lon-capa.org
Wed, 03 Oct 2007 19:57:30 -0000


This is a MIME encoded message

--raeburn1191441450
Content-Type: text/plain

raeburn		Wed Oct  3 15:57:30 2007 EDT

  Modified files:              
    /loncom	lond 
    /loncom/lonnet/perl	lonnet.pm 
    /loncom/interface	lonmodifycourse.pm coursecatalog.pm 
                     	courseclassifier.pm lonpickcourse.pm 
  Log:
  Store data in nohist_courseids.db as a hash.  Maintain backwards compatibility with writes to the db from legacy lonnet.pm, and also reads from the db from legacy lonnet.pm.
  
  Start towards inclusion of co-owners as well as a single owner, for the purposes of verifying access to official classlist data.
  
  lond 
  - &put_course_id_hash_handler() added to handle storage of data in nohist_courseids.db as a frozen hash.
  - &put_course_id_handler() will add to an existing hash if update is from a legacy lonnet which supplies : separated data.
  - &dump_course_id_handler() $as_hash flag extracted from tail. If set, data are returned as a hash.
  - validate_class_access_handler() will extract comma-separated owner and co-owners from ownerlist passed to it, and send array ref to localenroll::check_section() to determine if at least one on the owners is authorized to view classlist list data for the institutional section.  
  
  lonnet.pm
  - storage of hash via call to courseidputhash in lond.  If command is unrecognized on the lond side, subset of the data sent as : separated values
  - retrieval of data from nohist_courseids.db - additional $as_hash argument included in courseiddump call to indicate that data should be returned as a frozen hash.
  - auto_validate_class_sec() - if third argument is an array ref, then an owner list is built from the supplied owners and co-owners.
  - lasttime set on lonnet side (FIXME) - to be changed to lond side. 
  
  lomodifycourse.pm
  - updated course settings sent as a ref to a hash to lonnet::courseidput()
  - include LC_error in span for error messages
  - eliminate duplicate error message
  - display error if storage of changes fails
  - form name corrected to cmod.
  
  coursecatalog.pm 
  - eliminate unused arg from call to courseclassifier::retrieve_instcodes
  - display owner and co-owners (sort by lastname)
  - institutional section access for multiple owners
  
  courseclassifier.pm
  - course codes from course data if hash, or if : separated string.
   
  lonpickcourse.pm
  - course info extracted from hash
  - owner info displayed in a list if owner and co-owners exist.   
  
  
--raeburn1191441450
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20071003155730.txt"

Index: loncom/lond
diff -u loncom/lond:1.382 loncom/lond:1.383
--- loncom/lond:1.382	Sat Sep 29 00:03:39 2007
+++ loncom/lond	Wed Oct  3 15:57:23 2007
@@ -2,7 +2,7 @@
 # The LearningOnline Network
 # lond "LON Daemon" Server (port "LOND" 5663)
 #
-# $Id: lond,v 1.382 2007/09/29 04:03:39 albertel Exp $
+# $Id: lond,v 1.383 2007/10/03 19:57:23 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -53,13 +53,14 @@
 use LONCAPA::lonlocal;
 use LONCAPA::lonssl;
 use Fcntl qw(:flock);
+use Apache::lonnet;
 
 my $DEBUG = 0;		       # Non zero to enable debug log entries.
 
 my $status='';
 my $lastlog='';
 
-my $VERSION='$Revision: 1.382 $'; #' stupid emacs
+my $VERSION='$Revision: 1.383 $'; #' stupid emacs
 my $remoteVERSION;
 my $currenthostid="default";
 my $currentdomainid;
@@ -3304,23 +3305,32 @@
 	foreach my $pair (@pairs) {
             my ($key,$courseinfo) = split(/=/,$pair,2);
             $courseinfo =~ s/=/:/g;
-            my @current_items = split(/:/,$hashref->{$key},-1);
-            shift(@current_items); # remove description
-            pop(@current_items);   # remove last access
-            my $numcurrent = scalar(@current_items);
-            if ($numcurrent > 3) {
-                $numcurrent = 3;
-            }
-            my @new_items = split(/:/,$courseinfo,-1);
-            my $numnew = scalar(@new_items);
-            if ($numcurrent > 0) {
-                if ($numnew <= $numcurrent) { # flushcourselogs() from pre 2.2 
-                    for (my $j=$numcurrent-$numnew; $j>=0; $j--) {
-                        $courseinfo .= ':'.$current_items[$numcurrent-$j-1];
+            if (ref($hashref) eq 'HASH') {
+                my @items = ('description','inst_code','owner','type');
+                my @new_items = split(/:/,$courseinfo,-1);
+                for (my $i=0; $i<@new_items; $i++) {
+                    $hashref->{$key}{$items[$i]} = $new_items[$i];
+                }
+                $hashref->{$key}{'lasttime'} = $now;
+            } else {
+                my @current_items = split(/:/,$hashref->{$key},-1);
+                shift(@current_items); # remove description
+                pop(@current_items);   # remove last access
+                my $numcurrent = scalar(@current_items);
+                if ($numcurrent > 3) {
+                    $numcurrent = 3;
+                }
+                my @new_items = split(/:/,$courseinfo,-1);
+                my $numnew = scalar(@new_items);
+                if ($numcurrent > 0) {
+                    if ($numnew <= $numcurrent) { # flushcourselogs() from pre 2.2 
+                        for (my $j=$numcurrent-$numnew; $j>=0; $j--) {
+                            $courseinfo .= ':'.$current_items[$numcurrent-$j-1];
+                        }
                     }
                 }
+                $hashref->{$key}=$courseinfo.':'.$now;
             }
-	    $hashref->{$key}=$courseinfo.':'.$now;
 	}
 	if (&untie_domain_hash($hashref)) {
 	    &Reply( $client, "ok\n", $userinput);
@@ -3334,12 +3344,39 @@
 		 ." tie(GDBM) Failed ".
 		 "while attempting courseidput\n", $userinput);
     }
-    
 
     return 1;
 }
 &register_handler("courseidput", \&put_course_id_handler, 0, 1, 0);
 
+sub put_course_id_hash_handler {
+    my ($cmd, $tail, $client) = @_;
+    my $userinput = "$cmd:$tail";
+    my ($udom, $what) = split(/:/, $tail,2);
+    chomp($what);
+    my $now=time;
+    my @pairs=split(/\&/,$what);
+    my $hashref = &tie_domain_hash($udom, "nohist_courseids", &GDBM_WRCREAT(),
+                                   "P", $what);
+    if ($hashref) {
+        foreach my $pair (@pairs) {
+            my ($key,$value)=split(/=/,$pair);
+            $hashref->{$key} = $value;
+        }
+        if (&untie_domain_hash($hashref)) {
+            &Reply($client, "ok\n", $userinput);
+        } else {
+            &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
+                     "while attempting courseidputhash\n", $userinput);
+        }
+    } else {
+        &Failure( $client, "error: ".($!+0)." tie(GDBM) Failed ".
+                  "while attempting courseidputhash\n", $userinput);
+    }
+    return 1;
+}
+&register_handler("courseidputhash", \&put_course_id_hash_handler, 0, 1, 0);
+
 #  Retrieves the value of a course id resource keyword pattern
 #  defined since a starting date.  Both the starting date and the
 #  keyword pattern are optional.  If the starting date is not supplied it
@@ -3377,7 +3414,7 @@
     my $userinput = "$cmd:$tail";
 
     my ($udom,$since,$description,$instcodefilter,$ownerfilter,$coursefilter,
-        $typefilter,$regexp_ok) =split(/:/,$tail);
+        $typefilter,$regexp_ok,$as_hash) =split(/:/,$tail);
     if (defined($description)) {
 	$description=&unescape($description);
     } else {
@@ -3422,11 +3459,20 @@
     my $qresult='';
     my $hashref = &tie_domain_hash($udom, "nohist_courseids", &GDBM_WRCREAT());
     if ($hashref) {
-	while (my ($key,$value) = each(%$hashref)) {
+	while (my ($key,$rawvalue) = each(%$hashref)) {
 	    my ($descr,$lasttime,$inst_code,$owner,$type);
-            my @courseitems = split(/:/,$value);
-            $lasttime = pop(@courseitems);
-	    ($descr,$inst_code,$owner,$type)=@courseitems;
+            my $value = &Apache::lonnet::thaw_unescape($rawvalue);
+            if (ref($value) eq 'HASH') {
+                $descr = $value->{'description'};
+                $inst_code = $value->{'inst_code'};
+                $owner = $value->{'owner'};
+                $type = $value->{'type'};
+                $lasttime = $value->{'lasttime'};
+            } else {
+                my @courseitems = split(/:/,$rawvalue);
+                $lasttime = pop(@courseitems);
+	        ($descr,$inst_code,$owner,$type)=@courseitems;
+            }
 	    if ($lasttime<$since) { next; }
             my $match = 1;
 	    unless ($description eq '.') {
@@ -3482,6 +3528,7 @@
                     }
                 }
             }
+            my $unescapeCourse = &unescape($key);
             unless ($coursefilter eq '.' || !defined($coursefilter)) {
                 my $unescapeCourse = &unescape($key);
                 unless (eval('$unescapeCourse=~/^$udom(_)\Q$coursefilter\E$/')) {
@@ -3494,14 +3541,18 @@
                     if ($typefilter ne 'Course') {
                         $match = 0;
                     }
-                } else { 
+                } else {
                     unless (eval('$unescapeType=~/^\Q$typefilter\E$/')) {
                         $match = 0;
                     }
                 }
             }
             if ($match == 1) {
-                $qresult.=$key.'='.$descr.':'.$inst_code.':'.$owner.'&';
+                if ($as_hash) {
+                    $qresult.=$key.'='.$rawvalue.'&'; 
+                } else {
+                    $qresult.=$key.'='.$descr.':'.$inst_code.':'.$owner.'&';
+                }
             }
 	}
 	if (&untie_domain_hash($hashref)) {
@@ -3515,8 +3566,6 @@
 	&Failure($client, "error: ".($!+0)." tie(GDBM) Failed ".
 		"while attempting courseiddump\n", $userinput);
     }
-
-
     return 1;
 }
 &register_handler("courseiddump", \&dump_course_id_handler, 0, 1, 0);
@@ -4335,12 +4384,13 @@
 sub validate_class_access_handler {
     my ($cmd, $tail, $client) = @_;
     my $userinput = "$cmd:$tail";
-    my ($inst_class,$courseowner,$cdom) = split(/:/, $tail);
-    $courseowner = &unescape($courseowner);
+    my ($inst_class,$ownerlist,$cdom) = split(/:/, $tail);
+    $ownerlist = &unescape($ownerlist);
+    my @owners = split(/,/,&unescape($ownerlist));
     my $outcome;
     eval {
 	local($SIG{__DIE__})='DEFAULT';
-	$outcome=&localenroll::check_section($inst_class,$courseowner,$cdom);
+	$outcome=&localenroll::check_section($inst_class,\@owners,$cdom);
     };
     &Reply($client,"$outcome\n", $userinput);
 
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.917 loncom/lonnet/perl/lonnet.pm:1.918
--- loncom/lonnet/perl/lonnet.pm:1.917	Mon Oct  1 19:53:44 2007
+++ loncom/lonnet/perl/lonnet.pm	Wed Oct  3 15:57:26 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.917 2007/10/01 23:53:44 albertel Exp $
+# $Id: lonnet.pm,v 1.918 2007/10/03 19:57:26 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2183,23 +2183,20 @@
                delete $courselogs{$crsid};
             }
         }
-        if ($courseidbuffer{$coursehombuf{$crsid}}) {
-           $courseidbuffer{$coursehombuf{$crsid}}.='&'.
-			 &escape($crsid).'='.&escape($coursedescrbuf{$crsid}).
-                         ':'.&escape($courseinstcodebuf{$crsid}).':'.&escape($courseownerbuf{$crsid}).':'.&escape($coursetypebuf{$crsid});
-        } else {
-           $courseidbuffer{$coursehombuf{$crsid}}=
-			 &escape($crsid).'='.&escape($coursedescrbuf{$crsid}).
-                         ':'.&escape($courseinstcodebuf{$crsid}).':'.&escape($courseownerbuf{$crsid}).':'.&escape($coursetypebuf{$crsid});
-        }
+        $courseidbuffer{$coursehombuf{$crsid}}{$crsid} = (
+            'description' => &escape($coursedescrbuf{$crsid}),
+            'instcode'    => &escape($courseinstcodebuf{$crsid}),
+            'type'        => &escape($coursetypebuf{$crsid}),
+            'owner'       => &escape($courseownerbuf{$crsid}),
+        );
     }
 #
 # Write course id database (reverse lookup) to homeserver of courses 
 # Is used in pickcourse
 #
     foreach my $crs_home (keys(%courseidbuffer)) {
-        &courseidput(&host_domain($crs_home),$courseidbuffer{$crs_home},
-		     $crs_home);
+        my $response = &courseidput(&host_domain($crs_home),
+                                    $courseidbuffer{$crs_home},$crs_home);
     }
 #
 # File accesses
@@ -2505,31 +2502,65 @@
 #
 
 sub courseidput {
-    my ($domain,$what,$coursehome)=@_;
-    return &reply('courseidput:'.$domain.':'.$what,$coursehome);
+    my ($domain,$storehash,$coursehome)=@_;
+    my $items='';
+    my $now = time;
+    foreach my $item (keys(%$storehash)) {
+        $storehash->{$item}{'lasttime'} = $now;
+        $items.=&escape($item).'='.&freeze_escape($$storehash{$item}).'&';
+    }
+    $items=~s/\&$//;
+    my $outcome = &reply('courseidputhash:'.$domain.':'.$items,$coursehome);
+    if ($outcome eq 'unknown_cmd') {
+        my $what;
+        foreach my $cid (keys(%$storehash)) {
+            $what .= &escape($cid).'=';
+            foreach my $item ('description','instcode','owner','type') {
+                $what .= $storehash->{$item}.':';
+            }
+            $what =~ s/\:$/&/;
+        }
+        $what =~ s/\&$//;  
+        return &reply('courseidput:'.$domain.':'.$what,$coursehome);
+    } else {
+        return $outcome;
+    }
 }
 
 sub courseiddump {
     my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,$coursefilter,$hostidflag,$hostidref,$typefilter,$regexp_ok)=@_;
-    my %returnhash=();
-    unless ($domfilter) { $domfilter=''; }
+    my $as_hash = 1;
+    my %returnhash;
+    if (!$domfilter) { $domfilter=''; }
     my %libserv = &all_library();
     foreach my $tryserver (keys(%libserv)) {
         if ( (  $hostidflag == 1 
 	        && grep(/^\Q$tryserver\E$/,@{$hostidref}) ) 
 	     || (!defined($hostidflag)) ) {
 
-	    if ($domfilter eq ''
-		|| (&host_domain($tryserver) eq $domfilter)) {
-	        foreach my $line (
-                 split(/\&/,&reply('courseiddump:'.&host_domain($tryserver).':'.
-			       $sincefilter.':'.&escape($descfilter).':'.
-                               &escape($instcodefilter).':'.&escape($ownerfilter).':'.&escape($coursefilter).':'.&escape($typefilter).':'.&escape($regexp_ok),
-                               $tryserver))) {
-		    my ($key,$value)=split(/\=/,$line,2);
-                    if (($key) && ($value)) {
-		        $returnhash{&unescape($key)}=$value;
-                    }
+	    if (($domfilter eq '') ||
+		(&host_domain($tryserver) eq $domfilter)) {
+                my $rep = 
+                  &reply('courseiddump:'.&host_domain($tryserver).':'.
+                         $sincefilter.':'.&escape($descfilter).':'.
+                         &escape($instcodefilter).':'.&escape($ownerfilter).
+                         ':'.&escape($coursefilter).':'.&escape($typefilter).
+                         ':'.&escape($regexp_ok).':'.$as_hash,$tryserver); 
+                my @pairs=split(/\&/,$rep);
+                foreach my $item (@pairs) {
+                    my ($key,$value)=split(/\=/,$item,2);
+                    $key = &unescape($key);
+                    next if ($key =~ /^error: 2 /);
+                    my $result = &thaw_unescape($value);
+                    if (ref($result) eq 'HASH') {
+                        $returnhash{$key}=$result;
+                    } else {
+                        my @responses = split(/:/,$result);
+                        my @items = ('description','instcode','owner','type');
+                        for (my $i=0; $i<@responses; $i++) {
+                            $returnhash{$key}{$items[$i]} = $responses[$i];
+                        }
+                    } 
                 }
             }
         }
@@ -4975,10 +5006,16 @@
 } 
 
 sub auto_validate_class_sec {
-    my ($cdom,$cnum,$owner,$inst_class) = @_;
+    my ($cdom,$cnum,$owners,$inst_class) = @_;
     my $homeserver = &homeserver($cnum,$cdom);
+    my $ownerlist;
+    if (ref($owners) eq 'ARRAY') {
+        $ownerlist = join(',',@{$owners});
+    } else {
+        $ownerlist = $owners;
+    }
     my $response=&reply('autovalidateclass_sec:'.$inst_class.':'.
-                        &escape($owner).':'.$cdom,$homeserver);
+                        &escape($ownerlist).':'.$cdom,$homeserver);
     return $response;
 }
 
@@ -5507,9 +5544,15 @@
     }
 # ----------------------------------------------------------------- Course made
 # log existence
-    &courseidput($udom,&escape($udom.'_'.$uname).'='.&escape($description).
-                 ':'.&escape($inst_code).':'.&escape($course_owner).':'.
-                  &escape($crstype),$uhome);
+    my $newcourse = {
+                    $udom.'_'.$uname => {
+                                     description => &escape($description),
+                                     inst_code   => &escape($inst_code),
+                                     owner       => &escape($course_owner),
+                                     type        => &escape($crstype),
+                                                },
+                    };
+    &courseidput($udom,$newcourse);
     &flushcourselogs();
 # set toplevel url
     my $topurl=$url;
@@ -5540,7 +5583,7 @@
 sub is_course {
     my ($cdom,$cnum) = @_;
     my %courses = &courseiddump($cdom,'.',1,'.','.',$cnum,undef,
-				undef,'.');
+				undef,'.',undef,1);
     if (exists($courses{$cdom.'_'.$cnum})) {
         return 1;
     }
Index: loncom/interface/lonmodifycourse.pm
diff -u loncom/interface/lonmodifycourse.pm:1.32 loncom/interface/lonmodifycourse.pm:1.33
--- loncom/interface/lonmodifycourse.pm:1.32	Mon Sep 24 19:29:53 2007
+++ loncom/interface/lonmodifycourse.pm	Wed Oct  3 15:57:29 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # handler for DC-only modifiable course settings
 #
-# $Id: lonmodifycourse.pm,v 1.32 2007/09/24 23:29:53 raeburn Exp $
+# $Id: lonmodifycourse.pm,v 1.33 2007/10/03 19:57:29 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -368,7 +368,7 @@
     }
     unless ($curr_authtype eq '') {
         $curr_authfield = $curr_authtype.'arg';
-    } 
+    }
     my $javascript_validations=&Apache::londropadd::javascript_validations('modifycourse',$krbdefdom,$curr_authtype,$curr_authfield);
     my %param = ( formname => 'document.cmod',
 	   kerb_def_dom => $krbdefdom,
@@ -437,7 +437,7 @@
     my $mainheader = &mt('Course settings modifiable by [_1] only.',$dctitle);
     my $hidden_elements = &hidden_form_elements();
     $r->print(<<ENDDOCUMENT);
-<form action="/adm/modifycourse" method="post" name="setparms">
+<form action="/adm/modifycourse" method="post" name="cmod">
 <h3>$mainheader</h3>
 </p><p>
 <table width="100%" cellspacing="6" cellpadding="6">
@@ -561,9 +561,17 @@
     }
     if ($changeowner == 1 || $changecode == 1) {
         my $courseid_entry = &escape($cdom.'_'.$cnum).'='.&escape($description).':'.&escape($env{'form.coursecode'}).':'.&escape($env{'form.courseowner'}).':'.&escape($type);
-        &Apache::lonnet::courseidput($cdom,$courseid_entry,&Apache::lonnet::homeserver($cnum,$cdom));
+        my %courseid_entry = (
+             $cdom.'_'.$cnum => {
+                                description => &escape($description),
+                                inst_code   => &escape($env{'form.coursecode'}),
+                                owner       => &escape($env{'form.courseowner'}),
+                                type        => &escape($type),
+                               },
+        );
+        &Apache::lonnet::courseidput($cdom,\%courseid_entry,
+                                     &Apache::lonnet::homeserver($cnum,$cdom));
     }
-
     foreach my $param (@modifiable_params) {
         if ($currattr{$param} eq $newattr{$param}) {
             push(@nochanges,$param);
@@ -573,17 +581,16 @@
             push(@changes,$param);
         }
     }
-
     if (@changes > 0) {
         $chgresponse = &mt("The following automated enrollment parameters have been changed:<br/><ul>");
     }
     if (@nochanges > 0) { 
         $nochgresponse = &mt("The following automated enrollment parameters remain unchanged:<br/><ul>");
     }
-    if (@changes > 0) { 
+    if (@changes > 0) {
         my $putreply = &Apache::lonnet::put('environment',\%cenv,$cdom,$cnum);
         if ($putreply !~ /^ok$/) {
-            $response = &mt("There was a problem processing your requested changes. The automated enrollment settings for this course have been left unchanged.<br/>");
+            $response = &mt("There was a problem processing your requested changes. The automated enrollment settings for this course have been left unchanged.<br/>").&mt('Error: ').$putreply;
         } else {
             foreach my $attr (@modifiable_params) {
                 if (grep/^$attr$/,@changes) {
@@ -804,11 +811,18 @@
         my ($cdom,$cnum) = split(/_/,$env{'form.pickedcourse'});
         if ($cdom eq $dom) {
             my %courseIDs = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',
-                                                          $cnum,undef,undef,'.');
+                                               $cnum,undef,undef,'.');
             if (keys(%courseIDs) > 0) {
                 $ok_course = 'ok';
-                ($description,$instcode,$owner) = 
+                my ($description,$instcode,$owner);
+                if (ref($courseIDs{$cdom.'_'.$cnum}) eq 'HASH') {
+                    $description = $courseIDs{$cdom.'_'.$cnum}{'description'};
+                    $instcode = $courseIDs{$cdom.'_'.$cnum}{'inst_code'};
+                    $owner = $courseIDs{$cdom.'_'.$cnum}{'owner'};          
+                } else {
+                    ($description,$instcode,$owner) = 
                                        split(/:/,$courseIDs{$cdom.'_'.$cnum});
+                }
                 $description = &unescape($description);
                 $instcode = &unescape($instcode);
                 if ($instcode) {
@@ -817,10 +831,6 @@
             }
         }
     }
-
-    if ($ok_course ne 'ok') {
-        $r->print('<br/>'.&mt('The LON-CAPA course selected was not a valid course for the [_1] domain',$domdesc));
-    }
     return ($ok_course,$description);
 }
 
@@ -926,7 +936,7 @@
                         }
                     }
                 } else {
-                    $r->print(&mt('The course you selected is not a valid course in this domain')." ($domdesc)"); 
+                    $r->print('<span class="LC_error">'.&mt('The course you selected is not a valid course in this domain')." ($domdesc)".'</span>'); 
                 }
             }
         }
Index: loncom/interface/coursecatalog.pm
diff -u loncom/interface/coursecatalog.pm:1.21 loncom/interface/coursecatalog.pm:1.22
--- loncom/interface/coursecatalog.pm:1.21	Mon Oct  1 21:10:27 2007
+++ loncom/interface/coursecatalog.pm	Wed Oct  3 15:57:29 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler for displaying the course catalog interface
 #
-# $Id: coursecatalog.pm,v 1.21 2007/10/02 01:10:27 albertel Exp $
+# $Id: coursecatalog.pm,v 1.22 2007/10/03 19:57:29 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -128,7 +128,7 @@
     my $totcodes = 0;
     my $jscript = '';
     my ($numtitles,$lasttitle);
-    $totcodes = &Apache::courseclassifier::retrieve_instcodes(\%coursecodes,$codedom,$totcodes);
+    $totcodes = &Apache::courseclassifier::retrieve_instcodes(\%coursecodes,$codedom);
     if ($totcodes > 0) {
         $format_reply = &Apache::lonnet::auto_instcode_format($caller,$codedom,\%coursecodes,\%codes,\@codetitles,\%cat_titles,\%cat_order);
         if ($format_reply eq 'ok') {
@@ -431,7 +431,7 @@
     if ($env{'form.coursenum'} ne '') {
         %courses = &Apache::lonnet::courseiddump($domain,'.',1,'.','.',
                                                  $env{'form.coursenum'},
-                                                 undef,undef,'Course');
+                                                 undef,undef,'Course',1);
         if (keys(%courses) == 0) {
             $output .= &mt('The courseID provided does not match a course in this domain.');
             return $output;
@@ -457,11 +457,11 @@
     if (($details eq '') || ($env{'form.showdetails'})) {
         $sortname{'Code'} = 'code';
         $sortname{'Title'} = 'title';
-        $sortname{'Owner'} = 'owner';
+        $sortname{'Owner(s)'} = 'owner';
     }
     my $output = &Apache::loncommon::start_data_table().
                  &Apache::loncommon::start_data_table_header_row();
-    my @coltitles = ('Code','Sections','Crosslisted','Title','Owner');
+    my @coltitles = ('Code','Sections','Crosslisted','Title','Owner(s)');
     if (ref($usersections) eq 'HASH') {
        $coltitles[1] = 'Your Section';
     }
@@ -492,7 +492,7 @@
         if ($env{'form.sortby'} eq 'code') {
             push(@{$Sortby{$courseinfo{$course}{'code'}}},$course);
         } elsif ($env{'form.sortby'} eq 'owner') {
-            push(@{$Sortby{$courseinfo{$course}{'ownerlastname'}}},$course);
+            push(@{$Sortby{$courseinfo{$course}{'ownerlastnames'}}},$course);
         } else {
             push(@{$Sortby{$courseinfo{$course}{'title'}}},$course);
         }
@@ -520,7 +520,9 @@
     my $now = time;
     foreach my $course (keys(%{$courses})) {
         my $descr;
-        if ($courses->{$course} =~ m/^([^:]*):/i) {
+        if (ref($courses->{$course}) eq 'HASH') {
+            $descr = $courses->{$course}{'description'}; 
+        } elsif ($courses->{$course} =~ m/^([^:]*):/i) {
             $descr = &unescape($1);
         } else {
             $descr = &unescape($courses->{$course});
@@ -529,28 +531,50 @@
         $cleandesc=~s/'/\\'/g;
         $cleandesc =~ s/^\s+//;
         my ($cdom,$cnum)=split(/\_/,$course);
-
-        my ($desc,$instcode,$owner,$ttype) = split(/:/,$courses->{$course});
-        $owner = &unescape($owner);
-        my ($ownername,$ownerdom);
-        if ($owner =~ /:/) {
-            ($ownername,$ownerdom) = split(/:/,$owner);
+        my ($descr,$instcode,$singleowner,$ttype,@owners,%ownernames);
+        if (ref($courses->{$course}) eq 'HASH') {
+            $descr = $courses->{$course}{'description'};
+            $instcode =  $courses->{$course}{'instcode'};
+            $singleowner = $courses->{$course}{'owner'};
+            $ttype =  $courses->{$course}{'type'};
+            push(@owners,$singleowner);
+            if (ref($courses->{$course}{'co-owners'}) eq 'ARRAY') {
+                foreach my $item (@{$courses->{$course}{'co-owners'}}) {
+                    push(@owners,$item);
+                }
+            }
         } else {
-            $ownername = $owner;
-            if ($owner ne '') {
-                $ownerdom = $cdom;
+            ($descr,$instcode,$singleowner,$ttype) = 
+                split(/:/,$courses->{$course});
+            push(@owners,$singleowner);
+        }
+        foreach my $owner (@owners) {
+            my ($ownername,$ownerdom) = @_; 
+            if ($owner =~ /:/) {
+                ($ownername,$ownerdom) = split(/:/,$owner);
+            } else {
+                $ownername = $owner;
+                if ($owner ne '') {
+                    $ownerdom = $cdom;
+                }
+            }
+            if ($ownername ne '' && $ownerdom ne '') {
+                my %namehash=&Apache::loncommon::getnames($ownername,$ownerdom);
+                $ownernames{$ownername.':'.$ownerdom} = \%namehash; 
             }
-        }
-        my %ownernames;
-        if ($ownername ne '' && $ownerdom ne '') {
-            %ownernames = &Apache::loncommon::getnames($ownername,$ownerdom);
         }
         $courseinfo{$course}{'cdom'} = $cdom;
         $courseinfo{$course}{'cnum'} = $cnum;
         $courseinfo{$course}{'code'} = $instcode;
-        $courseinfo{$course}{'ownerlastname'} = $ownernames{'lastname'};
+        my @lastnames;
+        foreach my $owner (keys(%ownernames)) {
+            if (ref($ownernames{$owner}) eq 'HASH') {
+                push(@lastnames,$ownernames{$owner}{'lastname'});
+            }
+        }
+        $courseinfo{$course}{'ownerlastnames'} = join(', ',sort(@lastnames));
         $courseinfo{$course}{'title'} = $cleandesc;
-        $courseinfo{$course}{'owner'} = $owner;
+        $courseinfo{$course}{'owner'} = $singleowner;
 
         my %coursehash = &Apache::lonnet::dump('environment',$cdom,$cnum);
         my @classids;
@@ -571,11 +595,11 @@
         }
         $courseinfo{$course}{'showsyllabus'} = $showsyllabus;
         if (((defined($env{'form.coursenum'}) && ($cnum eq $env{'form.coursenum'}))) ||
-            ($knownuser && ($details == 1))) {  
+            ($knownuser && ($details == 1))) {
             $courseinfo{$course}{'counts'} =  &count_students($cdom,$cnum,$numsec);
             $courseinfo{$course}{'autoenrollment'} =
                 &autoenroll_info(\%coursehash,$now,$seclist,$xlist_items,
-                                 $instcode,$owner,$cdom,$cnum);
+                                 $instcode,\@owners,$cdom,$cnum);
 
             my $startaccess = '';
             my $endaccess = '';
@@ -641,7 +665,7 @@
         $cdom = $info->{'cdom'};
         $cnum = $info->{'cnum'};
         $title = $info->{'title'};
-        $ownerlast = $info->{'ownerlastname'};
+        $ownerlast = $info->{'ownerlastnames'};
         $code = $info->{'code'};
         $owner = $info->{'owner'};
         $seclist = $info->{'seclist'};
@@ -703,7 +727,7 @@
 }
 
 sub get_valid_classes {
-    my ($seclist,$xlist_items,$crscode,$owner,$cdom,$cnum) = @_;
+    my ($seclist,$xlist_items,$crscode,$owners,$cdom,$cnum) = @_;
     my $response;
     my %validations;
     @{$validations{'sections'}} = ();
@@ -712,7 +736,7 @@
     if ($seclist) {
         foreach my $sec (split(/, /,$seclist)) {
             my $class = $crscode.$sec;
-            if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owner,
+            if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owners,
 							 $class) eq 'ok') {
                 if (!grep(/^\Q$sec$\E/,@{$validations{'sections'}})) {
                     push(@{$validations{'sections'}},$sec);
@@ -723,7 +747,7 @@
     }
     if ($xlist_items) {
         foreach my $item (split(/, /,$xlist_items)) {
-            if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owner,
+            if (&Apache::lonnet::auto_validate_class_sec($cdom,$cnum,$owners,
 							 $item) eq 'ok') {
                 if (!grep(/^\Q$item$\E/,@{$validations{'xlists'}})) {
                     push(@{$validations{'xlists'}},$item);
@@ -885,7 +909,7 @@
 }
 
 sub autoenroll_info {
-    my ($coursehash,$now,$seclist,$xlist_items,$code,$owner,$cdom,$cnum) = @_;
+    my ($coursehash,$now,$seclist,$xlist_items,$code,$owners,$cdom,$cnum) = @_;
     my $autoenrolldates = &mt('Not enabled');
     if (defined($coursehash->{'internal.autoadds'}) && $coursehash->{'internal.autoadds'} == 1) {
         my ($autostart,$autoend);
@@ -901,7 +925,7 @@
             } else {
                 my $valid_classes = 
                    &get_valid_classes($seclist,$xlist_items,$code,
-                                      $owner,$cdom,$cnum);
+                                      $owners,$cdom,$cnum);
                 if ($valid_classes ne '') {
                     $autoenrolldates = &mt('Not enabled<br />Starts: ').
                                        $autostart.'<br />'.$valid_classes;                }
@@ -911,7 +935,7 @@
                 $autoenrolldates = &mt('Not enabled<br />Ended: ').$autoend;
             } else {
                 my $valid_classes = &get_valid_classes($seclist,$xlist_items,
-                                                       $code,$owner,$cdom,$cnum);
+                                                       $code,$owners,$cdom,$cnum);
                 if ($valid_classes ne '') {
                     $autoenrolldates = &mt('Currently enabled<br />').
                                        $valid_classes;
Index: loncom/interface/courseclassifier.pm
diff -u loncom/interface/courseclassifier.pm:1.1 loncom/interface/courseclassifier.pm:1.2
--- loncom/interface/courseclassifier.pm:1.1	Thu Oct 12 18:47:31 2006
+++ loncom/interface/courseclassifier.pm	Wed Oct  3 15:57:29 2007
@@ -29,10 +29,14 @@
 use LONCAPA;
 
 sub retrieve_instcodes {
-    my ($coursecodes,$codedom,$totcodes) = @_;
+    my ($coursecodes,$codedom) = @_;
+    my $totcodes;
     my %courses = &Apache::lonnet::courseiddump($codedom,'.',1,'.','.','.',                                                undef,undef,'Course');
-    foreach my $course (keys %courses) {
-        if ($courses{$course} =~ m/^[^:]*:([^:]+)/) {
+    foreach my $course (keys(%courses)) {
+        if (ref($courses{$course}) eq 'HASH') {
+            $$coursecodes{$course} = $courses{$course}{'instcode'};
+            $totcodes ++;
+        } elsif ($courses{$course} =~ m/^[^:]*:([^:]+)/) {
             $$coursecodes{$course} = &unescape($1);
             $totcodes ++;
         }
Index: loncom/interface/lonpickcourse.pm
diff -u loncom/interface/lonpickcourse.pm:1.63 loncom/interface/lonpickcourse.pm:1.64
--- loncom/interface/lonpickcourse.pm:1.63	Tue Mar 20 11:39:11 2007
+++ loncom/interface/lonpickcourse.pm	Wed Oct  3 15:57:29 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Pick a course
 #
-# $Id: lonpickcourse.pm,v 1.63 2007/03/20 15:39:11 albertel Exp $
+# $Id: lonpickcourse.pm,v 1.64 2007/10/03 19:57:29 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -175,7 +175,9 @@
     my $numcourses = keys(%courses);
     foreach my $course (keys(%courses)) {
         my $descr;
-        if ($courses{$course} =~ m/^([^:]*):/i) {
+        if (ref($courses{$course}) eq 'HASH') {
+            $descr = &unescape($courses{$course}{'description'});
+        } elsif ($courses{$course} =~ m/^([^:]*):/i) {
             $descr = &unescape($1);
         } else {
             $descr = &unescape($courses{$course});
@@ -195,18 +197,36 @@
             my $cleandesc=&HTML::Entities::encode($description,'<>&"');
             $cleandesc=~s/'/\\'/g;
             my ($cdom,$cnum)=split(/\_/,$course);
-            my ($descr,$instcode,$owner,$ttype) = split/:/,$courses{$course};
+            my ($descr,$instcode,$ttype,@owners);
+            if (ref($courses{$course}) eq 'HASH') {
+                $descr = $courses{$course}{'description'};
+                $instcode =  $courses{$course}{'instcode'};
+                $ttype =  $courses{$course}{'type'};
+                push(@owners,&unescape($courses{$course}{'owner'}));
+                if (ref($courses{$course}{'co-owners'}) eq 'ARRAY') {
+                    foreach my $item (@{$courses{$course}{'co-owners'}}) {
+                        push(@owners,&unescape($item));
+                    }
+                }
+            } else {
+                my $singleowner; 
+                ($descr,$instcode,$singleowner,$ttype)=split(/:/,$courses{$course});
+                push(@owners,&unescape($singleowner));
+            }
+            my $owner = join(', ',@owners);
             $r->print(&course_chooser($multiple,$cdom,$cnum,$cleandesc));
             $r->print($description.'('.
                       (&Apache::lonnet::domain($cdom,'description')?
                        &Apache::lonnet::domain($cdom,'description'):$cdom).")");
-            unless ($instcode eq '') {
+            if ($instcode ne '') {
                 $r->print(" - ".&unescape($instcode));
             }
-            unless ($owner eq '') {
-                $r->print(", owner - ".&unescape($owner));
+            if (@owners > 1) {
+                $r->print(', '.&mt('owners').' - ',join(', ',@owners)); 
+            } elsif (@owners == 1) {
+                $r->print(', '.&mt('owner').' - '.$owner);
             }
-            unless ($ttype eq '') {
+            if ($ttype ne '') {
                 $r->print('('.&unescape($ttype).')');
             }
             if ($multiple) { $r->print("</label>\n"); }

--raeburn1191441450--