File:  [LON-CAPA] / loncom / imspackages / imsimportdocs.pm
Revision 1.1: download - view: text, annotated - select for diffs
Tue Mar 2 15:45:06 2004 UTC (20 years, 5 months ago) by raeburn
Branches: MAIN
CVS tags: HEAD
Modularization of imsimport.pm -> imsprocessor.pm
imsprocessor.pm contains routines to allow import of IMS packages into both
an author's contrsuction space, and also into a course directly via the DOCS interface.

imsimportdocs provides the user interface for import on an IMS package directly into a course using the DOCS screen. Both are currently incomplete, as additional existing routines in imsimport.pm need to be modularized, (and ins ome cases modified) to support both DOCS and CSTR targets, before routines are moved to imsprocessor.pm

    1: package Apache::imsimportdocs;
    2: 
    3: use Apache::lonnet;
    4: use Apache::loncommon;
    5: use Apache::lonlocal;
    6: use Apache::imsprocessor;
    7: use LONCAPA::Configuration;
    8: 
    9: sub jscript_one {
   10:     my $javascript = shift;
   11:     $$javascript = qq#
   12: function verify() {
   13:  if ((document.forms.pickcms.uploadname.value == '')  || (!document.forms.pickcms.uploadname.value)) {
   14:    alert("You must provide the name of the IMS package to be imported")
   15:    return false
   16:  }
   17:  if (document.forms.pickcms.source.selectedIndex == 0) {
   18:    alert("You must choose the Course Management System from which the IMS package was exported");
   19:    return false
   20:  }
   21:  return true
   22: }
   23: 
   24: function nextPage() {
   25:  if (verify()) {
   26:    document.forms.pickcms.submit()
   27:  }
   28: }
   29: #;
   30:  
   31: }
   32: 
   33: sub jscript_two {
   34:     my $javascript = shift;
   35:     $$javascript = qq#
   36: function setOptions(caller,itemnum) {
   37:   var opForm = document.forms.pickoptions
   38:   var menu = 1 + itemnum*2
   39:   opForm.elements[menu].length = 0
   40:   if (opForm.elements[itemnum*2].checked == true) {
   41:     if (caller == "board") {
   42:       opForm.elements[menu].options[0] = new Option("Select","-1",true,true)
   43:       opForm.elements[menu].options[1] = new Option("Import topics only","topics",true,true)
   44:       opForm.elements[menu].options[2] = new Option("Import topics & posts (with author)","allpost",true,true)
   45:       opForm.elements[menu].options[3] = new Option("Import topics & posts (no author)","allanon",true,true)
   46:     }
   47:     else { 
   48:       if (caller == "users") {
   49:         opForm.elements[menu].length = 0
   50:         opForm.elements[menu].options[0] = new Option("Select","-1",true,true)
   51:         opForm.elements[menu].options[1] = new Option("Enroll students only","students",true,true)
   52:         opForm.elements[menu].options[2] = new Option("Enroll all users","all",true,true)
   53:       }
   54:     }
   55:   }
   56:   else {
   57:     opForm.elements[menu].options[0] = new Option("Not required","0",true,true)
   58:   }
   59:   opForm.elements[menu].selectedIndex = 0
   60: }
   61: 
   62: function verify(caller) { 
   63:   var opForm = document.forms.pickoptions
   64:   var totcheck = 0;
   65:   for (var i=0; i<caller; i++) {
   66:     if (opForm.elements[2*i].checked == true) {
   67:       totcheck ++
   68:       if (opForm.elements[2*i].name == "board") { 
   69:         if (opForm.elements[2*i+1].selectedIndex == 0) {     
   70:           alert("You must select one of the additional options when importing Discussion Boards ")
   71:           return false
   72:         }
   73:       }
   74:       if (opForm.elements[2*i].name == "users") {
   75:         if (opForm.elements[2*i+1].selectedIndex == 0) {     
   76:           alert("You must select one of the additional options when importing Enrollment")
   77:           return false
   78:         }
   79:       }
   80:     }
   81:   }
   82:   if (totcheck == 0) {
   83:     alert("You must check the Checkbox for at least one Content Type");
   84:     return false
   85:   }
   86:   return true
   87: }
   88: 
   89: function nextPage(caller) {
   90:  if (verify(caller)) {
   91:    document.forms.pickoptions.submit()
   92:  }
   93: }
   94: #;
   95: }
   96: 
   97: sub handler {
   98:     my $r = shift;
   99:     my $javascript = '';
  100:     &Apache::loncommon::content_type($r,'text/html');
  101:     $r->send_http_header;
  102:     return OK if $r->header_only;
  103: 
  104:     my @areas = ("doc","extlink","announce","staff","board","quiz","survey","pool","users");
  105:     my %cmsmap = ();
  106:     %{$cmsmap{bb5}} = (
  107:                 announce => 'resource/x-bb-announcement',
  108:                 board => 'resource/x-bb-discussionboard',
  109:                 doc => 'resource/x-bb-document',
  110:                 extlink => 'resource/x-bb-externallink',
  111:                 pool => 'assessment/x-bb-pool',
  112:                 quiz => 'assessment/x-bb-quiz',
  113:                 staff => 'resource/x-bb-staffinfo',
  114:                 survey => 'assessment/x-bb-survey',
  115:                 users => 'course/x-bb-user',
  116:                 );
  117:  
  118:     %{$cmsmap{angel}} =  (
  119:                 board => 'BOARD',
  120:                 extlink => 'LINK',
  121:                 msg => 'MESSAGE',
  122:                 quiz => 'QUIZ',
  123:                 survey => 'FORM',
  124:                 );
  125: 
  126:     @{$cmsmap{angel}{doc}} = ('FILE','PAGE');
  127: 
  128: # get course data
  129:     my $coursenum=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};
  130:     my $coursedom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
  131:     my $coursehome=$ENV{'course.'.$ENV{'request.course.id'}.'.home'};
  132: 
  133: # get personal data
  134:  
  135:     my $uname=$ENV{'user.name'};
  136:     my $udom=$ENV{'user.domain'};
  137:     my $plainname=&Apache::lonnet::escape(
  138:                      &Apache::loncommon::plainname($uname,$udom));
  139: 
  140: # does this user have privileges to post, etc?
  141:     my $allowed=&Apache::lonnet::allowed('mdc',$ENV{'request.course.id'});
  142:     unless ($allowed) {
  143:         $r->print("<html><head><title>The LearningOnline Network with CAPA</title></head>");
  144:         $r->print(&Apache::loncommon::bodytag('Import IMS package'));  
  145:         $r->print('<h3>'.&mt('Modification of Course Contents Disallowed').'</h3>'.&mt('Your current role does not grant you the right to modify course content in this course.').'</body></html>');
  146:         return OK;
  147:     }
  148: 
  149:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
  150:        ['phase']);
  151: 
  152:     if ($ENV{'form.phase'} eq 'one') {    
  153:         &jscript_one(\$javascript);
  154:     } elsif ($ENV{'form.phase'} eq 'two') {
  155:         &jscript_two(\$javascript);
  156:     }
  157: 
  158: # print screen
  159:     $r->print(<<ENDHEAD);
  160: <html>
  161: <head>
  162: <title>The LearningOnline Network with CAPA</title>
  163: <script type="text/javascript">
  164: <!--
  165: $javascript
  166: -->
  167: </script>
  168: </head>
  169: ENDHEAD
  170: # -------------------------------------------------------------------- Body tag
  171:     $r->print(&Apache::loncommon::bodytag('Import IMS package'));
  172:     if ($ENV{'form.phase'} eq 'one') {
  173:         &display_one($r);       
  174:     } elsif ($ENV{'form.phase'} eq 'two') {
  175:         &display_two($r,$coursenum,\@areas,%cmsmap);
  176:     } elsif ($ENV{'form.phase'} eq 'three') {
  177:         &display_three($r,$coursenum,$coursedom,$coursehome,\@areas,%cmsmap);
  178:     }   
  179:     $r->print("</body><html>");
  180: } 
  181: 
  182: sub uploadzip {
  183:     my $tempdir = shift;
  184:     my $fname=$ENV{'form.uploadname.filename'};
  185: # Replace Windows backslashes by forward slashes
  186:     $fname=~s/\\/\//g;
  187: # Get rid of everything but the actual filename
  188:     $fname=~s/^.*\/([^\/]+)$/$1/;
  189: # Replace spaces by underscores
  190:     $fname=~s/\s+/\_/g;
  191: # Replace all other weird characters by nothing
  192:     $fname=~s/[^\w\.\-]//g;
  193: # See if there is anything left
  194:     unless ($fname) { return 'error: no uploaded file'; }
  195: 
  196: # Save the file
  197:     chomp($ENV{'form.uploadname'});
  198:     open(my $fh,'>'.$tempdir.'/'.$fname);
  199:     print $fh $ENV{'form.uploadname'};
  200:     close($fh);
  201:     return $fname;   
  202: }
  203: 
  204: sub display_one {
  205:     my $r = shift;
  206:     my $timestamp = time;
  207:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['folder']);
  208: 
  209:     $r->print(<<ENDBLOCK);
  210: <form action="/adm/imsimportdocs" method="post" enctype="multipart/form-data" name="pickcms">
  211:   <table border='0' bgcolor='#F6F6F6' cellspacing='0' cellpadding ='0' width='100%'>
  212:    <tr>
  213:     <td colspan='2'>
  214:      <table border='0' cellspacing='0' cellpadding='0'>
  215:       <tr>
  216:         <td colspan='2'  align='left'>&nbsp;
  217:         </td>
  218:        </tr>
  219:        <tr bgcolor='#CCCCFF'>
  220:         <td valign='middle'><img src='/res/adm/pages/bl_step1.gif'>&nbsp;
  221:         </td>
  222:         <td width='100%' align='left'>&nbsp;&nbsp;
  223:          <font face='arial,helvetica,sans-serif'><b>Specify the Course Management system used to create the package.</b>&nbsp;&nbsp;
  224:          </font>
  225:        </td>
  226:       </tr>
  227:       <tr>
  228:        <td colspan='2'>&nbsp;</td>
  229:       </tr>
  230:       <tr>
  231:        <td>&nbsp;</td>
  232:        <td>
  233:         <font face='Arial,Helvetica,sans-serif'>
  234: Please choose the CMS used to create your IMS content package.&nbsp;&nbsp;
  235:         <select name="source">
  236:          <option value='-1' selected="true">Please select
  237:          <option value='bb5'>Blackboard 5
  238:          <option value='angel'>ANGEL
  239:         </select>
  240:         </font>
  241:        </td>
  242:       </tr>
  243:       <tr>
  244:        <td colspan='2'>&nbsp;</td>
  245:       </tr>
  246:       <tr>
  247:        <td colspan='2'>&nbsp;</td>
  248:       </tr>
  249:       <tr bgcolor='#CCCCFF'>
  250:         <td valign='middle'><img src='/res/adm/pages/bl_step2.gif'>&nbsp;
  251:         </td>
  252:         <td width='100%' align='left'>&nbsp;&nbsp;
  253:          <font face='arial,helvetica,sans-serif'><b>Locate the IMS content package you wish to upload.</b>&nbsp;&nbsp;
  254:          </font>
  255:        </td>
  256:       </tr>
  257:       <tr>
  258:        <td colspan='2'>&nbsp;</td>
  259:       </tr>
  260:       <tr>
  261:        <td colspan='2'>&nbsp;
  262:         <input type="hidden" name="folder" value="$ENV{'form.folder'}" />
  263:         <input type="hidden" name="phase" value="two" />
  264:         <input type="file" name="uploadname" size="40" />
  265:        </td>
  266:       </tr>
  267:       <tr>
  268:        <td colspan='2'>&nbsp;</td>
  269:       </tr>
  270:       <tr>
  271:        <td>&nbsp;</td>
  272:        <td><font face='arial,helvetica,sans-serif'>If you have selected the CMS, and located the IMS package, you should click the 'Upload IMS package' button to upload the file to the server.</font></td>
  273:       </tr>
  274:       <tr>
  275:        <td colspan='2'>&nbsp;</td>
  276:       </tr>
  277:       <tr
  278:        <td colspan='2'>
  279:         <table border='0' cellspacing='0' cellpadding='0' width="100%">
  280:          <tr>
  281:           <td align='left'>
  282:            <input type="button" name="exitpage" value="Exit now" onClick="javascript:self.close()">
  283:           </td>
  284:           <td align='right'>
  285:            <input type="button" name="nextpage" value="Upload IMS package" onClick="javascript:nextPage()">
  286:           </td>
  287:          </tr>
  288:         </table>
  289:        </td>
  290:       </tr>
  291:      </table>
  292:     </td>
  293:    </tr>
  294:   </table>
  295: </form>
  296: ENDBLOCK
  297: }
  298: 
  299: 
  300: sub display_two {
  301:     my ($r,$crs,$areasref,%cmsmap) = @_;
  302:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['folder','source']);
  303:     my $cms = $ENV{'form.source'};
  304:     my $tempdir = &Apache::imsprocessor::create_tempdir('DOCS',$crs);
  305:     my $fname = &uploadzip($tempdir);
  306:     my $unzip_result = '';
  307:     my $manifest_result = '';
  308:     unless ($tempdir eq '') {
  309:         $unzip_result = &Apache::imsprocessor::expand_zip($tempdir,$fname);
  310:     }
  311:     my %resources = ();
  312:     my %items = ();
  313:     my %hrefs = ();
  314:     my %count = ();
  315:     my @bgcolors = ("#eeeeee","#dddddd");
  316: 
  317:     my $counter = 0;
  318:     my $iter = 0;
  319:     my %count = (
  320:                 announce => 0,
  321:                 board => 0,
  322:                 doc => 0,
  323:                 extlink => 0,
  324:                 msg => 0,
  325:                 pool => 0,
  326:                 quiz => 0,
  327:                 staff => 0,
  328:                 survey => 0,
  329:                 users => 0,
  330:                 );
  331: 
  332:     my %areaname = (
  333:                 announce => 'Announcements',
  334:                 board => 'Discussion Boards',
  335:                 doc => 'Documents, pages &amp; folders',
  336:                 extlink => 'Links to external sites',
  337:                 pool => 'Question pools',
  338:                 quiz => 'Quizzes',
  339:                 staff => 'Staff information',
  340:                 survey => 'Surveys',
  341:                 users => 'Enrollment',
  342:                 );
  343:          
  344:     if ($unzip_result eq 'ok') {
  345:         $manifest_result = &Apache::imsprocessor::process_manifest($cms,$tempdir,\%resources,\%items,\%hrefs);
  346:         if ($manifest_result eq 'ok') {
  347:             foreach my $res (sort keys %resources) {
  348:                 if ($cms eq 'bb5') {
  349:                     foreach my $area (keys %{$cmsmap{$cms}}) {
  350:                         if ($resources{$res}{type} eq $cmsmap{$cms}{$area}) {
  351:                             $count{$area} ++;
  352:                         }
  353:                     }
  354:                 } elsif ($cms eq 'angel') {
  355:                     foreach my $area (keys %{$cmsmap{$cms}}) {
  356:                         if ($area eq 'doc') {
  357:                             if (grep/^$resources{$res}{type}$/,@{$cmsmap{$cms}{doc}}) {
  358:                                 $count{$area} ++;
  359:                             }
  360:                         } elsif ($resources{$res}{type} eq $cmsmap{$cms}{$area}) {
  361:                             $count{$area} ++;
  362:                         }
  363:                     }
  364:                 }
  365:             }
  366:             $r->print(<<ENDBLOCK);
  367: <form name="pickoptions" method="post">
  368:   <table border='0' bgcolor='#F6F6F6'' cellspacing='0' cellpadding ='0' width='100%'>
  369:    <tr>
  370:     <td colspan='2'>
  371:      <table border='0' cellspacing='0' cellpadding='0'>
  372:       <tr>
  373:        <td colspan='2'  align='left'>&nbsp;
  374:        </td>
  375:       </tr>
  376:       <tr bgcolor='#CCCCFF'>
  377:        <td valign='middle'><img src='/res/adm/pages/bl_step3.gif'>
  378:        </td>
  379:        <td width='100%' align='left'>&nbsp;&nbsp;
  380:         <font face='arial,helvetica,sans-serif'><b>Choose which content types you wish to import</b></font>
  381:        </td>
  382:       </tr>
  383:       <tr>
  384:        <td colspan='2'>&nbsp;</td>
  385:       </tr>
  386:       <tr>
  387:        <td>&nbsp;</td>
  388:        <td>
  389:         <table border='0' cellspacing='0' cellpadding='1' bgcolor='#000000'>
  390:          <tr>
  391:           <td>
  392:            <table border='0' cellspacing='0' cellpadding='0' bgcolor='#ffffff' width='100%'>
  393:             <tr>
  394:              <td>
  395:               <table border='0' cellspacing='1' cellpadding='1' bgcolor='#ffffff' width='100%'>
  396:                <tr bgcolor='#CCCCFF'>
  397:                 <td align='center'><font face='arial,helvetica,sans-serif'><b>Import?</b></font></td>           
  398:                 <td align='center'><font face='arial,helvetica,sans-serif'><b>Content type</b></font></td>
  399:                 <td align='center'><font face='arial,helvetica,sans-serif'><b>Additional options</b></font></td>
  400:                </tr>
  401: ENDBLOCK
  402:             foreach my $area (@{$areasref}) {
  403:                 if ($count{$area} > 0) {
  404:                     my $count_tag = 'flag_'.$counter;
  405:                     $r->print("               <tr bgcolor='@bgcolors[$iter]'>
  406:                 <td align='left'><font face='arial,helvetica,sans-serif'><input name='$area' type='checkbox' ");
  407:                     if ($area eq 'board' || $area eq 'users') {
  408:                         $r->print(qq|onClick='javascript:setOptions("$area","$counter")'|);
  409:                     }
  410:                     $r->print("/></font></td>
  411:                 <td align='left'><font face='arial,helvetica,sans-serif'>&nbsp;&nbsp;$areaname{$area}&nbsp;&nbsp; - $count{$area} item(s)</font></td>");
  412:                     if ($area eq 'board') {
  413:                         $r->print("            <td align='left'><font face='arial,helvetica,sans-serif'>&nbsp;&nbsp;
  414:                  <select name='bb_handling'>
  415:                   <option value='-2'>&lt;-- Check Import first
  416:                  </select></font>
  417:                 </td>");
  418:                     } elsif ($area eq 'users') {
  419:                         $r->print("            <td align='left'><font face='arial,helvetica,sans-serif'>&nbsp;&nbsp;
  420:                  <select name='user_handling'>
  421:                   <option value='-2'>&lt;-- Check Import first
  422:                  </select>
  423:                  </font>        
  424:                 </td>");
  425:                     } else {
  426:                         $r->print("            <td align='left'><font face='arial,helvetica,sans-serif'>&nbsp;&nbsp;None<input type='hidden' name='$count_tag' /></font></td>");
  427:                     }
  428:                     $counter ++;
  429:                     $iter = $counter%2;
  430:                 }
  431:             }
  432:             $r->print(<<ENDDOCUMENT);
  433:                </tr>
  434:               </table>
  435:              </td>
  436:             </tr>
  437:            </table>
  438:           </td>
  439:          </tr>
  440:         </table>
  441:        </td>
  442:       </tr>
  443:       <tr>
  444:        <td colspan='2'>&nbsp;<br /><br /></td>
  445:       </tr>
  446:       <tr>
  447:        <td>&nbsp;</td>
  448:        <td><font face='arial,helvetica,sans-serif'>Once you have checked the checkboxes for all areas you wish to import from the IMS package, and selected options (if available) you should click the 'Complete Import' button.</font></td>
  449:       </tr>
  450:       <tr>
  451:        <td colspan='2'>&nbsp;
  452:           <input type="hidden" name="folder" value="$ENV{'form.folder'}" />
  453:           <input type="hidden" name="source" value="$cms" />
  454:           <input type="hidden" name="tempdir" value="$tempdir" />
  455:           <input type="hidden" name="phase" value="three" />
  456:        </td>
  457:       </tr>
  458:       <tr>
  459:        <td colspan='2'>
  460:         <table border='0' cellspacing='0' cellpadding='0' width="100%">
  461:          <tr>
  462:           <td align='left'>
  463:            <input type='button' name='exitpage' value='Exit now' onClick="javascript:self.close()">
  464:           </td>
  465:           <td align='right'>
  466:            <input type="button" name="nextpage" value="Complete Import" onClick="javascript:nextPage($counter)">
  467:           </td>
  468:          </tr>
  469:         </table>
  470:        </td>
  471:       </tr>
  472:      </table>
  473:     </td>
  474:    </tr>
  475:   </table>
  476: ENDDOCUMENT
  477:         } else {
  478:             $r->print("Unpacking of your IMS package failed because an IMS manifest file was not located in the package\n");
  479:         }
  480:     } else {
  481:         $r->print("Processing of your IMS package failed because the file you uploaded could not be unzipped\n");
  482:     }
  483: }
  484: 
  485: 
  486: sub display_three {
  487:    my ($r,$crs,$cdom,$chome,$areas,%cmsmap) = @_;
  488:    $r->print("You reached phase three");
  489:    my $cms = $ENV{'form.source'};
  490:    my $tempdir = $ENV{'form.tempdir'};
  491:    my $longcrs = '';
  492:    if ($crs =~ m/^(\d)(\d)(\d)/) {
  493:        $longcrs = $1.'/'.$2.'/'.$3.'/'.$crs;
  494:    }
  495:    my $destdir = '';
  496:    my %imports = ();
  497:    my @targets = ();
  498:    my %resources = ();
  499:    my %items = ();
  500:    my %hrefs = ();
  501:    my %urls = ();
  502:    foreach my $area (@{$areas}) {
  503:        if (defined($ENV{"form.$area"}) ) {          
  504:            if ($cms eq 'angel' && $area eq 'doc') {
  505:                foreach (@{$cmsmap{$cms}{$area}}) {
  506:                    $imports{$_} = 1;
  507:                }
  508:            } else {
  509:                $imports{$cmsmap{$cms}{$area}} = 1;
  510:            }
  511:        }
  512:    }
  513:    
  514:    my $manifest_result = &Apache::imsprocessor::process_manifest($cms,$tempdir,\%resources,\%items,\%hrefs);
  515:    if ($manifest_result eq 'ok') {
  516:        &Apache::imsprocessor::target_resources(\%resources,\%imports,\@targets);
  517:        $copy_result = &Apache::imsprocessor::copy_resources('DOCS',$cms,\%hrefs,$tempdir,\@targets,\%urls,$crs,$cdom,$chome,$destdir); 
  518:    }
  519: }
  520: 
  521: 1;
  522: __END__

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