Annotation of loncom/imspackages/imsimport.pm, revision 1.47

1.25      www         1: # The LearningOnline Network with CAPA
                      2: # 
1.47    ! damieng     3: # $Id: imsimport.pm,v 1.46 2014/12/11 01:07:38 raeburn Exp $
1.25      www         4: #
1.7       raeburn     5: # Copyright Michigan State University Board of Trustees
                      6: #
                      7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      8: #
                      9: # LON-CAPA is free software; you can redistribute it and/or modify
                     10: # it under the terms of the GNU General Public License as published by
                     11: # the Free Software Foundation; either version 2 of the License, or
                     12: # (at your option) any later version.
                     13: #
                     14: # LON-CAPA is distributed in the hope that it will be useful,
                     15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17: # GNU General Public License for more details.
                     18: #
                     19: # You should have received a copy of the GNU General Public License
                     20: # along with LON-CAPA; if not, write to the Free Software
                     21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     22: #
                     23: # /home/httpd/html/adm/gpl.txt
                     24: #
                     25: # http://www.lon-capa.org/
                     26: #
                     27: 
1.1       raeburn    28: package Apache::imsimport;
                     29: 
1.4       raeburn    30: use strict;
                     31: use Apache::Constants qw(:common :http :methods);
                     32: use Apache::loncommon();
                     33: use Apache::lonnet;
1.5       raeburn    34: use Apache::imsprocessor;
1.23      raeburn    35: use Apache::lonlocal;
1.4       raeburn    36: use HTML::Parser;
                     37: use HTML::Entities();
                     38: use Apache::lonlocal;
                     39: use Apache::lonupload;
1.5       raeburn    40: use File::Basename();
1.21      albertel   41: use LONCAPA;
                     42: 
1.5       raeburn    43: # ----------------------------------------------------------------  Jscript One
                     44: sub jscript_one {
1.36      raeburn    45:     my ($fullpath,$formname) = @_;
1.14      albertel   46: 
1.20      albertel   47:     my %body_layout = ('rightmargin'  => "0",
                     48: 		       'leftmargin'   => "0",
                     49: 		       'marginwidth'  => "0",
                     50: 		       'topmargin'    => "0",
                     51: 		       'marginheight' => "0");
1.14      albertel   52:     my $start_page = 
                     53: 	&Apache::loncommon::start_page('Create IMS import directory',undef,
                     54: 				       {'only_body'   => 1,
1.20      albertel   55: 					'add_entries' => \%body_layout,
1.14      albertel   56: 					'js_ready'    => 1,});
                     57:     my $end_page = 
                     58: 	&Apache::loncommon::end_page({'js_ready' => 1,});
                     59: 
1.47    ! damieng    60:     my %js_lt = &Apache::lonlocal::texthash( 
1.23      raeburn    61:                ddir => 'You must choose a destination directory for the import',
                     62:                cmss => 'You must choose the Course Management System from which the IMS package was exported',
1.47    ! damieng    63:              );
        !            64:     my %html_lt = &Apache::lonlocal::texthash( 
1.23      raeburn    65:                loca => 'Location:',
                     66:                newd => 'New Directory',
                     67:                nndi => 'Enter the name of the new directory where you will store the contents of your IMS package.',
                     68:                go => 'Go', 
                     69:              );
1.47    ! damieng    70:     &js_escape(\%js_lt);
        !            71:     &html_escape(\%html_lt);
1.36      raeburn    72:     return <<"END_OF_ONE";
1.1       raeburn    73: function verify() {
1.23      raeburn    74:  if ((document.forms.$formname.newdir.value == '')  || (!document.forms.$formname.newdir.value)) {
1.47    ! damieng    75:    alert('$js_lt{'ddir'}')
1.1       raeburn    76:    return false
                     77:  }
1.23      raeburn    78:  if (document.forms.$formname.source.selectedIndex == 0) {
1.47    ! damieng    79:    alert('$js_lt{'cmss'}');
1.1       raeburn    80:    return false
1.2       raeburn    81:  }
1.1       raeburn    82:  return true
                     83: }
1.2       raeburn    84: 
1.1       raeburn    85: function nextPage() {
1.5       raeburn    86:   if (verify()) {
1.23      raeburn    87:     document.forms.$formname.submit();
1.5       raeburn    88:   }
1.1       raeburn    89: }
                     90: 
                     91: function createWin() {
1.23      raeburn    92:   document.$formname.newdir.value = "";
1.1       raeburn    93:   newWindow = window.open("","CreateDir","HEIGHT=400,WIDTH=750,scrollbars=yes")
                     94:   newWindow.document.open()
1.14      albertel   95:   newWindow.document.write('$start_page')
1.30      bisitz     96:   newWindow.document.write("\\n<img border='0' src='/adm/lonInterFace/author.jpg' alt='[Author Header]' />\\n")
1.23      raeburn    97:   newWindow.document.write("<table border='0' cellspacing='0' cellpadding='0' width='600'>\\n")
1.1       raeburn    98:   newWindow.document.write("<tr><td width='2'>&nbsp;</td><td width='3'>&nbsp;</td>\\n")
1.47    ! damieng    99:   newWindow.document.write("<td><h3>$html_lt{'loca'} <tt>$fullpath</tt></h3><h3>$html_lt{'newd'}</h3></td></tr>\\n")
1.1       raeburn   100:   newWindow.document.write("<tr><td width='2'>&nbsp;</td><td width='3'>&nbsp;</td>\\n")
                    101:   newWindow.document.write("<td><form name='fileaction' action='/adm/cfile' method='post'>\\n")
1.47    ! damieng   102:   newWindow.document.write("$html_lt{'nndi'}<br /><br />")
1.15      albertel  103:   newWindow.document.write("<input type='hidden' name='filename' value='$fullpath' />")
                    104:   newWindow.document.write("<input type='hidden' name='action' value='newdir' />")
                    105:   newWindow.document.write("<input type='hidden' name='callingmode' value='imsimport' />")
                    106:   newWindow.document.write("$fullpath<input type='text' name='newfilename' value='' />")
1.47    ! damieng   107:   newWindow.document.write("<input type='button' value='$html_lt{'go'}' onclick='document.fileaction.submit();' />")
1.1       raeburn   108:   newWindow.document.write("</td></tr>\\n")
1.14      albertel  109:   newWindow.document.write("</table>")
                    110:   newWindow.document.write('$end_page')
1.1       raeburn   111:   newWindow.document.close()
                    112:   newWindow.focus()
                    113: }
1.2       raeburn   114: 
1.5       raeburn   115: END_OF_ONE
                    116: 
                    117: }
                    118: 
                    119: # ----------------------------------------------------------------  Jscript Two
                    120: sub jscript_two {
1.36      raeburn   121:     my ($user,$dom,$numcrs) = @_;
1.5       raeburn   122:     my %crsentry = ();
                    123:     my $course_list;
                    124:     my $title_list;
                    125:     my @crslist = ();
                    126:     &get_ccroles($user,$dom,\%crsentry,\@crslist);
                    127:     if (@crslist > 0) {
                    128:         $crsentry{$crslist[0]} =~ s/("|,)//g;
                    129:         $title_list = '"'.$crsentry{$crslist[0]}.'"';
                    130:         if (@crslist > 1) {
                    131:             for (my $i=1; $i<@crslist; $i++) {
                    132:                 $crsentry{$crslist[$i]} =~ s/("|,)//g;
                    133:                 $title_list .= ',"'.$crsentry{$crslist[$i]}.'"';
                    134:             }
                    135:         }
                    136:     }
                    137:     $course_list = '"'.join('","',@crslist).'"';
                    138:     $$numcrs = @crslist;
                    139: 
1.47    ! damieng   140:     my %js_lt = &Apache::lonlocal::texthash(
1.45      bisitz    141:                   sel    => 'Please select',
                    142:                   impto  => 'Import topics only',
                    143:                   imptpa => 'Import topics + posts (with author)',
                    144:                   imptpn => 'Import topics + posts (no author)',
                    145:                   enrst  => 'Enroll students only',
                    146:                   enrall => 'Enroll all users',
                    147:                   notreq => 'Not required',
                    148:                   errao  => 'You must select one of the additional options when importing Discussion Boards.',
                    149:                   errtd  => 'You must select a target course when importing Discussion Boards.',
                    150:                   errap  => 'You must select one of the additional options when importing Enrollment.',
                    151:                   errte  => 'You must select a target course when importing enrollment information.',
                    152:                   errcc  => 'You must check at least one Content Type.',
                    153:        );
1.47    ! damieng   154:     &js_escape(\%js_lt);
1.36      raeburn   155:     return <<"END_OF_TWO";
1.5       raeburn   156: 
                    157: function checkCourse() {
                    158:   courseID_array = new Array($course_list)
                    159:   courseTitle_array = new Array($title_list)
                    160:   var step2Form = document.forms.pickoptions
                    161:   var conditionType = step2Form.conditions.value
                    162:   var curVal = step2Form.targetcourse.options[step2Form.targetcourse.selectedIndex].value
                    163:   if (curVal == -1) {
                    164:       if ( conditionType == 'both'  )  {
                    165:           if ( step2Form.board.checked == true || step2Form.users.checked == true ) {
                    166:               setCourse(step2Form,'add')
                    167:           }
                    168:       }
                    169:       if ( conditionType == 'users'  )  {
                    170:           if ( step2Form.users.checked == true ) {
                    171:               setCourse(step2Form,'add')
                    172:           }
                    173:       }
                    174:       if ( conditionType == 'board'  )  {
                    175:           if ( step2Form.board.checked == true ) {
                    176:               setCourse(step2Form,'add')
                    177:           }
                    178:       }
                    179:   }
                    180:   else { 
                    181:       if ( conditionType == 'both'  )  {
                    182:           if ( step2Form.board.checked == false && step2Form.users.checked == false ) {
                    183:               setCourse(step2Form,'clear')
                    184:           }
                    185:       }
                    186:       if ( conditionType == 'users'  )  {
                    187:           if ( step2Form.users.checked == false ) {
                    188:               setCourse(step2Form,'clear')
                    189:           }
                    190:       }
                    191:       if ( conditionType == 'board'  )  {
                    192:           if ( step2Form.board.checked == false ) {
                    193:               setCourse(step2Form,'clear')
                    194:           }
                    195:       }
                    196:   }
                    197: }
                    198: 
                    199: function setCourse(step2Form,call) {
                    200:     step2Form.targetcourse.length = 0
                    201:     if (call == 'add') {
                    202:         step2Form.targetcourse.length = 0
1.47    ! damieng   203:         step2Form.targetcourse.options[0] = new Option("$js_lt{'sel'}","0",true,true)
1.5       raeburn   204:         for (var i=0; i<courseID_array.length; i++) {
                    205:             step2Form.targetcourse.options[i+1] = new Option(courseTitle_array[i],courseID_array[i],false,false)
                    206:         }
                    207:         step2Form.targetcourse.selectedIndex = 0
                    208:     }
                    209:     else {
                    210:         step2Form.targetcourse.options[0] = new Option("Not required","-1",true,true)
                    211:         step2Form.targetcourse.selectedIndex = 0
                    212:     }
                    213: }
                    214: 
                    215: 
                    216: function setOptions(caller,itemnum) {
                    217:   var numCrs = $$numcrs
                    218:   var opForm = document.forms.pickoptions
                    219:   var menu = 1 + itemnum*2
                    220:   opForm.elements[menu].length = 0
                    221:   if (opForm.elements[itemnum*2].checked == true) {
                    222:     if (caller == "board") {
1.47    ! damieng   223:       opForm.elements[menu].options[0] = new Option("$js_lt{'sel'}","-1",true,true)
        !           224:       opForm.elements[menu].options[1] = new Option("$js_lt{'impto'}","topics",true,true)
        !           225:       opForm.elements[menu].options[2] = new Option("$js_lt{'imptpa'}","allpost",true,true)
        !           226:       opForm.elements[menu].options[3] = new Option("$js_lt{'imptpn'}","allanon",true,true)
1.5       raeburn   227:     }
                    228:     else { 
                    229:       if (caller == "users") {
                    230:         opForm.elements[menu].length = 0
1.47    ! damieng   231:         opForm.elements[menu].options[0] = new Option("$js_lt{'sel'}","-1",true,true)
        !           232:         opForm.elements[menu].options[1] = new Option("$js_lt{'enrst'}","students",true,true)
        !           233:         opForm.elements[menu].options[2] = new Option("$js_lt{'enrall'}","all",true,true)
1.5       raeburn   234:       }
                    235:     }
                    236:   }
                    237:   else {
1.47    ! damieng   238:     opForm.elements[menu].options[0] = new Option("$js_lt{'notreq'}","0",true,true)
1.5       raeburn   239:   }
                    240:   opForm.elements[menu].selectedIndex = 0
                    241:   if (numCrs > 0) {
                    242:       checkCourse()
                    243:   }
                    244: }
                    245: 
                    246: function verify(caller) {
                    247:   var numCrs = $$numcrs
                    248:   var opForm = document.forms.pickoptions
                    249:   var totcheck = 0;
                    250:   var totchg = 0;
                    251:   for (var i=0; i<caller; i++) {
                    252:     if (opForm.elements[2*i].checked == true) {
                    253:       totcheck ++
                    254:       if (opForm.elements[2*i].name == "board") { 
                    255:         if (opForm.elements[2*i+1].selectedIndex == 0) {     
1.47    ! damieng   256:           alert("$js_lt{'errao'}")
1.5       raeburn   257:           return false
                    258:         }
                    259:         if (numCrs == 0) {
                    260:             opForm.elements[2*i].checked = false
                    261:             totchg ++
                    262:         }
                    263:         else {
                    264:           if (opForm.targetcourse.selectedIndex == 0) {
1.47    ! damieng   265:             alert("$js_lt{'errtd'}")
1.5       raeburn   266:             return false
                    267:           }
                    268:         }
                    269:       }
                    270:       if (opForm.elements[2*i].name == "users") {
                    271:         if (opForm.elements[2*i+1].selectedIndex == 0) {     
1.47    ! damieng   272:           alert("$js_lt{'errap'}")
1.5       raeburn   273:           return false
                    274:         }
                    275:         if (numCrs == 0) {
                    276:             opForm.elements[2*i].checked = false
                    277:             totchg ++ 
                    278:         }
                    279:         else {
                    280:           if (opForm.targetcourse.selectedIndex == 0) {
1.47    ! damieng   281:             alert("$js_lt{'errte'}")
1.5       raeburn   282:             return false
                    283:           }
                    284:         }
                    285:       }
                    286:     }
                    287:   }
                    288:   if (totcheck == 0) {
1.47    ! damieng   289:     alert("$js_lt{'errcc'}");
1.5       raeburn   290:     return false
                    291:   }
                    292:   return true
                    293: }
                    294: 
                    295: function nextPage(caller) {
                    296:   if (verify(caller)) {
                    297:     document.forms.pickoptions.submit()
                    298:   }
1.2       raeburn   299: }
                    300: 
1.36      raeburn   301: END_OF_TWO
1.5       raeburn   302: 
                    303: }
1.1       raeburn   304: 
1.5       raeburn   305: # ---------------------------------------------------------------- Display One
                    306: sub display_one {
1.36      raeburn   307:     my ($r,$fn,$fullpath,$formname) = @_;
1.42      bisitz    308:     $r->print('<form name="'.$formname.'" method="post" action="">'.
1.23      raeburn   309:               &Apache::lonhtmlcommon::topic_bar(1,&mt('Specify the Course Management system used to create the package')).
                    310:         &mt('Choose the CMS used to create your IMS content package.').'&nbsp;&nbsp;
1.2       raeburn   311:         <select name="source">
1.45      bisitz    312:          <option value="-1" selected="selected">'.&mt('Please select').'</option>
1.23      raeburn   313:          <option value="bb5">Blackboard 5</option>
                    314:          <option value="bb6">Blackboard 6</option>
1.32      raeburn   315:          <option value="angel5">ANGEL 5.5</option>
1.23      raeburn   316:          <option value="webctce4">WebCT 4 Campus Edition</option>
                    317:          <option value="webctvista4">WebCT Vista 4</option>
                    318:         </select><br />'."\n".
                    319:         &Apache::lonhtmlcommon::topic_bar(2,&mt('Create a directory where you will unpack your IMS package'))."\n".
1.45      bisitz    320:          &mt('Create a destination LON-CAPA directory in which to store the contents of the IMS package file.').'&nbsp;&nbsp;<input type="button" name="createdir" value="'.&mt('Create Directory').'" onclick="javascript:createWin()" /><input type="hidden" name="newdir" value="" /><br /><br />
1.23      raeburn   321:           <input type="hidden" name="filename" value="'.$fn.'" />
1.15      albertel  322:           <input type="hidden" name="phase" value="three" />
1.41      bisitz    323:           <input type="button" name="nextpage" value="'.&mt('Proceed').'" onclick="javascript:nextPage();" />&nbsp;&nbsp;&nbsp;&nbsp;
                    324:           <input type="button" name="exitpage" value="'.&mt('Exit now').'" onclick="javascript:location.href='."'$fullpath'".'" />
1.23      raeburn   325:          </form>');
1.5       raeburn   326: }
                    327: 
                    328: # ---------------------------------------------------------------- Display Two
                    329: sub display_two {
1.36      raeburn   330:     my ($r,$zipupload,$areas,$areaname,$cmsmap,$fn,$numcrs,$fullpath) = @_;
1.5       raeburn   331:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['folder','source']);
1.11      albertel  332:     my $cms = $env{'form.source'};
1.36      raeburn   333:     my $tempdir = &Apache::imsprocessor::create_tempdir('CSTR',$env{'form.newdir'},'');
1.5       raeburn   334:     my $fname = &Apache::imsprocessor::uploadzip('CSTR',$tempdir,$zipupload);
                    335:     my $unzip_result = '';
                    336:     my $manifest_result = '';
                    337:     unless ($tempdir eq '') {
                    338:         $unzip_result = &Apache::imsprocessor::expand_zip($tempdir,$fname);
                    339:     }
                    340:     my %resources = ();
1.9       raeburn   341:     my %includedres = ();
                    342:     my %includeditems = ();
1.5       raeburn   343:     my %items = ();
                    344:     my %hrefs = ();
                    345:     my %resinfo = ();
                    346:     my %count = ();
1.23      raeburn   347: 
                    348:     my %lt = &Apache::lonlocal::texthash(
                    349:                   cont => 'Choose which content types you wish to import',
                    350:                   impo => 'Import',
                    351:                   type => 'Content type',
                    352:                   addo => 'Additional options',
                    353:                   chec => 'Check Import first',
1.44      bisitz    354:                   bbus => 'Choose a course to receive discussion boards and user enrollment',
                    355:                   list => 'A listing of possible course targets will be displayed if import of discussion boards and/or enrollment is checked above (step 3). If you do not plan to import either of these content types, there is no need to specify a course.',
1.23      raeburn   356:                   chco => 'Choose course:',
                    357:                   nreq => 'Not required',
1.44      bisitz    358:                   yodo => 'You do not have active course coordinator status in any LON-CAPA courses currently, so discussion boards and enrollment information included in your IMS package will be discarded, regardless of your import choice for these two items above (step 3).',
                    359:                   ifyo => "If you wish to import discussion boards and/or user information into LON-CAPA please click 'Exit now' to quit the current IMS import process, and contact your domain coordinator and request a course coordinator role in a LON-CAPA course into which you can upload discussion boards and/or enroll users.",
1.23      raeburn   360:                   impa => 'Import package',
                    361:                   unpa => 'Unpacking of your IMS package failed because an IMS manifest file was not located in the package',
                    362:                   proc => 'Processing of your IMS package failed because the file you uploaded could not be unzipped',
                    363:                   exit => 'Exit now',
                    364:     );
1.5       raeburn   365: 
                    366:     my $counter = 0;
                    367:     my $iter = 0;
                    368:     my %count = (
                    369:                 announce => 0,
                    370:                 board => 0,
                    371:                 doc => 0,
                    372:                 extlink => 0,
                    373:                 msg => 0,
                    374:                 pool => 0,
                    375:                 quiz => 0,
                    376:                 staff => 0,
                    377:                 survey => 0,
                    378:                 users => 0,
                    379:                 );
                    380:     my $conditions;
                    381:     if ($unzip_result eq 'ok') {
1.19      raeburn   382:         $manifest_result = &Apache::imsprocessor::process_manifest($cms,
                    383:                             $tempdir,\%resources,\%items,\%hrefs,\%resinfo,
                    384:                             'choose',\%includedres,\%includeditems);
1.5       raeburn   385:         if ($manifest_result eq 'ok') {
1.46      raeburn   386:             foreach my $res (sort(keys(%resources))) {
1.19      raeburn   387:                 if ($cms eq 'bb5' || $cms eq 'bb6' || $cms eq 'webctce4' 
                    388:                     || $cms eq 'webctvista4') {
1.46      raeburn   389:                     foreach my $area (keys(%{$$cmsmap{$cms}})) {
1.5       raeburn   390:                         if ($resources{$res}{type} eq $$cmsmap{$cms}{$area}) {
                    391:                             $count{$area} ++;
                    392:                         }
                    393:                     }
1.32      raeburn   394:                 } elsif ($cms eq 'angel5') {
1.46      raeburn   395:                     foreach my $area (keys(%{$$cmsmap{$cms}})) {
1.5       raeburn   396:                         if ($area eq 'doc') {
                    397:                             if (grep/^$resources{$res}{type}$/,@{$$cmsmap{$cms}{doc}}) {
                    398:                                 $count{$area} ++;
                    399:                             }
                    400:                         } elsif ($resources{$res}{type} eq $$cmsmap{$cms}{$area}) {
                    401:                             $count{$area} ++;                                
                    402:                         }
                    403:                     }
                    404:                 }
                    405:             }
                    406:             if ($count{board} > 0) {
                    407:                 if ($count{users} > 0) {
                    408:                     $conditions = 'both';
                    409:                 } else {
                    410:                     $conditions = 'board';
                    411:                 }
                    412:             } elsif ($count{users} > 0) {
                    413:                 $conditions = 'users';
                    414:             } else {
                    415:                 $conditions = 'none';
                    416:             }
                    417: 
1.42      bisitz    418:             $r->print('<form name="pickoptions" method="post" action="">'.
1.23      raeburn   419:                       &Apache::lonhtmlcommon::topic_bar(3,$lt{'cont'}).
                    420:                       &Apache::loncommon::start_data_table().
                    421:                       &Apache::loncommon::start_data_table_header_row().
1.24      raeburn   422:                       '<th>'.$lt{'impo'}.'</th><th>'.$lt{'type'}.'</th><th>'.
1.23      raeburn   423:                       $lt{'addo'}.'</th>'.
                    424:                       &Apache::loncommon::end_data_table_header_row());
1.5       raeburn   425:             foreach my $area (@{$areas}) {
                    426:                 if ($count{$area} > 0) {
                    427:                     my $count_tag = 'flag_'.$counter;
1.23      raeburn   428:                     $r->print(&Apache::loncommon::start_data_table_row()."\n".
                    429:                               '<td><input name="'.$area.'" type="checkbox" ');
1.5       raeburn   430:                     if ($area eq 'board' || $area eq 'users') {
1.41      bisitz    431:                         $r->print('onclick="javascript:setOptions('."'$area','$counter'".');" ');
1.5       raeburn   432:                     }
1.23      raeburn   433:                     $r->print('/></td>'.
                    434:                               '<td>&nbsp;&nbsp;'.$$areaname{$area}.'&nbsp;&nbsp; - '.
                    435:                               &mt('[quant,_1,item]',$count{$area}).'</td>');
1.5       raeburn   436:                     if ($area eq 'board') {
1.23      raeburn   437:                         $r->print('<td>&nbsp;&nbsp;
                    438:                  <select name="db_handling">
                    439:                   <option value="-2">&lt;-- '.$lt{'chec'}.'</option>
                    440:                  </select>
                    441:                 </td>');
1.5       raeburn   442:                     } elsif ($area eq 'users') {
1.23      raeburn   443:                         $r->print('<td>&nbsp;&nbsp;
                    444:                  <select name="user_handling">
                    445:                   <option value="-2">&lt;-- '.$lt{'chec'}.'</option>
1.2       raeburn   446:                  </select>
1.23      raeburn   447:                 </td>');
1.5       raeburn   448:                     } else {
1.23      raeburn   449:                         $r->print('<td>&nbsp;&nbsp;'.&mt('None')."\n".
                    450:                                   '<input type="hidden" name="'.$count_tag.'" /></td>');
1.5       raeburn   451:                     }
                    452:                     $counter ++;
1.23      raeburn   453:                     $r->print(&Apache::loncommon::end_data_table_row());
1.5       raeburn   454:                 }
                    455:             }
1.23      raeburn   456:             $r->print(&Apache::loncommon::end_data_table());
1.5       raeburn   457:             if ($count{board} + $count{users} > 0) {
1.23      raeburn   458:                 $r->print(&Apache::lonhtmlcommon::topic_bar(4,$lt{'bbus'}));
1.5       raeburn   459:                 if ($$numcrs > 0) {
1.23      raeburn   460:                     $r->print($lt{'list'}.'<br /><br />'.$lt{'chco'}.'&nbsp;&nbsp;'."\n".
                    461:                               '<select name="targetcourse">
                    462:                                 <option value="-1">'.$lt{'nreq'}.'</option>
                    463:                                </select>');
1.5       raeburn   464:                 } else {
1.23      raeburn   465:                     $r->print($lt{'yodo'}.' '.$lt{'ifyo'});
                    466:                 }
                    467:             }
                    468:             $r->print('<br /><br />
                    469:           <input type="hidden" name="newdir" value="'.$env{'form.newdir'}.'" />
                    470:           <input type="hidden" name="conditions" value="'.$conditions.'" />
                    471:           <input type="hidden" name="source" value="'.$cms.'" />
                    472:           <input type="hidden" name="tempdir" value="'.$tempdir.'" />
1.36      raeburn   473:           <input type="hidden" name="filename" value="'.$fn.'" />
1.23      raeburn   474:           <input type="hidden" name="phase" value="four" />'."\n");
1.5       raeburn   475:             if ($count{board} == 0) {
1.23      raeburn   476:                 $r->print('<input type="hidden" name="board" value="" />'."\n");
1.5       raeburn   477:             }
                    478:             if ($count{users} == 0) {
1.23      raeburn   479:                 $r->print('<input type="hidden" name="users" value="" />'."\n");
1.5       raeburn   480:             }
1.41      bisitz    481:             $r->print('<input type="button" name="nextpage" value="'.$lt{'impa'}.'" onclick="javascript:nextPage('."'$counter.'".')" />&nbsp;&nbsp;&nbsp;
                    482:            <input type="button" name="exitpage" value="'.$lt{'exit'}.'" onclick="javascript:location.href='."'$fullpath'".'" /></form>');
1.5       raeburn   483:         } else {
1.23      raeburn   484:             $r->print($lt{'unpa'});
1.2       raeburn   485:         }
1.4       raeburn   486:     } else {
1.45      bisitz    487:         $r->print(
                    488:             '<br />'.&Apache::loncommon::confirmwrapper(
                    489:                 &Apache::lonhtmlcommon::confirm_success($lt{'proc'},1)
                    490:                .'<br />'.&mt('Error: [_1]',$unzip_result))
                    491:         );
1.5       raeburn   492:     }
                    493: }
1.1       raeburn   494: 
1.5       raeburn   495: # ---------------------------------------------------------------- Display Three
                    496: sub display_three {
1.36      raeburn   497:     my ($r,$uname,$udom,$areas,$areaname,$cmsmap,$destdir,$dirpath) = @_;
1.5       raeburn   498:     my $crs = '';
                    499:     my $cdom = '';
                    500:     my $db_handling = '';
                    501:     my $timenow = time; 
                    502:     my $announce_handling = 'ok';
1.11      albertel  503:     my $cms = $env{'form.source'};
                    504:     if ( defined($env{'form.bb_crs'}) ) {
                    505:         ($cdom,$crs) = split/\//,$env{'form.bb_crs'};
1.4       raeburn   506:     } 
1.5       raeburn   507:     my $user_crs = '';
                    508:     my $user_cdom = '';
                    509:     my $user_handling = '';
1.11      albertel  510:     if ( defined($env{'form.user_crs'}) ) {
                    511:         ($user_cdom,$user_crs) = split/\//,$env{'form.user_crs'};
1.5       raeburn   512:     }
1.36      raeburn   513:     my $seqstem = "/res/$udom/$uname/$dirpath";
1.9       raeburn   514:     my %importareas = ();
                    515:     my %includedres = ();
                    516:     my %includeditems = ();
1.10      raeburn   517:     my %randompicks = ();
1.5       raeburn   518:     my @targets = ();
                    519:     my %resources = ();
                    520:     my %items = ();
                    521:     my %hrefs = ();
                    522:     my %urls = ();
                    523:     my %resinfo = ();
                    524:     my %total = (
                    525:                    page => 0,
                    526:                    prob => 0,
                    527:                    seq => 0,
                    528:                    board => 0,         
                    529:                    quiz => 0,
                    530:                    surv => 0,
1.23      raeburn   531:                    file => 0,
1.5       raeburn   532:     );
                    533: 
                    534:     my @pages = ();
                    535:     my @sequences = ();
                    536:     my @resrcfiles = ();
1.19      raeburn   537:     my @assessmentfiles = ();
1.5       raeburn   538: 
1.11      albertel  539:     my $tempdir = $env{'form.tempdir'};
1.5       raeburn   540: 
                    541:     foreach my $area (@{$areas}) {
1.11      albertel  542:         if (defined($env{"form.$area"}) ) {
1.32      raeburn   543:             if ($cms eq 'angel5' && $area eq 'doc') {
1.5       raeburn   544:                 foreach (@{$$cmsmap{$cms}{$area}}) {
1.9       raeburn   545:                     $importareas{$_} = 1;
1.1       raeburn   546:                 }
1.5       raeburn   547:             } else {
1.9       raeburn   548:                 $importareas{$$cmsmap{$cms}{$area}} = 1;
1.2       raeburn   549:             }
1.5       raeburn   550:             if ($area eq 'board') {
1.11      albertel  551:                 $db_handling = $env{'form.db_handling'};
1.5       raeburn   552:             } elsif ($area eq 'users') {
1.11      albertel  553:                 $user_handling = $env{'form.user_handling'};
1.4       raeburn   554:             }
1.1       raeburn   555:         }
                    556:     }
1.9       raeburn   557: 
1.23      raeburn   558:     my %lt = &Apache::lonlocal::texthash (
                    559:                  yims => 'Your IMS package has been processed successfully.',
                    560:                  plsv => 'Please view the imported items and use the LON-CAPA editing tools to make changes.',
                    561:                  tseq => "The sequences directory contains a file named 'Top.sequence' which includes links to the items found at the top level of your IMS package. From there you can follow links to display all the imported items. Alternatively, you can browse the pages, sequences, problems and resfiles directories directly. Note if you rename a file, you will need to modify any .sequence files or .page files which include a reference to the renamed file.",
1.39      raeburn   562:                  tfin => 'The final step in the IMS import process is to publish the materials you have imported into your Authoring Space so that you can use them in a course. Once your files are published, subsequent re-publication will result in the storage of information about changes between the different versions.',
1.23      raeburn   563:                  disp => 'Display new directory',
                    564:                  proc => 'Processing of your IMS package failed, because the IMS content package did not contain an IMS manifest file.'
                    565:              );
1.19      raeburn   566:     my $manifest_result = &Apache::imsprocessor::process_manifest($cms,$tempdir,
                    567:                           \%resources,\%items,\%hrefs,\%resinfo,'prepare',
                    568:                           \%includedres);
1.43      raeburn   569: 
1.9       raeburn   570:     if ($manifest_result eq 'ok') {
1.43      raeburn   571:         my %possibledep;
1.46      raeburn   572:         foreach my $res (sort(keys(%resources))) {
1.9       raeburn   573:             if ($importareas{$resources{$res}{type}}) {
                    574:                 $includedres{$res} = 1;
1.19      raeburn   575:                 if ($resources{$res}{type} eq 'webct.manifest' || 
                    576:                      $resources{$res}{type} eq 'webct.assessment' ||
                    577:                      $resources{$res}{type} eq 'webct.question') {
                    578:                     push(@assessmentfiles,$res);
                    579:                 }   
1.43      raeburn   580:             } elsif ($resources{$res}{usedby}) {
                    581:                 $possibledep{$res} = 1;
                    582:             }
                    583:         }
                    584:         foreach my $res (sort(keys(%possibledep))) {
                    585:             if ($includedres{$resources{$res}{usedby}}) {
                    586:                 $includedres{$res} = 1;
1.9       raeburn   587:             }
                    588:         }
1.46      raeburn   589:         foreach my $itm (sort(keys(%items))) {
1.9       raeburn   590:             &Apache::imsprocessor::get_imports(\%includeditems,\%items,\%resources,\%importareas,$itm);
                    591:         }
                    592:     }
                    593: 
1.46      raeburn   594:     foreach my $itm (sort(keys(%includeditems))) {
1.9       raeburn   595:         &Apache::imsprocessor::get_parents(\%includeditems,\%items,$itm);
                    596:     }
                    597: 
1.19      raeburn   598:     $manifest_result = &Apache::imsprocessor::process_manifest($cms,$tempdir,
                    599:                        \%resources,\%items,\%hrefs,\%resinfo,'build',
                    600:                        \%includedres,\%includeditems);
1.43      raeburn   601: 
1.5       raeburn   602:     if ($manifest_result eq 'ok') {
1.9       raeburn   603:         &Apache::imsprocessor::target_resources(\%resources,\%importareas,\@targets);
1.5       raeburn   604: 
                    605:         my @boards = ();
                    606:         my @announcements = ();
                    607:         my @quizzes = ();
                    608:         my @surveys = ();
1.9       raeburn   609:         my @pools = ();
1.5       raeburn   610:         my @groups = ();
                    611:         my %messages = ();
                    612:         my @timestamp = ();
                    613:         my %boardnum = ();
                    614:         my @topurls = ();
                    615:         my @topnames = ();
1.7       raeburn   616:         my @packages = ();
1.5       raeburn   617: 
1.10      raeburn   618:         &Apache::imsprocessor::process_resinfo($cms,'CSTR',$tempdir,$destdir,\%items,\%resources,\@targets,\@boards,\@announcements,\@quizzes,\@surveys,\@pools,\@groups,\%messages,\@timestamp,\%boardnum,\%resinfo,$udom,$uname,$cdom,$crs,$db_handling,$user_handling,\%total,$seqstem,$seqstem,\@resrcfiles,\@packages,\%hrefs,\@pages,\@sequences,\%randompicks);
1.7       raeburn   619: 
1.43      raeburn   620:         my $copy_result = &Apache::imsprocessor::copy_resources('CSTR',$cms,\%hrefs,\%resources,$tempdir,\@targets,\%urls,$crs,$cdom,$destdir,$timenow,\@assessmentfiles,\%total);
1.5       raeburn   621:    
1.36      raeburn   622:         &Apache::imsprocessor::build_structure($cms,'CSTR',$destdir,\%items,\%resinfo,\%resources,\@targets,\%hrefs,$udom,$uname,$dirpath,$timenow,$cdom,$crs,\@timestamp,\%total,\@boards,\@announcements,\@quizzes,\@surveys,\@pools,\%boardnum,\@pages,\@sequences,\@topurls,\@topnames,\@packages,\%includeditems,\%randompicks);
1.5       raeburn   623: 
1.45      bisitz    624:         my $message =
                    625:             &Apache::lonhtmlcommon::confirm_success(
                    626:                 &mt('IMS import completed'))
                    627:            .'<br />'.$lt{'yims'}.' ';
1.5       raeburn   628: 
1.32      raeburn   629:         if ($cms eq 'angel5') {
1.45      bisitz    630:             $message .= &mt('A total of [quant,_1,sequence], [quant,_2,composite page], and [quant,_3,discussion board] have been created, and [quant,_4,file] copied.',$total{seq},$total{page},$total{board},$total{file})."\n";
1.23      raeburn   631:         } else {
1.45      bisitz    632:             $message .= &mt('A total of [quant,_1,sequence], [quant,_2,composite page], [quant,_3,discussion board], [quant,_4,quiz,quizzes], [quant,_5,survey], and [quant,_6,problem] have been created, and [quant,_7,file] copied.',$total{seq},$total{page},$total{board},$total{quiz},$total{surv},$total{prob},$total{file})."\n";
1.5       raeburn   633:         }
1.45      bisitz    634:         $r->print(
                    635:             '<br />'.&Apache::loncommon::confirmwrapper($message)
                    636:            .'<p>'.$lt{'plsv'}.' '.$lt{'tseq'}.'</p>'
                    637:            .'<p>'.$lt{'tfin'}.'</p>'
                    638:            .&Apache::lonhtmlcommon::actionbox(
                    639:                 ['<a href="/priv/'.$udom.'/'.$uname.'/'.$dirpath.'/">'.$lt{'disp'}.'</a>'])
                    640:         );
1.36      raeburn   641:         my $londocroot = $r->dir_config('lonDocRoot');
                    642:         if ($destdir =~ m{^\Q$londocroot/priv/$udom/$uname/$dirpath\E}) {
1.9       raeburn   643:             system (" rm -r -f $destdir/temp");
                    644:         }
1.5       raeburn   645:     } elsif ($manifest_result eq 'nomanifest') {
1.45      bisitz    646:         $r->print(
                    647:             '<br />'.&Apache::loncommon::confirmwrapper(
                    648:                 &Apache::lonhtmlcommon::confirm_success($lt{'proc'},1))
                    649:         );
1.4       raeburn   650:     }
1.5       raeburn   651: }
                    652: 
                    653: # ---------------------------------------------------------------- Get LON-CAPA Course Coordinator roles for this user
                    654: sub get_ccroles {
                    655:     my ($user,$dom,$crsentry,$crslist) = @_;
1.33      raeburn   656:     my %roles;
1.5       raeburn   657:     unless ($user eq '') {
1.33      raeburn   658:         my $ccrole = 'cc';
                    659:         %roles = &Apache::lonnet::get_my_roles($user,$dom,'userroles',undef,[$ccrole]);
1.4       raeburn   660:     }
1.5       raeburn   661:     my $iter = 0;
                    662:     my @codes = ();
                    663:     my %courses = ();
                    664:     my @crslist = ();
                    665:     my %descrip =();
1.33      raeburn   666:     foreach my $key (keys(%roles)) {
1.21      albertel  667:         if ($key =~ m{^/($LONCAPA::domain_re)/($LONCAPA::username_re)_cc$}) {
1.5       raeburn   668:             my $cdom = $1;
                    669:             my $crs = $2;
1.33      raeburn   670:             my $currcode = '';
                    671:             my %settings = &Apache::lonnet::get('environment',['internal.coursecode','description'],$cdom,$crs);
                    672:             if (defined($settings{'description'}) ) {
                    673:                 $descrip{$crs} = $settings{'description'};
                    674:             } else {
                    675:                 $descrip{$crs} = 'Unknown';
1.5       raeburn   676:             }
1.33      raeburn   677:             if (defined($settings{'internal.coursecode'}) ) {
                    678:                 $currcode = $settings{'internal.coursecode'};
                    679:                 if ($currcode eq '') {
1.5       raeburn   680:                     $currcode = "____".$iter;
                    681:                     $iter ++;
                    682:                 }
1.33      raeburn   683:             } else {
                    684:                 $currcode = "____".$iter;
                    685:                 $iter ++;
                    686:             }
                    687:             unless (grep/^$currcode$/,@codes) {
                    688:                 push @codes,$currcode;
                    689:                 @{$courses{$currcode}} = ();
1.1       raeburn   690:             }
1.33      raeburn   691:             push @{$courses{$currcode}}, $cdom.'/'.$crs;
1.5       raeburn   692:         }
                    693:     }
1.46      raeburn   694:     foreach my $code (sort(@codes)) {
1.5       raeburn   695:         foreach my $crsdom (@{$courses{$code}}) {
1.2       raeburn   696:             my ($cdom,$crs) = split/\//,$crsdom;
                    697:             my $showcode = '';
                    698:             unless ($code =~m/^____\d+$/) {  $showcode = $code; }
                    699:             $$crsentry{$crsdom} = $showcode.':'.$descrip{$crs};
1.5       raeburn   700:             push @{$crslist}, $crsdom;
1.2       raeburn   701:         }
                    702:     }
1.5       raeburn   703:     return;
1.2       raeburn   704: }
1.1       raeburn   705: 
                    706: # ---------------------------------------------------------------- Main Handler
                    707: sub handler {
                    708:     my $r=shift;
1.5       raeburn   709: 
1.36      raeburn   710:     my $fn=$env{'form.filename'};
1.5       raeburn   711: 
1.36      raeburn   712:     if ($env{'form.filename1'}) {
                    713:         $fn=$env{'form.filename1'}.$env{'form.filename2'};
1.1       raeburn   714:     }
1.36      raeburn   715:     $fn=~s{\+}{}g;
                    716: 
                    717:     unless ($fn) {
1.11      albertel  718:         $r->log_reason($env{'user.name'}.' at '.$env{'user.domain'}.
1.1       raeburn   719:                        ' unspecified filename for upload', $r->filename);
                    720:         return HTTP_NOT_FOUND;
                    721:     }
1.36      raeburn   722: 
1.38      raeburn   723:     my ($uname,$udom) = &Apache::lonnet::constructaccess($fn);
1.36      raeburn   724:     if (($uname eq '') || ($udom eq '')) {
                    725:         $r->log_reason($uname.' at '.$udom.
                    726:                        ' trying to publish file '.$fn.' - not authorized',
                    727:                        $r->filename);
                    728:         return HTTP_NOT_ACCEPTABLE;
                    729:     }
                    730: 
                    731:     my $londocroot = $r->dir_config('lonDocRoot');
                    732:     my $zipupload = $londocroot.$fn;
                    733:     my $fullpath = &File::Basename::dirname($fn);
                    734:     unless ($fullpath =~ m{/$}) {
1.1       raeburn   735:         $fullpath .= '/';
                    736:     }
1.5       raeburn   737: 
1.36      raeburn   738: # get personal information for this user
                    739:     my $user=$env{'user.name'};
                    740:     my $dom=$env{'user.domain'};
                    741: 
                    742:     my $javascript = '';
                    743:     my $page_name = '';
                    744:     my $current_page = '';
                    745:     my $qcount = '';
1.5       raeburn   746:     my @areas = ();
                    747:     my %cmsmap = ();
                    748:     my %areaname = ();
                    749:     my $numcrs = 0;
                    750:              
                    751:     &Apache::imsprocessor::ims_config(\@areas,\%cmsmap,\%areaname);
1.1       raeburn   752: # ----------------------------------------------------------- Start page output
                    753:     &Apache::loncommon::content_type($r,'text/html');
                    754:     $r->send_http_header;
1.5       raeburn   755: 
1.23      raeburn   756:     my $formname_one = 'info';
1.11      albertel  757:     if ($env{'form.phase'} eq 'two') {
1.36      raeburn   758:         $javascript = &jscript_one($fullpath,$formname_one);
1.11      albertel  759:     } elsif ($env{'form.phase'} eq 'three') {
1.36      raeburn   760:         $javascript = &jscript_two($user,$dom,\$numcrs);
                    761:     }
                    762:     if ($javascript ne '') {
                    763:         $javascript = <<"END_JS";
                    764: <script type="text/javascript">
                    765: // <![CDATA[
                    766: 
                    767: $javascript
                    768: 
                    769: // ]]>
                    770: </script>
                    771: END_JS
1.1       raeburn   772:     }
1.14      albertel  773: 
1.39      raeburn   774:     my $title = 'Upload IMS package to Authoring Space';
1.20      albertel  775:     $r->print(&Apache::loncommon::start_page($title, $javascript));
1.14      albertel  776: 
1.11      albertel  777:     if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
1.37      bisitz    778:         $r->print('<p><span class="LC_info">'
1.31      bisitz    779:                   .&mt('Co-Author [_1]',$uname.':'.$udom)
                    780:                   .'</span></p>'
1.29      bisitz    781:         );
1.36      raeburn   782:     }
1.11      albertel  783:     if ($env{'form.phase'} eq 'two') {
1.36      raeburn   784:         my $flag = &Apache::lonupload::phasetwo($r,$fn,'imsimport');
1.1       raeburn   785:         if ($flag eq 'ok') {
1.36      raeburn   786:             &display_one($r,$fn,$fullpath,$formname_one);
1.45      bisitz    787:         } else {
                    788:             $r->print(
                    789:                 '<br />'.&Apache::loncommon::confirmwrapper(
                    790:                     &Apache::lonhtmlcommon::confirm_success(
                    791:                         &mt('Error uploading IMS package'),1))
                    792:             );
1.5       raeburn   793:         }
1.11      albertel  794:     } elsif ( ($env{'form.phase'} eq 'three') || ($env{'form.phase'} eq 'four') ) {
1.36      raeburn   795:         my $destdir = $env{'form.newdir'};
                    796:         my $dirpath = $destdir;
                    797:         $dirpath =~ s{^\Q$londocroot/priv/$udom/$uname/\E}{};
                    798: 
1.11      albertel  799:         if ($env{'form.phase'} eq 'three') {
1.36      raeburn   800:             &display_two($r,$zipupload,\@areas,\%areaname,\%cmsmap,$fn,\$numcrs,$fullpath);
1.11      albertel  801:         } elsif ($env{'form.phase'} eq 'four') {
1.36      raeburn   802:             &display_three($r,$uname,$udom,\@areas,\%areaname,\%cmsmap,$destdir,$dirpath);
1.1       raeburn   803:         }
                    804:     } else {
1.40      raeburn   805:         &Apache::lonupload::phaseone($r,$fn,'imsimport',$uname,$udom);
1.1       raeburn   806:     }
1.14      albertel  807:     $r->print(&Apache::loncommon::end_page());
1.1       raeburn   808:     return OK;
                    809: }
                    810: 1;
                    811: __END__

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