Annotation of loncom/interface/loncoursequeueadmin.pm, revision 1.52.2.2

1.1       raeburn     1: # The LearningOnline Network
1.19      raeburn     2: # Utilities to administer domain course requests and course self-enroll requests
1.1       raeburn     3: #
1.52.2.2! raeburn     4: # $Id: loncoursequeueadmin.pm,v 1.52.2.1 2016/08/31 23:28:05 raeburn Exp $
1.1       raeburn     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: 
1.23      raeburn    30: =pod
                     31: 
1.1       raeburn    32: =head1 NAME
                     33: 
                     34: Apache::loncoursequeueadmin.pm
                     35: 
                     36: =head1 SYNOPSIS
                     37: 
1.14      raeburn    38: Utilities used by domain coordinators to administer queued course creation requests,
                     39: and by course coordinators for queued self-enrollment requests, and by general
                     40: users to display their queued self-enrollment requests.  
1.1       raeburn    41: 
                     42: This is part of the LearningOnline Network with CAPA project
                     43: described at http://www.lon-capa.org.
                     44: 
                     45: =head1 SUBROUTINES
                     46: 
                     47: =over
                     48: 
                     49: =item send_selfserve_notification()
                     50: 
                     51: =item display_queued_requests()
                     52: 
1.23      raeburn    53: =item build_queue_display()
                     54: 
1.1       raeburn    55: =item update_request_queue()
                     56: 
                     57: =item get_student_counts()
                     58: 
1.13      raeburn    59: =item course_creation()
                     60: 
                     61: =item build_batchcreatehash()
                     62:  
                     63: =item can_clone_course()
                     64: 
                     65: =item get_processtype()
                     66: 
1.14      raeburn    67: =item queued_selfenrollment()
                     68: 
1.23      raeburn    69: =item update_coursereq_status()
                     70: 
                     71: =item process_official_reqs()
                     72: 
1.31      raeburn    73: =item is_active_author()
                     74: 
                     75: =item author_prompt()
                     76: 
                     77: =item reqauthor_check()
                     78: 
                     79: =item process_reqauthor()
                     80: 
1.1       raeburn    81: =back
                     82: 
                     83: =cut
                     84: 
                     85: package Apache::loncoursequeueadmin;
                     86: 
                     87: use strict;
                     88: use Apache::lonnet;
                     89: use Apache::loncommon;
                     90: use Apache::lonmsg;
                     91: use Apache::lonlocal;
1.2       raeburn    92: use Apache::lonuserutils;
1.45      raeburn    93: use LONCAPA::batchcreatecourse;
1.19      raeburn    94: use LONCAPA qw(:DEFAULT :match);
1.1       raeburn    95: 
                     96: sub send_selfserve_notification {
1.2       raeburn    97:     my ($notifylist,$textstr,$cid,$contextdesc,$timestamp,$context,$sender,
1.12      raeburn    98:         $approvedlist,$rejectedlist,$crstype) = @_;
1.1       raeburn    99: # FIXME locallocaltime needs to be able to take $sender_lh as an argument
                    100: #       so this can be localized to the recipients date display format/time zone
                    101:     $timestamp =&Apache::lonlocal::locallocaltime($timestamp);
1.26      raeburn   102:     my ($msgcc,$rawsubj,@rawmsg,$subject,$message,$reviewer,$msgtxt);
                    103:     my ($senderuname,$senderudom) = split(':',$sender);
1.1       raeburn   104:     if ($context eq 'coursemanagers') {
                    105:         $rawsubj = 'Self-enrollment requests processed';
                    106:         push(@rawmsg,{
1.10      raeburn   107:                       mt => 'Enrollment requests in the following course: [_1] have been processed.',
1.30      raeburn   108:                       args => ["\n$contextdesc"],
1.1       raeburn   109:                      });
                    110:     } elsif ($context eq 'domainmanagers') {
1.12      raeburn   111:         $rawsubj = 'Course/Community requests reviewed';
1.1       raeburn   112:         push(@rawmsg,{
1.31      raeburn   113:                       mt  => 'Course/Community creation requests in the following domain: "[_1]" have been reviewed.',
1.30      raeburn   114:                       args => ["\n$contextdesc"],
                    115:                      });
                    116:         if (ref($textstr) eq 'ARRAY') {
                    117:             push(@rawmsg,@{$textstr});
                    118:         }
                    119:     } elsif ($context eq 'authormanagers') {
1.42      bisitz    120:         $rawsubj = 'Authoring Space requests reviewed';
1.30      raeburn   121:         push(@rawmsg,{
1.31      raeburn   122:                       mt  => 'Authoring requests in the following domain: "[_1]" have been reviewed.',
1.30      raeburn   123:                       args => ["\n$contextdesc"],
1.1       raeburn   124:                      });
                    125:         if (ref($textstr) eq 'ARRAY') {
                    126:             push(@rawmsg,@{$textstr});
                    127:         }
1.43      raeburn   128:     } elsif ($context eq 'usernamemanagers') {
                    129:         $rawsubj = 'LON-CAPA account requests reviewed';
                    130:         push(@rawmsg,{
                    131:                       mt  => 'Account requests in the following domain: "[_1]" have been reviewed.',
                    132:                       args => ["\n$contextdesc"],
                    133:                      });
                    134:         if (ref($textstr) eq 'ARRAY') {
                    135:             push(@rawmsg,@{$textstr});
                    136:         }
1.1       raeburn   137:     } elsif ($context eq 'enroller') {
                    138:         $rawsubj = 'Enrollment request';
1.12      raeburn   139:         if ($crstype eq 'community') {
                    140:             $msgtxt = 'Your request for enrollment in the following community: [_1]requested on [_2]has been reviewed by a Coordinator.'
                    141:         } else {
                    142:             $msgtxt = 'Your request for enrollment in the following course: [_1]requested on [_2]has been reviewed by a Course Coordinator.';
                    143:         } 
1.1       raeburn   144:         push(@rawmsg,{
1.12      raeburn   145:                       mt  => $msgtxt,
1.2       raeburn   146:                       args => ["\n  ".$contextdesc.",\n",$timestamp.",\n"],
1.1       raeburn   147: 
                    148:                      });
                    149:         if (ref($textstr) eq 'ARRAY') {
                    150:             push(@rawmsg,@{$textstr});
                    151:         }
                    152:     } elsif ($context eq 'courserequestor') {
1.12      raeburn   153:         if ($crstype eq 'Community') {
                    154:             $rawsubj = 'Community request';
                    155:             $msgtxt = 'Your request for creation of the following community: [_1]requested on [_2]has been reviewed by a Domain Coordinator.';
                    156:         } else {
                    157:             $rawsubj = 'Course request';
                    158:             $msgtxt = 'Your request for creation of the following course: [_1]requested on [_2]has been reviewed by a Domain Coordinator.';
                    159:         }
1.1       raeburn   160:         push(@rawmsg,{
1.12      raeburn   161:                       mt  => $msgtxt,
1.2       raeburn   162:                       args => ["\n".$contextdesc.",\n",$timestamp.",\n"],
1.1       raeburn   163: 
                    164:                      });
                    165:         if (ref($textstr) eq 'ARRAY') {
                    166:             push(@rawmsg,@{$textstr});
                    167:         }
1.26      raeburn   168:     } elsif ($context eq 'pendingrequestor') {
                    169:         if ($crstype eq 'Community') {
                    170:             $rawsubj = 'Community request';
                    171:         } else {
                    172:             $rawsubj = 'Processed course request';
                    173:         }
                    174:         if (ref($textstr) eq 'ARRAY') {
                    175:             push(@rawmsg,@{$textstr});
                    176:         }
1.1       raeburn   177:     } elsif ($context eq 'coursereq') {
1.12      raeburn   178:         if ($crstype eq 'community') {
                    179:             $rawsubj = 'Community request to review';
                    180:             $msgtxt = 'Creation of the following community: [_1]was requested by [_2] on [_3].';
                    181:         } else {
                    182:             $rawsubj = 'Course request to review';
                    183:             $msgtxt = 'Creation of the following course: [_1]was requested by [_2] on [_3].';
                    184:         }
1.1       raeburn   185:         push(@rawmsg,{
1.12      raeburn   186:                       mt  => $msgtxt,
1.2       raeburn   187:                       args => ["\n  $contextdesc\n",$textstr,$timestamp],
1.1       raeburn   188:                      },
                    189:                      {
1.12      raeburn   190:                       mt =>'[_1]As Domain Coordinator, use: [_2]Main Menu -> Course and community creation -> Approve or reject requests[_3]to display a list of pending requests, which you can either approve or reject.',
1.31      raeburn   191:                       args => ["\n","\n\n","\n\n"],
1.1       raeburn   192:                      });
                    193:     } elsif ($context eq 'selfenrollreq') {
                    194:         $rawsubj = 'Self-enrollment request';
1.12      raeburn   195:         if ($crstype eq 'community') {
1.31      raeburn   196:             $msgtxt = 'Enrollment in the following community: [_1]was requested by [_2] on [_3].'
1.12      raeburn   197:         } else {
1.31      raeburn   198:             $msgtxt = 'Enrollment in the following course: [_1]was requested by [_2] on [_3].'
1.12      raeburn   199:         }
1.1       raeburn   200:         push(@rawmsg,{
1.12      raeburn   201:                       mt  => $msgtxt,
1.2       raeburn   202:                       args => ["\n  $contextdesc\n",$textstr,$timestamp."\n"],
                    203:                      });
1.12      raeburn   204:         my $directions;  
                    205:         if ($crstype eq 'community') {
                    206:             $directions = 'As Coordinator, use: [_1]Main Menu -> Manage Community Users -> Enrollment Requests[_2]to display a list of pending enrollment requests, which you can either approve or reject.';
1.2       raeburn   207:         } else {
1.12      raeburn   208:             $directions = 'As Course Coordinator, use: [_1]Main Menu -> Manage Course Users -> Enrollment Requests[_2]to display a list of pending enrollment requests, which you can either approve or reject.';
                    209:         }
                    210:         push(@rawmsg,
1.1       raeburn   211:                      {
1.12      raeburn   212:                       mt   => $directions,
1.2       raeburn   213:                       args => ["  \n\n","\n"],
1.1       raeburn   214:                      });
1.30      raeburn   215:     } elsif ($context eq 'authorreq') {
1.42      bisitz    216:         $rawsubj = 'Authoring Space request to review';
1.31      raeburn   217:         $msgtxt = 'Assignment of an author role in the [_1] domain[_2]was requested by [_3] on [_4].';
1.30      raeburn   218:         push(@rawmsg,{
                    219:                       mt  => $msgtxt,
                    220:                       args => [$contextdesc,"\n",$textstr,$timestamp],
                    221:                      },
                    222:                      {
1.42      bisitz    223:                       mt =>'[_1]As Domain Coordinator, use: [_2]Main Menu -> Create users or modify the roles and privileges of users -> Authoring Space requests[_3]to display a list of pending requests, which you can either approve or reject.',
1.30      raeburn   224:                       args => ["\n","\n\n  ","\n\n"],
                    225:                      });
                    226:     } elsif ($context eq 'requestauthor') {
1.42      bisitz    227:         $rawsubj = 'Authoring Space request';
                    228:         $msgtxt = 'Your request for an Authoring Space requested on [_1]has been reviewed by a Domain Coordinator.';
1.30      raeburn   229:         push(@rawmsg,{
                    230:                       mt  => $msgtxt,
                    231:                       args => [$timestamp."\n"],
                    232:                      });
                    233:         if (ref($textstr) eq 'ARRAY') {
                    234:             push(@rawmsg,@{$textstr});
                    235:         }
1.43      raeburn   236:     } elsif ($context eq 'usernamereq') {
                    237:         $rawsubj = 'LON-CAPA account request';
                    238:         $msgtxt = 'Creation of a LON-CAPA account in the [_1] domain[_2]was requested by [_3] on [_4].';
                    239:         push(@rawmsg,{
                    240:                       mt  => $msgtxt,
                    241:                       args => [$contextdesc,"\n",$textstr,$timestamp],
                    242:                      },
                    243:                      {
                    244:                       mt =>'[_1]As Domain Coordinator, use: [_2]Main Menu -> Create users or modify the roles and privileges of users
                    245:  -> LON-CAPA account requests[_3]to display a list of pending requests, which you can either approve or reject.',
                    246:                       args => ["\n","\n\n  ","\n\n"],
                    247:                      });
                    248:     } elsif ($context eq 'requestusername') {
                    249:         $rawsubj = 'LON-CAPA account request';
                    250:         $msgtxt = 'Your request for a LON-CAPA account requested on [_1]has been reviewed by a Domain Coordinator.';
                    251:         push(@rawmsg,{
                    252:                       mt  => $msgtxt,
                    253:                       args => [$timestamp."\n"],
                    254:                      });
                    255:         if (ref($textstr) eq 'ARRAY') {
                    256:             push(@rawmsg,@{$textstr});
                    257:         }
1.39      raeburn   258:     } elsif ($context eq 'uniquecode') {
                    259:         $rawsubj = 'Course Identifier';
                    260:         if (ref($textstr) eq 'ARRAY') {
                    261:             push(@rawmsg,@{$textstr});
                    262:         }
1.41      raeburn   263:     } elsif ($context eq 'queuedcrsreq') {
                    264:         $rawsubj = 'Course Request Queued';
                    265:         if (ref($textstr) eq 'ARRAY') {
                    266:             push(@rawmsg,@{$textstr});
                    267:         }
                    268:     } elsif ($context eq 'createdcrsreq') {
                    269:         $rawsubj = 'Course Creation Information';
                    270:         if (ref($textstr) eq 'ARRAY') {
                    271:             push(@rawmsg,@{$textstr});
                    272:         }
1.1       raeburn   273:     }
                    274:     my @to_notify = split(/,/,$notifylist);
                    275:     my $numsent = 0;
                    276:     my @recusers;
                    277:     my @recudoms;
                    278:     foreach my $cc (@to_notify) {
                    279:         my ($ccname,$ccdom) = split(/:/,$cc);
                    280:         if (!exists($msgcc->{$ccname.':'.$ccdom})) {
                    281:             push(@recusers,$ccname);
                    282:             push(@recudoms,$ccdom);
                    283:             $msgcc->{$ccname.':'.$ccdom}='';
                    284:             $numsent ++;
                    285:         }
                    286:     }
                    287:     my %reciphash = (
                    288:                      cc => $msgcc,
                    289:     );
1.43      raeburn   290:     my ($uname,$udom,$need_temp_env);
1.1       raeburn   291:     if ($sender =~ /:/) {
                    292:         ($uname,$udom) = split(/:/,$sender);
1.43      raeburn   293:         if ($context eq 'usernamereq') {
                    294:             unless ($env{'user.name'} && $env{'user.domain'}) {
                    295:                 $need_temp_env = 1;
                    296:             }
                    297:         }
1.2       raeburn   298:     } elsif ($context eq 'course') {
1.1       raeburn   299:         $uname = $sender;
                    300:         my %courseinfo = &Apache::lonnet::coursedescription($cid);
                    301:         $udom = $courseinfo{'num'};
                    302:     }
                    303:     my %sentmessage;
                    304:     my $stamp = time;
                    305:     my $msgcount = &Apache::lonmsg::get_uniq();
                    306:     my $sender_lh = &Apache::loncommon::user_lang($uname,$udom,$cid);
                    307:     $subject = &Apache::lonlocal::mt_user($sender_lh,$rawsubj);
                    308:     $message = '';
                    309:     foreach my $item (@rawmsg) {
                    310:         if (ref($item) eq 'HASH') {
                    311:             $message .= &Apache::lonlocal::mt_user($sender_lh,$item->{mt},@{$item->{args}})."\n";
                    312:         }
                    313:     }
1.43      raeburn   314:     &Apache::lonmsg::process_sent_mail($subject,'',$numsent,$stamp,$uname,$udom,$msgcount,$cid,$$,$message,
                    315:                                        \@recusers,\@recudoms,undef,undef,undef,undef,$senderuname,$senderudom);
1.1       raeburn   316:     my ($recipid,$recipstatus) = &Apache::lonmsg::store_recipients($subject,$uname,$udom,\%reciphash);
                    317:     my $status;
1.43      raeburn   318:     if ($need_temp_env) {
                    319:         $env{'user.name'} = $uname;
                    320:         $env{'user.domain'} = $udom;
                    321:     }
1.1       raeburn   322:     foreach my $recip (sort(keys(%{$msgcc}))) {
                    323:         my ($ccname,$ccdom) = split(/:/,$recip);
                    324:         my $recip_lh = &Apache::loncommon::user_lang($ccname,$ccdom,$cid);
                    325:         my $subject = &Apache::lonlocal::mt_user($sender_lh,$rawsubj);
                    326:         my $message = '';
                    327:         foreach my $item (@rawmsg) {
                    328:             if (ref($item) eq 'HASH') {
                    329:                 $message .= &Apache::lonlocal::mt_user($sender_lh,$item->{mt},
                    330:                                                        @{$item->{args}})."\n";
                    331:             }
                    332:         }
1.10      raeburn   333:         if ($context eq 'coursemanagers') {
1.1       raeburn   334:             if ($approvedlist) {
                    335:                 $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Approved enrollments:')."\n".$approvedlist;
                    336:             }
                    337:             if ($rejectedlist) {
                    338:                 $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Rejected enrollments:')."\n".$rejectedlist;
                    339:             }
                    340:         } elsif ($context eq 'domainmanagers') {
                    341:             if ($approvedlist) {
                    342:                 $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Approved course requests:')."\n".$approvedlist;
                    343:             }
                    344:             if ($rejectedlist) {
                    345:                 $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Rejected course requests:')."\n".$rejectedlist;
                    346:             }
1.30      raeburn   347:         } elsif ($context eq 'authormanagers') {
                    348:             if ($approvedlist) {
                    349:                 $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Approved author role requests:')."\n".$approvedlist;
                    350:             }
                    351:             if ($rejectedlist) {
                    352:                 $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Rejected author role requests:')."\n".$rejectedlist;
                    353:             }
1.43      raeburn   354:         } elsif ($context eq 'usernamemanagers') {
                    355:             if ($approvedlist) {
                    356:                 $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Approved LON-CAPA account requests:')."\n".$approvedlist;
                    357:             }
                    358:             if ($rejectedlist) {
                    359:                 $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Rejected LON-CAPA account requests:')."\n".$rejectedlist;
                    360:             }
1.1       raeburn   361:         }
1.43      raeburn   362:         $status .= &Apache::lonmsg::user_normal_msg($ccname,$ccdom,$subject,$message,undef,undef,undef,1,
                    363:                                                     \%sentmessage,undef,undef,undef,1,$recipid).',';
1.1       raeburn   364:     }
                    365:     $status =~ s/,$//;
1.43      raeburn   366:     if ($need_temp_env) {
                    367:         undef($env{'user.name'});
                    368:         undef($env{'user.domain'});
                    369:     }
1.1       raeburn   370:     return ($recipstatus,$status);
                    371: }
                    372: 
                    373: sub display_queued_requests {
                    374:     my ($context,$dom,$cnum) = @_;
1.2       raeburn   375:     my ($namespace,$formaction,$nextelement,%requesthash);
1.1       raeburn   376:     if ($context eq 'course') {
                    377:         $formaction = '/adm/createuser';
                    378:         $namespace = 'selfenrollrequests';
                    379:         %requesthash = &Apache::lonnet::dump($namespace,$dom,$cnum);
1.2       raeburn   380:         $nextelement = '<input type="hidden" name="state" value="done" />';
1.30      raeburn   381:     } elsif ($context eq 'requestauthor') {
                    382:         $formaction = '/adm/createuser';
                    383:         $namespace = 'requestauthorqueue';
                    384:         %requesthash = &Apache::lonnet::dump_dom($namespace,$dom);
                    385:         $nextelement = '<input type="hidden" name="state" value="done" />';
1.43      raeburn   386:     } elsif ($context eq 'requestusername') {
                    387:         $formaction = '/adm/createuser';
                    388:         $namespace = 'usernamequeue';
                    389:         %requesthash = &Apache::lonnet::dump_dom($namespace,$dom);
                    390:         $nextelement = '<input type="hidden" name="state" value="done" />';
1.1       raeburn   391:     } else {
                    392:         $formaction = '/adm/createcourse';
                    393:         $namespace = 'courserequestqueue';
1.23      raeburn   394:         my $disposition = 'approval';
1.24      raeburn   395:         my $nextphase = 'requestchange';
1.23      raeburn   396:         if ($context eq 'pending') {
                    397:             $disposition = 'pending';
1.24      raeburn   398:             $nextphase = 'requestvalidation';
1.52.2.2! raeburn   399:         } elsif ($context eq 'displaypending') {
        !           400:             $disposition = 'pending';
1.23      raeburn   401:         }
                    402:         %requesthash = &Apache::lonnet::dump_dom($namespace,$dom,'_'.$disposition);
1.24      raeburn   403:         $nextelement = '<input type="hidden" name="phase" value="'.$nextphase.'" />';
1.1       raeburn   404:     }
1.23      raeburn   405:     my ($output,%queue_by_date);
1.1       raeburn   406:     if (keys(%requesthash) > 0) {
1.2       raeburn   407:         $output = '<form method="post" name="changequeue" action="'.$formaction.'" />'."\n".
                    408:                   '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n".
1.23      raeburn   409:                   $nextelement."\n";
1.1       raeburn   410:         foreach my $item (keys(%requesthash)) {
1.23      raeburn   411:             my ($timestamp,$entry,$pending);
1.1       raeburn   412:             if ($context eq 'course') {
                    413:                 ($timestamp, my $usec) = split(/:/,$requesthash{$item});
                    414:                 $entry = $item.':'.$usec;
1.30      raeburn   415:             } elsif ($context eq 'requestauthor') {
                    416:                 $timestamp = $requesthash{$item};
                    417:                 ($entry) = ($item =~ /^($match_username)_approval$/);
1.43      raeburn   418:             } elsif ($context eq 'requestusername') {
                    419:                 $timestamp = $requesthash{$item};
                    420:                 ($entry) = (&unescape($item) =~ /^($match_username)_approval$/);
1.1       raeburn   421:             } else {
                    422:                 $timestamp = $requesthash{$item}{'timestamp'};
                    423:                 if (ref($requesthash{$item}) eq 'HASH') {
1.2       raeburn   424:                     my ($cnum,$disposition) = split('_',$item);
                    425:                     $entry = $cnum.':'.$requesthash{$item}{'ownername'}.':'.
1.23      raeburn   426:                              $requesthash{$item}{'ownerdom'}.':';
1.52.2.2! raeburn   427:                     if (($context eq 'pending') || ($context eq 'displaypending')) {
1.23      raeburn   428:                         $entry .= $requesthash{$item}{'instcode'};
                    429:                     } else {
                    430:                         $entry .= $requesthash{$item}{'crstype'};
                    431:                     }
                    432:                     $entry .= ':'.$requesthash{$item}{'description'};
1.1       raeburn   433:                 }
                    434:             }
                    435:             if ($entry ne '') {
1.23      raeburn   436:                 if (ref($queue_by_date{$timestamp}) eq 'ARRAY') {
                    437:                     push(@{$queue_by_date{$timestamp}},$entry);
1.1       raeburn   438:                 } else {
1.23      raeburn   439:                     $queue_by_date{$timestamp} = [$entry];
1.1       raeburn   440:                 }
                    441:             }
                    442:         }
1.23      raeburn   443:         if (keys(%queue_by_date) > 0) {
                    444:             if ($context eq 'course') {
                    445:                 $output .=  '<h3>'.&mt('Self-enrollment requests queued pending approval by a Coordinator').'</h3>';
1.52.2.2! raeburn   446:             } elsif (($context eq 'pending') || ($context eq 'displaypending')) {
1.23      raeburn   447:                 $output .= '<h3>'.&mt('Requests for official courses queued pending validation').'</h3>'.
                    448:                            '<p>'.&mt('Requests are validated against institutional data to confirm that the requestor is an instructor of record.').'<br />'.
1.52.2.2! raeburn   449:                            &mt('Validation is attempted when the request is submitted.').' '.
        !           450:                            &mt('If unvalidated, the request will be held in a queue.').' '.
        !           451:                            &mt('Validation of pending requests is automatically repeated daily.').'</p>';
1.30      raeburn   452:             } elsif ($context eq 'requestauthor') {
1.42      bisitz    453:                 $output .= '<h3>'.&mt('Requests for Authoring Space queued pending approval by a Domain Coordinator').'</h3>';
1.43      raeburn   454:             } elsif ($context eq 'requestusername') {
                    455:                 $output .= '<h3>'.&mt('Requests for LON-CAPA accounts queued pending approval by a Domain Coordinator').'</h3>';
1.23      raeburn   456:             } else {
1.30      raeburn   457:                 $output .= '<h3>'.&mt('Course/Community requests queued pending approval by a Domain Coordinator').'</h3>';
1.23      raeburn   458:             } 
                    459:             $output .= &build_queue_display($dom,$context,\%queue_by_date).
                    460:                        '<input type="hidden" name="queue" value="approval" />';
                    461:         } else {
                    462:             $output .= '<div class="LC_info">';
                    463:             if ($context eq 'course') {
                    464:                 $output .= &mt('There are currently no enrollment requests awaiting approval.');
                    465:             } elsif ($context eq 'pending') {
                    466:                 $output .= &mt('There are currently no requests for official courses awaiting validation.');
1.30      raeburn   467:             } elsif ($context eq 'requestauthor') {
1.42      bisitz    468:                 $output .= &mt('There are currently no requests for Authoring Space awaiting approval.');
1.43      raeburn   469:             } elsif ($context eq 'requestusername') {
                    470:                 $output .= &mt('There are currently no requests for LON-CAPA accounts awaiting approval.');
1.23      raeburn   471:             } elsif ($context eq 'domain') {
                    472:                 $output .= &mt('There are currently no course or community requests awaiting approval.');
                    473:             }
                    474:             $output .= '</div>'; 
                    475:         }
                    476:         if ($context eq 'pending') {
1.24      raeburn   477:             $output .= '<br /><input type="submit" name="validationcheck" value="'.
                    478:                        &mt('Validate').'" /><br />'."\n".
1.52.2.2! raeburn   479:                        '<p>'.&mt('Any course/community requests which are successfully validated will be created immediately.').' '.
        !           480:                              &mt('Unvalidated requests will be listed for manual approval/rejection.').'</p>';
        !           481:         } elsif (($context ne 'helpdesk') && ($context ne 'displaypending')) {
1.23      raeburn   482:             $output .= '<br /><input type="submit" name="processqueue" value="'.&mt('Save').'" />';
                    483:         }
                    484:         $output .= '</form>';
                    485:     } else {
                    486:         $output .= '<div class="LC_info">';
                    487:         if ($context eq 'course') {
                    488:             $output .= &mt('There are currently no enrollment requests awaiting approval.');
1.52.2.2! raeburn   489:         } elsif (($context eq 'pending') || ($context eq 'displaypending')) {
1.23      raeburn   490:             $output .= &mt('There are currently no requests for official courses awaiting validation.');
1.43      raeburn   491:         } elsif ($context eq 'requestauthor') {
                    492:             $output .= &mt('There are currently no requests for Authoring Space awaiting approval.');
                    493:         } elsif ($context eq 'requestusername') {
                    494:             $output .= &mt('There are currently no requests for LON-CAPA accounts awaiting approval.');
1.23      raeburn   495:         } else {
                    496:             $output .= &mt('There are currently no course or community requests awaiting approval.');
                    497:         }
                    498:         $output .= '</div>';
                    499:     }
                    500:     return $output;
                    501: }
1.1       raeburn   502: 
1.23      raeburn   503: sub build_queue_display {
                    504:     my ($dom,$context,$queue) = @_;
                    505:     return unless (ref($queue) eq 'HASH');
                    506:     my %crstypes;
                    507:     my $output =  &Apache::loncommon::start_data_table().
                    508:                   &Apache::loncommon::start_data_table_header_row();
1.52.2.2! raeburn   509:     unless (($context eq 'pending') || ($context eq 'displaypending') || ($context eq 'helpdesk')) {
1.23      raeburn   510:         $output .= '<th>'.&mt('Action').'</th>';
                    511:     }
                    512:     $output .= '<th>'.&mt('Requestor').'</th>';
                    513:     if ($context eq 'course') {
                    514:         $output .= '<th>'.&mt('Section').'</th>'.
                    515:                    '<th>'.&mt('Date requested').'</th>';
1.30      raeburn   516:     } elsif ($context eq 'requestauthor') {
                    517:         $output .= '<th>'.&mt('Date requested').'</th>';
1.43      raeburn   518:     } elsif ($context eq 'requestusername') {
                    519:         $output .= '<th>'.&mt('Date requested').'</th>'.
                    520:                    '<th>'.&mt('Details').'</th>';
1.52.2.2! raeburn   521:     } elsif ($context eq 'pending' || $context eq 'displaypending' || $context eq 'stillpending') {
1.23      raeburn   522:         $output .= '<th>'.&mt('Institutional code').'</th>'.
                    523:                    '<th>'.&mt('Date requested').'</th>'.
                    524:                    '<th>'.&mt('Details').'</th>';
                    525:     } else {
                    526:         %crstypes = &Apache::lonlocal::texthash (
                    527:                         official   => 'Official course',
                    528:                         unofficial => 'Unofficial course',
                    529:                         community  => 'Community',
1.38      raeburn   530:                         textbook   => 'Textbook course',
1.23      raeburn   531:                     );
                    532:         $output .= '<th>'.&mt('Type').'</th>'.
                    533:                    '<th>'.&mt('Date requested').'</th>'.
                    534:                    '<th>'.&mt('Details').'</th>';
                    535:     }
                    536:     $output .= &Apache::loncommon::end_data_table_header_row();
                    537:     my @sortedtimes = sort {$a <=> $b} (keys(%{$queue}));
                    538:     my $count = 0;
                    539:     foreach my $item (@sortedtimes) {
                    540:         if (ref($queue->{$item}) eq 'ARRAY') {
                    541:             foreach my $request (sort(@{$queue->{$item}})) {
                    542:                 my ($row,$approve,$reject,$showtime,$showsec,$namelink,
                    543:                     $detailslink,$crstype,$instcode);
                    544:                 $showtime = &Apache::lonlocal::locallocaltime($item);
                    545:                 if ($context eq 'course') {
                    546:                     my ($puname,$pudom,$pusec) = split(/:/,$request);
                    547:                     $approve = $count.':'.$puname.':'.$pudom.':'.$pusec;
                    548:                     $reject = $puname.':'.$pudom;
                    549:                     $showsec = $pusec;
                    550:                     if ($showsec eq '') {
                    551:                         $showsec = &mt('none');
                    552:                     }
                    553:                     $namelink = &Apache::loncommon::aboutmewrapper(
                    554:                                 &Apache::loncommon::plainname($puname,$pudom),
                    555:                                 $puname,$pudom);
1.30      raeburn   556:                 } elsif ($context eq 'requestauthor') {
                    557:                     if (&Apache::lonnet::homeserver($request,$dom) ne 'no_host') {
                    558:                         $approve = $count.':'.$request;
                    559:                         $reject = $request; 
                    560:                         $namelink = &Apache::loncommon::aboutmewrapper(
                    561:                                     &Apache::loncommon::plainname($request,$dom),
                    562:                                     $request,$dom);
                    563:                     }
1.43      raeburn   564:                 } elsif ($context eq 'requestusername') {
                    565:                     if (&Apache::lonnet::homeserver($request,$dom) eq 'no_host') {
                    566:                         my $queued = 'approval';
                    567:                         $approve = $count.':'.$request;
                    568:                         $reject = $request;
                    569:                         $detailslink='<a href="javascript:openusernamereqdisplay('.
                    570:                                      "'$dom','$request','$queued'".');">'.$request.'</a>';
                    571:                         $namelink = $request;
                    572:                     }
1.23      raeburn   573:                 } else {
                    574:                     my ($cnum,$ownername,$ownerdom,$type,$cdesc);
1.43      raeburn   575:                     my $queued = 'approval'; 
1.52.2.2! raeburn   576:                     if ($context eq 'pending' || $context eq 'displaypending' || $context eq 'stillpending') {
1.23      raeburn   577:                         ($cnum,$ownername,$ownerdom,$instcode,$cdesc)=split(/:/,$request,5);
1.43      raeburn   578:                         $queued = 'pending';                        
1.1       raeburn   579:                     } else {
1.23      raeburn   580:                         ($cnum,$ownername,$ownerdom,$type,$cdesc)=split(/:/,$request,5);
1.1       raeburn   581:                         $crstype = $type;
                    582:                         if (defined($crstypes{$type})) {
                    583:                             $crstype = $crstypes{$type};
                    584:                         }
                    585:                     }
1.23      raeburn   586:                     $detailslink='<a href="javascript:opencoursereqdisplay('.
1.43      raeburn   587:                                   "'$dom','$cnum','$queued'".');">'.$cdesc.'</a>';
1.23      raeburn   588:                     $approve = $count.':'.$cnum;
                    589:                     $reject = $cnum;
                    590:                     $namelink = &Apache::loncommon::aboutmewrapper(
                    591:                                 &Apache::loncommon::plainname($ownername,$ownerdom),
                    592:                                 $ownername,$ownerdom);
                    593:                 }
1.52.2.2! raeburn   594:                 unless (($context eq 'pending') || ($context eq 'displaypending') || ($context eq 'helpdesk')) {
1.1       raeburn   595:                     $row = '<td><span class="LC_nobreak"><label>'.
1.30      raeburn   596:                            '<input type="radio" value="'.$approve.'" name="'.$count.'radioreq" />'.&mt('Approve').'</label>'.
                    597:                            '<label>'.('&nbsp;'x2).
                    598:                            '<input type="radio" value="'.$reject.'" name="'.$count.'radioreq" />'.&mt('Reject').'</label>'.
                    599:                            '<label>'.('&nbsp;'x2).
1.29      golterma  600:                            '<input type="radio" value="'."later:".$reject.'" name="'.$count.'radioreq" checked />'.&mt('Decide Later').
                    601:                            '</label></span><br /></td>';
1.1       raeburn   602:                 }
1.23      raeburn   603:                 $row .= '<td>'.$namelink.'</td>'."\n";
                    604:                 if ($context eq 'course') {
                    605:                     $row .= '<td>'.$showsec.'</td>'."\n".
                    606:                             '<td>'.$showtime.'</td>'."\n";
1.30      raeburn   607:                 } elsif ($context eq 'requestauthor') {
                    608:                     $row .= '<td>'.$showtime.'</td>'."\n";
1.43      raeburn   609:                 } elsif ($context eq 'requestusername') {
                    610:                     $row .= '<td>'.$showtime.'</td>'."\n".
                    611:                             '<td>'.$detailslink.'</td>'."\n";
1.52.2.2! raeburn   612:                 } else {
        !           613:                     if ($context eq 'pending' || $context eq 'displaypending' || $context eq 'stillpending') {
1.23      raeburn   614:                         $row .= '<td>'.$instcode.'</td>'."\n";
                    615:                     } else {
                    616:                         $row .= '<td>'.$crstype.'</td>'."\n";
                    617:                     }
                    618:                     $row .= '<td>'.$showtime.'</td>'."\n".
                    619:                             '<td>'.$detailslink.'</td>'."\n";
                    620:                 }
                    621:                 $output .= &Apache::loncommon::start_data_table_row()."\n".
                    622:                            $row.
                    623:                            &Apache::loncommon::end_data_table_row()."\n";
                    624:                 $count ++;
1.1       raeburn   625:             }
                    626:         }
                    627:     }
1.23      raeburn   628:     $output .= &Apache::loncommon::end_data_table();
1.1       raeburn   629:     return $output;
                    630: }
                    631: 
                    632: sub update_request_queue {
                    633:     my ($context,$cdom,$cnum,$coursedesc) = @_;
                    634:     my ($output,$access_start,$access_end,$limit,$cap,$notifylist,$namespace,
1.26      raeburn   635:         $stucounts,$idx,$classlist,%requesthash,$cid,$domdesc,$now,
                    636:         $sender,$approvedmsg,$rejectedmsg,$beneficiary,
1.2       raeburn   637:         @existing,@missingreq,@invalidusers,@limitexceeded,@completed,
1.19      raeburn   638:         @processing_errors,@warn_approves,@warn_rejects,@approvals,@warn_dels,
1.30      raeburn   639:         @rejections,@rejectionerrors,@nopermissions,%courseroles,@toremove,
                    640:         %communityroles,%domdefs,%approvalmsg,%rejectionmsg,$crstype,$queue,
1.39      raeburn   641:         $firsturl,$uniquecode,%codes);
1.29      golterma  642:     my $count=0;
1.43      raeburn   643:     while (my $item = $env{'form.'.$count.'radioreq'}) {
                    644:         if ($item =~ /^\d+:/) {
                    645:             push(@approvals,$item);
                    646:         } elsif ($item !~ /^later:/) {
                    647:             push(@rejections,$item);
1.29      golterma  648:         }
1.43      raeburn   649:         $count ++;
1.29      golterma  650:     }
                    651: 
1.1       raeburn   652:     $now = time;
                    653:     $sender = $env{'user.name'}.':'.$env{'user.domain'};
                    654:     if ($context eq 'course') {
                    655:         $namespace = 'selfenrollrequests';
                    656:         $beneficiary = 'enroller';
                    657:         $cid = $env{'request.course.id'};
1.12      raeburn   658:         $crstype = lc(&Apache::loncommon::course_type());
1.26      raeburn   659:         $firsturl = &course_portal_url($cnum,$cdom);
1.1       raeburn   660:         %requesthash = &Apache::lonnet::dump($namespace,$cdom,$cnum);
                    661:         $access_start =  $env{'course.'.$cid.'.internal.selfenroll_start_access'};
                    662:         $access_end =  $env{'course.'.$cid.'.internal.selfenroll_end_access'};
                    663:         $limit = $env{'course.'.$cid.'.internal.selfenroll_limit'};
                    664:         $cap = $env{'course.'.$cid.'.internal.selfenroll_cap'};
                    665:         $notifylist = $env{'course.'.$cid.'.internal.selfenroll_notifylist'};
                    666:         ($stucounts,$idx,$classlist) = &get_student_counts($cdom,$cnum);
                    667:         $approvedmsg = [{
                    668:                             mt => 'Your request for enrollment has been approved.',
                    669:                         },
                    670:                         {
1.28      raeburn   671:                             mt   => 'Visit [_1] to log-in and access the course',
1.25      raeburn   672:                             args => [$firsturl],
1.1       raeburn   673:                         }];
                    674:         $rejectedmsg =  [{
                    675:                             mt => 'Your request for enrollment has not been approved.',
                    676:                         }];
1.30      raeburn   677:     } elsif ($context eq 'requestauthor') {
                    678:         $namespace = 'requestauthorqueue';
                    679:         $beneficiary = 'requestauthor';
                    680:         %requesthash = &Apache::lonnet::dump_dom($namespace,$cdom);
                    681:         my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
                    682:         if (ref($domdefs{'requestauthor'}) eq 'HASH') {
                    683:             if (ref($domdefs{'requestauthor'}{'notify'}) eq 'HASH') {
                    684:                 $notifylist = $domdefs{'requestauthor'}{'notify'}{'approval'};
                    685:             }
                    686:         }
                    687:         my $domconfiguser = &Apache::lonnet::get_domainconfiguser($cdom);
                    688:         $firsturl = &course_portal_url($domconfiguser,$cdom);
                    689:         $approvedmsg = [{
1.42      bisitz    690:                             mt => 'Your request for Authoring Space has been approved.',
1.30      raeburn   691:                         },
                    692:                         {
                    693:                             mt   => 'Visit [_1] to log-in and select your author role',
                    694:                             args => [$firsturl],
                    695:                         }];
                    696:         $rejectedmsg =  [{
1.42      bisitz    697:                             mt => 'Your request for Authoring Space has not been approved.',
1.30      raeburn   698:                         }];
                    699:         $domdesc = &Apache::lonnet::domain($cdom);
1.43      raeburn   700:     } elsif ($context eq 'requestusername') {
                    701:         $namespace = 'usernamequeue';
                    702:         $beneficiary = 'requestusername';
                    703:         %requesthash = &Apache::lonnet::dump_dom($namespace,$cdom);
                    704:         my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$cdom);
                    705:         if (ref($domconfig{'usercreation'}) eq 'HASH') {
                    706:             if (ref($domconfig{'usercreation'}{'cancreate'}) eq 'HASH') {
                    707:                 if (ref($domconfig{'usercreation'}{'cancreate'}{'notify'}) eq 'HASH') {
                    708:                     $notifylist = $domconfig{'usercreation'}{'cancreate'}{'notify'}{'approval'};
                    709:                 }
                    710:             }
                    711:         }
                    712:         my $domconfiguser = &Apache::lonnet::get_domainconfiguser($cdom);
                    713:         $firsturl = &course_portal_url($domconfiguser,$cdom);
                    714:         $approvedmsg = [{
                    715:                             mt => 'Your request for a LON-CAPA account has been approved.',
                    716:                         },
                    717:                         {
                    718:                             mt   => 'Visit [_1] to log-in.',
                    719:                             args => [$firsturl],
                    720:                         }];
                    721:         $rejectedmsg =  [{
                    722:                             mt => 'Your request for a LON-CAPA account has not been approved.',
                    723:                         }];
                    724:         $domdesc = &Apache::lonnet::domain($cdom);
1.1       raeburn   725:     } else {
1.2       raeburn   726:         $domdesc = &Apache::lonnet::domain($cdom);
                    727:         $namespace = 'courserequestqueue';
                    728:         $beneficiary = 'courserequestor';
1.23      raeburn   729:         $queue = 'approval';
                    730:         if ($env{'form.queue'} eq 'pending') {
                    731:             $queue = 'pending';
                    732:         }
                    733:         %requesthash = &Apache::lonnet::dump_dom($namespace,$cdom,'_'.$queue);
1.2       raeburn   734:         my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$cdom);
                    735:         if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                    736:             if (ref($domconfig{'requestcourses'}{'notify'}) eq 'HASH') { 
                    737:                 $notifylist = $domconfig{'requestcourses'}{'notify'}{'approval'};
                    738:             }
                    739:         }
1.12      raeburn   740:         $approvalmsg{'course'} = 
                    741:                         [{
1.2       raeburn   742:                             mt => 'Your course request has been approved.',
                    743:                         },
                    744:                         {
1.28      raeburn   745:                             mt   => 'Visit [_1] to log-in and access the course',
                    746:                             args => [],
1.2       raeburn   747:                         }];
1.12      raeburn   748:         $rejectionmsg{'course'} =
                    749:                         [{
1.2       raeburn   750:                             mt => 'Your course request has not been approved.',
                    751:                         }];
1.12      raeburn   752: 
                    753:         $approvalmsg{'community'} = 
                    754:                         [{
                    755:                             mt => 'Your community request has been approved.',
                    756:                         },
                    757:                         {
1.28      raeburn   758:                             mt   => 'Visit [_1] to log-in and access the community',
                    759:                             args => [],
1.12      raeburn   760:                         }];
                    761: 
                    762:         $rejectionmsg{'community'} = 
                    763:                         [{
                    764:                             mt => 'Your community request has not been approved.',
                    765:                         }];
                    766: 
1.2       raeburn   767:         %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
                    768:         my @roles = &Apache::lonuserutils::roles_by_context('course');
                    769:         foreach my $role (@roles) {
                    770:             $courseroles{$role}=&Apache::lonnet::plaintext($role,'Course');
                    771:         }
                    772:         foreach my $role (@roles) {
                    773:             $communityroles{$role}=&Apache::lonnet::plaintext($role,'Community');
                    774:         }
1.1       raeburn   775:     }
                    776:     foreach my $item (sort {$a <=> $b} @approvals) {
                    777:         if ($context eq 'course') {
                    778:             my ($num,$uname,$udom,$usec) = split(/:/,$item);
                    779:             my $uhome = &Apache::lonnet::homeserver($uname,$udom);
                    780:             if ($uhome ne 'no_host') {
                    781:                 if (exists($requesthash{$uname.':'.$udom})) {
                    782:                     if (exists($classlist->{$uname.':'.$udom})) {
                    783:                         if (ref($classlist->{$uname.':'.$udom}) eq 'ARRAY') {
                    784:                             if (($classlist->{$uname.':'.$udom}->[$idx->{'status'}] eq 'Active') ||
                    785:                                 ($classlist->{$uname.':'.$udom}->[$idx->{'status'}] eq 'Future')) {
                    786:                                 push(@existing,$uname.':'.$udom);
                    787:                                 next;
                    788:                             }
                    789:                         }
                    790:                     }
                    791:                 } else {
                    792:                     push(@missingreq,$uname.':'.$udom);
                    793:                     next;
                    794:                 }
                    795:                 if (!grep(/^\Q$item\E$/,@rejections)) {
                    796:                     if ($limit eq 'allstudents') {
                    797:                         if ($stucounts->{$limit} >= $cap) {
                    798:                             push(@limitexceeded,$uname.':'.$udom);
                    799:                             last;
                    800:                         }
                    801:                     } elsif ($limit eq 'selfenrolled') {
                    802:                         if ($stucounts->{$limit} >= $cap) {
                    803:                             push(@limitexceeded,$uname.':'.$udom);
                    804:                             last;
                    805:                         }
                    806:                     }
                    807:                     my $result =
                    808:                         &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$usec,$access_end,$access_start,'selfenroll',undef,$cdom.'_'.$cnum,1);
                    809:                     if ($result eq 'ok') {
1.2       raeburn   810:                         push(@completed,$uname.':'.$udom);
1.1       raeburn   811:                         $stucounts->{'allstudents'} ++;
                    812:                         $stucounts->{'selfenrolled'} ++;
                    813:                         &send_selfserve_notification($uname.':'.$udom,$approvedmsg,
1.26      raeburn   814:                                        $cid,$coursedesc,$now,$beneficiary,$sender,
                    815:                                        undef,undef,$crstype);
1.2       raeburn   816:                         my %userrequest = (
                    817:                             $cdom.'_'.$cnum => {
                    818:                                 timestamp   => $now,
                    819:                                 section     => $usec,
                    820:                                 adjudicator => $env{'user.name'}.':'.$env{'user.domain'},
                    821:                                 status      => 'approved',
                    822:                             }
                    823:                         );
1.1       raeburn   824:                         my $userresult =
                    825:                             &Apache::lonnet::put($namespace,\%userrequest,$udom,$uname);
                    826:                         if ($userresult ne 'ok') {
                    827:                             push(@warn_approves,$uname.':'.$udom);
                    828:                         }
                    829:                     } else {
1.2       raeburn   830:                         push(@processing_errors,$uname.':'.$udom);
1.1       raeburn   831:                     }
                    832:                 }
                    833:             } else {
                    834:                 push(@invalidusers,$uname.':'.$udom);
                    835:             }
1.30      raeburn   836:         } elsif ($context eq 'requestauthor') {
                    837:             my ($num,$uname) = split(/:/,$item);
                    838:             my $uhome = &Apache::lonnet::homeserver($uname,$cdom);
                    839:             if ($uhome ne 'no_host') {
                    840:                 my ($user_is_adv,$user_is_author) = &Apache::lonnet::is_advanced_user($cdom,$uname);
                    841:                 if ($user_is_author) {
                    842:                     push(@existing,$uname);
                    843:                 } elsif (&Apache::lonnet::usertools_access($uname,$cdom,'requestauthor',
                    844:                                                            undef,'requestauthor')) {
                    845:                     if (&Apache::lonnet::allowed('cau',$cdom)) {
                    846:                         if (&Apache::lonnet::assignrole($cdom,$uname,'/'.$cdom.'/','au',undef,time,undef,undef,'requestauthor') eq 'ok') {
                    847:                             push(@completed,$uname);
                    848:                             &send_selfserve_notification($uname.':'.$cdom,
                    849:                                                          $approvedmsg,undef,undef,$now,
                    850:                                                          $beneficiary,$sender);
                    851:                             my %userrequest = (
                    852:                                 author => {
                    853:                                           timestamp   => $now,
                    854:                                           adjudicator => $env{'user.name'}.':'.$env{'user.domain'},
                    855:                                           status      => 'approved',
                    856:                                         },
                    857:                                 author_status => 'approved',
                    858:                             );
                    859:                             my $userresult =
                    860:                                 &Apache::lonnet::put('requestauthor',\%userrequest,$cdom,$uname);
                    861:                             if ($userresult ne 'ok') {
1.43      raeburn   862:                                 push(@warn_approves,$uname.':'.$cdom);
1.30      raeburn   863:                             }
                    864:                         } else {
                    865:                             push(@processing_errors,$uname);
                    866:                         }
                    867:                     } else {
                    868:                         push(@nopermissions,$uname);
                    869:                     }
                    870:                 } else {
                    871:                     push(@nopermissions,$uname);
                    872:                 }
                    873:             } else {
                    874:                 push(@invalidusers,$uname.':'.$cdom);
                    875:             }
                    876:             push(@toremove,(@invalidusers,@nopermissions));
1.43      raeburn   877:         } elsif ($context eq 'requestusername') {
                    878:             my ($num,$uname) = split(/:/,$item);
                    879:             my $dbname = 'nohist_requestedusernames';
                    880:             my $domconfiguser = &Apache::lonnet::get_domainconfiguser($cdom);
                    881:             my %curr = &Apache::lonnet::get($dbname,[$uname],$cdom,$domconfiguser);
                    882:             
                    883:             if (ref($curr{$uname}) eq 'HASH') {
                    884:                 my ($username,$logtoken,$serverid,$encpass,$courseid,$id,$firstname,
1.44      raeburn   885:                     $middlename,$lastname,$generation,$inststatus);
1.43      raeburn   886:                 $curr{$uname}{'timestamp'} = $now;
                    887:                 $curr{$uname}{'adjudicator'} = $env{'user.name'}.':'.$env{'user.domain'};
                    888:                 $courseid   = $curr{$uname}{'courseid'};
                    889:                 $id         = $curr{$uname}{'id'};
                    890:                 $firstname  = $curr{$uname}{'firstname'};
                    891:                 $middlename = $curr{$uname}{'middlename'};
                    892:                 $lastname   = $curr{$uname}{'lastname'};
                    893:                 $generation = $curr{$uname}{'generation'};
1.46      raeburn   894:                 $inststatus = $curr{$uname}{'inststatus'};
1.43      raeburn   895: 
                    896:                 my ($key,$caller)=split(/&/,$curr{$uname}{'tmpinfo'});
                    897:                 if ($caller eq 'createaccount') {
                    898:                     my $upass = &Apache::loncommon::des_decrypt($key,$curr{$uname}{'upass'});
                    899:                     undef($curr{$uname}{'upass'});
                    900:                     my $result =
                    901:                         &Apache::lonnet::modifyuser($cdom,$uname,$id,'internal',$upass,
                    902:                                                     $firstname,$middlename,$lastname,
                    903:                                                     $generation,undef,undef,$uname);
                    904:                     if ($result eq 'ok') {
                    905:                         $curr{$uname}{'status'} = 'created';
                    906:                         push(@completed,$uname); 
                    907:                         my $uhome = &Apache::lonnet::homeserver($uname,$cdom);
                    908:                         if ($uhome eq 'no_host') {
                    909:                             push(@warn_approves,$uname);
                    910:                         } else {
1.44      raeburn   911:                             unless (($inststatus eq 'default') || ($inststatus eq '')) {
                    912:                                 &Apache::lonnet::put('environment',{inststatus => $inststatus},$cdom,$uname);
                    913:                             }
1.43      raeburn   914:                             &send_selfserve_notification($uname.':'.$cdom,
                    915:                                                          $approvedmsg,undef,undef,$now,
                    916:                                                          $beneficiary,$sender);
                    917:                             if (&Apache::lonnet::put($dbname,\%curr,$cdom,$domconfiguser) ne 'ok') {
                    918:                                 push(@warn_approves,$uname);
                    919:                             }
                    920:                         }
                    921:                     } else {
                    922:                         push(@processing_errors,$uname);
                    923:                     }
                    924:                 } else {
                    925:                     push(@processing_errors,$uname);
                    926:                 }
                    927:             } else {
                    928:                 push(@invalidusers,$uname);
                    929:             }
                    930:             push(@toremove,@invalidusers);
1.1       raeburn   931:         } else {
1.2       raeburn   932:             my ($num,$cnum) = split(':',$item);
1.23      raeburn   933:             if (ref($requesthash{$cnum.'_'.$queue}) eq 'HASH') {
1.2       raeburn   934:                 if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {
1.23      raeburn   935:                     my $ownername = $requesthash{$cnum.'_'.$queue}{'ownername'};
                    936:                     my $ownerdom = $requesthash{$cnum.'_'.$queue}{'ownerdom'};
                    937:                     $crstype = $requesthash{$cnum.'_'.$queue}{'crstype'};
                    938:                     my $coursedesc = $requesthash{$cnum.'_'.$queue}{'description'};
1.2       raeburn   939:                     my $longroles = \%courseroles;
                    940:                     if ($crstype eq 'community') {
                    941:                         $longroles = \%communityroles;
                    942:                     }
1.5       raeburn   943:                     my $cancreate;
                    944:                     if ($cdom eq $ownerdom) {
                    945:                         if (&Apache::lonnet::usertools_access($ownername,$ownerdom,$crstype,
                    946:                                                               undef,'requestcourses')) {
                    947:                             $cancreate = 1;
                    948:                         }
                    949:                     } else {
                    950:                         my %userenv = &Apache::lonnet::userenvironment($ownerdom,$ownername,'reqcrsotherdom.'.$crstype);
                    951:                         if ($userenv{'reqcrsotherdom.'.$crstype}) {
                    952:                             my @doms = split(',',$userenv{'reqcrsotherdom.'.$crstype});
                    953:                             if (grep(/^\Q$cdom\E:/,@doms)) {
                    954:                                 $cancreate = 1;
                    955:                             }
                    956:                         }
                    957:                     }
                    958:                     if ($cancreate) {
1.2       raeburn   959:                         my $requestkey = $cdom.'_'.$cnum;
                    960:                         my %history = 
                    961:                             &Apache::lonnet::restore($requestkey,'courserequests',
                    962:                                                      $ownerdom,$ownername);
                    963:                         if ((ref($history{'details'}) eq 'HASH') && 
1.23      raeburn   964:                             ($history{'disposition'} eq $queue)) {
1.41      raeburn   965:                             my ($logmsg,$newusermsg,$addresult,$enrollcount,$response,$keysmsg,$code,%customitems);
                    966:                             my $fullname = '';
                    967:                             my $inprocess = &Apache::lonnet::auto_crsreq_update($cdom,$cnum,$crstype,'process',$ownername,
                    968:                                                                                 $ownerdom,$fullname,$coursedesc);
                    969:                             if (ref($inprocess) eq 'HASH') {
                    970:                                 foreach my $key (keys(%{$inprocess})) {
                    971:                                     if (exists($history{'details'}{$key})) { 
                    972:                                         $customitems{$key} = $history{'details'}{$key};
                    973:                                     }
                    974:                                 }
                    975:                             }
1.50      raeburn   976:                             if ($history{'details'}{'clonecrs'}) {
                    977:                                 $customitems{'_LC_clonefrom'} = $history{'details'}{'clonedom'}.'_'.$history{'details'}{'clonecrs'};
                    978:                             }
1.41      raeburn   979:                             my ($result,$postprocess) = &course_creation($cdom,$cnum,$context,$history{'details'},\$logmsg,
                    980:                                                         \$newusermsg,\$addresult,\$enrollcount,
                    981:                                                         \$response,\$keysmsg,\%domdefs,$longroles,\$code,\%customitems);
1.2       raeburn   982:                             if ($result eq 'created') {
1.12      raeburn   983:                                 if ($crstype eq 'community') {
                    984:                                     $approvedmsg = $approvalmsg{'community'};
                    985:                                 } else {
                    986:                                     $approvedmsg = $approvalmsg{'course'};
                    987:                                 }
1.28      raeburn   988:                                 my $firsturl = &course_portal_url($cnum,$cdom);
                    989:                                 if (ref($approvedmsg) eq 'ARRAY') {
                    990:                                     if (ref($approvedmsg->[1]) eq 'HASH') {
                    991:                                         $approvedmsg->[1]->{'args'} = [$firsturl];
                    992:                                     }
1.39      raeburn   993:                                     if ($code) {
                    994:                                         push(@{$approvedmsg},
                    995:                                             {
                    996:                                               mt   => 'Students can automatically select your course by entering this code: [_1]',
                    997:                                               args => [$code],
                    998:                                             });
                    999:                                         $codes{$cnum} = $code;
                   1000:                                     }
1.41      raeburn  1001:                                     if (ref($postprocess) eq 'HASH') {
                   1002:                                         if (ref($postprocess->{'createdmsg'}) eq 'ARRAY') {
                   1003:                                             foreach my $item (@{$postprocess->{'createdmsg'}}) {
                   1004:                                                 if (ref($item) eq 'HASH') {
                   1005:                                                     if ($item->{'mt'} ne '') {
                   1006:                                                         push(@{$approvedmsg},$item);
                   1007:                                                     }
                   1008:                                                 }
                   1009:                                             }
                   1010:                                         }
                   1011:                                     }
1.28      raeburn  1012:                                 }
1.2       raeburn  1013:                                 push(@completed,$cnum);
1.19      raeburn  1014:                                 
1.23      raeburn  1015:                                 unless (&Apache::lonnet::del_dom($namespace,[$cnum.'_'.$queue],$cdom) eq 'ok') {
1.19      raeburn  1016:                                     push(@warn_dels,$cnum);
                   1017:                                 }
1.26      raeburn  1018:                                 &send_selfserve_notification($ownername.':'.$ownerdom,
                   1019:                                               $approvedmsg,$cid,$coursedesc,$now,
                   1020:                                               $beneficiary,$sender,undef,undef,$crstype);
1.2       raeburn  1021:                                 my %reqhash = (
                   1022:                                                 reqtime     => $history{'reqtime'},
                   1023:                                                 crstype     => $history{'crstype'},
                   1024:                                                 details     => $history{'details'},
                   1025:                                                 disposition => $history{'disposition'},
                   1026:                                                 status      => 'created',
                   1027:                                                 adjudicator => $env{'user.name'}.':'.
                   1028:                                                                $env{'user.domain'},
                   1029:                                               );
                   1030:                                 my $userresult =
                   1031:                                     &Apache::lonnet::store_userdata(\%reqhash,$requestkey,
                   1032:                                                    'courserequests',$ownerdom,$ownername);
                   1033:                                 if ($userresult eq 'ok') {
                   1034:                                     my %status = (
                   1035:                                                    'status:'.$cdom.':'.$cnum => 'created'
                   1036:                                                  );
                   1037:                                     my $statusresult = 
                   1038:                                         &Apache::lonnet::put('courserequests',\%status,
                   1039:                                                              $ownerdom,$ownername);
                   1040:                                     if ($statusresult ne 'ok') {
                   1041:                                         push(@warn_approves,$cnum);
                   1042:                                     }
                   1043:                                 }
                   1044:                                 if ($userresult ne 'ok') {
                   1045:                                     push(@warn_approves,$cnum);
                   1046:                                 }
                   1047:                             } else {
                   1048:                                 push(@processing_errors,$cnum);
                   1049:                             }
                   1050:                         } else {
                   1051:                             push(@processing_errors,$cnum);
                   1052:                         }
                   1053:                     } else {
1.5       raeburn  1054:                         push(@nopermissions,$cnum);
1.2       raeburn  1055:                     }
                   1056:                 } else {
                   1057:                     push(@existing,$cnum);
                   1058:                 }
                   1059:             } else {
                   1060:                 push(@missingreq,$cnum);
                   1061:             }
1.1       raeburn  1062:         }
                   1063:     }
1.2       raeburn  1064:     my @changes = (@completed,@rejections);
                   1065:     if ($context eq 'domain') {
1.23      raeburn  1066:         @changes = map {$_.'_'.$queue} (@changes);
1.30      raeburn  1067:     } elsif ($context eq 'requestauthor') {
                   1068:         @changes = map {$_.'_approval'} (@changes);
1.43      raeburn  1069:     } elsif ($context eq 'requestusername') {
                   1070:         @changes = map {&escape($_).'_approval'} (@changes);
1.2       raeburn  1071:     }
1.1       raeburn  1072:     if (@rejections) {
1.3       raeburn  1073:         foreach my $item (@rejections) {
1.30      raeburn  1074:             if (($context eq 'course') || ($context eq 'requestauthor')) {
1.43      raeburn  1075:                 my ($user,$uname,$udom,%userrequest,$key,$dbname);
1.30      raeburn  1076:                 if ($context eq 'requestauthor') {
                   1077:                     $uname = $item;
                   1078:                     $udom = $cdom;
                   1079:                     $user = $uname.':'.$udom;
                   1080:                     $key = 'author';
1.43      raeburn  1081:                     $dbname = 'requestauthor';
1.30      raeburn  1082:                 } else {
                   1083:                     $user = $item;
                   1084:                     ($uname,$udom) = split(/:/,$user);
                   1085:                     $key = $cdom.'_'.$cnum;
1.43      raeburn  1086:                     $dbname = $namespace;
1.30      raeburn  1087:                 }
1.2       raeburn  1088:                 &send_selfserve_notification($user,$rejectedmsg,$cid,$coursedesc,
1.26      raeburn  1089:                                              $now,$beneficiary,$sender,undef,undef,
                   1090:                                              $crstype);
1.30      raeburn  1091:                 %userrequest = (
                   1092:                     $key => {
1.1       raeburn  1093:                         timestamp   => $now,
                   1094:                         adjudicator => $env{'user.name'}.':'.$env{'user.domain'},
1.30      raeburn  1095:                         status      => 'rejection',
1.1       raeburn  1096:                     }
                   1097:                 );
1.30      raeburn  1098:                 if ($context eq 'requestauthor') {
                   1099:                     $userrequest{'author_status'} = 'rejection';  
                   1100:                 }
1.1       raeburn  1101:                 my $userresult =
1.43      raeburn  1102:                     &Apache::lonnet::put($dbname,\%userrequest,$udom,$uname);
1.1       raeburn  1103:                 if ($userresult ne 'ok') {
1.30      raeburn  1104:                     push(@warn_rejects,$item);
1.1       raeburn  1105:                 }
1.43      raeburn  1106:             } elsif ($context eq 'requestusername') {
                   1107:                 my ($uname,$udom,$dbname);
                   1108:                 $uname = $item;
                   1109:                 $udom = $cdom;
                   1110:                 $dbname = 'nohist_requestedusernames';
                   1111:                 my $domconfiguser = &Apache::lonnet::get_domainconfiguser($cdom);
                   1112:                 my %curr = &Apache::lonnet::get($dbname,[$uname],$cdom,$domconfiguser);
                   1113:                 if (ref($curr{$uname}) eq 'HASH') {
                   1114:                      $curr{$uname}{'status'} = 'rejected';
                   1115:                      $curr{$uname}{'timestamp'} = $now;
                   1116:                      $curr{$uname}{'adjudicator'} =  $env{'user.name'}.':'.$env{'user.domain'};
                   1117:                      undef($curr{$uname}{'tmpinfo'});
                   1118:                      undef($curr{$uname}{'upass'}); 
                   1119:                 }
                   1120:                 my $userresult =
                   1121:                     &Apache::lonnet::put($dbname,\%curr,$cdom,$domconfiguser);
                   1122:                 if ($userresult ne 'ok') {
                   1123:                     push(@warn_rejects,$uname);
                   1124:                 }
1.1       raeburn  1125:             } else {
1.3       raeburn  1126:                 my $cnum = $item;
1.23      raeburn  1127:                 if (ref($requesthash{$cnum.'_'.$queue}) eq 'HASH') {
1.3       raeburn  1128:                     if (&Apache::lonnet::homeserver($cnum,$cdom) eq 'no_host') {
                   1129:                         my $requestkey = $cdom.'_'.$cnum;
1.23      raeburn  1130:                         my $ownername = $requesthash{$cnum.'_'.$queue}{'ownername'};
                   1131:                         my $ownerdom = $requesthash{$cnum.'_'.$queue}{'ownerdom'};
                   1132:                         my $coursedesc = $requesthash{$cnum.'_'.$queue}{'description'};
                   1133:                         $crstype = $requesthash{$cnum.'_'.$queue}{'crstype'};
1.12      raeburn  1134:                         if ($crstype eq 'community') {
                   1135:                             $rejectedmsg = $rejectionmsg{'community'};
                   1136:                         } else {
                   1137:                             $rejectedmsg = $rejectionmsg{'course'};
                   1138:                         }
1.2       raeburn  1139:                         &send_selfserve_notification($ownername.':'.$ownerdom,$rejectedmsg,
                   1140:                                                      $cid,$coursedesc,$now,$beneficiary,
1.12      raeburn  1141:                                                      $sender,undef,undef,$crstype);
1.2       raeburn  1142:                         my %history =
1.3       raeburn  1143:                             &Apache::lonnet::restore($requestkey,'courserequests',
1.2       raeburn  1144:                                                      $ownerdom,$ownername);
                   1145:                         if ((ref($history{'details'}) eq 'HASH') &&
1.23      raeburn  1146:                             ($history{'disposition'} eq $queue)) {
1.2       raeburn  1147:                             my %reqhash = (
                   1148:                                             reqtime     => $history{'reqtime'},
                   1149:                                             crstype     => $history{'crstype'},
                   1150:                                             details     => $history{'details'},
                   1151:                                             disposition => $history{'disposition'},
                   1152:                                             status      => 'rejected',
                   1153:                                             adjudicator => $env{'user.name'}.':'.$env{'user.domain'},
                   1154:                                               );
                   1155:                             my $userresult =
1.3       raeburn  1156:                                 &Apache::lonnet::store_userdata(\%reqhash,$requestkey,
                   1157:                                                 'courserequests',$ownerdom,$ownername);
                   1158:                             if ($userresult eq 'ok') {
                   1159:                                 my %status = (
                   1160:                                                'status:'.$cdom.':'.$cnum => 'rejected'
                   1161:                                              );
                   1162:                                 my $statusresult =
                   1163:                                     &Apache::lonnet::put('courserequests',\%status,
                   1164:                                                          $ownerdom,$ownername);
                   1165:                                 if ($statusresult ne 'ok') {
                   1166:                                     push(@warn_rejects,$cnum);
                   1167:                                 }
                   1168:                             } else {
                   1169:                                 push(@warn_rejects,$cnum);
1.2       raeburn  1170:                             }
1.23      raeburn  1171:                             unless (&Apache::lonnet::del_dom($namespace,[$cnum.'_'.$queue],$cdom) eq 'ok') {
1.19      raeburn  1172:                                 push(@warn_dels,$cnum);
                   1173:                             }
1.3       raeburn  1174:                         } else {
                   1175:                             push(@warn_rejects,$cnum);
1.2       raeburn  1176:                         }
1.3       raeburn  1177:                     } else {
                   1178:                         push(@existing,$cnum);
1.2       raeburn  1179:                     }
1.3       raeburn  1180:                 } else {
                   1181:                     push(@rejectionerrors,$cnum);
1.2       raeburn  1182:                 }
1.1       raeburn  1183:             }
                   1184:         }
                   1185:     }
1.30      raeburn  1186:     if (@toremove) {
1.43      raeburn  1187:         my $domconfiguser = &Apache::lonnet::get_domainconfiguser($cdom);
1.30      raeburn  1188:         foreach my $item (@toremove) {
1.43      raeburn  1189:             if ($context eq 'requestauthor') {
                   1190:                 my %userrequest = (
                   1191:                     author => {
                   1192:                                 timestamp   => $now,
                   1193:                                 adjudicator => $env{'user.name'}.':'.$env{'user.domain'},
                   1194:                                 status      => 'deleted',
                   1195:                               },
                   1196:                               author_status => 'deleted',
                   1197:                 );
                   1198:                 &Apache::lonnet::put('requestauthor',\%userrequest,$cdom,$item);
                   1199:             } elsif ($context eq 'requestusername') {
                   1200:                 my $dbname = 'nohist_requestedusernames';
                   1201:                 my %curr = &Apache::lonnet::get($dbname,[$item],$cdom,$domconfiguser);
                   1202:                 if (ref($curr{$item}) eq 'HASH') {
                   1203:                     $curr{$item}{'status'} = 'deleted';
                   1204:                     $curr{$item}{'timestamp'} = $now;
                   1205:                     $curr{$item}{'adjudicator'} = $env{'user.name'}.':'.$env{'user.domain'};
                   1206:                     undef($curr{$item}{'upass'});
                   1207:                     undef($curr{$item}{'tmpinfo'}); 
                   1208:                 }
                   1209:             }
1.30      raeburn  1210:         }
                   1211:         @toremove = map {$_.'_approval'} (@toremove);
                   1212:         my $delresult = &Apache::lonnet::del_dom($namespace,\@toremove,$cdom);
                   1213:     }
1.1       raeburn  1214:     if (@changes) {
                   1215:         my $delresult;
                   1216:         if ($context eq 'course') {
                   1217:             $delresult = &Apache::lonnet::del($namespace,\@changes,$cdom,$cnum);
                   1218:         } else {
                   1219:             $delresult = &Apache::lonnet::del_dom($namespace,\@changes,$cdom);
                   1220:         }
                   1221:         if ($delresult eq 'ok') {
                   1222:             my $namelink =
                   1223:                 &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'}).' ('.$env{'user.name'}.':'.$env{'user.domain'}.')';
                   1224:             my ($chgmsg,$approvedlist,$rejectedlist);
                   1225:             if ($context eq 'course') {
                   1226:                 $chgmsg = "'Action was taken on the following enrollment requests by [_1].',$namelink";
1.2       raeburn  1227:                 if (@completed) {
                   1228:                     $approvedlist = join("\n",@completed);
1.12      raeburn  1229:                     if ($crstype eq 'community') {
                   1230:                         $output .= '<p>'.&mt('The following were enrolled in the community:').'<ul>';
                   1231:                     } else {
                   1232:                         $output .= '<p>'.&mt('The following were enrolled in the course:').'<ul>';
                   1233:                     }
1.2       raeburn  1234:                     foreach my $user (@completed) {
1.1       raeburn  1235:                         my ($uname,$udom) = split(/:/,$user);
                   1236:                         my $userlink =
                   1237:                             &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$udom),$uname,$udom);
                   1238:                         $output .= '<li>'.$userlink.'</li>';
                   1239:                     }
                   1240:                     $output .= '</ul></p>';
                   1241:                 }
                   1242:                 if (@rejections) {
                   1243:                     $rejectedlist = join("\n",@rejections);
                   1244:                     $output .= '<p>'.&mt('The following enrollment requests were rejected:').'<ul>';
                   1245:                     foreach my $user (@rejections) {
                   1246:                         $output .= '<li>'.$user.'</li>';
                   1247:                     }
                   1248:                     $output .= '</ul></p>';
                   1249:                 }
1.2       raeburn  1250:                 if ($notifylist ne '') {
                   1251:                     &send_selfserve_notification($notifylist,$chgmsg,$cid,$coursedesc,
                   1252:                                                  $now,'coursemanagers',$sender,
1.12      raeburn  1253:                                                  $approvedlist,$rejectedlist,$crstype);
1.2       raeburn  1254:                 }
1.30      raeburn  1255:             } elsif ($context eq 'requestauthor') {
1.42      bisitz   1256:                 $chgmsg = "'Action was taken on the following Authoring Space requests by [_1].',$namelink";
1.30      raeburn  1257:                 if (@completed) {
                   1258:                     $approvedlist = join("\n",@completed);
                   1259:                     $output .= '<p>'.&mt('The following requests were approved:').'<ul>';
                   1260:                     foreach my $uname (@completed) {
                   1261:                         my $userlink =
                   1262:                             &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$cdom),$uname,$cdom);
                   1263:                         $output .= '<li>'.$userlink.'</li>';
                   1264:                         
                   1265:                     }
                   1266:                     $output .= '</ul></p>';
                   1267:                 }
                   1268:                 if (@rejections) {
                   1269:                     $rejectedlist = join("\n",@rejections);
                   1270:                     $output .= '<p>'.&mt('The following requests were rejected:').'<ul>';
                   1271:                     foreach my $uname (@rejections) {
                   1272:                         my $userlink =
                   1273:                             &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$cdom),$uname,$cdom);
                   1274:                         $output .= '<li>'.$userlink.'</li>';
                   1275:                     }
                   1276:                     $output .= '</ul></p>';
                   1277:                 }
                   1278:                 if ($notifylist ne '') {
                   1279:                     &send_selfserve_notification($notifylist,$chgmsg,undef,$domdesc,
                   1280:                                                  $now,'authormanagers',$sender,
                   1281:                                                  $approvedlist,$rejectedlist);
                   1282:                 }
1.43      raeburn  1283:             } elsif ($context eq 'requestusername') {
                   1284:                 $chgmsg = "'Action was taken on the following LON-CAPA account requests by [_1].',$namelink";
                   1285:                 if (@completed) {
                   1286:                     $approvedlist = join("\n",@completed);
                   1287:                     $output .= '<p>'.&mt('The following requests were approved:').'<ul>';
                   1288:                     foreach my $uname (@completed) {
                   1289:                         $output .= '<li>'.$uname.'</li>';
                   1290: 
                   1291:                     }
                   1292:                     $output .= '</ul></p>';
                   1293:                 }
                   1294:                 if (@rejections) {
                   1295:                     $rejectedlist = join("\n",@rejections);
                   1296:                     $output .= '<p>'.&mt('The following requests were rejected:').'<ul>';
                   1297:                     foreach my $uname (@rejections) {
                   1298:                         $output .= '<li>'.$uname.'</li>';
                   1299:                     }
                   1300:                     $output .= '</ul></p>';
                   1301:                 }
                   1302:                 if ($notifylist ne '') {
                   1303:                     &send_selfserve_notification($notifylist,$chgmsg,undef,$domdesc,
                   1304:                                                  $now,'usernamemanagers',$sender,
                   1305:                                                  $approvedlist,$rejectedlist);
                   1306:                 }
1.1       raeburn  1307:             } else {
1.12      raeburn  1308:                 $chgmsg = "'Action was taken on the following course and community requests by [_1].',$namelink";
1.2       raeburn  1309:                 if (@completed) {
                   1310:                     $approvedlist = join("\n",@completed);
1.12      raeburn  1311:                     $output .= '<p>'.&mt('The following courses/communities were created:').'<ul>';
1.2       raeburn  1312:                     foreach my $cnum (@completed) {
                   1313:                         my $showcourse;
1.23      raeburn  1314:                         if (ref($requesthash{$cnum.'_'.$queue})) {
                   1315:                             $showcourse = $requesthash{$cnum.'_'.$queue}{'description'};
1.2       raeburn  1316:                         } else {
                   1317:                             $showcourse = $cnum;
                   1318:                         }
                   1319:                         my $syllabuslink =
                   1320:                             &Apache::loncommon::syllabuswrapper($showcourse,$cnum,$cdom);
1.40      raeburn  1321:                         if ($codes{$cnum}) {
1.49      raeburn  1322:                             $syllabuslink .= ' '.&mt('Unique code: [_1]',$codes{$cnum});
1.39      raeburn  1323:                         }
1.2       raeburn  1324:                         $output .= '<li>'.$syllabuslink.'</li>';
                   1325:                     }
                   1326:                     $output .= '</ul></p>';
                   1327:                 }
                   1328:                 if (@rejections) {
                   1329:                     $rejectedlist = join("\n",@rejections);
                   1330:                     $output .= '<p>'.&mt('The following requests were rejected:').'<ul>';
                   1331:                     foreach my $cnum (@rejections) {
                   1332:                         my $showcourse;
1.23      raeburn  1333:                         if (ref($requesthash{$cnum.'_'.$queue})) {
                   1334:                             $showcourse = $requesthash{$cnum.'_'.$queue}{'description'};
1.2       raeburn  1335:                         } else {
                   1336:                             $showcourse = $cnum;
                   1337:                         }
                   1338:                         $output .= '<li>'.$showcourse.'</li>';
                   1339:                     }
                   1340:                     $output .= '</ul></p>';
                   1341:                 }
                   1342:                 if ($notifylist ne '') {
                   1343:                     &send_selfserve_notification($notifylist,$chgmsg,$cid,$domdesc,
                   1344:                                                  $now,'domainmanagers',$sender,
1.12      raeburn  1345:                                                  $approvedlist,$rejectedlist,$crstype);
1.2       raeburn  1346:                 }
1.1       raeburn  1347:             }
1.43      raeburn  1348:         } else {
                   1349:             if (($context eq 'requestauthor') || ($context eq 'requestusername')) {
                   1350:                 push(@warn_dels,@changes);
                   1351:             }
1.1       raeburn  1352:         }
                   1353:     }
                   1354:     if (@existing) {
                   1355:         if ($context eq 'course') {
                   1356:             $output .= '<p>'.&mt('The following enrollment requests were deleted because the user is already enrolled in the course:').'<ul>';
                   1357:             foreach my $user (@existing) {
                   1358:                 $output .= '<li>'.$user.'</li>';
                   1359:             }
                   1360:             $output .= '</ul></p>';
1.30      raeburn  1361:         } elsif ($context eq 'requestauthor') {
1.42      bisitz   1362:             $output .= '<p>'.&mt('Authoring Space requests from the following users were deleted because one already exists:').'<ul>';
1.30      raeburn  1363:             foreach my $uname (@existing) {
                   1364:                 my $userlink =
                   1365:                     &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$cdom),$uname,$cdom);
                   1366:                 $output .= '<li>'.$userlink.'</li>';
                   1367:             }
                   1368:             $output .= '</ul></p>';
1.1       raeburn  1369:         } else {
1.12      raeburn  1370:             $output .= '<p>'.&mt('The following course/community creation requests were deleted because the course or community has already been created:').'<ul>';
1.2       raeburn  1371:             foreach my $cnum (@existing) {
                   1372:                 my $showcourse;
                   1373:                 my %coursehash = &Apache::lonnet::coursedescription($cdom.'/'.$cnum);
                   1374:                 if ($coursehash{'description'} ne '') {
                   1375:                     $showcourse = $coursehash{'description'};
                   1376:                 } else {
                   1377:                     $showcourse = $cnum;
                   1378:                 }
                   1379:                 $output .= '<li>'.$showcourse.'</li>';
                   1380:             }
                   1381:             $output .= '</ul></p>';
1.1       raeburn  1382:         }
                   1383:     }
                   1384:     if (@missingreq) {
                   1385:         if ($context eq 'course') {
                   1386:             $output .= '<p>'.&mt('The following enrollment requests were ignored because the request is no longer in the enrollment queue:').'<ul>';
                   1387:             foreach my $user (@missingreq) {
                   1388:                 $output .= '<li>'.$user.'</li>';
                   1389:             }
                   1390:             $output .= '</ul></p>';
1.30      raeburn  1391:         } elsif ($context eq 'requestauthor') {
                   1392:             $output .= '<p>'.&mt('The following requests were ignored because the request is no longer in the queue:').'<ul>';
                   1393:             foreach my $uname (@missingreq) {
                   1394:                 my $userlink =
                   1395:                     &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$cdom),$uname,$cdom);
                   1396:                 $output .= '<li>'.$userlink.'</li>';
                   1397:             }
                   1398:             $output .= '</ul></p>';
1.2       raeburn  1399:         } else {
1.12      raeburn  1400:             $output .= '<p>'.&mt('The following course/community creation requests were ignored because the request is no longer in the queue:').'<ul>';
1.2       raeburn  1401:             foreach my $cnum (@missingreq) {
                   1402:                 $output .= '<li>'.$cnum.'</li>';
                   1403:             }
                   1404:             $output .= '</ul></p>';
1.1       raeburn  1405:         }
                   1406:     }
                   1407:     if (@invalidusers) {
                   1408:         if ($context eq 'course') {
                   1409:             $output .= '<p>'.&mt('The following enrollment requests were deleted because the requestor does not have a LON-CAPA account:').'<ul>';
                   1410:             foreach my $user (@invalidusers) {
                   1411:                 $output .= '<li>'.$user.'</li>';
                   1412:             }
                   1413:             $output .= '</ul></p>';
1.30      raeburn  1414:         } elsif ($context eq 'requestauthor') {
1.42      bisitz   1415:             $output .= '<p>'.&mt('The following Authoring Space requests were deleted because the requestor does not have a LON-CAPA account:').'<ul>';
1.30      raeburn  1416:             foreach my $uname (@invalidusers) {
                   1417:                 my $userlink =
                   1418:                     &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$cdom),$uname,$cdom);
                   1419:                 $output .= '<li>'.$userlink.'</li>';
                   1420:             }
                   1421:             $output .= '</ul></p>';
1.1       raeburn  1422:         }
                   1423:     }
                   1424:     if (@limitexceeded) {
                   1425:         if ($context eq 'course') {
                   1426:             $output .= '<p>'.&mt('The following enrollment requests were skipped because the enrollment limit has been reached for the course:').'<ul>';
                   1427:             foreach my $user (@limitexceeded) {
                   1428:                 $output .= '<li>'.$user.'</li>';
                   1429:             }
                   1430:             $output .= '</ul></p>';
                   1431:         }
                   1432:     }
1.5       raeburn  1433:     if (@nopermissions) {
1.30      raeburn  1434:         if ($context eq 'course') {
                   1435:             $output .= '<p>'.&mt('The following course/community creation requests could not be processed because the owner does not have rights to create this type of course:').'<ul>';
                   1436:             foreach my $cnum (@nopermissions) {
                   1437:                 my $showcourse;
                   1438:                 if (ref($requesthash{$cnum.'_'.$queue})) {
                   1439:                     $showcourse = $requesthash{$cnum.'_'.$queue}{'description'};
                   1440:                 } else {
                   1441:                     $showcourse = $cnum;
                   1442:                 }
                   1443:                 $output .= '<li>'.$showcourse.'</li>';
                   1444:             }
                   1445:             $output .= '</ul></p>';
                   1446:         } elsif ($context eq 'requestauthor') {
1.42      bisitz   1447:             $output .= '<p>'.&mt('The following requests could not be processed because the requestor does not have rights to request an Authoring Space:').'<ul>';
1.30      raeburn  1448:             foreach my $uname (@nopermissions) {
                   1449:                 my $userlink =
                   1450:                     &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$cdom),$uname,$cdom);
                   1451:                 $output .= '<li>'.$userlink.'</li>';
1.5       raeburn  1452:             }
1.30      raeburn  1453:             $output .= '</ul></p>';
1.5       raeburn  1454:         }
                   1455:     }
1.2       raeburn  1456:     if (@processing_errors) {
1.1       raeburn  1457:         if ($context eq 'course') {
                   1458:             $output .= '<p>'.&mt('The following enrollment requests could not be processed because an error occurred:').'<ul>';
1.2       raeburn  1459:             foreach my $user (@processing_errors) {
1.1       raeburn  1460:                 $output .= '<li>'.$user.'</li>';
                   1461:             }
                   1462:             $output .= '</ul></p>';
1.30      raeburn  1463:         } elsif ($context eq 'requestauthor') {
                   1464:             $output .= '<p>'.&mt('The following requests could not be processed because an error occurred:').'<ul>';
                   1465:             foreach my $uname (@processing_errors) {
                   1466:                 my $userlink =
                   1467:                     &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$cdom),$uname,$cdom);
                   1468:                 $output .= '<li>'.$userlink.'</li>';
                   1469:             }
                   1470:             $output .= '</ul></p>';
1.43      raeburn  1471:         } elsif ($context eq 'requestusername') {
                   1472:             $output .= '<p>'.&mt('The following requests could not be processed because an error occurred:').'<ul>';
                   1473:             foreach my $uname (@processing_errors) {
                   1474:                 $output .= '<li>'.$uname.'</li>';
                   1475:             }
                   1476:             $output .= '</ul></p>';
1.1       raeburn  1477:         } else {
1.12      raeburn  1478:             $output .= '<p>'.&mt('The following course/community creation requests could not be processed because an error occurred:').'<ul>';
1.2       raeburn  1479:             foreach my $cnum (@processing_errors) {
                   1480:                 my $showcourse;
1.23      raeburn  1481:                 if (ref($requesthash{$cnum.'_'.$queue})) {
                   1482:                     $showcourse = $requesthash{$cnum.'_'.$queue}{'description'};
1.2       raeburn  1483:                 } else {
                   1484:                     $showcourse = $cnum;
                   1485:                 }
                   1486:                 $output .= '<li>'.$showcourse.'</li>';
                   1487:             }
                   1488:             $output .= '</ul></p>';
1.1       raeburn  1489:         }
                   1490:     }
1.3       raeburn  1491:     if (@rejectionerrors) {
1.12      raeburn  1492:         $output .= '<p>'.&mt('The following course/community creation request rejections could not be fully processed because an error occurred:').'<ul>';
1.3       raeburn  1493:         foreach my $cnum (@rejectionerrors) {
                   1494:             my $showcourse;
1.23      raeburn  1495:             if (ref($requesthash{$cnum.'_'.$queue})) {
                   1496:                 $showcourse = $requesthash{$cnum.'_'.$queue}{'description'};
1.3       raeburn  1497:             } else {
                   1498:                 $showcourse = $cnum;
                   1499:             }
                   1500:             $output .= '<li>'.$showcourse.'</li>';
                   1501:         }
                   1502:         $output .= '</ul></p>';
                   1503:     }
1.2       raeburn  1504:     if (@warn_approves || @warn_rejects) {
1.1       raeburn  1505:         if ($context eq 'course') {
                   1506:             $output .= '<p>'.&mt("For the following users, an error occurred when updating the user's own self-enroll requests record:").'<ul>';
                   1507:             foreach my $user (@warn_approves) {
                   1508:                 $output .= '<li>'.$user.'</li>';
                   1509:             }
                   1510:             $output .= '</ul></p>';
1.30      raeburn  1511:         } elsif ($context eq 'requestauthor') {
                   1512:             $output .= '<p>'.&mt("For the following users, an error occurred when updating the user's own author request record:").'<ul>';
                   1513:             foreach my $uname (@warn_approves,@warn_rejects) {
                   1514:                 my $userlink =
                   1515:                     &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$cdom),$uname,$cdom);
                   1516:                 $output .= '<li>'.$userlink.'</li>';
                   1517:             }
                   1518:             $output .= '</ul></p>';
1.43      raeburn  1519:         } elsif ($context eq 'requestusername') {
                   1520:             $output .= '<p>'.&mt("For the following users, an error occurred when updating the account request record for the user:").'<ul>';
                   1521:             foreach my $uname (@warn_approves,@warn_rejects) {
                   1522:                 $output .= '<li>'.$uname.'</li>';
                   1523:             }
                   1524:             $output .= '</ul></p>';
1.1       raeburn  1525:         } else {
1.12      raeburn  1526:             $output .= '<p>'.&mt("For the following course/community requests an error occurred when updating the requestor's own requests record:").'<ul>';
1.2       raeburn  1527:             foreach my $cnum (@warn_approves,@warn_rejects) {
                   1528:                 my $showcourse;
1.23      raeburn  1529:                 if (ref($requesthash{$cnum.'_'.$queue})) {
                   1530:                     $showcourse = $requesthash{$cnum.'_'.$queue}{'description'};
1.2       raeburn  1531:                 } else {
                   1532:                     $showcourse = $cnum;
                   1533:                 }
                   1534:                 $output .= '<li>'.$showcourse.'</li>';
1.1       raeburn  1535:             }
                   1536:             $output .= '</ul></p>';
                   1537:         }
                   1538:     }
1.19      raeburn  1539:     if (@warn_dels) {
1.30      raeburn  1540:         if ($context eq 'requestauthor') {
                   1541:             $output .= '<p>'.&mt("For the following requests an error occurred when removing the request from the queue:").'<ul>';
                   1542:             foreach my $uname (@warn_dels) {
                   1543:                 my $userlink =
                   1544:                     &Apache::loncommon::aboutmewrapper(&Apache::loncommon::plainname($uname,$cdom),$uname,$cdom);
                   1545:                 $output .= '<li>'.$userlink.'</li>';
                   1546:             }
                   1547:             $output .= '</ul></p>';
1.43      raeburn  1548:         } elsif ($context eq 'requestusername') {
                   1549:             $output .= '<p>'.&mt("For the following requests an error occurred when removing the request from the queue:").'<ul>';
                   1550:             foreach my $item (@warn_dels) {
                   1551:                 my ($escuname) = split(/_/,$item);
                   1552:                 $output .= '<li>'.&unescape($escuname).'</li>';
                   1553:             }
                   1554:             $output .= '</ul></p>';            
1.30      raeburn  1555:         } else {
1.36      bisitz   1556:             $output .= '<p>'.&mt("For the following course/community requests an error occurred when removing requests from the pending queue:").'<ul>';
1.30      raeburn  1557:             foreach my $cnum (@warn_dels) {
                   1558:                 my $showcourse;
                   1559:                 if (ref($requesthash{$cnum.'_'.$queue})) {
                   1560:                     $showcourse = $requesthash{$cnum.'_'.$queue}{'description'};
                   1561:                 } else {
                   1562:                     $showcourse = $cnum;
                   1563:                 }
                   1564:                 $output .= '<li>'.$showcourse.'</li>';
1.19      raeburn  1565:             }
1.30      raeburn  1566:             $output .= '</ul></p>';
1.19      raeburn  1567:         }
                   1568:     }
1.1       raeburn  1569:     return $output;
                   1570: }
                   1571: 
1.26      raeburn  1572: sub course_portal_url {
                   1573:     my ($cnum,$cdom) = @_;
                   1574:     my $chome = &Apache::lonnet::homeserver($cnum,$cdom);
                   1575:     my $hostname = &Apache::lonnet::hostname($chome);
                   1576:     my $protocol = $Apache::lonnet::protocol{$chome};
                   1577:     $protocol = 'http' if ($protocol ne 'https');
                   1578:     my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
                   1579:     my $firsturl;
                   1580:     if ($domdefaults{'portal_def'}) {
                   1581:         $firsturl = $domdefaults{'portal_def'};
                   1582:     } else {
                   1583:         $firsturl = $protocol.'://'.$hostname;
                   1584:     }
                   1585:     return $firsturl;
                   1586: }
                   1587: 
1.1       raeburn  1588: sub get_student_counts {
                   1589:     my ($cdom,$cnum) = @_;
                   1590:     my (%idx,%stucounts);
                   1591:     my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cnum);
                   1592:     $idx{'type'} = &Apache::loncoursedata::CL_TYPE();
                   1593:     $idx{'status'} = &Apache::loncoursedata::CL_STATUS();
                   1594:     while (my ($student,$data) = each(%$classlist)) {
                   1595:         if (($data->[$idx{'status'}] eq 'Active') ||
                   1596:             ($data->[$idx{'status'}] eq 'Future')) {
                   1597:             if ($data->[$idx{'type'}] eq 'selfenroll') {
                   1598:                 $stucounts{'selfenroll'} ++;
                   1599:             }
                   1600:             $stucounts{'allstudents'} ++;
                   1601:         }
                   1602:     }
                   1603:     return (\%stucounts,\%idx,$classlist);
                   1604: }
                   1605: 
1.2       raeburn  1606: sub course_creation {
                   1607:     my ($dom,$cnum,$context,$details,$logmsg,$newusermsg,$addresult,$enrollcount,$output,
1.41      raeburn  1608:         $keysmsg,$domdefs,$longroles,$coderef,$customhash) =  @_;
1.2       raeburn  1609:     unless ((ref($details) eq 'HASH') && (ref($domdefs) eq 'HASH') && 
                   1610:             (ref($longroles) eq 'HASH')) {
1.52.2.2! raeburn  1611:         return ('error: Invalid request');
1.2       raeburn  1612:     }
                   1613:     my ($result,$ownername,$ownerdom);
                   1614:     my $crstype = $details->{'crstype'};
1.41      raeburn  1615:     my $coursedesc = $details->{'cdescr'};
1.47      raeburn  1616:     my $accessstart = $details->{'accessstart'};
                   1617:     my $accessend = $details->{'accessend'};
                   1618:     my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom);
1.40      raeburn  1619:     if (ref($domconfig{'requestcourses'}) eq 'HASH') {
                   1620:         if (ref($domconfig{'requestcourses'}{'uniquecode'}) eq 'HASH') {
                   1621:             if ($domconfig{'requestcourses'}{'uniquecode'}{$crstype}) {
                   1622:                 $details->{'uniquecode'} = 1;
                   1623:             }
                   1624:         }
                   1625:     }
1.2       raeburn  1626:     if ($context eq 'domain') {
                   1627:         $ownername = $details->{'owner'};
                   1628:         $ownerdom  = $details->{'domain'};
                   1629:     } else {
                   1630:         $ownername = $env{'user.name'};
                   1631:         $ownerdom  = $env{'user.domain'};
                   1632:     }
1.41      raeburn  1633:     my $fullname = &Apache::loncommon::plainname($ownername,$ownerdom);
1.2       raeburn  1634:     my $owneremail;
                   1635:     my %emails = &Apache::loncommon::getemails($ownername,$ownerdom);
                   1636:     foreach my $email ('permanentemail','critnotification','notification') {
                   1637:         $owneremail = $emails{$email};
                   1638:         last if ($owneremail ne '');
                   1639:     }
1.8       raeburn  1640:     my %reqdetails = &build_batchcreatehash($dom,$context,$details,$owneremail,$domdefs);
1.2       raeburn  1641:     my $cid = &LONCAPA::batchcreatecourse::build_course($dom,$cnum,'requestcourses',
1.22      raeburn  1642:                   \%reqdetails,$longroles,$logmsg,$newusermsg,$addresult,
1.39      raeburn  1643:                   $enrollcount,$output,$keysmsg,$ownerdom,$ownername,$cnum,$crstype,$coderef);
1.41      raeburn  1644:     my $postprocess;
1.2       raeburn  1645:     if ($cid eq "/$dom/$cnum") {
                   1646:         $result = 'created';
1.41      raeburn  1647:         my $code;
                   1648:         if (ref($coderef)) {
                   1649:             $code = $$coderef;
                   1650:         }
                   1651:         $postprocess = &Apache::lonnet::auto_crsreq_update($dom,$cnum,$crstype,$result,$ownername,
1.47      raeburn  1652:                                                            $ownerdom,$fullname,$coursedesc,$code,
                   1653:                                                            $accessstart,$accessend,$customhash);
1.2       raeburn  1654:     } else {
                   1655:         $result = 'error: '.$cid;
                   1656:     }
1.41      raeburn  1657:     return ($result,$postprocess);
1.2       raeburn  1658: }
                   1659: 
                   1660: sub build_batchcreatehash {
1.8       raeburn  1661:     my ($dom,$context,$details,$owneremail,$domdefs) = @_;
1.2       raeburn  1662:     my %batchhash;
1.39      raeburn  1663:     my @items = qw{owner domain coursehome clonecrs clonedom datemode dateshift enrollstart enrollend accessstart accessend sections crosslists users uniquecode};
1.2       raeburn  1664:     if ((ref($details) eq 'HASH') && (ref($domdefs) eq 'HASH')) {
1.17      raeburn  1665:         my $emailenc = &escape($owneremail);
1.2       raeburn  1666:         my $owner = $details->{'owner'}.':'.$details->{'domain'};
                   1667:         foreach my $item (@items) {
                   1668:             $batchhash{$item} = $details->{$item};
                   1669:         }
                   1670:         $batchhash{'title'} = $details->{'cdescr'};
                   1671:         $batchhash{'coursecode'} = $details->{'instcode'};
1.35      raeburn  1672:         if ($domdefs->{'officialcredits'} || $domdefs->{'unofficialcredits'}) {
                   1673:             $batchhash{'defaultcredits'} = $details->{'defaultcredits'};
                   1674:         }
1.2       raeburn  1675:         $batchhash{'emailenc'} = $emailenc;
                   1676:         $batchhash{'adds'} = $details->{'autoadds'};
                   1677:         $batchhash{'drops'} = $details->{'autodrops'};
                   1678:         $batchhash{'authtype'} = $domdefs->{'auth_def'};
                   1679:         $batchhash{'authparam'} = $domdefs->{'auth_arg_def'};
                   1680:         if ($details->{'crstype'} eq 'community') {
                   1681:             $batchhash{'crstype'} = 'Community';
                   1682:         } else {
1.41      raeburn  1683:             if ($details->{'crstype'} eq 'textbook') {
                   1684:                 if ($details->{'clonecrs'} && $details->{'clonedom'}) {
                   1685:                     my %clonedfrom = &Apache::lonnet::coursedescription($details->{'clonedom'}.'_'.$details->{'clonecrs'});
                   1686:                     $batchhash{'textbook'} = $clonedfrom{'description'};
                   1687:                 }
                   1688:             }
1.2       raeburn  1689:             $batchhash{'crstype'} = 'Course';
                   1690:         }
1.8       raeburn  1691:         my ($owner_firstname,$owner_lastname);
                   1692:         if ($context eq 'domain') {
                   1693:             my %userenv = &Apache::lonnet::userenvironment($details->{'domain'},
                   1694:                                                            $details->{'owner'},
                   1695:                                                            'firstname','lastname');
                   1696:             $owner_firstname = $userenv{'firstname'};
                   1697:             $owner_lastname = $userenv{'lastname'};
                   1698:         } else {
                   1699:             $owner_firstname = $env{'environment.firstname'};
                   1700:             $owner_lastname = $env{'environment.lastname'};
                   1701:         }
                   1702:         if (ref($details->{'personnel'}) eq 'HASH') {
                   1703:             %{$batchhash{'users'}} = %{$details->{'personnel'}};
                   1704:             if (ref($batchhash{'users'}) eq 'HASH') {  
                   1705:                 foreach my $userkey (keys(%{$batchhash{'users'}})) {
                   1706:                     if (ref($batchhash{'users'}{$userkey}) eq 'HASH') {
                   1707:                         if (ref($batchhash{'users'}{$userkey}{'roles'}) eq 'ARRAY') {
                   1708:                             foreach my $role (@{$batchhash{'users'}{$userkey}{'roles'}}) {
                   1709:                                 my $start = '';
                   1710:                                 my $end = '';
                   1711:                                 if ($role eq 'st') {
                   1712:                                     $start = $details->{'accessstart'};
                   1713:                                     $end = $details->{'accessend'};
                   1714:                                 }
                   1715:                                 $batchhash{'users'}{$userkey}{$role}{'start'} = $start;
                   1716:                                 $batchhash{'users'}{$userkey}{$role}{'end'} = $end;
                   1717:                             } 
                   1718:                         }
                   1719:                     }
                   1720:                 }
                   1721:             }
                   1722:         }
                   1723:         $batchhash{'users'}{$owner}{firstname} = $owner_firstname;
                   1724:         $batchhash{'users'}{$owner}{lastname} = $owner_lastname;
                   1725:         $batchhash{'users'}{$owner}{emailenc} = $emailenc;
                   1726:         $batchhash{'users'}{$owner}{owneremail} = $owneremail;
1.52.2.1  raeburn  1727:         $batchhash{'setcomment'} = 1;
1.2       raeburn  1728:     }
                   1729:     return %batchhash;
                   1730: }
                   1731: 
1.4       raeburn  1732: sub can_clone_course {
1.51      raeburn  1733:     my ($uname,$udom,$clonecrs,$clonedom,$crstype,$dom,$instcode) = @_;
1.4       raeburn  1734:     my $canclone;
1.11      raeburn  1735:     my $ccrole = 'cc';
1.12      raeburn  1736:     if ($crstype eq 'community') {
1.11      raeburn  1737:         $ccrole = 'co';
                   1738:     }
1.4       raeburn  1739:     my %roleshash = &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
1.11      raeburn  1740:                                                   [$ccrole],[$clonedom]);
                   1741:     if (exists($roleshash{$clonecrs.':'.$clonedom.':'.$ccrole})) {
1.4       raeburn  1742:         $canclone = 1;
                   1743:     } else {
1.51      raeburn  1744:         my %courseenv = &Apache::lonnet::userenvironment($clonedom,$clonecrs,
                   1745:                                                          ('cloners','internal.coursecode'));
1.4       raeburn  1746:         my $cloners = $courseenv{'cloners'};
1.51      raeburn  1747:         my $clonefromcode = $courseenv{'internal.coursecode'};
1.4       raeburn  1748:         if ($cloners ne '') {
                   1749:             my @cloneable = split(',',$cloners);
                   1750:             if (grep(/^\*$/,@cloneable)) {
                   1751:                 $canclone = 1;
1.51      raeburn  1752:             } elsif (grep(/^\*:\Q$udom\E$/,@cloneable)) {
                   1753:                 $canclone = 1;
                   1754:             } elsif (grep(/^\Q$uname\E:\Q$udom\E$/,@cloneable)) {
                   1755:                 $canclone = 1;
1.4       raeburn  1756:             }
1.51      raeburn  1757:             unless ($canclone) {
                   1758:                 if (($clonefromcode) && ($instcode) && ($clonedom eq $dom)) {
                   1759:                     my (%gotdomdefaults,%gotcodedefaults);
                   1760:                     foreach my $cloner (@cloneable) {
                   1761:                         if (($cloner ne '*') && ($cloner !~ /^\*\:$match_domain$/) &&
                   1762:                             ($cloner !~ /^$match_username\:$match_domain$/) && ($cloner ne '')) {
                   1763:                             if ($cloner =~ /\=/) {
                   1764:                                 my (%codedefaults,@code_order);
                   1765:                                 if (ref($gotcodedefaults{$clonedom}) eq 'HASH') {
                   1766:                                     if (ref($gotcodedefaults{$clonedom}{'defaults'}) eq 'HASH') {
                   1767:                                         %codedefaults = %{$gotcodedefaults{$clonedom}{'defaults'}};
                   1768:                                     }
                   1769:                                     if (ref($gotcodedefaults{$clonedom}{'order'}) eq 'ARRAY') {
                   1770:                                         @code_order = @{$gotcodedefaults{$dom}{'order'}};
                   1771:                                     }
                   1772:                                 } else {
                   1773:                                     &Apache::lonnet::auto_instcode_defaults($clonedom,
                   1774:                                                                             \%codedefaults,
                   1775:                                                                             \@code_order);
                   1776:                                     $gotcodedefaults{$clonedom}{'defaults'} = \%codedefaults;
                   1777:                                     $gotcodedefaults{$clonedom}{'order'} = \@code_order;
                   1778:                                 }
                   1779:                                 if (@code_order > 0) {
                   1780:                                     if (&Apache::lonnet::check_instcode_cloning(\%codedefaults,\@code_order,
                   1781:                                                                                 $cloner,$clonefromcode,$instcode)) {
                   1782:                                         $canclone = 1;
                   1783:                                         last; 
                   1784:                                     }
                   1785:                                 }
                   1786:                             }
                   1787:                         }
                   1788:                     }
                   1789:                 }
1.4       raeburn  1790:             }
1.51      raeburn  1791:         } else {
                   1792:             my %domdefs = &Apache::lonnet::get_domain_defaults($clonedom);
                   1793:             if ($domdefs{'canclone'}) {
                   1794:                 unless ($domdefs{'canclone'} eq 'none') {
                   1795:                     if ($domdefs{'canclone'} eq 'domain') {
                   1796:                         if ($udom eq $clonedom) {
                   1797:                             $canclone = 1;
                   1798:                         }
                   1799:                     } elsif (($clonefromcode) && ($instcode) &&
                   1800:                              ($clonedom eq $dom)) {
                   1801:                         if (&Apache::lonnet::default_instcode_cloning($clonedom,$domdefs{'canclone'},
                   1802:                                                                       $clonefromcode,$instcode)) {
                   1803:                             $canclone = 1;
                   1804:                         }
                   1805:                     }
                   1806:                 }
1.4       raeburn  1807:             }
                   1808:         }
1.18      raeburn  1809:         unless ($canclone) {
                   1810:             if (&Apache::lonnet::is_course_owner($clonedom,$clonecrs,$uname,$udom)) {
1.20      bisitz   1811:                 $canclone = 1;
1.18      raeburn  1812:             }
                   1813:         }
1.4       raeburn  1814:     }
                   1815:     return $canclone;
                   1816: }
                   1817: 
1.13      raeburn  1818: sub get_processtype {
1.30      raeburn  1819:     my ($context,$uname,$udom,$isadv,$dom,$crstype,$inststatuses,$domconfig) = @_;
1.13      raeburn  1820:     return unless ((ref($inststatuses) eq 'ARRAY') && (ref($domconfig) eq 'HASH'));
                   1821:     if ($uname eq '' || $udom eq '') {
                   1822:         $uname = $env{'user.name'};
                   1823:         $udom = $env{'user.domain'};
                   1824:         $isadv = $env{'user.adv'};
                   1825:     }
1.30      raeburn  1826:     my (%userenv,%settings,$val,@options,$envkey);
                   1827:     if ($context eq 'course') {
                   1828:         @options = ('autolimit','validate','approval');
                   1829:         $envkey = 'requestcourses.'.$crstype;
                   1830:         if (ref($domconfig->{'requestcourses'}) eq 'HASH') {
                   1831:             if (ref($domconfig->{'requestcourses'}->{$crstype}) eq 'HASH') {
                   1832:                 %settings = %{$domconfig->{'requestcourses'}->{$crstype}};
                   1833:             }
                   1834:         }
                   1835:     } else {
                   1836:         @options = ('automatic','approval');
                   1837:         $envkey = 'requestauthor';
                   1838:         if (ref($domconfig->{'requestauthor'}) eq 'HASH') { 
                   1839:             %settings = %{$domconfig->{'requestauthor'}};
                   1840:         }
                   1841:     }
                   1842:     if (($dom eq $udom) || ($context eq 'requestauthor')) {
1.13      raeburn  1843:         %userenv =
1.30      raeburn  1844:             &Apache::lonnet::userenvironment($udom,$uname,$envkey,'inststatus');
                   1845:         if ($userenv{$envkey}) {
                   1846:             $val = $userenv{$envkey};
1.13      raeburn  1847:             @{$inststatuses} = ('_custom_');
                   1848:         } else {
1.30      raeburn  1849:             my %alltasks;
                   1850:             if (($isadv) && ($settings{'_LC_adv'} ne '')) {
1.33      raeburn  1851:                 $val = $settings{'_LC_adv'};
1.30      raeburn  1852:                 @{$inststatuses} = ('_LC_adv_');
                   1853:             } else {
                   1854:                 if ($userenv{'inststatus'} ne '') {
                   1855:                     @{$inststatuses} = split(',',$userenv{'inststatus'});
                   1856:                 } else {
                   1857:                     @{$inststatuses} = ('default');
                   1858:                 }
                   1859:                 foreach my $status (@{$inststatuses}) {
                   1860:                     if (exists($settings{$status})) {
                   1861:                         my $value = $settings{$status};
                   1862:                         next unless ($value);
                   1863:                         unless (exists($alltasks{$value})) {
                   1864:                             if (ref($alltasks{$value}) eq 'ARRAY') {
                   1865:                                 unless(grep(/^\Q$status\E$/,@{$alltasks{$value}})) {
                   1866:                                     push(@{$alltasks{$value}},$status);
1.13      raeburn  1867:                                 }
1.30      raeburn  1868:                             } else {
                   1869:                                 @{$alltasks{$value}} = ($status);
1.13      raeburn  1870:                             }
                   1871:                         }
1.30      raeburn  1872:                     }
                   1873:                 }
                   1874:                 my $maxlimit = 0;
                   1875:                 if ($context eq 'course') {
                   1876:                     foreach my $key (sort(keys(%alltasks))) {
                   1877:                         if ($key =~ /^autolimit=(\d*)$/) {
                   1878:                             if ($1 eq '') {
                   1879:                                 $val ='autolimit=';
                   1880:                                 last;
                   1881:                             } elsif ($1 > $maxlimit) {
                   1882:                                 $maxlimit = $1;
1.13      raeburn  1883:                             }
                   1884:                         }
1.30      raeburn  1885:                     }
                   1886:                 }
                   1887:                 if (($context eq 'requestauthor') || (!$val)) {
                   1888:                     if ($context eq 'course' && $maxlimit) {
                   1889:                         $val = 'autolimit='.$maxlimit;
                   1890:                     } else {
                   1891:                         foreach my $option (@options) {
                   1892:                             if ($alltasks{$option}) {
                   1893:                                 $val = $option;
                   1894:                                 last;
1.13      raeburn  1895:                             }
                   1896:                         }
                   1897:                     }
                   1898:                 }
                   1899:             }
                   1900:         }
                   1901:     } else {
                   1902:         %userenv = &Apache::lonnet::userenvironment($udom,$uname,'reqcrsotherdom.'.$crstype);
                   1903:         if ($userenv{'reqcrsotherdom.'.$crstype}) {
                   1904:             my @doms = split(',',$userenv{'reqcrsotherdom.'.$crstype});
                   1905:             my $optregex = join('|',@options);
                   1906:             foreach my $item (@doms) {
                   1907:                 my ($extdom,$extopt) = split(':',$item);
                   1908:                 if ($extdom eq $dom) {
                   1909:                     if ($extopt =~ /^($optregex)(=?\d*)$/) {
                   1910:                         $val = $1.$2;
                   1911:                     }
                   1912:                     last;
                   1913:                 }
                   1914:             }
                   1915:             @{$inststatuses} = ('_external_');
                   1916:         }
                   1917:     }
                   1918:     return $val;
                   1919: }
                   1920: 
1.14      raeburn  1921: sub queued_selfenrollment {
                   1922:     my ($notitle) = @_;
                   1923:     my $output;
                   1924:     my %selfenrollrequests = &Apache::lonnet::dump('selfenrollrequests');
                   1925:     my %reqs_by_date;
                   1926:     foreach my $item (keys(%selfenrollrequests)) {
                   1927:         if (ref($selfenrollrequests{$item}) eq 'HASH') {
                   1928:             if ($selfenrollrequests{$item}{'status'} eq 'request') {
                   1929:                 if ($selfenrollrequests{$item}{'timestamp'}) {
                   1930:                     push(@{$reqs_by_date{$selfenrollrequests{$item}{'timestamp'}}},$item);
                   1931:                 }
                   1932:             }
                   1933:         }
                   1934:     }
                   1935:     if (keys(%reqs_by_date)) {
                   1936:         unless ($notitle) {
1.32      raeburn  1937:             $output .= '<br /><b>'.&mt('Enrollment requests pending Course Coordinator approval').'</b><br />';
1.14      raeburn  1938:         }
                   1939:         $output .= &Apache::loncommon::start_data_table().
                   1940:                    &Apache::loncommon::start_data_table_header_row().
                   1941:                    '<th>'.&mt('Date requested').'</th><th>'.&mt('Course title').'</th>'.
                   1942:                    '<th>'.&mt('User role').'</th><th>'.&mt('Section').'</th>'.
                   1943:                    &Apache::loncommon::end_data_table_header_row();
                   1944:         my @sorted = sort { $a <=> $b } (keys(%reqs_by_date));
                   1945:         foreach my $item (@sorted) {
                   1946:             if (ref($reqs_by_date{$item}) eq 'ARRAY') {
                   1947:                 foreach my $crs (@{$reqs_by_date{$item}}) {
                   1948:                     my %courseinfo = &Apache::lonnet::coursedescription($crs);
                   1949:                     my $usec = $selfenrollrequests{$crs}{'section'};
1.16      raeburn  1950:                     my $rolename = &Apache::lonnet::plaintext('st',$courseinfo{'type'},$crs);
1.14      raeburn  1951:                     if ($usec eq '') {
                   1952:                         $usec = &mt('No section');
                   1953:                     }
                   1954:                     $output .= &Apache::loncommon::start_data_table_row().
                   1955:                                '<td>'.&Apache::lonlocal::locallocaltime($item).'</td>'.
                   1956:                                '<td>'.$courseinfo{'description'}.'</td>'.
                   1957:                                '<td>'.$rolename.'</td><td>'.$usec.'</td>'.
                   1958:                                &Apache::loncommon::end_data_table_row();
                   1959:                 }
                   1960:             }
                   1961:         }
                   1962:         $output .= &Apache::loncommon::end_data_table();
                   1963:     }
                   1964:     return $output;
                   1965: }
                   1966: 
1.19      raeburn  1967: sub update_coursereq_status {
1.26      raeburn  1968:     my ($reqhash,$dom,$cnum,$reqstatus,$context,$udom,$uname) = @_;
1.19      raeburn  1969:     my ($storeresult,$statusresult,$output);
                   1970:     my $requestkey = $dom.'_'.$cnum;
                   1971:     if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
                   1972:         $storeresult = &Apache::lonnet::store_userdata($reqhash,$requestkey,
1.26      raeburn  1973:                                                        'courserequests',$udom,$uname);
1.19      raeburn  1974:         if ($storeresult eq 'ok') {
                   1975:             my %status = (
                   1976:                              'status:'.$dom.':'.$cnum => $reqstatus,
                   1977:                          );
1.26      raeburn  1978:             $statusresult = &Apache::lonnet::put('courserequests',\%status,$udom,$uname);
1.19      raeburn  1979:         }
                   1980:     } else {
                   1981:         $storeresult = 'error: invalid requestkey format';
                   1982:     }
                   1983:     if ($storeresult ne 'ok') {
                   1984:         $output = &mt('An error occurred saving a record of the details of your request: [_1].',$storeresult);
                   1985:         if ($context eq 'domain') {
                   1986:             $output .= "\n";  
                   1987:         } else {
                   1988:             $output =  '<span class="LC_warning">'.$output.'</span><br />';
                   1989:         }
1.26      raeburn  1990:         &Apache::lonnet::logthis("Error saving course request - $requestkey for $uname:$udom - $storeresult");
1.19      raeburn  1991:     } elsif ($statusresult ne 'ok') {
                   1992:         $output = &mt('An error occurred saving a record of the status of your request: [_1].',$statusresult);
                   1993:         if ($context eq 'domain') {
                   1994:             $output .= "\n";
                   1995:         } else {
                   1996:             $output = '<span class="LC_warning">'.$output.'</span><br />';
                   1997:         }
1.26      raeburn  1998:         &Apache::lonnet::logthis("Error saving course request status for $requestkey (for $uname:$udom) - $statusresult");
1.19      raeburn  1999:     }
                   2000:     return ($storeresult,$output);
                   2001: }
                   2002: 
1.23      raeburn  2003: sub process_official_reqs {
1.26      raeburn  2004:     my ($context,$dom,$dcname,$dcdom) = @_;
1.23      raeburn  2005:     my $reqsnamespace = 'courserequestqueue';
                   2006:     my %requesthash =
1.24      raeburn  2007:         &Apache::lonnet::dump_dom($reqsnamespace,$dom,'_pending');
1.23      raeburn  2008:     my (%newcids,%longroles,%stillpending);
                   2009:     my @courseroles = ('cc','in','ta','ep','ad','st');
                   2010:     foreach my $role (@courseroles) {
                   2011:         $longroles{$role}=&Apache::lonnet::plaintext($role);
                   2012:     }
                   2013:     my %domdefs = &Apache::lonnet::get_domain_defaults($dom);
                   2014:     my ($output,$linefeed);
                   2015:     if ($context eq 'auto') {
                   2016:         $linefeed = "\n";
                   2017:     } else {
                   2018:         $linefeed = '<br />'."\n";
                   2019:     }
                   2020:     foreach my $key (keys(%requesthash)) {
                   2021:         my ($cnum,$status) = split('_',$key);
                   2022:         next if (&Apache::lonnet::homeserver($cnum,$dom) ne 'no_host');
                   2023:         if (ref($requesthash{$key}) eq 'HASH') {
                   2024:             my $ownername = $requesthash{$key}{'ownername'};
                   2025:             my $ownerdom = $requesthash{$key}{'ownerdom'};
                   2026:             next if (&Apache::lonnet::homeserver($ownername,$ownerdom) eq 'no_host');
                   2027:             my $inststatus;
                   2028:             my %userenv =
                   2029:                 &Apache::lonnet::get('environment',['inststatus'],
                   2030:                                      $ownerdom,$ownername);
                   2031:             my ($tmp) = keys(%userenv);
                   2032:             if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
                   2033:                 $inststatus = $userenv{'inststatus'};
                   2034:             } else {
                   2035:                 undef(%userenv);
                   2036:             }
                   2037:             my $reqkey = $dom.'_'.$cnum;
                   2038:             my %history = &Apache::lonnet::restore($reqkey,'courserequests',
                   2039:                                                    $ownerdom,$ownername);
                   2040:             if (ref($history{'details'}) eq 'HASH') {
                   2041:                 my $instcode = $history{'details'}{'instcode'};
                   2042:                 my $crstype = $history{'details'}{'crstype'};
                   2043:                 my $reqtime = $history{'details'}{'reqtime'};
                   2044:                 my $cdescr = $history{'details'}{'cdescr'};
                   2045:                 my @currsec;
                   2046:                 my $sections = $history{'details'}{'sections'};
                   2047:                 if (ref($sections) eq 'HASH') {
                   2048:                     foreach my $i (sort(keys(%{$sections}))) {
                   2049:                         if (ref($sections->{$i}) eq 'HASH') {
                   2050:                             my $sec = $sections->{$i}{'inst'};
                   2051:                             if (!grep(/^\Q$sec\E$/,@currsec)) {
                   2052:                                 push(@currsec,$sec);
                   2053:                             }
                   2054:                         }
                   2055:                     }
                   2056:                 }
                   2057:                 my $instseclist = join(',',@currsec);
                   2058:                 my ($validationchk,$disposition,$reqstatus,$message,
                   2059:                     $validation,$validationerror);
                   2060:                 $validationchk =
                   2061:                     &Apache::lonnet::auto_courserequest_validation($dom,
                   2062:                         $ownername.':'.$ownerdom,$crstype,$inststatus,
                   2063:                         $instcode,$instseclist);
                   2064:                 if ($validationchk =~ /:/) {
                   2065:                     ($validation,$message) = split(':',$validationchk);
                   2066:                 } else {
                   2067:                     $validation = $validationchk;
                   2068:                 }
                   2069:                 if ($validation =~ /^error(.*)$/) {
                   2070:                     $disposition = 'approval';
                   2071:                     $validationerror = $1;
                   2072:                 } else {
                   2073:                     $disposition = $validation;
                   2074:                 }
                   2075:                 $reqstatus = $disposition;
                   2076:                 if ($disposition eq 'process') {
1.39      raeburn  2077:                     my ($logmsg,$newusermsg,$addresult,$enrollcount,$response,$keysmsg,$code);
1.41      raeburn  2078:                     my %customitems;
                   2079:                     my $fullname = &Apache::loncommon::plainname($ownername,$ownerdom);
                   2080:                     my $inprocess = &Apache::lonnet::auto_crsreq_update($dom,$cnum,$crstype,'process',$ownername,
                   2081:                                                                         $ownerdom,$fullname,$cdescr);
                   2082:                     if (ref($inprocess) eq 'HASH') {
                   2083:                         foreach my $key (keys(%{$inprocess})) {
                   2084:                             if (exists($history{'details'}{$key})) {
                   2085:                                 $customitems{$key} = $history{'details'}{$key};
                   2086:                             }
                   2087:                         }
                   2088:                     }
1.50      raeburn  2089:                     if ($history{'details'}{'clonecrs'}) {
                   2090:                         $customitems{'_LC_clonefrom'} = $history{'details'}{'clonedom'}.'_'.$history{'details'}{'clonecrs'};
                   2091:                     }
1.41      raeburn  2092:                     my ($result,$postprocess) = 
                   2093:                         &course_creation($dom,$cnum,'domain',$history{'details'},\$logmsg,\$newusermsg,\$addresult,
                   2094:                                          \$enrollcount,\$response,\$keysmsg,\%domdefs,\%longroles,\$code,\%customitems);
1.23      raeburn  2095:                     if ($result eq 'created') {
                   2096:                         $disposition = 'created';
                   2097:                         $reqstatus = 'created';
1.26      raeburn  2098:                         my $cid = $dom.'_'.$cnum;
                   2099:                         push(@{$newcids{$instcode}},$cid);
                   2100:                         if ($dcname && $dcdom) {
                   2101:                             my $firsturl = &course_portal_url($cnum,$dom);
                   2102:                             my $beneficiary = 'pendingrequestor';
                   2103:                             my $now = time;
                   2104:                             my $owner = $ownername.':'.$ownerdom;
                   2105:                             my $approvedmsg =
                   2106:                                 [{
1.27      raeburn  2107:                                     mt => 'Your requested course: [_1], (queued pending validation) has now been created.',
                   2108:                                     args => [$cdescr],
1.26      raeburn  2109:                                  },
                   2110:                                  {
1.28      raeburn  2111:                                     mt   => 'Visit [_1] to log-in and access the course.',
1.26      raeburn  2112:                                     args => [$firsturl],
1.27      raeburn  2113:                                  },
                   2114:                                  {
                   2115:                                     mt => 'If currently logged-in to LON-CAPA, log-out and log-in again to select your new course role.'
1.26      raeburn  2116:                                  }];
                   2117:                             my $sender = $dcname.':'.$dcdom;
1.41      raeburn  2118:                             if (ref($postprocess) eq 'HASH') {
                   2119:                                 if (ref($postprocess->{'createdmsg'}) eq 'ARRAY') {
                   2120:                                     foreach my $item (@{$postprocess->{'createdmsg'}}) {
                   2121:                                         if (ref($item) eq 'HASH') {
                   2122:                                              if ($item->{'mt'} ne '') {
                   2123:                                                  push(@{$approvedmsg},$item);
                   2124:                                              }
                   2125:                                         }
                   2126:                                     }
                   2127:                                 }
1.48      raeburn  2128:                                 if (ref($postprocess->{'createdactions'}) eq 'HASH') {
                   2129:                                     if (ref($postprocess->{'createdactions'}{'environment'}) eq 'HASH') {
                   2130:                                         &postprocess_crsenv($dom,$cnum,$postprocess->{'createdactions'}{'environment'});
                   2131:                                     }
                   2132:                                 }
1.41      raeburn  2133:                             }
1.26      raeburn  2134:                             &send_selfserve_notification($owner,$approvedmsg,
                   2135:                                                          $cid,$cdescr,$now,
                   2136:                                                          $beneficiary,$sender,
                   2137:                                                          undef,undef,$crstype);
                   2138:                         }
1.23      raeburn  2139:                     }
                   2140:                 } elsif ($disposition eq 'rejected') {
                   2141:                     $output .= &mt('Queued course request for [_1] submitted by [_2] with status [_3] rejected when validating.',$instcode,$ownername.':'.$ownerdom,$inststatus).$linefeed;
                   2142:                 } elsif ($disposition eq 'approval') {
                   2143:                     $output .= &mt('Queued course request for [_1] submitted by [_2] with status [_3] switched to "approval by DC" because of validation error: [_4].',$instcode,$ownername.':'.$ownerdom,$inststatus,$validationerror).$linefeed;
                   2144: 
                   2145:                     my $requestid = $cnum.'_'.$disposition;
                   2146:                     my $request = {
                   2147:                             $requestid => {
                   2148:                                             timestamp   => $reqtime,
                   2149:                                             crstype     => $crstype,
                   2150:                                             ownername   => $ownername,
                   2151:                                             ownerdom    => $ownerdom,
                   2152:                                             description => $cdescr,
                   2153:                                           },
                   2154:                           };
                   2155:                     my $putresult = &Apache::lonnet::newput_dom('courserequestqueue',$request,$dom);
                   2156:                     unless ($putresult eq 'ok') {
                   2157:                         $output .= &mt("An error occurred saving the modified course request for [_1] submitted by [_2] in the domain's courserequestqueue.db.",$instcode,$ownername.':'.$ownerdom).$linefeed;
                   2158:                     }
                   2159:                 } elsif ($disposition eq 'pending') {
                   2160:                     my $instcode = $requesthash{$key}{'instcode'};
                   2161:                     my $description = $requesthash{$key}{'description'};
                   2162:                     my $timestamp = $requesthash{$key}{'timestamp'};
                   2163:                     my $entry = $cnum.':'.$ownername.':'.$ownerdom.':'.
                   2164:                                 $instcode.':'.$description;
                   2165:                     if (ref($stillpending{$timestamp}) eq 'ARRAY') {
                   2166:                         push(@{$stillpending{$timestamp}},$entry);
                   2167:                     } else {
                   2168:                         $stillpending{$timestamp} = [$entry];
                   2169:                     }
                   2170:                 }
                   2171:                 unless ($disposition eq 'pending') {
                   2172:                     my ($statusresult,$output) =
                   2173:                         &update_coursereq_status(\%requesthash,$dom,$cnum,
1.26      raeburn  2174:                                                  $reqstatus,'domain',$ownerdom,
                   2175:                                                  $ownername);
1.23      raeburn  2176:                     unless (&Apache::lonnet::del_dom($reqsnamespace,[$cnum.'_pending'],$dom) eq 'ok') {
                   2177:                         $output .= &mt('An error occurred when removing the request for [_1] submitted by [_2] from the pending queue.',$instcode,$ownername.':'.$ownerdom).$linefeed;
                   2178:                     }
                   2179:                 }
                   2180:             }
                   2181:         }
                   2182:     }
                   2183:     foreach my $key (sort(keys(%newcids))) {
                   2184:         if (ref($newcids{$key}) eq 'ARRAY') {
                   2185:             $output .= "created course from queued request: $key - ".join(', ',@{$newcids{$key}}).$linefeed;
                   2186:             my $newcourse = &LONCAPA::escape($key.':'.$newcids{$key});
                   2187:         }
                   2188:     }
                   2189:     unless ($context eq 'auto') {
                   2190:         if (keys(%stillpending) > 0) {
                   2191:             $output .= '<form method="post" name="changequeue" action="/adm/createcourse" />'."\n".
                   2192:                        '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n".
                   2193:                        '<input type="hidden" name="phase" value="requestchange" />'.
                   2194:                        '<p>'.&mt('For the following requests, the requestor could [_1]not[_2] be validated as official course personnel, so the request remains in the pending queue.','<b>','</b>').'<br />'.&mt('Requests may be left in the queue, or you can manually approve or reject them.').'</p>'.
                   2195:                        &build_queue_display($dom,'stillpending',\%stillpending).
                   2196:                        '<br /><input type="hidden" name="queue" value="pending" />'."\n".
                   2197:                        '<input type="submit" name="processqueue" value="'.&mt('Save').'" />'.
                   2198:                        '</form>';
                   2199:         }
                   2200:     }
                   2201:     return $output;
                   2202: }
                   2203: 
1.48      raeburn  2204: sub postprocess_crsenv {
                   2205:     my ($dom,$cnum,$postprocessenv) = @_;
                   2206:     if (ref($postprocessenv) eq 'HASH') {    
                   2207:         my $cid = $dom.'_'.$cnum;
                   2208:         my %settablecrsenv = (
                   2209:                               'internal.selfenroll_types'        => 1,
                   2210:                               'internal.selfenroll_registered'   => 1,
                   2211:                               'internal.selfenroll_section'      => 1,
                   2212:                               'internal.selfenroll_start_access' => 1,
                   2213:                               'internal.selfenroll_end_access'   => 1,
                   2214:                               'internal.selfenroll_limit'        => 1,
                   2215:                               'internal.selfenroll_cap'          => 1,
                   2216:                               'internal.selfenroll_approval'     => 1,
                   2217:                               'internal.selfenroll_notifylist'   => 1,
                   2218:                              );
                   2219:         my %needcrsidput = (
                   2220:                               'internal.selfenroll_types'      => 1,
                   2221:                               'internal.selfenroll_start_date' => 1,
                   2222:                               'internal. selfenroll_end_date'  => 1,
                   2223:                            );
                   2224:         my (@needupdate,%newcrsenv);
                   2225:         foreach my $key (keys(%{$postprocessenv})) { 
                   2226:             if ($settablecrsenv{$key}) {
                   2227:                 $newcrsenv{$key} = $postprocessenv->{$key};
                   2228:                 if ($needcrsidput{$key}) {
                   2229:                     push(@needupdate,$key); 
                   2230:                 }
                   2231:             }
                   2232:             if (keys(%newcrsenv)) {
                   2233:                 my $putresult = &Apache::lonnet::put('environment',\%newcrsenv,$dom,$cnum);
                   2234:                 if ($putresult eq 'ok') {
                   2235:                     if (@needupdate) {
                   2236:                         my %crsinfo =
                   2237:                             &Apache::lonnet::courseiddump($dom,'.',1,'.','.',$cnum,undef,undef,'.');
                   2238:                         if (ref($crsinfo{$cid}) eq 'HASH') {
                   2239:                             foreach my $key (@needupdate) {
                   2240:                                 $crsinfo{$cid}{$key} = $newcrsenv{$key};
                   2241:                             }
                   2242:                             my $chome = &Apache::lonnet::homeserver($cnum,$dom);
                   2243:                             &Apache::lonnet::courseidput($dom,\%crsinfo,$chome,'notime');
                   2244:                         }
                   2245:                     }
                   2246:                 }
                   2247:             }
                   2248:         }
                   2249:     }
                   2250:     return;
                   2251: }
                   2252: 
                   2253: 
1.45      raeburn  2254: sub requestcourses_validation_types {
                   2255:     my @items = ('url','fields','button','markup');
                   2256:     my %names =  &Apache::lonlocal::texthash (
                   2257:             url      => 'Web address of validation server/script',
                   2258:             fields   => 'Form fields to send to validator',
                   2259:             button   => 'Text for validation button',
                   2260:             markup   => 'Validation description (HTML)',
                   2261:     );
                   2262:     my @fields = ('owner','course','coursetype','description');
                   2263:     return (\@items,\%names,\@fields);
                   2264: }
                   2265: 
1.31      raeburn  2266: sub is_active_author {
                   2267:     if ($env{'user.role.au./'.$env{'user.domain'}.'/'} =~ /^(\d*)\.(\d*)$/) {
                   2268:         if ((!$1 || $1 < time) &&
                   2269:             (!$2 || $2 > time)) {
                   2270:             return 1;
                   2271:         }
                   2272:     }
                   2273: }
                   2274: 
                   2275: sub author_prompt {
                   2276:     my ($is_active_author,$offer_author);
                   2277:     if ($env{'environment.canrequest.author'}) {
                   2278:         unless (&is_active_author()) {
1.32      raeburn  2279:             unless (&reqauthor_check() =~ /^approval:\d+$/) {
                   2280:                 $offer_author = 1;
1.31      raeburn  2281:             }
                   2282:         }
                   2283:     }
                   2284:     return $offer_author;
                   2285: }
                   2286: 
                   2287: sub reqauthor_check {
                   2288:     my $queued = $env{'environment.requestauthorqueued'};
                   2289:     my %reqauthor = &Apache::lonnet::get('requestauthor',['author_status','author'],
                   2290:                                          $env{'user.domain'},$env{'user.name'});
                   2291:     my $reqstatus = $reqauthor{'author_status'};
                   2292:     if (($reqstatus eq '' && $queued ne '') ||
                   2293:         ($env{'environment.requestauthorqueued'} !~ /^\Q$reqstatus\E/)) {
                   2294:         if (ref($reqauthor{'author'}) eq 'HASH') {
                   2295:             $queued = $reqstatus.':'.$reqauthor{'author'}{'timestamp'};
                   2296:         } else {
                   2297:             undef($queued);
                   2298:         }
                   2299:         &Apache::lonnet::appenv({'environment.requestauthorqueued' => $queued});
                   2300:     }
                   2301:     return $queued;
                   2302: }
                   2303: 
                   2304: sub process_reqauthor {
                   2305:     my ($dispositionref,$updateref) = @_;
                   2306:     if (&is_active_author()) {
                   2307:         return '<span class="LC_warning">'.
1.42      bisitz   2308:                 &mt('An Authoring Space has already been assigned to you.').'<br />'.
1.31      raeburn  2309:                 &mt('Please select the Author role from your [_1]roles page[_2].','<a href="/adm/roles">',
                   2310:                 '</a>').'</span>';
                   2311:     }
                   2312:     unless ($env{'environment.canrequest.author'}) {
                   2313:         return '<span class="LC_warning">'.
1.42      bisitz   2314:                 &mt('You do not currently have rights to request an Authoring Space.').'<br />'.
1.37      raeburn  2315:                 &mt('Please contact the [_1]helpdesk[_2] for assistance.','<a href="/adm/helpdesk">',
1.31      raeburn  2316:                 '</a>').'</span>';
                   2317:     }
                   2318:     my $queued = &reqauthor_check();
                   2319:     if ($queued =~ /^approval:(\d+)$/) {
                   2320:         my $timestamp = $1;
                   2321:         return '<span class="LC_info">'.
1.42      bisitz   2322:                &mt('A request for Authoring Space submitted on [_1] is awaiting approval',
1.31      raeburn  2323:                &Apache::lonlocal::locallocaltime($timestamp)).
                   2324:                '</span>';
                   2325:     } elsif ($queued =~ /^approved:(\d+)$/) {
                   2326:         my $timestamp = $1;   
                   2327:         my %roleshash = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},'userroles',
                   2328:                                                       ['active'],['au'],[$env{'user.domain'}]);
                   2329:         if (keys(%roleshash) > 0) {
                   2330:             return '<span class="LC_info">'.
1.42      bisitz   2331:                    &mt('A request for Authoring Space submitted on [_1] has been approved.',
1.31      raeburn  2332:                    &Apache::lonlocal::locallocaltime($timestamp)).
                   2333:                    '</span>';
                   2334:         }
                   2335:     }
                   2336:     my ($output,@inststatuses,%domconfig);
                   2337:     %domconfig = &Apache::lonnet::get_dom('configuration',['requestauthor'],
                   2338:                                           $env{'user.domain'});
                   2339:     my $val = &get_processtype('requestauthor',$env{'user.name'},$env{'user.domain'},
                   2340:                                $env{'user.adv'},$env{'user.domain'},undef,
                   2341:                                \@inststatuses,\%domconfig);
                   2342:     my $now = time;
                   2343:     if ($val eq 'automatic') {
                   2344:         my $start = $now-1;
                   2345:         if (&Apache::lonnet::assignrole($env{'user.domain'},$env{'user.name'},'/'.$env{'user.domain'}.'/',
                   2346:                                         'au',undef,$start,undef,undef,'requestauthor') eq 'ok') {
                   2347:             $output = '<span class="LC_info">'.
1.42      bisitz   2348:                       &mt('Access to Authoring Space has been activated').'</span><br />';
1.31      raeburn  2349:                       &Apache::lonroles::update_session_roles();
                   2350:             &Apache::lonnet::appenv({'user.update.time'  => $now});
                   2351:             if (ref($updateref)) {
                   2352:                 $$updateref = $now;
                   2353:             }
                   2354:             if (ref($dispositionref)) {
                   2355:                 $$dispositionref = 'created';
                   2356:             }
                   2357:         } else {
                   2358:             $output = '<span class="LC_info">'.
1.42      bisitz   2359:                       &mt('An error occurred while activating your access to Authoring Space');
1.31      raeburn  2360:         }
                   2361:     } elsif ($val eq 'approval') {
                   2362:         my $domconfiguser = &Apache::lonnet::get_domainconfiguser($env{'user.domain'});
                   2363:         if (&Apache::lonnet::put('requestauthorqueue',{ $env{'user.name'}.'_'.$val => $now },
                   2364:                                  $env{'user.domain'},$domconfiguser) eq 'ok') {
                   2365:             my %userrequest = (
                   2366:                 author => {
                   2367:                             timestamp   => $now,
                   2368:                             status      => $val,
                   2369:                           },
                   2370:                 author_status => $val,
                   2371:             );
                   2372:             my $req_notifylist;
                   2373:             if (ref($domconfig{'requestauthor'}) eq 'HASH') {
                   2374:                 if (ref($domconfig{'requestauthor'}{'notify'}) eq 'HASH') {
                   2375:                     my $req_notifylist = $domconfig{'requestauthor'}{'notify'}{'approval'};
                   2376:                     if ($req_notifylist) {
                   2377:                         my $fullname = &Apache::loncommon::plainname($env{'user.name'},
                   2378:                                                                      $env{'user.domain'});
                   2379:                         my $sender = $env{'user.name'}.':'.$env{'user.domain'};
                   2380:                         my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description');
                   2381:                         &send_selfserve_notification($req_notifylist,
                   2382:                                                      "$fullname ($env{'user.name'}:$env{'user.domain'})",
                   2383:                                                      undef,$domdesc,$now,'authorreq',$sender);
                   2384:                     }
                   2385:                 }
                   2386:             }
                   2387:             my $userresult =
                   2388:                 &Apache::lonnet::put('requestauthor',\%userrequest,$env{'user.domain'},$env{'user.name'});
                   2389:             $output = '<span class="LC_info">'.
1.42      bisitz   2390:                       &mt('Your request for Authoring Space has been submitted for approval.').
1.31      raeburn  2391:                       '</span>';
                   2392:             &Apache::lonnet::appenv({'environment.requestauthorqueued' => $val.':'.$now});
                   2393:         } else {
                   2394:             $output = '<span class="LC_info">'.
1.42      bisitz   2395:                       &mt('An error occurred saving your request for Authoring Space.').
1.31      raeburn  2396:                       '</span>';
                   2397:         }
                   2398:     }
                   2399:     return $output;
                   2400: }
                   2401: 
1.1       raeburn  2402: 1;

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.