--- rat/lonpageflip.pm 2015/03/14 22:26:50 1.88 +++ rat/lonpageflip.pm 2017/02/18 23:39:24 1.92 @@ -2,7 +2,7 @@ # # Page flip handler # -# $Id: lonpageflip.pm,v 1.88 2015/03/14 22:26:50 raeburn Exp $ +# $Id: lonpageflip.pm,v 1.92 2017/02/18 23:39:24 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -36,6 +36,7 @@ use LONCAPA; use Apache::Constants qw(:common :http REDIRECT); use Apache::lonnet; use Apache::loncommon(); +use Apache::lonnavmaps(); use Apache::lonuserstate; use Apache::lonlocal; use HTML::TokeParser; @@ -83,11 +84,18 @@ sub hash_src { my ($mapid,$resid)=split(/\./,$id); my $symb=&Apache::lonnet::encode_symb($hash{'map_id_'.$mapid}, $resid,$hash{'src_'.$id}); + my $anchor; + if ($hash{'ext_'.$id} eq 'true:') { + if ($hash{'src_'.$id} =~ /(\#.+)$/) { + $anchor = $1; + } + } if ($hash{'encrypted_'.$id}) { return (&Apache::lonenc::encrypted($hash{'src_'.$id}), - &Apache::lonenc::encrypted($symb)); + &Apache::lonenc::encrypted($symb), + $hash{'encrypted_'.$id},$anchor); } - return ($hash{'src_'.$id},$symb); + return ($hash{'src_'.$id},$symb,$hash{'encrypted_'.$id},$anchor); } sub move { @@ -237,6 +245,7 @@ sub first_accessible_resource { my ($newmapid,$newresid)=split(/\./,$newrid); my $symb=&Apache::lonnet::encode_symb($newmap,$newresid,$hash{'src_'.$newrid}); $furl=&add_get_param($hash{'src_'.$newrid},{ 'symb' => $symb }); + &check_for_syllabus(\$furl); if ($hash{'encrypted_'.$newrid}) { $furl=&Apache::lonenc::encrypted($furl); } @@ -248,6 +257,43 @@ sub first_accessible_resource { } } +sub first_answerable_ressymb { + my $navmap = Apache::lonnavmaps::navmap->new; + return unless (ref($navmap)); + my $iterator = $navmap->getIterator(undef,undef,undef,1); + return unless (ref($iterator)); + my ($curRes,$result); + while ($curRes = $iterator->next()) { + if (ref($curRes) && $curRes->is_problem()) { + foreach my $part (@{$curRes->parts()}) { + if ($curRes->tries($part) < $curRes->maxtries($part)) { + $result = $curRes->link().'?symb='.$curRes->shown_symb(); + last; + } + } + } + } + if ($result) { + return $result; + } else { + return &first_accessible_resource(); + } +} + +sub check_for_syllabus { + my ($srcref) = @_; + return unless (ref($srcref) eq 'SCALAR'); + if ($env{'request.course.id'}) { + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + if (($$srcref =~ m{^\Q/public/$cdom/$cnum/syllabus\E($|\?)}) && + ($ENV{'SERVER_PORT'} == 443) && + ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) { + $$srcref .= (($$srcref =~/\?/)? '&':'?') . 'usehttp=1'; + } + } +} + # ================================================================ Main Handler sub handler { @@ -264,39 +310,73 @@ sub handler { my %cachehash=(); my $multichoice=0; my %multichoicehash=(); - my ($redirecturl,$redirectsymb); + my ($redirecturl,$redirectsymb,$enc,$anchor); my $next=''; my @possibilities=(); &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['postdata']); if (($env{'form.postdata'})&&($env{'request.course.fn'})) { my ($direction,$currenturl) = ($env{'form.postdata'}=~/(\w+)\:(.*)/); - + if ($currenturl=~m|^/enc/|) { + $currenturl=&Apache::lonenc::unencrypted($currenturl); + } + $currenturl=~s/\.\d+\.(\w+)$/\.$1/; + $currenturl=~s/^https?\:\/\///; + $currenturl=~s/^[^\/]+//; + my ($preupdatepos,$last,$reinitcheck); + if ($direction eq 'return') { + if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', + &GDBM_READER(),0640)) { + $last=$hash{'last_known'}; + untie(%hash); + } + } elsif ($direction eq 'firstanswerable') { + my $furl = &first_answerable_ressymb(); + &Apache::loncommon::content_type($r,'text/html'); + $r->header_out(Location => + &Apache::lonnet::absolute_url().$furl); + return REDIRECT; + } elsif ($direction eq 'endplacement') { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + $r->print(&Apache::lonplacementtest::showresult()); + return OK; + } if ($env{'request.course.id'}) { # Check if course needs to be re-initialized my $loncaparev = $r->dir_config('lonVersion'); - my ($result,@reinit) = &Apache::loncommon::needs_coursereinit($loncaparev); - if ($result eq 'switch') { + ($reinitcheck,my @reinit) = &Apache::loncommon::needs_coursereinit($loncaparev); + if ($reinitcheck eq 'switch') { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; $r->print(&Apache::loncommon::check_release_result(@reinit)); return OK; - } elsif ($result eq 'update') { + } elsif ($reinitcheck eq 'update') { my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + $preupdatepos = &Apache::lonnet::symbread($currenturl); + unless ($direction eq 'return') { + if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', + &GDBM_READER(),0640)) { + $last=$hash{'last_known'}; + untie(%hash); + } + } my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum"); if ($ferr) { my $requrl = $r->uri; $env{'user.error.msg'}="$requrl:bre:0:0:Course not initialized"; $env{'user.reinit'} = 1; return HTTP_NOT_ACCEPTABLE; + } else { + if ($last) { + my ($murl,$id,$fn)=&Apache::lonnet::decode_symb($last); + unless (&Apache::lonnet::symbverify($last,$fn)) { + undef($last); + } + } } } } - - if ($currenturl=~m|^/enc/|) { - $currenturl=&Apache::lonenc::unencrypted($currenturl); - } - $currenturl=~s/\.\d+\.(\w+)$/\.$1/; if ($direction eq 'firstres') { my $furl=&first_accessible_resource(); &Apache::loncommon::content_type($r,'text/html'); @@ -305,14 +385,8 @@ sub handler { return REDIRECT; } - if ($direction eq 'return') { + if ($direction eq 'return') { # -------------------------------------------------------- Return to last known - my $last; - if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', - &GDBM_READER(),0640)) { - $last=$hash{'last_known'}; - untie(%hash); - } my $newloc; if (($last) && (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db', &GDBM_READER(),0640))) { @@ -320,46 +394,56 @@ sub handler { $id=$hash{'map_pc_'.&Apache::lonnet::clutter($murl)}.'.'.$id; $newloc=$hash{'src_'.$id}; if ($newloc) { - if ($hash{'encrypted_'.$id}) { $newloc=&Apache::lonenc::encrypted($newloc); } - + &check_for_syllabus(\$newloc); + if ($hash{'encrypted_'.$id}) { + $newloc=&Apache::lonenc::encrypted($newloc); + } elsif ($newloc =~ m{^(/adm/wrapper/ext/[^\#]+)\#([^\#]+)$}) { + $newloc = $1.&escape('#').$2; + } } else { $newloc='/adm/navmaps'; } untie %hash; } else { $newloc='/adm/navmaps'; - } - &Apache::loncommon::content_type($r,'text/html'); - $r->header_out(Location => - &Apache::lonnet::absolute_url().$newloc); + } + &Apache::loncommon::content_type($r,'text/html'); + $r->header_out(Location => + &Apache::lonnet::absolute_url().$newloc); - return REDIRECT; + return REDIRECT; } - $currenturl=~s/^https?\:\/\///; - $currenturl=~s/^[^\/]+//; # # Is the current URL on the map? If not, start with last known URL # + unless (&Apache::lonnet::is_on_map($currenturl)) { - my $last; - if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', - &GDBM_READER(),0640)) { - $last=$hash{'last_known'}; + if ($preupdatepos) { + undef($preupdatepos); + } elsif (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', + &GDBM_READER(),0640)) { + $last=$hash{'last_known'}; untie(%hash); } + my $newloc; if ($last) { $currenturl=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($last))[2]); } else { - &Apache::loncommon::content_type($r,'text/html'); - $r->header_out(Location => - &Apache::lonnet::absolute_url(). - '/adm/noidea.html'); - return REDIRECT; + &Apache::loncommon::content_type($r,'text/html'); + $r->header_out(Location => + &Apache::lonnet::absolute_url(). + '/adm/navmaps'); + return REDIRECT; } } # ------------------------------------------- Do we have any idea where we are? my $position; - if ($position=Apache::lonnet::symbread($currenturl)) { + if ($preupdatepos) { + $position = $preupdatepos; + } else { + $position=Apache::lonnet::symbread($currenturl); + } + if ($position) { # ------------------------------------------------------------------------- Yes my ($startoutmap,$mapnum,$thisurl)=&Apache::lonnet::decode_symb($position); $cachehash{$startoutmap}{$thisurl}=[$thisurl,$mapnum]; @@ -382,7 +466,7 @@ sub handler { @possibilities=split(/\,/,$next); if ($#possibilities==0) { # ---------------------------------------------- Only one possibility, redirect - ($redirecturl,$redirectsymb)=&hash_src($next); + ($redirecturl,$redirectsymb,$enc,$anchor)=&hash_src($next); $cachehash{$endupmap}{$redirecturl}= [$redirecturl,(split(/\./,$next))[1]]; } else { @@ -429,11 +513,20 @@ sub handler { } # ------------------------------------- Check for and display critical messages my ($redirect, $url) = &Apache::loncommon::critical_redirect(300); - unless ($redirect) { + unless ($redirect) { + &check_for_syllabus(\$redirecturl); $url=&Apache::lonnet::absolute_url().$redirecturl; - $url = &add_get_param($url, { 'symb' => $redirectsymb}); + my $addanchor; + if (($anchor ne '') && (!$enc || $env{'request.role.adv'})) { + $addanchor = 1; + $url =~ s/\#.+$//; + } + $url = &add_get_param($url, { 'symb' => $redirectsymb}); + if ($addanchor) { + $url .= $anchor; + } } - &Apache::loncommon::content_type($r,'text/html'); + &Apache::loncommon::content_type($r,'text/html'); $r->header_out(Location => $url); return REDIRECT; } else { @@ -450,7 +543,11 @@ sub handler { 'pick' => 'Please click on the the resource you intend to access', 'titleheader' => 'Title', - 'type' => 'Type'); + 'type' => 'Type', + 'update' => 'Content updated', + 'expupdate' => 'As a result of a recent update to the sequence of materials, it is not possible to complete the page flip.', + 'gonav' => 'Go to the Contents page to select a resource to display.', + ); if (&Apache::loncommon::course_type() eq 'Community') { $lt{'nav'} = &mt('Community Contents'); } @@ -467,9 +564,11 @@ $lt{'pick'}: $lt{'titleheader'}$lt{'type'} ENDSTART foreach my $id (@possibilities) { + my $src = $multichoicehash{'src_'.$id}; + &check_for_syllabus(\$src); $r->print( ''. @@ -479,17 +578,52 @@ ENDSTART } $r->print(''); } else { - $r->print( - &Apache::loncommon::start_page('No Resource') - .'

'.$lt{'title'}.'

' - .'

'.$lt{'explain'}.'

'); + if ($reinitcheck) { + if (&Apache::loncommon::course_type() eq 'Community') { + $r->print( + &Apache::loncommon::start_page('Community Contents Updated')); + } else { + $r->print( + &Apache::loncommon::start_page('Course Contents Updated')); + } + $r->print('

'.$lt{'update'}.'

' + .'

'.$lt{'expupdate'}.'
' + .$lt{'gonav'}.'

'); + } else { + if (($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') && + (!$env{'request.role.adv'})) { + my ($score,$incomplete) = &Apache::lonplacementtest::check_completion(undef,undef,1); + if ($incomplete) { + $r->print(&Apache::lonplacementtest::showincomplete($incomplete)); + } else { + $r->print(&Apache::lonplacementtest::showresult(1)); + } + } else { + $r->print( + &Apache::loncommon::start_page('No Resource') + .'

'.$lt{'title'}.'

' + .'

'.$lt{'explain'}.'

'); + } + } + } + unless (($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') || + ($env{'request.role.adv'})) { + if ((!@possibilities) && ($reinitcheck)) { + $r->print( + &Apache::lonhtmlcommon::actionbox( + ['
'.$lt{'nav'}.'' + ])); + } else { + $r->print( + &Apache::lonhtmlcommon::actionbox( + [''.$lt{'back'}.'', + ''.$lt{'nav'}.'' + ])); + } + } - $r->print( - &Apache::lonhtmlcommon::actionbox( - [''.$lt{'back'}.'', - ''.$lt{'nav'}.'' - ]) - .&Apache::loncommon::end_page()); + $r->print(&Apache::loncommon::end_page()); + return OK; } } else {