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

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

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