--- loncom/interface/londocs.pm 2013/01/09 04:01:16 1.528 +++ loncom/interface/londocs.pm 2013/01/09 04:31:57 1.529 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.528 2013/01/09 04:01:16 raeburn Exp $ +# $Id: londocs.pm,v 1.529 2013/01/09 04:31:57 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -40,7 +40,6 @@ use Apache::lonxml; use Apache::lonclonecourse; use Apache::lonnavmaps; use Apache::lonnavdisplay(); -use Apache::lonuserstate(); use Apache::lonextresedit(); use HTML::Entities; use HTML::TokeParser; @@ -271,7 +270,9 @@ sub dumpcourse { sub group_import { my ($coursenum, $coursedom, $folder, $container, $caller, @files) = @_; - + my ($donechk,$allmaps,%hierarchy,%titles,%addedmaps,%removefrommap, + %removeparam,$importuploaded,$fixuperrors); + $allmaps = {}; while (@files) { my ($name, $url, $residx) = @{ shift(@files) }; if (($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$}) @@ -297,6 +298,24 @@ sub group_import { } } if ($url) { + if (($caller eq 'londocs') && + ($folder =~ /^default/)) { + unless ($donechk) { + my $chome = &Apache::lonnet::homeserver($coursenum,$coursedom); + my $cid = $coursedom.'_'.$coursenum; + $allmaps = + &Apache::loncommon::allmaps_incourse($coursedom,$coursenum, + $chome,$cid); + $donechk = 1; + } + if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$}) { + &contained_map_check($url,$folder,\%removefrommap,\%removeparam, + \%addedmaps,\%hierarchy,\%titles,$allmaps); + $importuploaded = 1; + } elsif ($url =~ m{^/res/.+\.(page|sequence)$}) { + next if ($allmaps->{$url}); + } + } if (!$residx || defined($LONCAPA::map::zombies[$residx])) { $residx = &LONCAPA::map::getresidx($url,$residx); @@ -310,7 +329,27 @@ sub group_import { join(':', ($name, $url, $ext, 'normal', 'res')); } } - return &storemap($coursenum, $coursedom, $folder.'.'.$container,1); + if ($importuploaded) { + my %import_errors; + my %updated = ( + removefrommap => \%removefrommap, + removeparam => \%removeparam, + ); + &apply_fixups($folder,1,$coursedom,$coursenum,\%import_errors,\%updated); + if (keys(%import_errors) > 0) { + $fixuperrors = + '

'."\n". + &mt('The following files are either dependencies of a web page or references within a folder and/or composite page for which errors occurred during import:')."\n". + '

'."\n"; + } + } + my ($errtext,$fatal) = + &storemap($coursenum, $coursedom, $folder.'.'.$container,1); + return ($errtext,$fatal,$fixuperrors); } sub log_docs { @@ -895,30 +934,23 @@ sub do_paste_from_buffer { %dbcopies,%zombies,%params,%docmoves,%mapmoves,%newsubdir,%newurls); $oldurl = $url; if ($is_map) { - if ($folder =~ /^default/) { - my $lastchange = &Apache::lonnet::get_coursechange($coursedom,$coursenum); - if ($lastchange > $env{'request.course.tied'}) { - &reinit_role($coursedom,$coursenum,$env{"course.$env{'request.course.id'}.home"}); - } - } # If pasting a map, check if map contains other maps - my (%allmaps,%hierarchy,%titles); + my ($allmaps,%hierarchy,%titles); + $allmaps = {}; if ($folder =~ /^default/) { - my $navmap = Apache::lonnavmaps::navmap->new(); - if (defined($navmap)) { - foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_map() },1,0,1)) { - $allmaps{$res->src()} = 1; - } - } + $allmaps = + &Apache::loncommon::allmaps_incourse($coursedom,$coursenum, + $env{"course.$env{'request.course.id'}.home"}, + $env{'request.course.id'}); } &contained_map_check($url,$folder,\%removefrommap,\%removeparam, - \%addedmaps,\%hierarchy,\%titles,\%allmaps); + \%addedmaps,\%hierarchy,\%titles,$allmaps); if ($url=~ m{^/uploaded/}) { my $newurl; unless ($env{'form.docs.markedcopy_options'} eq 'move') { ($newurl,my $error) = &get_newmap_url($url,$folder,$prefixchg,$coursedom,$coursenum, - $srcdom,$srcnum,\$title,\%allmaps,\%newurls); + $srcdom,$srcnum,\$title,$allmaps,\%newurls); if ($error) { return ($error); } @@ -934,14 +966,14 @@ sub do_paste_from_buffer { if (($srcdom ne $coursedom) || ($srcnum ne $coursenum) || ($prefixchg) || (($newurl ne '') && ($newurl ne $url))) { unless (&url_paste_fixups($url,$folder,$prefixchg,$coursedom,$coursenum, - \%allmaps,\%rewrites,\%retitles,\%copies,\%dbcopies, + $allmaps,\%rewrites,\%retitles,\%copies,\%dbcopies, \%zombies,\%params,\%mapmoves,\%mapchanges,\%tomove, \%newsubdir,\%newurls)) { $mapmoves{$url} = 1; } $url = $newurl; } elsif ($env{'docs.markedcopy_nested'}) { - &url_paste_fixups($url,$folder,$prefixchg,$coursedom,$coursenum,\%allmaps,\%rewrites, + &url_paste_fixups($url,$folder,$prefixchg,$coursedom,$coursenum,$allmaps,\%rewrites, \%retitles,\%copies,\%dbcopies,\%zombies,\%params,\%mapmoves, \%mapchanges,\%tomove,\%newsubdir,\%newurls); } @@ -950,7 +982,7 @@ sub do_paste_from_buffer { &Apache::lonnet::delenv('docs.markedcopy'); # if pasting published map (main content are only) check map is not already in course if ($folder =~ /^default/) { - if ($allmaps{$url}) { + if ((ref($allmaps) eq 'HASH') && ($allmaps->{$url})) { return (&mt('Paste failed: only one instance of a particular published sequence or page is allowed within each course.')); } } @@ -1016,11 +1048,28 @@ sub do_paste_from_buffer { } # Apply any changes to maps, or copy dependencies for uploaded HTML pages my ($result,$save_err); + my %updated = ( + rewrites => \%rewrites, + zombies => \%zombies, + removefrommap => \%removefrommap, + removeparam => \%removeparam, + dbcopies => \%dbcopies, + retitles => \%retitles, + ); + my %info = ( + newsubdir => \%newsubdir, + params => \%params, + before => \%before, + after => \%after, + ); + my %moves = ( + copies => \%copies, + docmoves => \%docmoves, + mapmoves => \%mapmoves, + ); $result = - &apply_fixups($folder,$is_map,$prefixchg,$coursedom,$coursenum,$oldurl, - $url,\%removefrommap,\%removeparam,\%rewrites,\%retitles, - \%copies,\%dbcopies,\%zombies,\%params,\%docmoves, - \%mapmoves,\%newsubdir,$errors,\%before,\%after); + &apply_fixups($folder,$is_map,$coursedom,$coursenum,$errors, + \%updated,\%info,\%moves,$prefixchg,$oldurl,$url,'paste'); if ($result eq 'ok') { if ($is_map) { my ($errtext,$fatal) = &mapread($coursenum,$coursedom, @@ -1180,7 +1229,7 @@ sub contained_map_check { $titles->{$url}{$token->[2]->{'id'}} = $token->[2]->{'title'}; } else { if ($allmaps->{$ressrc}) { - $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; + $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; } elsif (ref($addedmaps->{$ressrc}) eq 'ARRAY') { $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; } else { @@ -1204,15 +1253,6 @@ sub contained_map_check { return; } -sub reinit_role { - my ($cdom,$cnum,$chome) = @_; - my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum"); - unless ($ferr) { - &Apache::loncommon::update_content_constraints($cdom,$cnum,$chome,$cdom.'_'.$cnum); - } - return; -} - sub url_paste_fixups { my ($oldurl,$folder,$prefixchg,$cdom,$cnum,$allmaps,$rewrites,$retitles,$copies, $dbcopies,$zombies,$params,$mapmoves,$mapchanges,$tomove,$newsubdir,$newurls) = @_; @@ -1331,23 +1371,71 @@ sub url_paste_fixups { } sub apply_fixups { - my ($folder,$is_map,$prefixchg,$cdom,$cnum,$oldurl,$url,$removefrommap, - $removeparam,$rewrites,$retitles,$copies,$dbcopies,$zombies,$params, - $docmoves,$mapmoves,$newsubdir,$errors,$before,$after) = @_; - foreach my $key (keys(%{$copies}),keys(%{$docmoves})) { + my ($folder,$is_map,$cdom,$cnum,$errors,$updated,$info,$moves,$prefixchg, + $oldurl,$url,$caller) = @_; + my (%rewrites,%zombies,%removefrommap,%removeparam,%dbcopies,%retitles, + %params,%newsubdir,%before,%after,%copies,%docmoves,%mapmoves); + if (ref($updated) eq 'HASH') { + if (ref($updated->{'rewrites'}) eq 'HASH') { + %rewrites = %{$updated->{'rewrites'}}; + } + if (ref($updated->{'zombies'}) eq 'HASH') { + %zombies = %{$updated->{'zombies'}}; + } + if (ref($updated->{'removefrommap'}) eq 'HASH') { + %removefrommap = %{$updated->{'removefrommap'}}; + } + if (ref($updated->{'removeparam'}) eq 'HASH') { + %removeparam = %{$updated->{'removeparam'}}; + } + if (ref($updated->{'dbcopies'}) eq 'HASH') { + %dbcopies = %{$updated->{'dbcopies'}}; + } + if (ref($updated->{'retitles'}) eq 'HASH') { + %retitles = %{$updated->{'retitles'}}; + } + } + if (ref($info) eq 'HASH') { + if (ref($info->{'newsubdir'}) eq 'HASH') { + %newsubdir = %{$info->{'newsubdir'}}; + } + if (ref($info->{'params'}) eq 'HASH') { + %params = %{$info->{'params'}}; + } + if (ref($info->{'before'}) eq 'HASH') { + %before = %{$info->{'before'}}; + } + if (ref($info->{'after'}) eq 'HASH') { + %after = %{$info->{'after'}}; + } + } + if (ref($moves) eq 'HASH') { + if (ref($moves->{'copies'}) eq 'HASH') { + %copies = %{$moves->{'copies'}}; + } + if (ref($moves->{'docmoves'}) eq 'HASH') { + %docmoves = %{$moves->{'docmoves'}}; + } + if (ref($moves->{'mapmoves'}) eq 'HASH') { + %mapmoves = %{$moves->{'mapmoves'}}; + } + } + foreach my $key (keys(%copies),keys(%docmoves)) { my @allcopies; - if (ref($copies->{$key}) eq 'HASH') { - my %added; - foreach my $innerkey (keys(%{$copies->{$key}})) { - if (($innerkey ne '') && (!$added{$innerkey})) { - push(@allcopies,$innerkey); - $added{$innerkey} = 1; + if (exists($copies{$key})) { + if (ref($copies{$key}) eq 'HASH') { + my %added; + foreach my $innerkey (keys(%{$copies{$key}})) { + if (($innerkey ne '') && (!$added{$innerkey})) { + push(@allcopies,$innerkey); + $added{$innerkey} = 1; + } } + undef(%added); } - undef(%added); } if ($key eq $oldurl) { - if ((exists($docmoves->{$key}))) { + if ((exists($docmoves{$key}))) { unless (grep(/^\Q$oldurl\E/,@allcopies)) { push(@allcopies,$oldurl); } @@ -1361,16 +1449,16 @@ sub apply_fixups { my $content = &Apache::lonnet::getfile($item); unless ($content eq '-1') { my $storefn; - if (($key eq $oldurl) && (ref($docmoves) eq 'HASH') && (exists($docmoves->{$key}))) { - $storefn = $docmoves->{$key}; + if (($key eq $oldurl) && (exists($docmoves{$key}))) { + $storefn = $docmoves{$key}; } else { $storefn = $relpath; $storefn =~s{^/uploaded/$match_domain/$match_courseid/}{}; - if ($prefixchg) { - $storefn =~ s/^\Q$before->{'doc'}\E/$after->{'doc'}/; + if ($prefixchg && $before{'doc'} && $after{'doc'}) { + $storefn =~ s/^\Q$before{'doc'}\E/$after{'doc'}/; } - if ($newsubdir->{$key}) { - $storefn =~ s#^(docs|supplemental)/\Q$oldsubdir\E/#$1/$newsubdir->{$key}#; + if ($newsubdir{$key}) { + $storefn =~ s#^(docs|supplemental)/\Q$oldsubdir\E/#$1/$newsubdir{$key}#; } } ©_dependencies($item,$storefn,$relpath,$errors,\$content); @@ -1378,7 +1466,7 @@ sub apply_fixups { &Apache::lonclonecourse::writefile($env{'request.course.id'}, $storefn.$fname,$content); if ($copyurl eq '/adm/notfound.html') { - if ((ref($docmoves) eq 'HASH') && (exists($docmoves->{$oldurl}))) { + if (exists($docmoves{$oldurl})) { return &mt('Paste failed: an error occurred copying the file.'); } elsif (ref($errors) eq 'HASH') { $errors->{$item} = 1; @@ -1389,14 +1477,14 @@ sub apply_fixups { } } } - foreach my $key (keys(%{$mapmoves})) { + foreach my $key (keys(%mapmoves)) { my $storefn=$key; $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{}; - if ($prefixchg) { - $storefn =~ s/^\Q$before->{'map'}\E/$after->{'map'}/; + if ($prefixchg && $before{'map'} && $after{'map'}) { + $storefn =~ s/^\Q$before{'map'}\E/$after{'map'}/; } - if ($newsubdir->{$key}) { - $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir->{$key}/; + if ($newsubdir{$key}) { + $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/; } my $mapcontent = &Apache::lonnet::getfile($key); if ($mapcontent eq '-1') { @@ -1416,48 +1504,39 @@ sub apply_fixups { } my %updates; if ($is_map) { - foreach my $key (keys(%{$rewrites})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$zombies})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$removefrommap})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$removeparam})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$dbcopies})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$retitles})) { - $updates{$key} = 1; + if (ref($updated) eq 'HASH') { + foreach my $type (keys(%{$updated})) { + if (ref($updated->{$type}) eq 'HASH') { + foreach my $key (keys(%{$updated->{$type}})) { + $updates{$key} = 1; + } + } + } } foreach my $key (keys(%updates)) { my (%torewrite,%toretitle,%toremove,%remparam,%currparam,%zombie,%newdb); - if (ref($rewrites->{$key}) eq 'HASH') { - %torewrite = %{$rewrites->{$key}}; + if (ref($rewrites{$key}) eq 'HASH') { + %torewrite = %{$rewrites{$key}}; } - if (ref($retitles->{$key}) eq 'HASH') { - %toretitle = %{$retitles->{$key}}; + if (ref($retitles{$key}) eq 'HASH') { + %toretitle = %{$retitles{$key}}; } - if (ref($removefrommap->{$key}) eq 'HASH') { - %toremove = %{$removefrommap->{$key}}; + if (ref($removefrommap{$key}) eq 'HASH') { + %toremove = %{$removefrommap{$key}}; } - if (ref($removeparam->{$key}) eq 'HASH') { - %remparam = %{$removeparam->{$key}}; + if (ref($removeparam{$key}) eq 'HASH') { + %remparam = %{$removeparam{$key}}; } - if (ref($zombies->{$key}) eq 'HASH') { - %zombie = %{$zombies->{$key}}; + if (ref($zombies{$key}) eq 'HASH') { + %zombie = %{$zombies{$key}}; } - if (ref($dbcopies->{$key}) eq 'HASH') { - foreach my $item (keys(%{$dbcopies->{$key}})) { + if (ref($dbcopies{$key}) eq 'HASH') { + foreach my $item (keys(%{$dbcopies{$key}})) { $newdb{$item} = &dbcopy($item); } } - if (ref($params->{$key}) eq 'HASH') { - %currparam = %{$params->{$key}}; + if (ref($params{$key}) eq 'HASH') { + %currparam = %{$params{$key}}; } my ($errtext,$fatal) = &LONCAPA::map::mapread($key); if ($fatal) { @@ -1471,40 +1550,41 @@ sub apply_fixups { } } } - for (my $i=0; $i<@LONCAPA::map::resources; $i++) { - if (defined($LONCAPA::map::resources[$i])) { + for (my $i=0; $i<@LONCAPA::map::order; $i++) { + my $idx = $LONCAPA::map::order[$i]; + if (defined($LONCAPA::map::resources[$idx])) { my $changed; - my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::resources[$i]); - if ($toremove{$src} eq $i) { + my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::resources[$idx]); + if ((exists($toremove{$idx})) && ($toremove{$idx} eq $src)) { splice(@LONCAPA::map::order,$i,1); - if (ref($currparam{$i}) eq 'ARRAY') { - foreach my $name (@{$currparam{$i}}) { - &LONCAPA::map::delparameter($i,'parameter_'.$name); + if (ref($currparam{$idx}) eq 'ARRAY') { + foreach my $name (@{$currparam{$idx}}) { + &LONCAPA::map::delparameter($idx,'parameter_'.$name); } } next; } my $origsrc = $src; - if ((exists($toretitle{$src})) && ($toretitle{$src} eq $i)) { + if ((exists($toretitle{$src})) && ($toretitle{$src} eq $idx)) { if ($title =~ m{^\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) { $changed = 1; } } - if ((exists($torewrite{$src})) && ($torewrite{$src} eq $i)) { + if ((exists($torewrite{$src})) && ($torewrite{$src} eq $idx)) { $src =~ s{^/(uploaded|adm|public)/$match_domain/$match_courseid/}{/$1/$cdom/$cnum/}; if ($origsrc =~ m{^/uploaded/}) { - if ($prefixchg) { + if ($prefixchg && $before{'map'} && $after{'map'}) { if ($src =~ /\.(page|sequence)$/) { - $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before->{'map'}\E#$1$after->{'map'}#; + $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before{'map'}\E#$1$after{'map'}#; } else { - $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before->{'doc'}\E#$1$after->{'doc'}#; + $src =~ s#^(/uploaded/$match_domain/$match_courseid/)\Q$before{'doc'}\E#$1$after{'doc'}#; } } - if ($newsubdir->{$origsrc}) { + if ($newsubdir{$origsrc}) { if ($src =~ /\.(page|sequence)$/) { - $src =~ s#^(/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_)(\d+)#$1$newsubdir->{$origsrc}#; + $src =~ s#^(/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_)(\d+)#$1$newsubdir{$origsrc}#; } else { - $src =~ s#^(/uploaded/$match_domain/$match_courseid/\w+/)(\d+)#$1$newsubdir->{$origsrc}#; + $src =~ s#^(/uploaded/$match_domain/$match_courseid/\w+/)(\d+)#$1$newsubdir{$origsrc}#; } } } @@ -1514,7 +1594,7 @@ sub apply_fixups { $changed = 1; } if ($changed) { - $LONCAPA::map::resources[$i] = join(':',($title,$src,$ext,$type)); + $LONCAPA::map::resources[$idx] = join(':',($title,$src,$ext,$type)); } } } @@ -1532,11 +1612,11 @@ sub apply_fixups { } else { $storefn = $key; $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{}; - if ($prefixchg) { - $storefn =~ s/^\Q$before->{'map'}\E/$after->{'map'}/; + if ($prefixchg && $before{'map'} && $after{'map'}) { + $storefn =~ s/^\Q$before{'map'}\E/$after{'map'}/; } - if ($newsubdir->{$key}) { - $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir->{$key}/; + if ($newsubdir{$key}) { + $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/; } } my $report; @@ -1546,7 +1626,9 @@ sub apply_fixups { (my $outtext,$errtext) = &LONCAPA::map::storemap("/uploaded/$cdom/$cnum/$storefn",1,$report); if ($errtext) { - return &mt('Paste failed: an error occurred saving the folder or page.'); + if ($caller eq 'paste') { + return &mt('Paste failed: an error occurred saving the folder or page.'); + } } } } @@ -1790,9 +1872,13 @@ sub editor { push(@imports, [$name, $url, $residx]); } } - ($errtext,$fatal)=&group_import($coursenum, $coursedom, $folder, - $container,'londocs',@imports); + ($errtext,$fatal,my $fixuperrors) = + &group_import($coursenum, $coursedom, $folder,$container, + 'londocs',@imports); return $errtext if ($fatal); + if ($fixuperrors) { + $r->print($fixuperrors); + } } # Loading a complete map if ($env{'form.loadmap'}) { @@ -4843,8 +4929,6 @@ Return hash with valid author names =item contained_map_check() -=item reinit_role() - =item url_paste_fixups() =item apply_fixups()