--- rat/lonpageflip.pm 2021/12/31 20:03:33 1.80.8.13.2.1 +++ rat/lonpageflip.pm 2021/02/18 14:48:02 1.102 @@ -2,7 +2,7 @@ # # Page flip handler # -# $Id: lonpageflip.pm,v 1.80.8.13.2.1 2021/12/31 20:03:33 raeburn Exp $ +# $Id: lonpageflip.pm,v 1.102 2021/02/18 14:48:02 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -99,12 +99,10 @@ sub hash_src { } sub move { - my ($next,$endupmap,$direction,$firstres) = @_; + my ($next,$endupmap,$direction) = @_; my $safecount=0; my $allowed=0; my $deeplinkonly=0; - my $deeplinkchecked; - my $deeplink_login_pc; my $prev=$next; my ($prevmapid)=split(/\./,$next); do { @@ -117,80 +115,26 @@ sub move { if ($url eq '' || $symb eq '') { $allowed = 0; } else { - my $nodeeplinkcheck = 0; - if ($hash{'is_map_'.$next}) { - $nodeeplinkcheck = 1; - } - my $priv = &Apache::lonnet::allowed('bre',$url,$symb,'','','','',$nodeeplinkcheck); - $allowed = (($priv eq 'F') || ($priv eq '2') || ($priv eq 'A')); + my $priv = &Apache::lonnet::allowed('bre',$url,$symb); + $allowed = (($priv eq 'F') || ($priv eq '2')); } $deeplinkonly = 0; if ($hash{'deeplinkonly_'.$next}) { - my ($value,$level) = map { &unescape($_); } split(/:/,$hash{'deeplinkonly_'.$next}); - my ($state,$others,$listed,$scope,$protect) = split(/,/,$value); - unless (($state eq 'both') || ($hash{'is_map_'.$next})) { - if ($level eq 'resource') { + my ($value,$level) = split(/:/,$hash{'deeplinkonly_'.$next}); + if ($level eq 'resource') { + $deeplinkonly = 1; + } elsif ($level eq 'map') { + if ($mapid != $prevmapid) { $deeplinkonly = 1; - } elsif ($level eq 'map') { - if ($scope eq 'rec') { - unless ($mapid == $prevmapid) { - unless ($deeplinkchecked) { - $deeplink_login_pc = &get_deeplink_login_pc(); - $deeplinkchecked = 1; - } - if ($deeplink_login_pc) { - my $poss_map_pc; - if ($hash{'is_map_'.$next}) { - $poss_map_pc = $hash{'map_pc_'.$url}; - } else { - $poss_map_pc = $hash{'map_pc_'.$hash{'map_id_'.$mapid}}; - } - unless ($deeplink_login_pc == $poss_map_pc) { - unless (grep(/^$deeplink_login_pc$/,split(/,/,$hash{'map_hierarchy_'.$poss_map_pc}))) { - $deeplinkonly = 1; - } - } - } else { - $deeplinkonly = 1; - } - } - } elsif ($mapid != $prevmapid) { - $deeplinkonly = 1; - } } } - } elsif (($hash{'deeplinkonly_'.$prev}) && (!$firstres)) { - my ($value,$level) = map { &unescape($_); } split(/:/,$hash{'deeplinkonly_'.$prev}); - my ($state,$others,$listed,$scope,$protect) = split(/,/,$value); - unless (($state eq 'both') || ($hash{'is_map_'.$prev})) { - if ($level eq 'resource') { + } elsif ($hash{'deeplinkonly_'.$prev}) { + my ($value,$level) = split(/:/,$hash{'deeplinkonly_'.$prev}); + if ($level eq 'resource') { + $deeplinkonly = 1; + } elsif ($level eq 'map') { + if ($mapid != $prevmapid) { $deeplinkonly = 1; - } elsif ($level eq 'map') { - if ($scope eq 'rec') { - unless ($mapid == $prevmapid) { - unless ($deeplinkchecked) { - $deeplink_login_pc = &get_deeplink_login_pc(); - $deeplinkchecked = 1; - } - if ($deeplink_login_pc) { - my $poss_map_pc; - if ($hash{'is_map_'.$prev}) { - $poss_map_pc = $hash{'map_pc_'.$url}; - } else { - $poss_map_pc = $hash{'map_pc_'.$hash{'map_id_'.$mapid}}; - } - unless ($deeplink_login_pc == $poss_map_pc) { - unless (grep(/^$deeplink_login_pc$/,split(/,/,$hash{'map_hierarchy_'.$poss_map_pc}))) { - $deeplinkonly = 1; - } - } - } - } - } else { - if ($mapid != $prevmapid) { - $deeplinkonly = 1; - } - } } } } @@ -200,10 +144,9 @@ sub move { && ( (!$hash{'src_'.$next}) || ( - (!$env{'request.role.adv'}) - && (($hash{'randomout_'.$next}) - || ($deeplinkonly) - || ($hash{'deeplinkout_'.$next})) + (!$env{'request.role.adv'}) + && (($hash{'randomout_'.$next}) + || ($deeplinkonly)) ) || (!$allowed) ) @@ -238,7 +181,7 @@ sub get_next_possible_move { } if ($thiscond>$mincond) { $mincond=$thiscond; } } - } + } foreach my $id (split(/\,/,$posnext)) { my ($linkid,$condval)=split(/\:/,$id); if ($condval>=$mincond) { @@ -280,7 +223,7 @@ sub get_next_possible_move { } if ($thiscond>$mincond) { $mincond=$thiscond; } } - } + } foreach my $id (split(/\,/,$posnext)) { my ($linkid,$condval)=split(/\:/,$id); if ($condval>=$mincond) { @@ -313,33 +256,23 @@ sub first_accessible_resource { if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db', &GDBM_READER(),0640)) { $furl=$hash{'first_url'}; - my (%args,$url,$argstr); - if ($furl =~ m{^/enc/}) { - ($url,$argstr) = split(/\?/,&Apache::lonenc::unencrypted($furl)); - } else { - ($url,$argstr) = split(/\?/,$furl); - } - foreach my $pair (split(/\&/,$argstr)) { + my %args; + my ($url,$args) = split(/\?/,$furl); + foreach my $pair (split(/\&/,$args)) { my ($name,$value) = split(/=/,$pair); $args{&unescape($name)} = &unescape($value); } - my $priv = &Apache::lonnet::allowed('bre',$url,$args{'symb'}); - my $allowed = (($priv eq 'F') || ($priv eq '2') || ($priv eq 'A')); - if (!$allowed) { + if (!&Apache::lonnet::allowed('bre',$url,$args{'symb'})) { # Wow, we cannot see this ... move forward to the next one that we can see - my ($newrid,$newmap)=&move($hash{'first_rid'},$hash{'first_mapurl'},'forward',1); + my ($newrid,$newmap)=&move($hash{'first_rid'},$hash{'first_mapurl'},'forward'); # Build the new URL - if ($newrid eq '') { - $furl = '/adm/navmaps'; - } else { - 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 }); - if ($hash{'encrypted_'.$newrid}) { - $furl=&Apache::lonenc::encrypted($furl); - } - } - } + 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 }); + if ($hash{'encrypted_'.$newrid}) { + $furl=&Apache::lonenc::encrypted($furl); + } + } untie(%hash); return $furl; } else { @@ -347,8 +280,31 @@ 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_http_req { - my ($srcref,$hostname) = @_; + my ($srcref) = @_; return unless (ref($srcref) eq 'SCALAR'); my $usehttp; if ($env{'request.course.id'}) { @@ -357,17 +313,15 @@ sub check_http_req { if (($$srcref =~ m{^\Q/public/$cdom/$cnum/syllabus\E($|\?)}) && ($ENV{'SERVER_PORT'} == 443) && ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) { - unless ((&Apache::lonnet::uses_sts()) || - (&Apache::lonnet::waf_allssl($hostname))) { + unless (&Apache::lonnet::uses_sts()) { $$srcref .= (($$srcref =~/\?/)? '&':'?') . 'usehttp=1'; $usehttp = 1; } } elsif (($$srcref =~ m{^\Q/adm/wrapper/ext/\E(?!https:)}) && ($ENV{'SERVER_PORT'} == 443)) { - unless ((&Apache::lonnet::uses_sts()) || - (&Apache::lonnet::waf_allssl($hostname))) { + unless (&Apache::lonnet::uses_sts()) { my ($url,$anchor) = ($$srcref =~ /^([^\#]+)(?:|(\#[^\#]+))$/); - $$srcref = $url . (($$srcref =~/\?/)? '&':'?') . 'usehttp=1' .$anchor; + $$srcref = $url . (($$srcref =~/\?/)? '&':'?') . 'usehttp=1' .$anchor; $usehttp = 1; } } @@ -397,25 +351,6 @@ setTimeout(function() { END } -sub get_deeplink_login_pc { - my $deeplink_login_pc; - if (($env{'request.deeplink.login'}) && ($env{'request.course.id'})) { - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - my $deeplink_symb = &Apache::loncommon::deeplink_login_symb($cnum,$cdom); - if ($deeplink_symb) { - my $loginmap; - if ($deeplink_symb =~ /\.(page|sequence)$/) { - $loginmap = &Apache::lonnet::clutter((&Apache::lonnet::decode_symb($deeplink_symb))[2]); - } else { - $loginmap = &Apache::lonnet::clutter((&Apache::lonnet::decode_symb($deeplink_symb))[0]); - } - $deeplink_login_pc = $hash{'map_pc_'.$loginmap}; - } - } - return $deeplink_login_pc; -} - # ================================================================ Main Handler sub handler { @@ -453,6 +388,22 @@ sub handler { $last=$hash{'last_known'}; untie(%hash); } + } elsif ($direction eq 'firstanswerable') { + my $furl = &first_answerable_ressymb(); + my $usehttp = &check_http_req(\$furl); + if (($usehttp) && ($hostname ne '')) { + $furl='http://'.$hostname.$furl; + } else { + $furl=&Apache::lonnet::absolute_url().$furl; + } + &Apache::loncommon::content_type($r,'text/html'); + $r->header_out(Location => $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 @@ -504,7 +455,7 @@ sub handler { } if ($direction eq 'firstres') { my $furl=&first_accessible_resource(); - my $usehttp = &check_http_req(\$furl,$hostname); + my $usehttp = &check_http_req(\$furl); if (($usehttp) && ($hostname ne '')) { $furl='http://'.$hostname.$furl; } else { @@ -530,8 +481,8 @@ sub handler { $id=$hash{'map_pc_'.&Apache::lonnet::clutter($murl)}.'.'.$id; $newloc=$hash{'src_'.$id}; if ($newloc) { - $usehttp = &check_http_req(\$newloc,$hostname); - if ($hash{'encrypted_'.$id}) { + $usehttp = &check_http_req(\$newloc); + if ($hash{'encrypted_'.$id}) { $newloc=&Apache::lonenc::encrypted($newloc); } if ($newloc =~ m{^(/adm/wrapper/ext/[^\#]+)(?:|(\#[^\#]+))$}) { @@ -557,9 +508,9 @@ sub handler { $r->print(&Apache::loncommon::end_page()); return OK; } else { - &Apache::loncommon::content_type($r,'text/html'); - $r->header_out(Location => $newloc); - return REDIRECT; + &Apache::loncommon::content_type($r,'text/html'); + $r->header_out(Location => $newloc); + return REDIRECT; } } # @@ -578,15 +529,15 @@ sub handler { $currenturl=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($last))[2]); } else { my $newloc = &Apache::lonnet::absolute_url(). - '/adm/navmaps'; + '/adm/navmaps'; if ($reinitcheck eq 'update') { &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); $r->print(&reinited_js($newloc,$env{'request.course.id'},100)); $r->print(&Apache::loncommon::end_page()); return OK; } else { - &Apache::loncommon::content_type($r,'text/html'); - $r->header_out(Location => $newloc); + &Apache::loncommon::content_type($r,'text/html'); + $r->header_out(Location => $newloc); return REDIRECT; } } @@ -646,14 +597,8 @@ sub handler { } else { # -------------------------------------------------------------- No place to go $multichoice=-1; - if ($position && $env{'request.deeplink.login'}) { - my ($map,$resid,$url) = &Apache::lonnet::decode_symb($position); - my $mapid = $hash{'map_pc_'.&Apache::lonnet::clutter($map)}; - my $position_deeplink = $hash{'deeplinkonly_'.$mapid.'.'.$resid}; - if ($position_deeplink) { - (my $value,$deeplinklevel) = map { &unescape($_); } - split(/:/,$position_deeplink); - } + if ($hash{'deeplinkonly_'.$rid}) { + (my $value,$deeplinklevel) = split(/:/,$hash{'deeplinkonly_'.$rid}); } } # ----------------- The program must come past this point to untie the big hash @@ -676,9 +621,9 @@ sub handler { &Apache::lonnet::linklog($redirecturl,$currenturl); } # ------------------------------------- Check for and display critical messages - my ($redirect, $url) = &Apache::loncommon::critical_redirect(300.'flip'); + my ($redirect, $url) = &Apache::loncommon::critical_redirect(300,'flip'); unless ($redirect) { - my $usehttp = &check_http_req(\$redirecturl,$hostname); + my $usehttp = &check_http_req(\$redirecturl); if (($usehttp) && ($hostname ne '')) { $url='http://'.$hostname.$redirecturl; } else { @@ -696,7 +641,7 @@ sub handler { } if ($reinitcheck eq 'update') { &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); - $r->print(&reinited_js($url,$env{'request.course.id'},100)); + $r->print(&reinited_js($url,$env{'request.course.id'},100)); $r->print(&Apache::loncommon::end_page()); return OK; } else { @@ -726,7 +671,8 @@ sub handler { '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.'); + 'gonav' => 'Go to the Contents page to select a resource to display.', + ); if (&Apache::loncommon::course_type() eq 'Community') { $lt{'nav'} = &mt('Community Contents'); } @@ -744,7 +690,7 @@ $lt{'pick'}: ENDSTART foreach my $id (@possibilities) { my $src = $multichoicehash{'src_'.$id}; - my $usehttp = &check_http_req(\$src,$hostname); + my $usehttp = &check_http_req(\$src); if (($usehttp) && ($hostname ne '')) { $src = 'http://'.$hostname.$src; } @@ -772,35 +718,49 @@ ENDSTART .'

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

'); } else { - $r->print( - &Apache::loncommon::start_page('No Resource')); - if ($deeplinklevel eq 'resource') { - $r->print('

'.$lt{'deeplink'}.'

' - .'

'.$lt{'deeplinkres'}.'

'); - } elsif ($deeplinklevel eq 'map') { - $r->print('

'.$lt{'title'}.'

' - .'

'.$lt{'deeplinkmap'}.'

'); + 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('

'.$lt{'title'}.'

' - .'

'.$lt{'explain'}.'

'); + $r->print( + &Apache::loncommon::start_page('No Resource')); + if ($deeplinklevel eq 'resource') { + $r->print('

'.$lt{'deeplink'}.'

' + .'

'.$lt{'deeplinkres'}.'

'); + } elsif ($deeplinklevel eq 'map') { + $r->print('

'.$lt{'title'}.'

' + .'

'.$lt{'deeplinkmap'}.'

'); + } else { + $r->print('

'.$lt{'title'}.'

' + .'

'.$lt{'explain'}.'

'); + } } } } - if ($deeplinklevel) { - $r->print( - &Apache::lonhtmlcommon::actionbox( - [''.$lt{'back'}.''])); - } elsif ((!@possibilities) && ($reinitcheck)) { - $r->print( - &Apache::lonhtmlcommon::actionbox( - [''.$lt{'nav'}.'' - ])); - } else { - $r->print( - &Apache::lonhtmlcommon::actionbox( - [''.$lt{'back'}.'', - ''.$lt{'nav'}.'' - ])); + unless (($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') || + ($env{'request.role.adv'})) { + if ($deeplinklevel) { + $r->print( + &Apache::lonhtmlcommon::actionbox( + [''.$lt{'back'}.''])); + } elsif ((!@possibilities) && ($reinitcheck)) { + $r->print( + &Apache::lonhtmlcommon::actionbox( + [''.$lt{'nav'}.'' + ])); + } else { + $r->print( + &Apache::lonhtmlcommon::actionbox( + [''.$lt{'back'}.'', + ''.$lt{'nav'}.'' + ])); + } + } $r->print(&Apache::loncommon::end_page()); @@ -811,7 +771,7 @@ ENDSTART if ($reinitcheck eq 'update') { &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); $r->print(&Apache::loncommon::end_page()); - } + } $env{'user.error.msg'}="/adm/flip:bre:0:1:Course Data Missing"; return HTTP_NOT_ACCEPTABLE; }