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

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

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