Annotation of loncom/interface/loncreatecourse.pm, revision 1.92

1.65      raeburn     1: # The LearningOnline Network
1.1       www         2: # Create a course
1.5       albertel    3: #
1.92    ! www         4: # $Id: loncreatecourse.pm,v 1.91 2006/06/03 21:05:04 albertel Exp $
1.5       albertel    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: #
1.48      www        28: ###
                     29: 
1.1       www        30: package Apache::loncreatecourse;
                     31: 
                     32: use strict;
                     33: use Apache::Constants qw(:common :http);
                     34: use Apache::lonnet;
1.12      www        35: use Apache::loncommon;
1.13      www        36: use Apache::lonratedt;
                     37: use Apache::londocs;
1.38      www        38: use Apache::lonlocal;
1.41      raeburn    39: use Apache::londropadd;
1.90      raeburn    40: use LONCAPA::batchcreatecourse;
1.44      raeburn    41: use lib '/home/httpd/lib/perl';
1.89      www        42: use LONCAPA;
1.28      www        43: 
                     44: # ================================================ Get course directory listing
                     45: 
1.62      www        46: my @output=();
                     47: 
1.28      www        48: sub crsdirlist {
                     49:     my ($courseid,$which)=@_;
1.62      www        50:     @output=();
                     51:     return &innercrsdirlist($courseid,$which);
                     52: }
                     53: 
                     54: sub innercrsdirlist {
                     55:     my ($courseid,$which,$path)=@_;
                     56:     my $dirptr=16384;
1.63      www        57:     unless ($which) { $which=''; } else { $which.='/'; }
                     58:     unless ($path)  { $path=''; } else { $path.='/'; }
1.28      www        59:     my %crsdata=&Apache::lonnet::coursedescription($courseid);
                     60:     my @listing=&Apache::lonnet::dirlist
                     61: 	($which,$crsdata{'domain'},$crsdata{'num'},
1.89      www        62: 	 &propath($crsdata{'domain'},$crsdata{'num'}));
1.28      www        63:     foreach (@listing) {
                     64: 	unless ($_=~/^\./) {
1.62      www        65: 	    my @unpackline = split (/\&/,$_);
                     66: 	    if ($unpackline[3]&$dirptr) {
                     67: # is a directory, recurse
1.63      www        68: 		&innercrsdirlist($courseid,$which.$unpackline[0],
                     69: 				            $path.$unpackline[0]);
1.62      www        70: 	    } else { 
                     71: # is a file, put into output
1.63      www        72: 		push (@output,$path.$unpackline[0]);
1.62      www        73: 	    }
1.28      www        74: 	}
                     75:     }
                     76:     return @output;
1.29      www        77: }
                     78: 
                     79: # ============================================================= Read a userfile
                     80: 
                     81: sub readfile {
                     82:     my ($courseid,$which)=@_;
                     83:     my %crsdata=&Apache::lonnet::coursedescription($courseid);
                     84:     return &Apache::lonnet::getfile('/uploaded/'.$crsdata{'domain'}.'/'.
                     85: 				    $crsdata{'num'}.'/'.$which);
                     86: }
                     87: 
                     88: # ============================================================ Write a userfile
                     89: 
                     90: sub writefile {
1.78      albertel   91:     (my $courseid, my $which,$env{'form.output'})=@_;
1.29      www        92:     my %crsdata=&Apache::lonnet::coursedescription($courseid);
                     93:     return &Apache::lonnet::finishuserfileupload(
                     94: 					  $crsdata{'num'},$crsdata{'domain'},
                     95: 					  'output',$which);
                     96: }
                     97: 
1.36      www        98: # ===================================================================== Rewrite
                     99: 
                    100: sub rewritefile {
                    101:     my ($contents,%rewritehash)=@_;
                    102:     foreach (keys %rewritehash) {
                    103: 	my $pattern=$_;
                    104: 	$pattern=~s/(\W)/\\$1/gs;
                    105: 	my $new=$rewritehash{$_};
                    106: 	$contents=~s/$pattern/$new/gs;
                    107:     }
                    108:     return $contents;
                    109: }
                    110: 
1.29      www       111: # ============================================================= Copy a userfile
                    112: 
                    113: sub copyfile {
                    114:     my ($origcrsid,$newcrsid,$which)=@_;
1.36      www       115:     unless ($which=~/\.sequence$/) {
                    116: 	return &writefile($newcrsid,$which,
                    117: 		      &readfile($origcrsid,$which));
                    118:     } else {
                    119: 	my %origcrsdata=&Apache::lonnet::coursedescription($origcrsid);
                    120: 	my %newcrsdata= &Apache::lonnet::coursedescription($newcrsid);
                    121: 	return &writefile($newcrsid,$which,
                    122: 		 &rewritefile(
                    123:                      &readfile($origcrsid,$which),
                    124: 	    (
                    125:        '/uploaded/'.$origcrsdata{'domain'}.'/'.$origcrsdata{'num'}.'/'
1.66      albertel  126:     => '/uploaded/'. $newcrsdata{'domain'}.'/'. $newcrsdata{'num'}.'/',
                    127:        '/public/'.$origcrsdata{'domain'}.'/'.$origcrsdata{'num'}.'/'
                    128:     => '/public/'. $newcrsdata{'domain'}.'/'. $newcrsdata{'num'}.'/'
1.36      www       129:             )));
                    130:     }
1.30      www       131: }
                    132: 
                    133: # =============================================================== Copy a dbfile
                    134: 
                    135: sub copydb {
                    136:     my ($origcrsid,$newcrsid,$which)=@_;
                    137:     $which=~s/\.db$//;
                    138:     my %origcrsdata=&Apache::lonnet::coursedescription($origcrsid);
                    139:     my %newcrsdata= &Apache::lonnet::coursedescription($newcrsid);
                    140:     my %data=&Apache::lonnet::dump
                    141: 	($which,$origcrsdata{'domain'},$origcrsdata{'num'});
1.72      albertel  142:     foreach my $key (keys(%data)) {
                    143: 	if ($key=~/^internal./) { delete($data{$key}); }
                    144:     }
1.30      www       145:     return &Apache::lonnet::put
                    146: 	($which,\%data,$newcrsdata{'domain'},$newcrsdata{'num'});
                    147: }
                    148: 
1.35      www       149: # ========================================================== Copy resourcesdata
                    150: 
                    151: sub copyresourcedb {
                    152:     my ($origcrsid,$newcrsid)=@_;
                    153:     my %origcrsdata=&Apache::lonnet::coursedescription($origcrsid);
                    154:     my %newcrsdata= &Apache::lonnet::coursedescription($newcrsid);
                    155:     my %data=&Apache::lonnet::dump
                    156: 	('resourcedata',$origcrsdata{'domain'},$origcrsdata{'num'});
                    157:     $origcrsid=~s/^\///;
                    158:     $origcrsid=~s/\//\_/;
                    159:     $newcrsid=~s/^\///;
                    160:     $newcrsid=~s/\//\_/;
                    161:     my %newdata=();
                    162:     undef %newdata;
                    163:     my $startdate=$data{$origcrsid.'.0.opendate'};
1.85      albertel  164:     if (!$startdate) {
                    165: 	# now global start date for assements try the enrollment start
                    166: 	my %start=&Apache::lonnet::get('environment',
                    167: 				   ['default_enrollment_start_date'],
                    168: 				   $origcrsdata{'domain'},$origcrsdata{'num'});
                    169: 
                    170: 	$startdate = $start{'default_enrollment_start_date'};
                    171:     }
1.35      www       172:     my $today=time;
                    173:     my $delta=0;
                    174:     if ($startdate) {
                    175: 	my $oneday=60*60*24;
                    176: 	$delta=$today-$startdate;
                    177: 	$delta=int($delta/$oneday)*$oneday;
                    178:     }
                    179: # ugly retro fix for broken version of types
                    180:     foreach (keys %data) {
                    181: 	if ($_=~/\wtype$/) {
                    182: 	    my $newkey=$_;
                    183: 	    $newkey=~s/type$/\.type/;
                    184: 	    $data{$newkey}=$data{$_};
                    185: 	    delete $data{$_};
                    186: 	}
                    187:     }
1.37      www       188: # adjust symbs
                    189:     my $pattern='uploaded/'.$origcrsdata{'domain'}.'/'.$origcrsdata{'num'}.'/';
                    190:     $pattern=~s/(\W)/\\$1/gs;
                    191:     my $new=    'uploaded/'. $newcrsdata{'domain'}.'/'. $newcrsdata{'num'}.'/';
                    192:     foreach (keys %data) {
                    193: 	if ($_=~/$pattern/) {
                    194: 	    my $newkey=$_;
                    195: 	    $newkey=~s/$pattern/$new/;
                    196: 	    $data{$newkey}=$data{$_};
                    197: 	    delete $data{$_};
                    198: 	}
                    199:     }
1.35      www       200: # adjust dates
                    201:     foreach (keys %data) {
                    202: 	my $thiskey=$_;
                    203: 	$thiskey=~s/^$origcrsid/$newcrsid/;
                    204: 	$newdata{$thiskey}=$data{$_};
1.75      albertel  205: 	if ($data{$_.'.type'}=~/^date_(start|end)$/) {
1.85      albertel  206: 	    if ($delta > 0) {
                    207: 		$newdata{$thiskey}=$newdata{$thiskey}+$delta;
                    208: 	    } else {
                    209: 		# no delta, it's unlikely we want the old dates and times
                    210: 		delete($newdata{$thiskey});
                    211: 		delete($newdata{$thiskey.'.type'});
                    212: 	    }
1.35      www       213: 	}
                    214:     }
                    215:     return &Apache::lonnet::put
                    216: 	('resourcedata',\%newdata,$newcrsdata{'domain'},$newcrsdata{'num'});
                    217: }
                    218: 
1.30      www       219: # ========================================================== Copy all userfiles
                    220: 
                    221: sub copyuserfiles {
                    222:     my ($origcrsid,$newcrsid)=@_;
                    223:     foreach (&crsdirlist($origcrsid,'userfiles')) {
1.69      albertel  224: 	if ($_ !~m|^scantron_|) {
                    225: 	    &copyfile($origcrsid,$newcrsid,$_);
                    226: 	}
1.30      www       227:     }
                    228: }
                    229: # ========================================================== Copy all userfiles
                    230: 
                    231: sub copydbfiles {
                    232:     my ($origcrsid,$newcrsid)=@_;
1.82      albertel  233: 
                    234:     my ($origcrs_discussion) = ($origcrsid=~m|^/(.*)|);
                    235:     $origcrs_discussion=~s|/|_|g;
1.30      www       236:     foreach (&crsdirlist($origcrsid)) {
                    237: 	if ($_=~/\.db$/) {
                    238: 	    unless 
1.88      albertel  239:              ($_=~/^(nohist\_|discussiontimes|classlist|versionupdate|resourcedata|\Q$origcrs_discussion\E|slots|slot_reservations|gradingqueue|reviewqueue|CODEs)/) {
1.30      www       240: 		 &copydb($origcrsid,$newcrsid,$_);
                    241: 	     }
                    242: 	}
                    243:     }
1.31      www       244: }
                    245: 
                    246: # ======================================================= Copy all course files
                    247: 
                    248: sub copycoursefiles {
                    249:     my ($origcrsid,$newcrsid)=@_;
                    250:     &copyuserfiles($origcrsid,$newcrsid);
                    251:     &copydbfiles($origcrsid,$newcrsid);
1.35      www       252:     &copyresourcedb($origcrsid,$newcrsid);
1.28      www       253: }
1.13      www       254: 
1.2       www       255: # ===================================================== Phase one: fill-in form
                    256: 
1.10      matthew   257: sub print_course_creation_page {
1.2       www       258:     my $r=shift;
1.90      raeburn   259:     my $crstype = 'Group';
                    260:     if ($env{'form.phase'} eq 'courseone') {
                    261:         $crstype = 'Course';
                    262:     }
1.78      albertel  263:     my $defdom=$env{'request.role.domain'};
1.10      matthew   264:     my %host_servers = &Apache::loncommon::get_library_servers($defdom);
                    265:     my $course_home = '<select name="course_home" size="1">'."\n";
                    266:     foreach my $server (sort(keys(%host_servers))) {
1.14      matthew   267:         $course_home .= qq{<option value="$server"};
                    268:         if ($server eq $Apache::lonnet::perlvar{'lonHostID'}) {
                    269:             $course_home .= " selected ";
                    270:         }
                    271:         $course_home .= qq{>$server $host_servers{$server}</option>};
1.10      matthew   272:     }
                    273:     $course_home .= "\n</select>\n";
1.9       matthew   274:     my $domform = &Apache::loncommon::select_dom_form($defdom,'ccdomain');
1.32      www       275:     my $cloneform=&Apache::loncommon::select_dom_form
1.78      albertel  276: 	($env{'request.role.domain'},'clonedomain').
1.32      www       277: 		     &Apache::loncommon::selectcourse_link
1.90      raeburn   278: 	     ('ccrs','clonecourse','clonedomain',undef,undef,undef,$crstype);
1.78      albertel  279:     my $coursebrowserjs=&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'});
1.90      raeburn   280:     my ($enroll_table,$access_table,$krbdef,$krbdefdom,$krbform,$intform,$locform,
                    281:         $javascript_validations);
                    282:     if ($crstype eq 'Course') {
                    283:         my $starttime = time;
                    284:         my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
                    285:         $enroll_table = &Apache::londropadd::date_setting_table($starttime,
                    286:                                                 $endtime,'create_enrolldates');
                    287:         $access_table = &Apache::londropadd::date_setting_table($starttime,
                    288:                                                $endtime,'create_defaultdates');
                    289:         ($krbdef,$krbdefdom) =
                    290:         &Apache::loncommon::get_kerberos_defaults($defdom);
                    291:         $javascript_validations=&Apache::londropadd::javascript_validations(
                    292:                                                     'createcourse',$krbdefdom);
                    293:         my %param = ( formname      => 'document.ccrs',
                    294:                       kerb_def_dom  => $krbdefdom,
                    295:                       kerb_def_auth => $krbdef
                    296:                     );
                    297:         $krbform = &Apache::loncommon::authform_kerberos(%param);
                    298:         $intform = &Apache::loncommon::authform_internal(%param);
                    299:         $locform = &Apache::loncommon::authform_local(%param);
                    300:     } else {
                    301:         $javascript_validations = qq|
                    302: function validate(formname) {
                    303:     if (formname.title == '') {
                    304:         alert("A group title is required");
                    305:         return;
                    306:     }
                    307:     if (formname.ccuname == '') {
                    308:         alert("The username of the group coordinator is required");
                    309:     }
                    310:     formname.submit();
                    311: }
                    312:         |;
                    313:     }
1.46      sakharuk  314:     my %lt=&Apache::lonlocal::texthash(
                    315: 		    'cinf' => "Course Information",
                    316:                     'ctit' => "Course Title",
                    317:                     'chsr' => "Course Home Server",
                    318:                     'cidn' => "Course ID/Number",
                    319:                     'opt'  => "optional",
                    320:                     'iinf' => "Institutional Information",
                    321:                     'stat' => "The following entries will be used to identify the course according to the naming scheme adopted by your institution. Your choices will be used to map an internal LON-CAPA course ID to the corresponding course section ID(s) used by the office responsible for providing official class lists for courses at your institution. This mapping is required if you choose to employ automatic population of class lists.",
                    322:                     'ccod' => "Course Code",
                    323:                     'toin' => "to interface with institutional data, e.g., fs03glg231 for Fall 2003 Geology 231",
1.90      raeburn   324:                     'snid' => "Section Numbers and corresponding LON-CAPA section IDs",
                    325:                     'csli' => "a comma separated list of institutional section numbers, each separated by a colon from the (optional) corresponding section ID to be used in LON-CAPA e.g., 001:1,002:2",
1.46      sakharuk  326:                     'crcs' => "Crosslisted courses",
1.90      raeburn   327:                     'cscs' => "a comma separated list of course sections crosslisted with the current course, with each entry including the institutional course section name followed by a colon and then the (optional) sectionID to be used in LON-CAPA, e.g., fs03ent231001:ent1,fs03bot231001:bot1,fs03zol231002:zol2",
1.46      sakharuk  328:                     'crco' => "Course Content",
                    329:                     'cncr' => "Completely new course",
                    330:                     'cecr' => "Clone an existing course", 
                    331:                     'map'  => "Map",
                    332:                     'smap' => "Select Map",
                    333:                     'sacr' => "Do NOT generate as standard course",
                    334:                     'ocik' => "only check if you know what you are doing",
                    335:                     'fres' => "First Resource",
                    336:                     'stco' => "standard courses only",
                    337:                     'blnk' => "Blank",
                    338:                     'sllb' => "Syllabus",
                    339:                     'navi' => "Navigate",
                    340:                     'cid'  => "Course ID",
                    341:                     'dmn'  => "Domain",
                    342:                     'asov' => "Additional settings, if specified below, will override cloned settings",
                    343:                     'assp' => "Assessment Parameters",
                    344:                     'oaas' => "Open all assessments",
                    345:                     'mssg' => "Messaging",
                    346:                     'scpf' => "Set course policy feedback to Course Coordinator",
                    347:                     'scfc' => "Set content feedback to Course Coordinator",
                    348:                     'cmmn' => "Communication",
                    349:                     'dsrd' => "Disable student resource discussion",
                    350:                     'dsuc' => "Disable student use of chatrooms",
                    351:                     'acco' => "Access Control",
                    352:                     'snak' => "Students need access key to enter course",
1.56      www       353: 		    'kaut' => 
                    354: 		    'Key authority (<tt>id@domain</tt>) if other than course',
1.46      sakharuk  355:                     'cc'   => "Course Coordinator",
                    356:                     'user' => "Username",
                    357:                     'aens' => "Automated enrollment settings",
                    358:                     'aesc' => "The following settings control automatic enrollment of students in this class based on information available for this specific course from your institution's official classlists.",
                    359:                     'aadd' => "Automated adds",
                    360:                     'yes'  => "Yes",
                    361:                     'no'   => "No",
                    362:                     'audr' => "Automated drops",
                    363:                     'dacu' => "Duration of automated classlist updates",
1.60      raeburn   364:                     'dacc' => "Default start and end dates for student access",
1.46      sakharuk  365:                     'psam' => "Please select the authentication mechanism",
                    366:                     'pcda' => "Please choose the default authentication method to be used by new users added to this LON-CAPA domain by the automated enrollment process",
                    367:                     'nech' => "Notification of enrollment changes",
                    368:                     'nccl' => "Notification to course coordinator via LON-CAPA message when enrollment changes occur during the automated update?",
1.77      raeburn   369:                     'ndcl' => "Notification to domain coordinator via LON-CAPA message when enrollment changes occur during the automated update?",
1.46      sakharuk  370:                     'irsp' => "Include retrieval of student photographs?",
1.55      www       371: 		    'rshm' => 'Resource Space Home',
1.90      raeburn   372:                     'opco' => "Open Course",
                    373:                     'ginf' => "Group Information",
                    374:                     'gtit' => "Group Title",
                    375:                     'ghsr' => "Group Home Server",
                    376:                     'gidn' => "Group ID/Number",
                    377:                     'grco' => "Group Content",
                    378:                     'cngr' => "Completely new group",
                    379:                     'cegr' => "Clone an existing group",
                    380:                     'sagr' => "Do NOT generate as standard group",
                    381:                     'stgo' => "standard groups only",
                    382:                     'sgpf' => "Set group policy feedback to Group Coordinator",
                    383:                     'scfg' => "Set content feedback to Group Coordinator",
                    384:                     'dmrd' => "Disable member resource discussion",
                    385:                     'dmuc' => "Disable member use of chatrooms",
                    386:                     'mnak' => "Members need access key to enter group",
                    387:                     'kaug' =>
                    388:                     'Key authority (<tt>id@domain</tt>) if other than group',
                    389:                     'gc'   => "Group Coordinator",
                    390:                     'gid'  => "Group ID",
                    391:                     'crgr' => "Create Group",
1.46      sakharuk  392: 				       );
1.90      raeburn   393: 
1.86      albertel  394:     my $js = <<END;
                    395: <script type="text/javascript">
1.6       matthew   396: var editbrowser = null;
                    397: function openbrowser(formname,elementname) {
                    398:     var url = '/res/?';
                    399:     if (editbrowser == null) {
                    400:         url += 'launch=1&';
                    401:     }
                    402:     url += 'catalogmode=interactive&';
                    403:     url += 'mode=edit&';
                    404:     url += 'form=' + formname + '&';
1.7       matthew   405:     url += 'element=' + elementname + '&';
                    406:     url += 'only=sequence' + '';
1.6       matthew   407:     var title = 'Browser';
                    408:     var options = 'scrollbars=1,resizable=1,menubar=0';
                    409:     options += ',width=700,height=600';
                    410:     editbrowser = open(url,title,options,'1');
                    411:     editbrowser.focus();
                    412: }
1.41      raeburn   413: $javascript_validations
1.6       matthew   414: </script>
1.32      www       415: $coursebrowserjs
1.86      albertel  416: END
                    417: 
1.90      raeburn   418:     my %titles = &Apache::lonlocal::texthash(
                    419:                   courseone => 'Create a New Course',
                    420:                   groupone => 'Create a New Group',
                    421:     );  
1.86      albertel  422:     my $start_page = 
1.90      raeburn   423:         &Apache::loncommon::start_page($titles{$env{'form.phase'}},$js);
1.86      albertel  424:     my $end_page = 
                    425:         &Apache::loncommon::end_page();
1.91      albertel  426:     my $crumbs = 
                    427: 	&Apache::lonhtmlcommon::breadcrumbs($crstype.' Information',
                    428: 					    'Create_Course',undef,
                    429: 					    'Create_Courses');
1.90      raeburn   430:     $r->print($start_page.$crumbs);
                    431:     if ($crstype eq 'Course') {
                    432:         $r->print(<<ENDDOCUMENT);
1.6       matthew   433: <form action="/adm/createcourse" method="post" name="ccrs">
1.46      sakharuk  434: <h2>$lt{'cinf'}</h2>
1.10      matthew   435: <p>
1.68      matthew   436: <label><b>$lt{'ctit'}:</b>
                    437: <input type="text" size="50" name="title" /></label>
1.10      matthew   438: </p><p>
1.68      matthew   439: <label>
                    440:     <b>$lt{'chsr'}:</b>$course_home
                    441: </label>
                    442: </p><p>
                    443: <label>
                    444:     <b>$lt{'cidn'} ($lt{'opt'})</b>
                    445:     <input type="text" size="30" name="crsid" />
                    446: </label>
1.40      raeburn   447: </p><p>
1.46      sakharuk  448: <h2>$lt{'iinf'}</h2>
1.40      raeburn   449: <p>
1.46      sakharuk  450: $lt{'stat'}
1.40      raeburn   451: </p><p>
1.68      matthew   452: <label>
                    453:     <b>$lt{'ccod'}</b>
                    454:     <input type="text" size="30" name="crscode" />
                    455: </label>
                    456: <br/>
1.46      sakharuk  457: ($lt{'toin'})
1.40      raeburn   458: </p><p>
1.68      matthew   459: <label>
                    460:     <b>$lt{'snid'}</b>
                    461:     <input type="text" size="30" name="crssections" />
                    462: </label>
                    463: <br/>
1.46      sakharuk  464: ($lt{'csli'})
1.40      raeburn   465: </p><p>
1.68      matthew   466: <label>
                    467:     <b>$lt{'crcs'}</b>
                    468:     <input type="text" size="30" name="crsxlist" />
                    469: </label>
                    470: <br/>
1.46      sakharuk  471: ($lt{'cscs'})
1.13      www       472: </p>
1.46      sakharuk  473: <h2>$lt{'crco'}</h2>
1.32      www       474: <table border="2">
1.46      sakharuk  475: <tr><th>$lt{'cncr'}</th><th>$lt{'cecr'}</th></tr>
1.32      www       476: <tr><td>
1.13      www       477: <p>
1.68      matthew   478: <label>
                    479:     <b>$lt{'map'}:</b>
                    480:     <input type="text" size="50" name="topmap" />
                    481: </label>
1.46      sakharuk  482: <a href="javascript:openbrowser('ccrs','topmap')">$lt{'smap'}</a>
1.10      matthew   483: </p><p>
1.68      matthew   484: <label for="nonstd"><b>$lt{'sacr'}</b></label>
                    485: <br />
1.46      sakharuk  486: ($lt{'ocik'}):
1.68      matthew   487: <input id="nonstd" type="checkbox" name="nonstandard" />
                    488: </p><p>
1.46      sakharuk  489: <b>$lt{'fres'}</b><br />($lt{'stco'}):
1.68      matthew   490: <label>
                    491:     <input type="radio" name="firstres" value="blank" />$lt{'blnk'}
                    492: </label>
1.13      www       493: &nbsp;
1.68      matthew   494: <label>
                    495:     <input type="radio" name="firstres" value="syl" checked />$lt{'sllb'}
                    496: </label>
1.13      www       497: &nbsp;
1.68      matthew   498: <label>
                    499:     <input type="radio" name="firstres" value="nav" />$lt{'navi'}
                    500: </label>
1.13      www       501: </p>
1.32      www       502: </td><td>
1.68      matthew   503: <label>
                    504:     $lt{'cid'}: <input type="text" size="25" name="clonecourse" value="" />
                    505: </label>
                    506: <br />
                    507: <label>
                    508:     $lt{'dmn'}: $cloneform
                    509: </label>
1.32      www       510: <br />
1.68      matthew   511: &nbsp;<br />
1.46      sakharuk  512: $lt{'asov'}.
1.32      www       513: </td></tr>
                    514: </table>
1.46      sakharuk  515: <h2>$lt{'assp'}</h2>
1.13      www       516: <p>
1.68      matthew   517: <label>
                    518:     <b>$lt{'oaas'}: </b>
                    519:     <input type="checkbox" name="openall" />
                    520: </label>
1.13      www       521: </p>
1.46      sakharuk  522: <h2>$lt{'mssg'}</h2>
1.13      www       523: <p>
1.68      matthew   524: <label>
                    525:     <b>$lt{'scpf'}: </b>
                    526:     <input type="checkbox" name="setpolicy" checked />
                    527: </label>
1.55      www       528: <br />
1.68      matthew   529: <label>
                    530:     <b>$lt{'scfc'}: </b>
                    531:     <input type="checkbox" name="setcontent" checked />
                    532: </label>
1.11      www       533: </p>
1.46      sakharuk  534: <h2>$lt{'cmmn'}</h2>
1.16      www       535: <p>
1.68      matthew   536: <label>
                    537:     <b>$lt{'dsrd'}: </b>
                    538:     <input type="checkbox" name="disresdis" />
                    539: </label>
                    540: <br />
                    541: <label>
                    542:     <b>$lt{'dsuc'}: </b>
                    543:     <input type="checkbox" name="disablechat" />
                    544: </label>
1.16      www       545: </p>
1.46      sakharuk  546: <h2>$lt{'acco'}</h2>
1.18      www       547: <p>
1.68      matthew   548: <label>
                    549:     <b>$lt{'snak'}: </b>
                    550:     <input type="checkbox" name="setkeys" />
                    551: </label>
                    552: <br />
                    553: <label>
                    554:     <b>$lt{'kaut'}: </b>
                    555:     <input type="text" size="30" name="keyauth" />
                    556: </label>
1.18      www       557: </p>
1.55      www       558: <h2>$lt{'rshm'}</h2>
                    559: <p>
1.68      matthew   560: <label>
                    561:     <b>$lt{'rshm'}: </b>
                    562:     <input type="text" name="reshome" size="30" value="/res/$defdom/" />
                    563: </label>
1.55      www       564: </p>
1.10      matthew   565: <p>
1.46      sakharuk  566: <h2>$lt{'aens'}</h2>
                    567: $lt{'aesc'}
1.40      raeburn   568: </p>
                    569: <p>
1.46      sakharuk  570: <b>$lt{'aadd'}</b>
1.68      matthew   571: <label><input type="radio" name="autoadds" value="1" />$lt{'yes'}</label> 
                    572: <label><input type="radio" name="autoadds" value="0" checked="true" />$lt{'no'}
                    573: </label>
1.40      raeburn   574: </p><p>
1.46      sakharuk  575: <b>$lt{'audr'}</b>
1.68      matthew   576: <label><input type="radio" name="autodrops" value="1" />$lt{'yes'}</label> 
                    577: <label><input type="radio" name="autodrops" value="0" checked="true" />$lt{'no'}</label>
1.40      raeburn   578: </p><p>
1.46      sakharuk  579: <b>$lt{'dacu'}</b>
1.60      raeburn   580: $enroll_table
1.40      raeburn   581: </p><p>
1.60      raeburn   582: <b>$lt{'dacc'}</b>
                    583: $access_table
                    584: <p></p>
1.46      sakharuk  585: <b>$lt{'psam'}.</b><br />
                    586: $lt{'pcda'}.
1.40      raeburn   587: </p><p>
                    588: $krbform
                    589: <br />
                    590: $intform
                    591: <br />
                    592: $locform
                    593: </p><p>
1.46      sakharuk  594: <b>$lt{'nech'}</b><br />
                    595: $lt{'nccl'}<br/>
1.68      matthew   596: <label>
1.77      raeburn   597:     <input type="radio" name="notify_owner" value="1" />$lt{'yes'}
1.68      matthew   598: </label> 
                    599: <label>
1.77      raeburn   600:     <input type="radio" name="notify_owner" value="0" checked="true" />$lt{'no'}
                    601: </label>
                    602: <br />
                    603: $lt{'ndcl'}<br/>
                    604: <label>
                    605:     <input type="radio" name="notify_dc" value="1" />$lt{'yes'}
                    606: </label>
                    607: <label>
                    608:     <input type="radio" name="notify_dc" value="0" checked="true" />$lt{'no'}
1.68      matthew   609: </label>
                    610: </p><p>
                    611: <b>$lt{'irsp'}</b>
                    612: <label>
                    613:     <input type="radio" name="showphotos" value="1" />$lt{'yes'}
                    614: </label> 
                    615: <label>
                    616:     <input type="radio" name="showphotos" value="0" checked="true" />$lt{'no'}
                    617: </label>
1.55      www       618: </p>
                    619: <hr />
                    620: <h2>$lt{'cc'}</h2>
                    621: <p>
1.68      matthew   622: <label>
                    623:     <b>$lt{'user'}:</b> <input type="text" size="15" name="ccuname" />
                    624: </label>
                    625: </p><p>
                    626: <label>
                    627:     <b>$lt{'dmn'}:</b> $domform
                    628: </label>
1.55      www       629: </p>
                    630: <p>
1.90      raeburn   631: <input type="hidden" name="prevphase" value="courseone" />
                    632: <input type="hidden" name="phase" value="coursetwo" />
1.68      matthew   633: <input type="button" onClick="verify_message(this.form)" value="$lt{'opco'}" />
1.10      matthew   634: </p>
1.2       www       635: </form>
                    636: ENDDOCUMENT
1.90      raeburn   637:     } elsif ($crstype eq 'Group') {
                    638:         $r->print(<<ENDDOCUMENT);
                    639: <form action="/adm/createcourse" method="post" name="ccrs">
                    640: <h2>$lt{'ginf'}</h2>
                    641: <p>
                    642: <label><b>$lt{'gtit'}:</b>
                    643: <input type="text" size="50" name="title" /></label>
                    644: </p><p>
                    645: <label>
                    646:     <b>$lt{'ghsr'}:</b>$course_home
                    647: </label>
                    648: </p><p>
                    649: <label>
                    650:     <b>$lt{'gidn'} ($lt{'opt'})</b>
                    651:     <input type="text" size="30" name="crsid" />
                    652: </label>
                    653: </p>
                    654: <h2>$lt{'grco'}</h2>
                    655: <table border="2">
                    656: <tr><th>$lt{'cngr'}</th><th>$lt{'cegr'}</th></tr>
                    657: <tr><td>
                    658: <p>
                    659: <label>
                    660:     <b>$lt{'map'}:</b>
                    661:     <input type="text" size="50" name="topmap" />
                    662: </label>
                    663: <a href="javascript:openbrowser('ccrs','topmap')">$lt{'smap'}</a>
                    664: </p><p>
                    665: <label for="nonstd"><b>$lt{'sagr'}</b></label>
                    666: <br />
                    667: ($lt{'ocik'}):
                    668: <input id="nonstd" type="checkbox" name="nonstandard" />
                    669: </p><p>
                    670: <b>$lt{'fres'}</b><br />($lt{'stgo'}):
                    671: <label>
                    672:     <input type="radio" name="firstres" value="blank" />$lt{'blnk'}
                    673: </label>
                    674: &nbsp;
                    675: <label>
                    676:     <input type="radio" name="firstres" value="syl" checked />$lt{'sllb'}
                    677: </label>
                    678: &nbsp;
                    679: <label>
                    680:     <input type="radio" name="firstres" value="nav" />$lt{'navi'}
                    681: </label>
                    682: </p>
                    683: </td><td>
                    684: <label>
                    685:     $lt{'gid'}: <input type="text" size="25" name="clonecourse" value="" />
                    686: </label>
                    687: <br />
                    688: <label>
                    689:     $lt{'dmn'}: $cloneform
                    690: </label>
                    691: <br />
                    692: &nbsp;<br />
                    693: $lt{'asov'}.
                    694: </td></tr>
                    695: </table>
                    696: </p>
                    697: <p>
                    698: <h2>$lt{'mssg'}</h2>
                    699: <p>
                    700: <label>
                    701:     <b>$lt{'sgpf'}: </b>
                    702:     <input type="checkbox" name="setpolicy" checked />
                    703: </label>
                    704: <br />
                    705: <label>
                    706:     <b>$lt{'scfg'}: </b>
                    707:     <input type="checkbox" name="setcontent" checked />
                    708: </label>
                    709: </p>
                    710: <h2>$lt{'cmmn'}</h2>
                    711: <p>
                    712: <label>
                    713:     <b>$lt{'dmrd'}: </b>
                    714:     <input type="checkbox" name="disresdis" />
                    715: </label>
                    716: <br />
                    717: <label>
                    718:     <b>$lt{'dmuc'}: </b>
                    719:     <input type="checkbox" name="disablechat" />
                    720: </label>
                    721: </p>
                    722: <h2>$lt{'acco'}</h2>
                    723: <p>
                    724: <label>
                    725:     <b>$lt{'mnak'}: </b>
                    726:     <input type="checkbox" name="setkeys" />
                    727: </label>
                    728: <br />
                    729: <label>
                    730:     <b>$lt{'kaug'}: </b>
                    731:     <input type="text" size="30" name="keyauth" />
                    732: </label>
                    733: </p>
                    734: <h2>$lt{'rshm'}</h2>
                    735: <p>
                    736: <label>
                    737:     <b>$lt{'rshm'}: </b>
                    738:     <input type="text" name="reshome" size="30" value="/res/$defdom/" />
                    739: </label>
                    740: </p>
                    741: <hr />
                    742: <h2>$lt{'gc'}</h2>
                    743: <p>
                    744: <label>
                    745:     <b>$lt{'user'}:</b> <input type="text" size="15" name="ccuname" />
                    746: </label>
                    747: </p><p>
                    748: <label>
                    749:     <b>$lt{'dmn'}:</b> $domform
                    750: </label>
                    751: </p>
                    752: <p>
                    753: <input type="hidden" name="prevphase" value="groupone" />
                    754: <input type="hidden" name="phase" value="grouptwo" />
                    755: <input type="button" onClick="validate(this.form)" value="$lt{'crgr'}" />
                    756: </p>
                    757: </form>
                    758: ENDDOCUMENT
                    759:     }
                    760:     $r->print($end_page);
1.40      raeburn   761: }
                    762: 
1.2       www       763: # ====================================================== Phase two: make course
                    764: 
1.10      matthew   765: sub create_course {
1.2       www       766:     my $r=shift;
1.78      albertel  767:     my $ccuname=$env{'form.ccuname'};
                    768:     my $ccdomain=$env{'form.ccdomain'};
1.2       www       769:     $ccuname=~s/\W//g;
                    770:     $ccdomain=~s/\W//g;
1.90      raeburn   771:     my $crstype = 'Group';
                    772:     my ($enrollstart,$enrollend,$startaccess,$endaccess);
1.74      raeburn   773: 
1.90      raeburn   774:     if ($env{'form.phase'} eq 'coursetwo') {
                    775:         $crstype='Course';
                    776:         $enrollstart=&Apache::lonhtmlcommon::get_date_from_form('startenroll');
                    777:         $enrollend=&Apache::lonhtmlcommon::get_date_from_form('endenroll');
                    778: 
                    779:     }
                    780:     $startaccess = &Apache::lonhtmlcommon::get_date_from_form('startaccess');
                    781:     $endaccess   = &Apache::lonhtmlcommon::get_date_from_form('endaccess');
1.74      raeburn   782: 
                    783:     my $autharg;
                    784:     my $authtype;
                    785: 
1.78      albertel  786:     if ($env{'form.login'} eq 'krb') {
1.74      raeburn   787:         $authtype = 'krb';
1.78      albertel  788:         $authtype .=$env{'form.krbver'};
                    789:         $autharg = $env{'form.krbarg'};
                    790:     } elsif ($env{'form.login'} eq 'int') {
1.74      raeburn   791:         $authtype ='internal';
1.78      albertel  792:         if ((defined($env{'form.intarg'})) && ($env{'form.intarg'})) {
                    793:             $autharg = $env{'form.intarg'};
1.74      raeburn   794:         }
1.78      albertel  795:     } elsif ($env{'form.login'} eq 'loc') {
1.74      raeburn   796:         $authtype = 'localauth';
1.78      albertel  797:         if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) {
                    798:             $autharg = $env{'form.locarg'};
1.74      raeburn   799:         }
                    800:     }
1.90      raeburn   801:     my $logmsg;
1.91      albertel  802:     my $start_page=&Apache::loncommon::start_page('Create a New '.$crstype);
1.90      raeburn   803:     my $crumbs = &Apache::lonhtmlcommon::breadcrumbs('Creation Outcome','Create_Course',undef,'Create_Courses');
1.74      raeburn   804: 
1.90      raeburn   805:     $r->print($start_page.$crumbs);
1.74      raeburn   806: 
                    807:     my $args = {
1.90      raeburn   808:                crstype => $crstype,
1.74      raeburn   809:                ccuname => $ccuname,
                    810:                ccdomain => $ccdomain,
1.78      albertel  811:                cdescr => $env{'form.title'},
                    812:                curl => $env{'form.topmap'},
                    813:                course_domain => $env{'request.role.domain'},
                    814:                course_home =>  $env{'form.course_home'},
                    815:                nonstandard => $env{'form.nonstandard'},
                    816:                crscode => $env{'form.crscode'},
                    817:                clonecourse => $env{'form.clonecourse'},
                    818:                clonedomain => $env{'form.clonedomain'},
                    819:                crsid => $env{'form.crsid'},
                    820:                curruser => $env{'user.name'},
                    821:                crssections => $env{'form.crssections'},
                    822:                crsxlist => $env{'form.crsxlist'},
                    823:                autoadds => $env{'form.autoadds'},
                    824:                autodrops => $env{'form.autodrops'},
                    825:                notify_owner => $env{'form.notify_owner'},
                    826:                notify_dc => $env{'form.notify_dc'},
                    827:                no_end_date => $env{'form.no_end_date'},
                    828:                showphotos => $env{'form.showphotos'},
1.74      raeburn   829:                authtype => $authtype,
                    830:                autharg => $autharg,
                    831:                enrollstart => $enrollstart,
                    832:                enrollend => $enrollend,
                    833:                startaccess => $startaccess,
                    834:                endaccess => $endaccess,
1.78      albertel  835:                setpolicy => $env{'form.setpolicy'},
                    836:                setcontent => $env{'form.setcontent'},
                    837:                reshome => $env{'form.reshome'},
                    838:                setkeys => $env{'form.setkeys'},
                    839:                keyauth => $env{'form.keyauth'},
                    840:                disresdis => $env{'form.disresdis'},
                    841:                disablechat => $env{'form.disablechat'},
                    842:                openall => $env{'form.openall'},
                    843:                firstres => $env{'form.firstres'}
1.74      raeburn   844:                };
                    845: 
1.10      matthew   846:     #
                    847:     # Verify data
                    848:     #
                    849:     # Check the veracity of the course coordinator
1.2       www       850:     if (&Apache::lonnet::homeserver($ccuname,$ccdomain) eq 'no_host') {
1.52      albertel  851: 	$r->print('<form action="/adm/createuser" method="post" name="crtuser">');
                    852:         $r->print(&mt('No such user').' '.$ccuname.' '.&mt('at').' '.$ccdomain.'.<br />');
                    853: 	$r->print(&mt("Please click Back on your browser and select another user, or "));
                    854: 	$r->print('
                    855: 	    <input type="hidden" name="phase" value="get_user_info" />
                    856:             <input type="hidden" name="ccuname" value="'.$ccuname.'" />
                    857:             <input type="hidden" name="ccdomain" value="'.$ccdomain.'" />
                    858:             <input name="userrole" type="submit" value="'.
                    859: 		  &mt('Create User').'" />
1.86      albertel  860: 	</form>'.&Apache::loncommon::end_page());
1.2       www       861: 	return;
                    862:     }
1.10      matthew   863:     # Check the proposed home server for the course
                    864:     my %host_servers = &Apache::loncommon::get_library_servers
1.78      albertel  865:         ($env{'request.role.domain'});
                    866:     if (! exists($host_servers{$env{'form.course_home'}})) {
1.46      sakharuk  867:         $r->print(&mt('Invalid home server for course').': '.
1.86      albertel  868:                   $env{'form.course_home'}.&Apache::loncommon::end_page());
1.10      matthew   869:         return;
                    870:     }
1.74      raeburn   871:     my ($courseid,$crsudom,$crsunum);
1.78      albertel  872:     $r->print(&construct_course($args,\$logmsg,\$courseid,\$crsudom,\$crsunum,$env{'user.domain'},$env{'user.name'}));
1.74      raeburn   873: 
                    874: #
1.90      raeburn   875: # Make the requested user a course coordinator or group coordinator
1.74      raeburn   876: #
1.90      raeburn   877:     if (($ccdomain) && ($ccuname)) {
                    878:         $r->print(&mt('Assigning role of [_1] Coordinator to [_2] at [_3]:',
                    879:                      $crstype,$ccuname,$ccdomain).
                    880:                   &Apache::lonnet::assignrole($ccdomain,$ccuname,$courseid,
                    881:                                               'cc').'<p>');
                    882:     }
1.78      albertel  883:     if ($env{'form.setkeys'}) {
1.74      raeburn   884:         $r->print(
                    885:  '<p><a href="/adm/managekeys?cid='.$crsudom.'_'.$crsunum.'">'.&mt('Manage Access Keys').'</a></p>');
                    886:     }
                    887: # Flush the course logs so reverse user roles immediately updated
                    888:     &Apache::lonnet::flushcourselogs();
1.86      albertel  889:     $r->print('<p>'.&mt('Roles will be active at next login').'.</p>'.
1.87      www       890: 	      '<p><a href="/adm/createcourse">'.
1.90      raeburn   891: 	      &mt('Create Another [_1]',$crstype).'</a></p>'.
1.86      albertel  892: 	      &Apache::loncommon::end_page());
1.74      raeburn   893: }
                    894: 
                    895: sub construct_course {
1.77      raeburn   896:     my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname) = @_;
1.74      raeburn   897:     my $outcome;
                    898: 
1.2       www       899: #
                    900: # Open course
                    901: #
1.90      raeburn   902:     my $crstype = lc($args->{'crstype'});
1.32      www       903:     my %cenv=();
1.74      raeburn   904:     $$courseid=&Apache::lonnet::createcourse($args->{'course_domain'},
                    905:                                                $args->{'cdescr'},
                    906:                                                $args->{'curl'},
                    907:                                                $args->{'course_home'},
                    908:                                                $args->{'nonstandard'},
                    909:                                                $args->{'crscode'},
1.90      raeburn   910:                                                $args->{'ccuname'},
                    911:                                                $args->{'crstype'});
1.2       www       912: 
1.27      bowersj2  913:     # Note: The testing routines depend on this being output; see 
                    914:     # Utils::Course. This needs to at least be output as a comment
                    915:     # if anyone ever decides to not show this, and Utils::Course::new
                    916:     # will need to be suitably modified.
1.90      raeburn   917:     $outcome .= &mt('New LON-CAPA [_1] ID: [_2]<br />',$crstype,$$courseid);
1.4       www       918: #
1.12      www       919: # Check if created correctly
1.4       www       920: #
1.74      raeburn   921:     ($$crsudom,$$crsunum)=($$courseid=~/^\/(\w+)\/(\w+)$/);
                    922:     my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom);
                    923:     $outcome .= &mt('Created on').': '.$crsuhome.'<br>';
1.12      www       924: #
1.32      www       925: # Are we cloning?
                    926: #
                    927:     my $cloneid='';
1.74      raeburn   928:     if (($args->{'clonecourse'}) && ($args->{'clonedomain'})) {
                    929: 	$cloneid='/'.$args->{'clonedomain'}.'/'.$args->{'clonecourse'};
1.32      www       930:         my ($clonecrsudom,$clonecrsunum)=($cloneid=~/^\/(\w+)\/(\w+)$/);
                    931: 	my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
                    932: 	if ($clonehome eq 'no_host') {
1.74      raeburn   933: 	    $outcome .=
1.90      raeburn   934:     '<br /><font color="red">'.&mt('Attempting to clone non-existing [_1]',$crstype).' '.$cloneid.'</font>';
1.32      www       935: 	} else {
1.74      raeburn   936: 	    $outcome .= 
1.90      raeburn   937:     '<br /><font color="green">'.&mt('Cloning [_1] from [_2]',$crstype,$clonehome).'</font>';
1.74      raeburn   938: 	    my %oldcenv=&Apache::lonnet::dump('environment',$$crsudom,$$crsunum);
1.32      www       939: # Copy all files
1.74      raeburn   940: 	    &copycoursefiles($cloneid,$$courseid);
1.37      www       941: # Restore URL
                    942: 	    $cenv{'url'}=$oldcenv{'url'};
1.32      www       943: # Restore title
1.37      www       944: 	    $cenv{'description'}=$oldcenv{'description'};
1.67      albertel  945: # restore grading mode
                    946: 	    if (defined($oldcenv{'grading'})) {
                    947: 		$cenv{'grading'}=$oldcenv{'grading'};
                    948: 	    }
1.37      www       949: # Mark as cloned
1.35      www       950: 	    $cenv{'clonedfrom'}=$cloneid;
1.54      albertel  951: 	    delete($cenv{'default_enrollment_start_date'});
                    952: 	    delete($cenv{'default_enrollment_end_date'});
1.32      www       953: 	}
                    954:     }
                    955: #
                    956: # Set environment (will override cloned, if existing)
1.12      www       957: #
1.64      raeburn   958:     my @sections = ();
                    959:     my @xlists = ();
1.90      raeburn   960:     if ($args->{'crstype'}) {
                    961:         $cenv{'type'}=$args->{'crstype'};
                    962:     }
1.74      raeburn   963:     if ($args->{'crsid'}) {
                    964:         $cenv{'courseid'}=$args->{'crsid'};
1.40      raeburn   965:     }
1.74      raeburn   966:     if ($args->{'crscode'}) {
                    967:         $cenv{'internal.coursecode'}=$args->{'crscode'};
1.40      raeburn   968:     }
1.74      raeburn   969:     if ($args->{'ccuname'}) {
                    970:         $cenv{'internal.courseowner'} = $args->{'ccuname'};
1.64      raeburn   971:     } else {
1.74      raeburn   972:         $cenv{'internal.courseowner'} = $args->{'curruser'};
1.64      raeburn   973:     }
                    974: 
                    975:     my @badclasses = (); # Used to accumulate sections/crosslistings that did not pass classlist access check for course owner.
1.74      raeburn   976:     if ($args->{'crssections'}) {
1.64      raeburn   977:         $cenv{'internal.sectionnums'} = '';
1.74      raeburn   978:         if ($args->{'crssections'} =~ m/,/) {
                    979:             @sections = split/,/,$args->{'crssections'};
1.44      raeburn   980:         } else {
1.74      raeburn   981:             $sections[0] = $args->{'crssections'};
1.44      raeburn   982:         }
                    983:         if (@sections > 0) {
1.64      raeburn   984:             foreach my $item (@sections) {
                    985:                 my ($sec,$gp) = split/:/,$item;
1.74      raeburn   986:                 my $class = $args->{'crscode'}.$sec;
1.81      raeburn   987:                 my $addcheck = &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$class,$cenv{'internal.courseowner'});
1.73      raeburn   988:                 $cenv{'internal.sectionnums'} .= $item.',';
                    989:                 unless ($addcheck eq 'ok') {
1.64      raeburn   990:                     push @badclasses, $class;
                    991:                 }
1.44      raeburn   992:             }
1.64      raeburn   993:             $cenv{'internal.sectionnums'} =~ s/,$//;
1.44      raeburn   994:         }
1.40      raeburn   995:     }
1.49      www       996: # do not hide course coordinator from staff listing, 
                    997: # even if privileged
1.74      raeburn   998:     $cenv{'nothideprivileged'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
                    999: # add crosslistings
                   1000:     if ($args->{'crsxlist'}) {
1.64      raeburn  1001:         $cenv{'internal.crosslistings'}='';
1.74      raeburn  1002:         if ($args->{'crsxlist'} =~ m/,/) {
                   1003:             @xlists = split/,/,$args->{'crsxlist'};
1.44      raeburn  1004:         } else {
1.74      raeburn  1005:             $xlists[0] = $args->{'crsxlist'};
1.44      raeburn  1006:         }
                   1007:         if (@xlists > 0) {
1.64      raeburn  1008:             foreach my $item (@xlists) {
                   1009:                 my ($xl,$gp) = split/:/,$item;
1.74      raeburn  1010:                 my $addcheck =  &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$xl,$cenv{'internal.courseowner'});
1.73      raeburn  1011:                 $cenv{'internal.crosslistings'} .= $item.',';
                   1012:                 unless ($addcheck eq 'ok') {
1.64      raeburn  1013:                     push @badclasses, $xl;
                   1014:                 }
1.44      raeburn  1015:             }
1.64      raeburn  1016:             $cenv{'internal.crosslistings'} =~ s/,$//;
1.44      raeburn  1017:         }
1.40      raeburn  1018:     }
1.74      raeburn  1019:     if ($args->{'autoadds'}) {
                   1020:         $cenv{'internal.autoadds'}=$args->{'autoadds'};
1.40      raeburn  1021:     }
1.74      raeburn  1022:     if ($args->{'autodrops'}) {
                   1023:         $cenv{'internal.autodrops'}=$args->{'autodrops'};
1.40      raeburn  1024:     }
1.77      raeburn  1025: # check for notification of enrollment changes
                   1026:     my @notified = ();
                   1027:     if ($args->{'notify_owner'}) {
                   1028:         if ($args->{'ccuname'} ne '') {
                   1029:             push(@notified,$args->{'ccuname'}.'@'.$args->{'ccdomain'});
                   1030:         }
                   1031:     }
                   1032:     if ($args->{'notify_dc'}) {
                   1033:         if ($uname ne '') { 
                   1034:             push(@notified,$uname.'@'.$udom);
                   1035:         }
                   1036:     }
                   1037:     if (@notified > 0) {
                   1038:         my $notifylist;
                   1039:         if (@notified > 1) {
                   1040:             $notifylist = join(',',@notified);
                   1041:         } else {
                   1042:             $notifylist = $notified[0];
                   1043:         }
                   1044:         $cenv{'internal.notifylist'} = $notifylist;
1.40      raeburn  1045:     }
1.64      raeburn  1046:     if (@badclasses > 0) {
                   1047:         my %lt=&Apache::lonlocal::texthash(
1.73      raeburn  1048:                 'tclb' => 'The courses listed below were included as sections or crosslistings affiliated with your new LON-CAPA course.  However, if automated course roster updates are enabled for this class, these particular sections/crosslistings will not contribute towards enrollment, because the user identified as the course owner for this LON-CAPA course',
1.64      raeburn  1049:                 'dnhr' => 'does not have rights to access enrollment in these classes',
                   1050:                 'adby' => 'as determined by the policies of your institution on access to official classlists'
                   1051:         );
1.74      raeburn  1052:         $outcome .= '<font color="red">'.$lt{'tclb'}.' ('.$cenv{'internal.courseowner'}.') - '.$lt{'dnhr'}.' ('.$lt{'adby'}.').<br /><ul>'."\n";
1.64      raeburn  1053:         foreach (@badclasses) {
1.74      raeburn  1054:             $outcome .= "<li>$_</li>\n";
1.44      raeburn  1055:         }
1.74      raeburn  1056:         $outcome .= "</ul><br /><br /></font>\n";
1.40      raeburn  1057:     }
1.74      raeburn  1058:     if ($args->{'no_end_date'}) {
                   1059:         $args->{'endaccess'} = 0;
1.40      raeburn  1060:     }
1.74      raeburn  1061:     $cenv{'internal.autostart'}=$args->{'enrollstart'};
                   1062:     $cenv{'internal.autoend'}=$args->{'enrollend'};
                   1063:     $cenv{'default_enrollment_start_date'}=$args->{'startaccess'};
                   1064:     $cenv{'default_enrollment_end_date'}=$args->{'endaccess'};
                   1065:     if ($args->{'showphotos'}) {
                   1066:       $cenv{'internal.showphotos'}=$args->{'showphotos'};
1.40      raeburn  1067:     }
1.74      raeburn  1068:     $cenv{'internal.authtype'} = $args->{'authtype'};
                   1069:     $cenv{'internal.autharg'} = $args->{'autharg'}; 
1.40      raeburn  1070:     if ( ($cenv{'internal.authtype'} =~ /^krb/) && ($cenv{'internal.autoadds'} == 1)) {
                   1071:         if (! defined($cenv{'internal.autharg'}) || $cenv{'internal.autharg'}  eq '') {
1.74      raeburn  1072:             $outcome .= '<font color="red" size="+1">'.
                   1073:                       &mt('As you did not include the default Kerberos domain to be used for authentication in this class, the institutional data used by the automated enrollment process must include the Kerberos domain for each new student').'</font></p>';
1.40      raeburn  1074:         }
1.12      www      1075:     }
1.74      raeburn  1076:     if (($args->{'ccdomain'}) && ($args->{'ccuname'})) {
                   1077:        if ($args->{'setpolicy'}) {
                   1078:            $cenv{'policy.email'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
1.12      www      1079:        }
1.74      raeburn  1080:        if ($args->{'setcontent'}) {
                   1081:            $cenv{'question.email'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
1.18      www      1082:        }
1.55      www      1083:     }
1.74      raeburn  1084:     if ($args->{'reshome'}) {
                   1085: 	$cenv{'reshome'}=$args->{'reshome'}.'/';
1.55      www      1086: 	$cenv{'reshome'}=~s/\/+$/\//;
1.18      www      1087:     }
1.56      www      1088: #
                   1089: # course has keyed access
                   1090: #
1.74      raeburn  1091:     if ($args->{'setkeys'}) {
1.18      www      1092:        $cenv{'keyaccess'}='yes';
1.16      www      1093:     }
1.56      www      1094: # if specified, key authority is not course, but user
                   1095: # only active if keyaccess is yes
1.74      raeburn  1096:     if ($args->{'keyauth'}) {
                   1097: 	$args->{'keyauth'}=~s/[^\w\@]//g;
                   1098: 	if ($args->{'keyauth'}) {
                   1099: 	    $cenv{'keyauth'}=$args->{'keyauth'};
1.56      www      1100: 	}
                   1101:     }
                   1102: 
1.74      raeburn  1103:     if ($args->{'disresdis'}) {
1.16      www      1104:         $cenv{'pch.roles.denied'}='st';
1.26      matthew  1105:     }
1.74      raeburn  1106:     if ($args->{'disablechat'}) {
1.26      matthew  1107:         $cenv{'plc.roles.denied'}='st';
1.21      albertel 1108:     }
1.23      bowersj2 1109: 
1.32      www      1110:     # Record we've not yet viewed the Course Initialization Helper for this 
                   1111:     # course
1.23      bowersj2 1112:     $cenv{'course.helper.not.run'} = 1;
1.21      albertel 1113:     #
                   1114:     # Use new Randomseed
                   1115:     #
1.22      albertel 1116:     $cenv{'rndseed'}=&Apache::lonnet::latest_rnd_algorithm_id();;
1.51      albertel 1117:     $cenv{'receiptalg'}=&Apache::lonnet::latest_receipt_algorithm_id();;
1.53      www      1118:     #
                   1119:     # The encryption code and receipt prefix for this course
                   1120:     #
                   1121:     $cenv{'internal.encseed'}=$Apache::lonnet::perlvar{'lonReceipt'}.$$.time.int(rand(9999));
                   1122:     $cenv{'internal.encpref'}=100+int(9*rand(99));
1.25      matthew  1123:     #
                   1124:     # By default, use standard grading
1.67      albertel 1125:     if (!defined($cenv{'grading'})) { $cenv{'grading'} = 'standard'; }
1.22      albertel 1126: 
1.74      raeburn  1127:     $outcome .= ('<br />'.&mt('Setting environment').': '.                 
                   1128:           &Apache::lonnet::put('environment',\%cenv,$$crsudom,$$crsunum).'<br>');
1.12      www      1129: #
                   1130: # Open all assignments
                   1131: #
1.74      raeburn  1132:     if ($args->{'openall'}) {
                   1133:        my $storeunder=$$crsudom.'_'.$$crsunum.'.0.opendate';
1.33      www      1134:        my %storecontent = ($storeunder         => time,
                   1135:                            $storeunder.'.type' => 'date_start');
1.12      www      1136:        
1.74      raeburn  1137:        $outcome .= &mt('Opening all assignments').': '.&Apache::lonnet::cput
                   1138:                  ('resourcedata',\%storecontent,$$crsudom,$$crsunum).'<br>';
1.12      www      1139:    }
1.13      www      1140: #
                   1141: # Set first page
                   1142: #
1.74      raeburn  1143:     unless (($args->{'nonstandard'}) || ($args->{'firstres'} eq 'blank')
1.48      www      1144: 	    || ($cloneid)) {
1.74      raeburn  1145: 	$outcome .= &mt('Setting first resource').': ';
1.13      www      1146:         my ($errtext,$fatal)=
1.74      raeburn  1147:            &Apache::londocs::mapread($$crsunum,$$crsudom,'default.sequence');
                   1148:         $outcome .= ($fatal?$errtext:'read ok').' - ';
1.13      www      1149:         my $title; my $url;
1.74      raeburn  1150:         if ($args->{'firstres'} eq 'syl') {
1.13      www      1151: 	    $title='Syllabus';
1.74      raeburn  1152:             $url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus';
1.13      www      1153:         } else {
                   1154:             $title='Navigate Contents';
                   1155:             $url='/adm/navmaps';
                   1156:         }
                   1157:         $Apache::lonratedt::resources[1]=$title.':'.$url.':false:start:res';
1.15      albertel 1158:         ($errtext,$fatal)=
1.74      raeburn  1159:            &Apache::londocs::storemap($$crsunum,$$crsudom,'default.sequence');
                   1160:         $outcome .= ($fatal?$errtext:'write ok').'<br>';
1.20      www      1161:     }
1.74      raeburn  1162:     return $outcome;
1.2       www      1163: }
                   1164: 
1.90      raeburn  1165: sub print_intro_page {
                   1166:     my $r = shift;
                   1167:     my $start_page =
                   1168:         &Apache::loncommon::start_page('Create a New Course or Group Space');
                   1169:     my $crumbs = &Apache::lonhtmlcommon::breadcrumbs('Creation Options','Create_Course',undef,'Create_Courses');
                   1170:     my $end_page =
                   1171:         &Apache::loncommon::end_page();
                   1172:     my $helplink=&Apache::loncommon::help_open_topic('Create_Course_GroupSpace',&mt('Help on Creating Courses and Groups'));
                   1173: 
                   1174:     my @choices = ({ internal_name => 'courseone',
                   1175:                      name => &mt('Create a single course'),
                   1176:                      short_description =>
                   1177:     &mt('Create a new course by completing an online form.'),
                   1178:                  },
                   1179:                    { internal_name => 'groupone',
                   1180:                      name => &mt('Create a single collaborative group space '),
                   1181:                      short_description =>
                   1182:     &mt('Create a new group space for non-course use by completing an online form .'),
                   1183:                  },
                   1184:                    { internal_name => 'batchone',
                   1185:                      name => &mt('Create courses/groups by uploading an attributes file'),
                   1186:                      short_description =>
                   1187:     &mt('Upload an attributes file containing specifications for one or more courses or groups in XML format'),
                   1188:                  },
                   1189:     );
                   1190:     my $options;
                   1191:     foreach my $choice (@choices) {
                   1192:         $options .='    <h3><a href="/adm/createcourse?phase='.
                   1193:             $choice->{'internal_name'}.'" >'.
                   1194:             $choice->{'name'}."</a></h3>\n";
                   1195:         $options .= '    '.('&nbsp;'x8).$choice->{'short_description'}.
                   1196:             "\n";
                   1197:     }
                   1198: 
                   1199:     $r->print(<<ENDDOCUMENT);
                   1200: $start_page
                   1201: $crumbs
                   1202: $options
                   1203: $end_page
                   1204: ENDDOCUMENT
                   1205: }
                   1206: 
                   1207: sub upload_batchfile {
                   1208:     my $r = shift;
                   1209:     my $start_page =
                   1210:         &Apache::loncommon::start_page('Create a New Course or Group Space');
                   1211:     my $crumbs = &Apache::lonhtmlcommon::breadcrumbs('Upload Course/Group Attributes File','Create_Course',undef,'Create_Courses');
                   1212:     my $end_page =
                   1213:         &Apache::loncommon::end_page();
                   1214:     $r->print($start_page.$crumbs);
                   1215:     $r->print('<h3>'.&mt('Upload a courses or groups attributes file').'</h3>');
                   1216:     $r->print('<form name="batchcreate" method="post" '.
                   1217:                 'enctype="multipart/form-data" action="/adm/createcourse">'.
                   1218:               '<input type="file" name="coursecreatorxml" />'.
                   1219:               '<input type="hidden" name="phase" value="batchtwo"><br /><br />'.
                   1220:               '<input type="submit" name="batchsubmit" '.
                   1221:               'value="Create Courses/Groups" /></form>');
                   1222:     $r->print($end_page);
                   1223:     return;
                   1224: }
                   1225: 
                   1226: sub process_batchfile {
                   1227:     my $r = shift;
                   1228:     my $start_page =
                   1229:         &Apache::loncommon::start_page('Create a New Course or Group Space');
                   1230:     my $crumbs = &Apache::lonhtmlcommon::breadcrumbs('Creation Outcome','Create_Course',undef,'Create_Courses');
                   1231:     my $end_page =
                   1232:         &Apache::loncommon::end_page();
                   1233:     my $defdom=$env{'request.role.domain'};
                   1234:     my $batchfilepath=&Apache::lonnet::userfileupload('coursecreatorxml',undef,
                   1235:                                                       'batchupload',undef,undef,
                   1236:                                                        undef,undef,$defdom);
                   1237:     my ($batchdir,$filename) = ($batchfilepath =~ m-^(.+)/pending/([^/]+)$-);
                   1238:     my ($result,$logmsg);
                   1239:     if (-e "$batchfilepath") {
                   1240:         open(FILE,"<$batchfilepath");
                   1241:         my @buffer = <FILE>;
                   1242:         close(FILE);
                   1243:         if ((defined($filename)) && (defined($batchdir))) {
                   1244:             my @requests = ($filename);
                   1245:             my %courseids = ();
                   1246:             ($result,$logmsg) = &LONCAPA::batchcreatecourse::create_courses(
                   1247:                                         \@requests,\%courseids,'web',$defdom,
                   1248:                                         $env{'user.name'},$env{'user.domain'});
                   1249:             if ($result) {
                   1250:                 if (!-e "$batchdir/processed") {
                   1251:                     mkdir("$batchdir/processed", 0755);
                   1252:                     open(FILE,">$batchdir/processed/$filename");
                   1253:                     print FILE @buffer;
                   1254:                     close(FILE);
                   1255:                     if (-e "$batchdir/processed/$filename") {
                   1256:                         unlink("$batchdir/pending/$filename");
                   1257:                     }
                   1258:                 }
                   1259:             }
                   1260:         }
                   1261:     }
                   1262:     $r->print($start_page.$crumbs.$result.$end_page);
                   1263:  
                   1264: }
                   1265: 
1.2       www      1266: # ===================================================================== Handler
1.1       www      1267: sub handler {
                   1268:     my $r = shift;
                   1269: 
                   1270:     if ($r->header_only) {
1.38      www      1271:        &Apache::loncommon::content_type($r,'text/html');
1.1       www      1272:        $r->send_http_header;
                   1273:        return OK;
                   1274:     }
                   1275: 
1.78      albertel 1276:     if (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) {
1.38      www      1277:        &Apache::loncommon::content_type($r,'text/html');
1.1       www      1278:        $r->send_http_header;
                   1279: 
1.90      raeburn  1280:        &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   1281:                                             ['phase']);
                   1282:        &Apache::lonhtmlcommon::clear_breadcrumbs();
                   1283:        &Apache::lonhtmlcommon::add_breadcrumb
                   1284:           ({href=>"/adm/createcourse",
                   1285:             text=>"Creation Options",
                   1286:             faq=>79,bug=>'Dom Coord Interface',});
                   1287:        if (($env{'form.phase'} eq 'coursetwo') ||
                   1288:            ($env{'form.phase'} eq 'grouptwo')) {
                   1289:            &Apache::lonhtmlcommon::add_breadcrumb
                   1290:                  ({href=>"/adm/createcourse?phase=$env{'form.prevphase'}",
                   1291:                    text=>&mt('[_1] Creation Settings',),
                   1292:                    faq=>9,bug=>'Dom Coord Interface',});
                   1293:           &Apache::lonhtmlcommon::add_breadcrumb
                   1294:                  ({href=>"/adm/createcourse?phase=$env{'form.phase'}",
                   1295:                    text=>"Creation Outcome",
                   1296:                    faq=>9,bug=>'Dom Coord Interface',});
1.10      matthew  1297:            &create_course($r);
1.90      raeburn  1298:        } elsif (($env{'form.phase'} eq 'courseone') || 
                   1299:                 ($env{'form.phase'} eq 'groupone')) {
                   1300:            &Apache::lonhtmlcommon::add_breadcrumb
                   1301:                  ({href=>"/adm/createcourse?phase=$env{'form.phase'}",
                   1302:                    text=>&mt('[_1] Creation Settings',),
                   1303:                    faq=>9,bug=>'Dom Coord Interface',});
                   1304: 	   &print_course_creation_page($r);
                   1305:        } elsif ($env{'form.phase'} eq 'batchone') {
                   1306:            &Apache::lonhtmlcommon::add_breadcrumb
                   1307:                  ({href=>"/adm/createcourse?phase=$env{'form.phase'}",
                   1308:                    text=>"Upload Description File",
                   1309:                    faq=>9,bug=>'Dom Coord Interface',});
                   1310:            &upload_batchfile($r);
                   1311:        } elsif ($env{'form.phase'} eq 'batchtwo') {
                   1312:            &Apache::lonhtmlcommon::add_breadcrumb
                   1313:                  ({href=>"/adm/createcourse?phase=$env{'form.prevphase'}",
                   1314:                    text=>"Upload Description File",
                   1315:                    faq=>9,bug=>'Dom Coord Interface',});
                   1316:            &Apache::lonhtmlcommon::add_breadcrumb
                   1317:                  ({href=>"/adm/createcourse?phase=$env{'form.phase'}",
                   1318:                    text=>"Creation Outcome",
                   1319:                    faq=>9,bug=>'Dom Coord Interface',});
                   1320:            &process_batchfile($r);
1.2       www      1321:        } else {
1.90      raeburn  1322:            &print_intro_page($r);
1.2       www      1323:        }
1.1       www      1324:    } else {
1.78      albertel 1325:       $env{'user.error.msg'}=
1.90      raeburn  1326:         "/adm/createcourse:ccc:0:0:Cannot create courses or groups";
1.1       www      1327:       return HTTP_NOT_ACCEPTABLE; 
                   1328:    }
                   1329:    return OK;
1.90      raeburn  1330: }
1.1       www      1331: 
                   1332: 1;
                   1333: __END__

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