File:  [LON-CAPA] / rat / lonsequence.pm
Revision 1.48.2.1: download - view: text, annotated - select for diffs
Wed Feb 6 23:45:14 2019 UTC (5 years, 2 months ago) by raeburn
Branches: version_2_11_X
CVS tags: version_2_11_2_msu
- For 2.11
  Backport 1.51

    1: # The LearningOnline Network with CAPA
    2: #
    3: # Sequence Handler
    4: #
    5: # $Id: lonsequence.pm,v 1.48.2.1 2019/02/06 23:45:14 raeburn Exp $
    6: #
    7: # Copyright Michigan State University Board of Trustees
    8: #
    9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   10: #
   11: # LON-CAPA is free software; you can redistribute it and/or modify
   12: # it under the terms of the GNU General Public License as published by
   13: # the Free Software Foundation; either version 2 of the License, or
   14: # (at your option) any later version.
   15: #
   16: # LON-CAPA is distributed in the hope that it will be useful,
   17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19: # GNU General Public License for more details.
   20: #
   21: # You should have received a copy of the GNU General Public License
   22: # along with LON-CAPA; if not, write to the Free Software
   23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   24: #
   25: # /home/httpd/html/adm/gpl.txt
   26: #
   27: # http://www.lon-capa.org/
   28: #
   29: 
   30: 
   31: 
   32: package Apache::lonsequence;
   33: 
   34: use strict;
   35: use Apache::lonnet;
   36: use Apache::Constants qw(:common :http REDIRECT);
   37: use GDBM_File;
   38: use LONCAPA::map();
   39: use LONCAPA;
   40: use Apache::lonpageflip();
   41: use Apache::loncommon();
   42: use Apache::groupsort();
   43: use Apache::lonlocal;
   44: use Apache::lonnavmaps();
   45: use Apache::lonenc();
   46: use HTML::Entities();
   47: 
   48: my %selhash;
   49: my $successtied;
   50: 
   51: # ----------------------------------------- Attempt to read from resource space
   52: 
   53: sub attemptread {
   54:     my ($fn,$unsorted)=@_;
   55:     &Apache::lonnet::repcopy($fn);
   56:     if (-e $fn) {
   57: 	return &LONCAPA::map::attemptread($fn,$unsorted);
   58:     } else {
   59:         return ();
   60:     }
   61: }
   62: 
   63: sub mapread {
   64:     my $fn=shift;
   65:     &Apache::lonnet::repcopy($fn);
   66:     if (-e $fn) {
   67: 	return &LONCAPA::map::mapread($fn,'');
   68:     } else {
   69:         return ();
   70:     }
   71: }
   72: 
   73: # ---------------------------------------------------------------- View Handler
   74: 
   75: sub viewmap {
   76:     my ($r,$url)=@_;
   77: 
   78:     my $js;
   79:     if ($env{'form.forceselect'}) {
   80: 	$js = (<<ENDSCRIPT);
   81: <script type="text/javascript">
   82: 
   83: function select_group() {
   84:     window.location="/adm/groupsort?catalogmode=groupsec&mode=rat&acts="+document.forms.fileattr.acts.value;
   85: }
   86: 
   87: function queue(val) {
   88:     if (eval("document.forms."+val+".filelink.checked")) {
   89: 	var l=val.length;
   90: 	var v=val.substring(4,l);
   91: 	document.forms.fileattr.acts.value+='1a'+v+'b';
   92:     }
   93:     else {
   94: 	var l=val.length;
   95: 	var v=val.substring(4,l);
   96: 	document.forms.fileattr.acts.value+='0a'+v+'b';
   97:     }
   98: }
   99: 
  100: </script>
  101: ENDSCRIPT
  102:     }
  103: 
  104:     $r->print(&Apache::loncommon::start_page('Map Contents',$js).
  105: 	      '<h1>'.$url.'</h1>');
  106: # ------------------ This is trying to select. Provide buttons and tie %selhash
  107:     if ($env{'form.forceselect'}) { $r->print(<<ENDSELECT);
  108: <form name="fileattr"><input type="hidden" name="acts" value="" />
  109: <input type="button" name="close" value="CLOSE" onClick="self.close()" />
  110: <input type="button" name="groupimport" value="GROUP IMPORT"
  111: onClick="javascript:select_group()" />
  112: </form>   
  113: ENDSELECT
  114:     my $diropendb = 
  115:   LONCAPA::tempdir() .
  116:     "$env{'user.domain'}\_$env{'user.name'}_sel_res.db";
  117:         if (tie(%selhash,'GDBM_File',$diropendb,&GDBM_WRCREAT(),0640)) {
  118: 	    if ($env{'form.launch'} eq '1') {
  119: 	       &start_fresh_session();
  120: 	    }
  121:             $successtied=1;
  122: 
  123: # - Evaluate actions from previous page (both cumulatively and chronologically)
  124: 	    if ($env{'form.catalogmode'} eq 'import') {
  125: 		&Apache::groupsort::update_actions_hash(\%selhash);
  126: 	    }
  127: # -
  128:         }
  129:     }
  130: # ----------------------------- successtied is now '1' if in working selectmode
  131:     my ($errtext,$fatal)=&mapread(&Apache::lonnet::filelocation('',$url),'');
  132:     if ($fatal==1) {
  133:        $r->print('<p class="LC_warning">'
  134:                 .&mt('Map contents are not shown in order.')
  135:                 .'</p><br />');
  136:     }
  137:     my $idx=0;
  138:     foreach my $entry (&attemptread(&Apache::lonnet::filelocation('',$url))) {
  139: 	if (defined($entry)) {
  140:             $idx++;
  141:             if ($successtied) { 
  142: 		$r->print('<form name="form'.$idx.'">');
  143:             }
  144: 	    my ($title,$url)=split(/\:/,$entry);
  145: 	    $title = &LONCAPA::map::qtescape($title);
  146: 	    unless ($title) { $title=(split(/\//,$url))[-1] };
  147:             my $enc_title = &HTML::Entities::encode($title,'\'"<>&');
  148: 	    unless ($title) {
  149: 		$title='<i>'.&mt('Empty').'</i>';
  150: 		$enc_title = &mt('Empty');
  151: 	    }
  152: 	    $url  = &LONCAPA::map::qtescape($url);
  153:             my $enc_url = &HTML::Entities::encode($url,'\'"<>&');
  154:             if ($url) {
  155: 		if ($successtied) {
  156: 		    my $checked='';
  157: 	           if ($selhash{'store_'.$url}) {
  158: 	       	      $checked=' checked="checked"';
  159: 	           }
  160: 	           $selhash{"pre_${idx}_link"}=$url;
  161: 	           $selhash{"pre_${idx}_title"}=$title;
  162: 		    
  163: 		    $url  = &HTML::Entities::encode($url, '\'"<>&');
  164: 		    $r->print(<<ENDCHECKBOX);
  165: <input type='checkbox' name='filelink' 
  166: value='$enc_url' onClick='javascript:queue("form$idx")'$checked />
  167: <input type='hidden' name='title' value='$enc_title' />
  168: ENDCHECKBOX
  169:                 }
  170: 		$r->print('<a href="'.$enc_url.'">');
  171:             }
  172:             $r->print($enc_title);
  173:             if ($url) { $r->print('</a>'); }
  174:             if ($successtied) {
  175: 		$r->print('</form>');
  176:             } else {
  177: 		$r->print('<br />');
  178:             }
  179:         }
  180:     }
  181:     $r->print(&Apache::loncommon::end_page());
  182:     if ($successtied) {
  183: 	untie %selhash;
  184:     }
  185: }
  186: 
  187: # ----------------------------------------------------------- Clean out selhash
  188: sub start_fresh_session {
  189:     foreach my $item (keys(%selhash)) {
  190: 	if ($item =~ /^pre_/) {
  191: 	    delete $selhash{$item};
  192: 	}
  193: 	if ($item =~ /^store/) {
  194: 	    delete $selhash{$item};
  195: 	}
  196:     }
  197: }
  198: 
  199: 
  200: # ================================================================ Main Handler
  201: 
  202: sub handler {
  203:    my $r=shift;
  204: 
  205:    if ($r->header_only) {
  206:       &Apache::loncommon::content_type($r,'text/html');
  207:       $r->send_http_header;
  208:       return OK;
  209:    }
  210: 
  211:    my $requrl=$r->uri;
  212:    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
  213:                                           ['forceselect','launch','navmap']);
  214: 
  215:    if (($env{'request.course.fn'}) && ($env{'form.navmap'}) && ($env{'request.course.id'})) {
  216:        my $crstype = &Apache::loncommon::course_type();
  217:        unless (($crstype eq 'Placement') && (!$env{'request.role.adv'})) {
  218: 
  219:            # Check for critical messages and redirect if present.
  220:            my ($redirect,$url) = &Apache::loncommon::critical_redirect(300,'contents');
  221:            if ($redirect) {
  222:                &Apache::loncommon::content_type($r,'text/html');
  223:                $r->header_out(Location => $url);
  224:                return REDIRECT;
  225:            }
  226: 
  227:            # Check if course needs to be re-initialized
  228:            my $loncaparev = $r->dir_config('lonVersion');
  229:            my ($result,@reinit) = &Apache::loncommon::needs_coursereinit($loncaparev);
  230: 
  231:            if ($result eq 'switch') {
  232:                &Apache::loncommon::content_type($r,'text/html');
  233:                $r->send_http_header;
  234:                $r->print(&Apache::loncommon::check_release_result(@reinit));
  235:                return OK;
  236:            } elsif ($result eq 'update') {
  237:                my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
  238:                my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
  239:                my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum");
  240:                if ($ferr) {
  241:                    my $requrl = $r->uri;
  242:                    $env{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";
  243:                    $env{'user.reinit'} = 1;
  244:                    return HTTP_NOT_ACCEPTABLE;
  245:                }
  246:            }
  247: 
  248:            &Apache::loncommon::content_type($r,'text/html');
  249:            $r->send_http_header;
  250: 
  251:            my $mapurl = &Apache::lonnet::declutter($requrl);
  252:            my $maptitle = &Apache::lonnet::gettitle($mapurl);
  253:            my @crumbs = ({text => $maptitle, no_mt => 1});
  254:            my $args = {'bread_crumbs' => \@crumbs,
  255:                        'bread_crumbs_nomenu' => 1};
  256: 
  257:            # Create the nav map
  258:            my $navmap = Apache::lonnavmaps::navmap->new();
  259: 
  260:            if (ref($navmap)) {
  261:                # renderer call
  262:                if (&Apache::lonnet::is_on_map($requrl)) {
  263:                    @crumbs = ({text  => $crstype.' Contents',
  264:                                href  => "javascript:gopost('/adm/navmaps','')"});
  265:                    my $res = $navmap->getResourceByUrl($mapurl);
  266:                    if (ref($res)) {
  267:                        my $symb = $res->symb();
  268:                        if ($symb) {
  269:                            my ($parent) = &Apache::lonnet::decode_symb($res->symb());
  270:                            if ($parent ne $env{'course.'.$env{'request.course.id'}.'.url'}) {
  271:                                my @mapcrumbs = $navmap->recursed_crumbs($parent);
  272:                                if (@mapcrumbs) {
  273:                                    push(@crumbs,@mapcrumbs);
  274:                                }
  275:                            }
  276:                            $env{'request.symb'} = $symb;
  277:                        }
  278:                    }
  279:                    push(@crumbs,{text => $maptitle, no_mt => 1});
  280:                    $args = {'bread_crumbs' => \@crumbs,
  281:                             'bread_crumbs_nomenu' => 1};
  282:                    $r->print(&Apache::loncommon::start_page($maptitle,undef,$args));
  283: 
  284:                    my $renderArgs = { 'cols'                    => [0,1,2,3],
  285:                                       'url'                     => $mapurl,
  286:                                       'navmap'                  => $navmap,
  287:                                       'suppressNavmap'          => 1,
  288:                                       'suppressEmptySequences'  => 1,
  289:                                       'filterFunc'              => undef,
  290:                                       'resource_no_folder_link' => 1,
  291:                                       'r'                       => $r,
  292:                                       'caller'                  => 'sequence',
  293:                                       'notools'                 => 1,
  294:                                       'iterator_map'            => $mapurl,
  295:                                     };
  296: 
  297:                    my $render = &Apache::lonnavmaps::render($renderArgs);
  298: 
  299:                    # If no resources were found let the user know.
  300:                    if ($renderArgs->{'counter'} == 0) {
  301:                        $r->print('<p class="LC_info">'.
  302:                                  &mt('No items found in folder').
  303:                                  '</p>');
  304:                    }
  305:                    $r->print(&Apache::loncommon::end_page());
  306:                } else {
  307:                    $r->print(&Apache::loncommon::start_page($maptitle,undef,$args).
  308:                              '<p class="LC_info">'.
  309:                              &mt('Folder no longer appears to be a part of the course').
  310:                              '</p>'.
  311:                              &Apache::loncommon::end_page());
  312:                }
  313:            } else {
  314:                $r->print(&Apache::loncommon::start_page($maptitle,undef,$args).
  315:                          '<p class="LC_warning">'.
  316:                          &mt('Error: could not determine contents of folder').
  317:                          '</p>'.
  318:                          &Apache::loncommon::end_page());
  319:            }
  320:            $r->rflush();
  321:            return OK;
  322:        }
  323:    }
  324: 
  325:    my %hash;
  326:    my %bighash;
  327: 
  328:    $successtied=0;
  329: # ------------------------------------------------------------ Tie symb db file
  330:   my $disurl='';
  331:   my $dismapid='';
  332:   my $exitdisid = '';
  333:   my $arrow_dir = '';
  334:   my $is_encrypted = '';
  335: 
  336:   if (($env{'request.course.fn'}) && (!$env{'form.forceselect'})) {
  337:        my $last;
  338:        if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
  339:                     &GDBM_READER(),0640)) {
  340: 	   $last=$hash{'last_direction'};
  341:            untie(%hash);
  342:        }
  343:        my $direction='';
  344:        my $prevmap='';
  345:        if ($last) {
  346: 	   ($prevmap,undef,$direction)=&Apache::lonnet::decode_symb($last);
  347:        }
  348: # ------------------------------------------------------------- Tie big db file
  349:        if (tie(%bighash,'GDBM_File',$env{'request.course.fn'}.'.db',
  350:                     &GDBM_READER(),0640)) {
  351: 	   my $disid='';
  352:            my $randomout ='';
  353: 
  354:            if ($direction eq 'back') {
  355: 	       $disid=$bighash{'map_finish_'.$requrl};
  356:            } else {
  357:                $disid=$bighash{'map_start_'.$requrl};
  358:            }
  359:            if ($disid) {
  360: 	       $disurl=$bighash{'src_'.$disid};
  361:                $dismapid=(split(/\./,$disid))[1];
  362: 	       if (!$env{'request.role.adv'}) {
  363: 		   $randomout = $bighash{'randomout_'.$disid};
  364: 	       }
  365:                if (!$env{'request.role.adv'}) {
  366:                    $is_encrypted = $bighash{'encrypted_'.$disid};
  367:                }
  368:            } elsif (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
  369:                     &GDBM_READER(),0640)) {
  370:                $last=$hash{'last_known'};
  371:                untie(%hash);
  372:            }
  373: 
  374: 
  375: # ----------- If this is an empty one, or hidden, skip to next non-empty or non-hidden one
  376:            while ( ((!$disurl) && ($disid)) || ($randomout && $disid) ) {
  377: 	       $direction=($direction?$direction:'forward');
  378:                ($disid,$requrl)=
  379:                          &Apache::lonpageflip::fullmove($disid,
  380:                            &Apache::lonnet::declutter($requrl),$direction);
  381:                if ($disid) {
  382: 	           $disurl=$bighash{'src_'.$disid};
  383:                    $dismapid=(split(/\./,$disid))[1];
  384: 		   if (!$env{'request.role.adv'}) {
  385: 		       $randomout = $bighash{'randomout_'.$disid};
  386: 		   }
  387:                    if (!$env{'request.role.adv'}) {
  388:                        $is_encrypted = $bighash{'encrypted_'.$disid};
  389:                    }
  390:                }
  391:  	   }
  392:            $exitdisid = $disid;
  393:            $arrow_dir = $direction;
  394: 
  395: # --------------------------------------- Untie hash, make sure to come by here
  396:            untie(%bighash);
  397:        }
  398:    }
  399: 
  400: # now either disurl is set (going to first page), or we need another display
  401:    if ($disurl) {
  402: # -------------------------------------------------- Has first or last resource
  403:       my $showdisurl = $disurl;
  404:       if ($is_encrypted) {
  405:           $showdisurl = &Apache::lonenc::encrypted($disurl);
  406:       }
  407:       &Apache::lonnet::symblist($requrl,$disurl => [$disurl,$dismapid],
  408: 				'last_known' => [$disurl,$dismapid]); 
  409:       &Apache::loncommon::content_type($r,'text/html');
  410:       $r->header_out(Location => &Apache::lonnet::absolute_url($ENV{'SERVER_NAME'}).
  411:                                  $showdisurl);
  412:       return REDIRECT;
  413:    } else {
  414:        &Apache::loncommon::content_type($r,'text/html');
  415:        $r->send_http_header;
  416:        if ($exitdisid eq '' && $arrow_dir ne '') {
  417:            my %lt =&Apache::lonlocal::texthash(
  418:                    'nere' => 'Next resource could not be displayed',
  419:                    'goba' => 'Go Back',
  420:                    'nacc' => 'Course Contents',
  421:                           );
  422:            if (&Apache::loncommon::course_type() eq 'Community') {
  423:                $lt{'nav'} = &mt('Community Contents');
  424:            }
  425:            my $warnmsg;
  426:            if ($arrow_dir eq 'forward') {
  427:                $warnmsg = &mt('As all folders and sequences '
  428:                              .'following the current resource were empty, '
  429:                              .'you have now reached the end of the course.');
  430:            } elsif ($arrow_dir eq 'back') {
  431:                $warnmsg = &mt('As all folders and sequences '
  432:                              .'preceding the current resource were empty, '
  433:                              .'you have now reached the beginning of the course.');
  434:            }
  435:            my $start_page=
  436: 	       &Apache::loncommon::start_page('Empty Folder/Sequence');
  437:            my $end_page=
  438: 	       &Apache::loncommon::end_page();
  439:            $r->print(<<ENDNONE);
  440: $start_page
  441: <h3>$lt{'nere'}</h3>
  442: <p>$warnmsg</p>
  443: <ul>
  444:   <li><a href="javascript:history.go(-1)">$lt{'goba'}</a></li>
  445:   <li><a href="/adm/navmaps">$lt{'nacc'}</a></li>
  446: </ul>
  447: $end_page
  448: ENDNONE
  449:        } else {
  450:            &viewmap($r,$requrl);
  451:        }
  452:        return OK;
  453:    }
  454: }
  455: 
  456: 1;
  457: __END__
  458: 
  459: =head1 NAME
  460: 
  461: Apache::lonsequence
  462: 
  463: =head1 SYNOPSIS
  464: 
  465: Handler for showing sequence objects of
  466: educational resources.
  467: 
  468: This is part of the LearningOnline Network with CAPA project
  469: described at http://www.lon-capa.org.
  470: 
  471: =head1 SUBROUTINES
  472: 
  473: =over
  474: 
  475: =item handler()
  476: 
  477: =item viewmap()
  478: 
  479: =item attemptread()
  480: 
  481: =item mapread()
  482: 
  483: =item start_fresh_session()
  484: 
  485: =back
  486: 
  487: =cut
  488: 
  489: 
  490: 
  491: 
  492: 

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