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

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

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