[LON-CAPA-cvs] cvs: loncom /interface londocs.pm

raeburn raeburn at source.lon-capa.org
Sun Jul 22 00:01:25 EDT 2012


raeburn		Sun Jul 22 04:01:25 2012 EDT

  Modified files:              
    /loncom/interface	londocs.pm 
  Log:
  - Pasting from paste buffer
    - Allow copying of uploaded maps which contain other uploaded maps.
    - If content of paste buffer was result of a "cut" in current course, 
      and paste item is an uploaded map, provide option to either:
      (a) copy i.e., to new map, when pasting or (b) "move", i.e,
      retain current map, when pasting.
    - If paste item is an uploaded map resulting from cut show
      hierarchy of nested sub-folders etc.
    - Generation of newurl moved to subroutine so it can be called repeatedly
      when pasting a map containing nested sub-folders etc.  
    - Saving of pasted map(s) incorporates changes to urls of contained resources
      to reflect changes in course, parent map, prefix (i.e., supplemental to
      main, and vide versa), as well as removal of unallowed content (e.g.,
      parameters etc. in supplemental, or multiple instances of a published map.
  work in progess.
  
  
-------------- next part --------------
Index: loncom/interface/londocs.pm
diff -u loncom/interface/londocs.pm:1.491 loncom/interface/londocs.pm:1.492
--- loncom/interface/londocs.pm:1.491	Fri Jul 13 13:36:24 2012
+++ loncom/interface/londocs.pm	Sun Jul 22 04:01:24 2012
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Documents
 #
-# $Id: londocs.pm,v 1.491 2012/07/13 13:36:24 raeburn Exp $
+# $Id: londocs.pm,v 1.492 2012/07/22 04:01:24 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -69,10 +69,14 @@
 }
 
 sub storemap {
-    my ($coursenum,$coursedom,$map)=@_;
+    my ($coursenum,$coursedom,$map,$contentchg)=@_;
+    my $report;
+    if (($contentchg) && ($map =~ /^default/)) {
+       $report = 1;
+    }
     my ($outtext,$errtext)=
       &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
-			      $map,1);
+			      $map,1,$report);
     if ($errtext) { return ($errtext,2); }
 
     $hadchanges=1;
@@ -305,7 +309,7 @@
 		join(':', ($name, $url, $ext, 'normal', 'res'));
 	}
     }
-    return &storemap($coursenum, $coursedom, $folder.'.'.$container);
+    return &storemap($coursenum, $coursedom, $folder.'.'.$container,1);
 }
 
 sub breadcrumbs {
@@ -612,7 +616,7 @@
 }
 
 sub update_paste_buffer {
-    my ($coursenum,$coursedom) = @_;
+    my ($coursenum,$coursedom,$folder) = @_;
 
     return if (!defined($env{'form.markcopy'}));
     return if (!defined($env{'form.copyfolder'}));
@@ -633,75 +637,211 @@
     }
     $url=~s{http(:|:)//https(:|:)//}{https$2//};
 
-    &Apache::lonnet::appenv({'docs.markedcopy_title' => $title,
-			    'docs.markedcopy_url'   => $url});
+    (my $cmd,undef)=split('_',$env{'form.cmd'});
+
+    my %addtoenv = (
+                    'docs.markedcopy_title' => $title,
+                    'docs.markedcopy_url'   => $url,
+                    'docs.markedcopy_cmd'   => $cmd,
+                   );
+    &Apache::lonnet::delenv('docs.markedcopy_nested');
+    &Apache::lonnet::delenv('docs.markedcopy_nestednames');
+    if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(default|supplemental)_?(\d*)\.(page|sequence)$}) {
+        my $prefix = $1;
+        my $subdir =$2;
+        if ($subdir eq '') {
+            $subdir = $prefix;
+        }
+        my (%addedmaps,%removefrommap,%removeparam,%hierarchy,%titles,%allmaps);
+        &contained_map_check($url,$folder,\%removefrommap,\%removeparam,\%addedmaps,
+                             \%hierarchy,\%titles,\%allmaps);
+        if (ref($hierarchy{$url}) eq 'HASH') {
+            my ($nested,$nestednames);
+            &recurse_uploaded_maps($url,$subdir,\%hierarchy,\%titles,\$nested,\$nestednames);
+            $nested =~ s/\&$//;
+            $nestednames =~ s/\Q___&&&___\E$//;
+            if ($nested ne '') {
+                $addtoenv{'docs.markedcopy_nested'} = $nested;
+            }
+            if ($nestednames ne '') {
+                $addtoenv{'docs.markedcopy_nestednames'} = $nestednames;
+            }
+        }
+    }
+    &Apache::lonnet::appenv(\%addtoenv);
     delete($env{'form.markcopy'});
 }
 
+sub recurse_uploaded_maps {
+    my ($url,$dir,$hierarchy,$titlesref,$nestref,$namesref) = @_;
+    if (ref($hierarchy->{$url}) eq 'HASH') {
+        my @maps = map { $hierarchy->{$url}{$_}; } sort { $a <=> $b } (keys(%{$hierarchy->{$url}}));
+        my @titles = map { $titlesref->{$url}{$_}; } sort { $a <=> $b } (keys(%{$titlesref->{$url}}));
+        my (@uploaded, at names,%shorter);
+        for (my $i=0; $i<@maps; $i++) {
+            my ($inner) = ($maps[$i] =~ m{^/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_(\d+)\.(?:page|sequence)$});
+            if ($inner ne '') {
+                push(@uploaded,$inner);
+                push(@names,&escape($titles[$i]));
+                $shorter{$maps[$i]} = $inner;
+            }
+        }
+        $$nestref .= "$dir:".join(',', at uploaded).'&';
+        $$namesref .= "$dir:".(join(',', at names)).'___&&&___';
+        foreach my $map (@maps) {
+            if ($shorter{$map} ne '') {
+                &recurse_uploaded_maps($map,$shorter{$map},$hierarchy,$titlesref,$nestref,$namesref);
+            }
+        }
+    }
+    return;
+}
+
 sub print_paste_buffer {
-    my ($r,$container,$folder) = @_;
+    my ($r,$container,$folder,$coursedom,$coursenum) = @_;
     return if (!defined($env{'docs.markedcopy_url'}));
 
-    my $is_external;
+    my ($is_external,$othercourse,$fromsupp,$is_uploaded_map,$parent);
     my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1];
     if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) {
         $is_external = 1;
     }
 
-    my $canpaste;
+    my ($canpaste,$nopaste,$othercrs,$areachange,$is_uploaded_map);
     if ($folder =~ /^supplemental/) {
-        $canpaste = &supp_pasteable($env{'docs.markedcopy_url'}); 
+        $canpaste = &supp_pasteable($env{'docs.markedcopy_url'});
+        unless ($canpaste) {
+            $nopaste = &mt('Paste into Supplemental Content unavailable for this type of content.');
+        } 
     } else {
         $canpaste = 1;
     }
 
-    my $pasteinfo;
     if ($canpaste) {
-        $pasteinfo = '<form name="pasteform" action="/adm/coursedocs" method="post">'
-                    .'<input type="submit" name="pastemarked" value="'.&mt('Paste').'" /> ';
-    } else {
-        $pasteinfo = &mt('Paste buffer contains:').' ';
+        if ($env{'docs.markedcopy_url'} =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)$}) {
+            my $srcdom = $1;
+            my $srcnum = $2;
+            my $rem = $3;
+            if (($srcdom ne $coursedom) || ($srcnum ne $coursenum)) {
+                $othercourse = 1;
+                if ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) {
+                    if ($canpaste) {
+                        $othercrs = '<br />'.&mt('(from another course).');  
+                    }
+                } else {
+                    $canpaste = 0;
+                    $nopaste = &mt('Paste from another course unavailable.') 
+                }
+            }
+            if ($rem =~ m{^(default|supplemental)_?(\d*)\.(?:page|sequence)$}) {
+                my $prefix = $1;
+                $parent = $2;
+                if ($folder !~ /^\Q$prefix\E/) {
+                    $areachange = 1;
+                }
+                $is_uploaded_map = 1;
+            }
+        }
     }
 
     $r->print('<fieldset>'
-             .'<legend>'.&mt('Clipboard').'</legend>'
-             .$pasteinfo
-             );
-
-    my $type;
+             .'<legend>'.&mt('Clipboard').'</legend>');
+    my ($type,$buffer);
     if ($is_external) {
-	$type = &mt('External Resource');
-	$r->print($type.': '.
-		  &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('.
-		  &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')');
+        $type = &mt('External Resource');
+        $buffer = $type.': '.
+                  &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('.
+                  &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')';
     }  else {
-	my $icon = &Apache::loncommon::icon($extension);
-	if ($extension eq 'sequence' &&
-	    $env{'docs.markedcopy_url'} =~ m{/default_\d+\.sequence$ }x) {
-	    $icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL'));
-	    $icon .= '/navmap.folder.closed.gif';
-	}
-	$icon = '<img src="'.$icon.'" alt="" class="LC_icon" />';
-	$r->print($icon.$type.': '.  &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'})));
+        my $icon = &Apache::loncommon::icon($extension);
+        if ($extension eq 'sequence' &&
+            $env{'docs.markedcopy_url'} =~ m{/default_\d+\.sequence$ }x) {
+            $icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL'));
+            $icon .= '/navmap.folder.closed.gif';
+        }
+        $icon = '<img src="'.$icon.'" alt="" class="LC_icon" />';
+        $buffer = $icon.$type.': '.  &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}));
     }
     if ($canpaste) {
+        $r->print('<form name="pasteform" action="/adm/coursedocs" method="post">'.$buffer);
+        if (($is_uploaded_map) && (!$areachange)) {
+            if ((!$othercourse) && ($env{'docs.markedcopy_cmd'} eq 'cut')) {
+                $r->print((' 'x 4).'<span id="pasteoptionstext">'.
+                          '<a href="javascript:showPasteOptions();" class="LC_menubuttons_link">'.
+                          &mt('Show Paste Options').'</a></span><br />'.
+                          '<div id="pasteoptions" class="LC_dccid">'.(' 'x 4).
+                          '<label>'.
+                          '<input type="radio" name="docs.markedcopy_options" value="new" checked="checked" />'.
+                          &mt('Copy to new folder').'</label>'.(' ' x2).
+                          '<label>'.   
+                          '<input type="radio" name="docs.markedcopy_options" value="move" />'.
+                          &mt('Move old folder').'</label><br />');
+                if ($env{'docs.markedcopy_nested'}) {
+                    $r->print('<br />'.&mt('Folder to paste contains sub-folders').
+                              '<br /><table border="0">');
+                    my @pastemaps = split(/\&/,$env{'docs.markedcopy_nested'});
+                    my @titles = split(/\Q___&&&___\E/,$env{'docs.markedcopy_nestednames'});
+                    my $lastdir = $parent;
+                    my %depths = (
+                                   $lastdir => 0,
+                                 );
+                    my (%display,%deps); 
+                    for (my $i=0; $i<@pastemaps; $i++) {
+                        ($lastdir,my $subfolderstr) = split(/\:/,$pastemaps[$i]);
+                        my ($namedir,$esctitlestr) = split(/\:/,$titles[$i]);
+                        my @subfolders = split(/,/,$subfolderstr);
+                        $deps{$lastdir} = \@subfolders;
+                        my @subfoldertitles = map { &unescape($_); } split(/,/,$esctitlestr);
+                        my $depth = $depths{$lastdir} + 1;
+                        my $offset = int($depth * 4);
+                        my $indent = (' ' x $offset);
+                        for (my $j=0; $j<@subfolders; $j++) {
+                            $depths{$subfolders[$j]} = $depth;
+                            $display{$subfolders[$j]} = 
+                                  '<tr><td>'.$indent.$subfoldertitles[$j].' </td>'.
+                                  '<td><label>'.
+                                  '<input type="radio" name="docs.markedcopy_'.$subfolders[$j].'" value="new" checked="checked" />'.&mt('Copy to new').'</label>'.(' ' x2).
+                                  '<label>'.
+                                  '<input type="radio" name="docs.markedcopy_'.$subfolders[$j].'" value="move" />'.
+                                  &mt('Move old').'</label>'.
+                                  '</td></tr>';
+                        }
+                    }
+                    &recurse_print($r,$parent,\%deps,\%display);
+                    $r->print('</table>');
+                }
+                $r->print('</div>');
+            }
+        }
+        $r->print('<br /><input type="submit" name="pastemarked" value="'.&mt('Paste').'" />'.$othercrs);
         if ($container eq 'page') {
-	    $r->print('
-	<input type="hidden" name="pagepath" value="'.&HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" />
-	<input type="hidden" name="pagesymb" value="'.&HTML::Entities::encode($env{'form.pagesymb'},'<>&"').'" />
+            $r->print('
+        <input type="hidden" name="pagepath" value="'.&HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" />
+        <input type="hidden" name="pagesymb" value="'.&HTML::Entities::encode($env{'form.pagesymb'},'<>&"').'" />
 ');
         } else {
-	    $r->print('
+            $r->print('
         <input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />
 ');
         }
         $r->print('</form>');
     } else {
-        $r->print('<br /><p class="LC_info">'.&mt('Paste into Supplemental Content unavailable for this type of content.').'</p>');
+        $r->print(&mt('Paste buffer contains:').' '.$buffer.
+                  '<br /><p class="LC_info">'.$nopaste.'</p>');
     }
     $r->print('</fieldset>');
 }
 
+sub recurse_print {
+    my ($r,$dir,$deps,$display) = @_;
+    $r->print($display->{$dir}."\n");
+    if (ref($deps->{$dir}) eq 'ARRAY') {
+        foreach my $subdir (@{$deps->{$dir}}) {
+            &recurse_print($r,$subdir,$deps,$display);
+        }
+    }
+}
+
 sub supp_pasteable {
     my ($url) = @_;
     if (($url =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//}) ||
@@ -714,18 +854,53 @@
     return;
 }
 
+sub paste_popup_js {
+    my %lt = &Apache::lonlocal::texthash(
+                                          show => 'Show Paste Options',
+                                          hide => 'Hide Paste Options',
+                                        );
+    return <<"END";
+
+function showPasteOptions() {
+    document.getElementById('pasteoptions').style.display='block';
+    document.getElementById('pasteoptions').style.textAlign='left';
+    document.getElementById('pasteoptions').style.textFace='normal';
+    document.getElementById('pasteoptionstext').innerHTML ='<a href="javascript:hidePasteOptions();" class="LC_menubuttons_link">$lt{'hide'}</a><br />';
+    return;
+}
+
+function hidePasteOptions() {
+    document.getElementById('pasteoptions').style.display='none';
+    document.getElementById('pasteoptionstext').innerHTML ='<a href="javascript:showPasteOptions()" class="LC_menubuttons_link">$lt{'show'}</a>';
+    return;
+}
+
+END
+
+}
+
+
 sub do_paste_from_buffer {
-    my ($coursenum,$coursedom,$folder,$errors) = @_;
+    my ($coursenum,$coursedom,$folder,$container,$errors) = @_;
 
+# Early out if paste buffer is empty
     if (!$env{'form.pastemarked'}) {
-        return;
+        return ();
     }
 
-# Preparing to paste resource at end of list
+# Supplemental content may only include certain types of content
+# Early out if pasted content is not supported in Supplemental area
+    if ($folder =~ /^supplemental/) {
+        unless (&supp_pasteable($env{'docs.markedcopy_url'})) {
+            return (&mt('Paste failed: content type is not supported within Supplemental Content'));
+        }
+    }
+
+# Prepare to paste resource at end of list
     my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url'});
     my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title'});
 
-    my ($is_map,$srcdom,$srcnum,$prefixchg,%before,%after,%mapchanges);
+    my ($is_map,$srcdom,$srcnum,$prefixchg,%before,%after,%mapchanges,%tomove);
     if ($url=~/\.(page|sequence)$/) {
         $is_map = 1; 
     }
@@ -733,11 +908,16 @@
         $srcdom = $1;
         $srcnum = $2;
         my $oldprefix = $3;
+# When paste buffer was populated using an active role in a different course
+# check for mdc privilege in the course from which the resource was pasted 
         if (($srcdom ne $coursedom) || ($srcnum ne $coursenum)) {
             unless ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) {
-                return &mt('Paste failed: Item is from a different course which you do not have rights to edit.');
+                return (&mt('Paste failed: Item is from a different course which you do not have rights to edit.'));
             }
         }
+# When pasting content from Main Content to Supplemental Content and vice versa 
+# URLs will contain different paths (which depend on whether pasted item is
+# a folder/page or a document.   
         if (($folder =~ /^supplemental/) && (($oldprefix =~ /^default/) || ($oldprefix eq 'docs'))) {
             $prefixchg = 1;
             %before = ( map => 'default',
@@ -751,27 +931,42 @@
             %after  = ( map => 'default',
                         doc => 'docs');
         }
-    }
 
-# Supplemental content may only include certain types of content
-    if ($folder =~ /^supplemental/) {
-        unless (&supp_pasteable($env{'docs.markedcopy_url'})) {
-            return &mt('Paste failed: content type is not supported within Supplemental Content'); 
+# If pasting an uploaded map, get list of contained uploaded maps.
+        my @nested;
+        if ($env{'docs.markedcopy_nested'}) {
+            my ($type) = ($oldprefix =~ /^(default|supplemental)/);
+            my @items = split(/\&/,$env{'docs.markedcopy_nested'});
+            my @deps = map { /\d+:([\d,]+$)/ } @items;
+            foreach my $dep (@deps) {
+                if ($dep =~ /,/) {
+                    push(@nested,split(/,/,$dep));
+                } else {
+                    push(@nested,$dep);
+                }
+            }
+            foreach my $item (@nested) {
+                if ($env{'form.docs.markedcopy_'.$item} eq 'move') {
+                    $tomove{$type.'_'.$item} = 1;
+                }
+            }
         }
     }
 
 # Maps need to be copied first
-    my ($oldurl,%removefrommap,%addedmaps,%rewrites,%retitles,%copies,%dbcopies,%zombies,
-        %params,%docmoves,%mapmoves);
+    my ($oldurl,%removefrommap,%removeparam,%addedmaps,%rewrites,%retitles,%copies,
+        %dbcopies,%zombies,%params,%docmoves,%mapmoves,%newsubdir,%newurls);
     $oldurl = $url;
     if ($is_map) {
-# If pasting a map, check if map contains other maps
-        my %allmaps;
-        &contained_map_check($url,$folder,\%removefrommap,\%addedmaps);
         if ($folder =~ /^default/) {
-            if (keys(%addedmaps) > 0) {
-                &reinit_role($coursedom,$coursenum,$env{"course.$env{'request.course.id'}.home"});
+            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);
+        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)) {
@@ -779,84 +974,47 @@
                 }
             }
         }
+        &contained_map_check($url,$folder,\%removefrommap,\%removeparam,
+                             \%addedmaps,\%hierarchy,\%titles,\%allmaps);
         if ($url=~ m{^/uploaded/}) {
-	    $title=&mt('Copy of').' '.$title;
-        }
-        my $now = time;
-	my $suffix=$$.int(rand(100)).$now;
-	my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/);
-        if ($oldid =~ m{^(/uploaded/$match_domain/$match_courseid/)(\D+)(\d+)$}) {
-            my $path = $1;
-            my $prefix = $2;
-            my $ancestor = $3;
-            if (length($ancestor) > 10) {
-                $ancestor = substr($ancestor,-10,10);
-            }
-            my ($newurl,$newid);
-            if ($prefixchg) {
-                if ($folder =~ /^supplemental/) {
-                    $prefix =~ s/^default/supplemental/;                   
-                } else {
-                    $prefix =~ s/^supplemental/default/;
-                }
-            }
-            if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) {
-                $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext;
-            } else {
-                $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$now.'.'.$ext;
-            }
-            my $counter = 0;
-            my $is_unique = &uniqueness_check($newurl);
-            if ($folder =~ /^default/) {
-                if ($allmaps{$newurl}) {
-                    $is_unique = 0;
-                }
-            }
-            while (!$is_unique && $allmaps{$newurl} && $counter < 100) {
-                $counter ++;
-                $suffix ++;
-                if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) {
-                    $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext;
-                } else {
-                    $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$ancestor.$suffix.'.'.$ext;
-                }
-                $is_unique = &uniqueness_check($newurl);
-            }
-            if ($is_unique) {
-                if ($newurl ne $oldurl) {
-                    $mapchanges{$oldurl} = 1;
-                }
-                if (($srcdom ne $coursedom) || ($srcnum ne $coursenum) || ($prefixchg)) {
-                    &url_paste_fixups($url,$prefixchg,$coursedom,$coursenum,\%allmaps,
-                                      \%rewrites,\%retitles,\%copies,\%dbcopies,\%zombies,
-                                      \%params,\%mapmoves,\%mapchanges);
-                }
-            } else {
-                if ($url=~/\.page$/) {
-                    return &mt('Paste failed: an error occurred creating a unique URL for the composite page');
-                } else {
-                    return &mt('Paste failed: an error occurred creating a unique URL for the folder');
+            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);
+                if ($error) {
+                    return ($error);
+                }
+                if ($newurl ne '') {
+                    if ($newurl ne $url) {
+                        if ($newurl =~ /(?:default|supplemental)_(\d+).(?:sequence|page)$/) {
+                            $newsubdir{$url} = $1;
+                        }
+                        $mapchanges{$url} = 1;
+                    }
                 }
             }
-	    my $storefn=$newurl;
-	    $storefn=~s{^/\w+/$match_domain/$match_username/}{};
-	    my $paste_map_result =
-                &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,
-					           &Apache::lonnet::getfile($url));
-            if ($paste_map_result eq '/adm/notfound.html') {
-                if ($url=~/\.page$/) {
-                    return &mt('Paste failed: an error occurred saving the composite page.');
-                } else {
-                    return &mt('Paste failed: an error occurred saving the folder.');
-                }
+            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,
+                                          \%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,
+                                  \%retitles,\%copies,\%dbcopies,\%zombies,\%params,\%mapmoves,
+                                  \%mapchanges,\%tomove,\%newsubdir,\%newurls); 
             }
-	    $url = $newurl;
         } elsif ($url=~m {^/res/}) {
 # published maps can only exists once, so remove it from paste buffer when done
             &Apache::lonnet::delenv('docs.markedcopy');
-            if ($folder =~ /^default/) {  
+# if pasting published map (main content are only) check map is not already in course
+            if ($folder =~ /^default/) {
                 if ($allmaps{$url}) {
-                    return &mt('Paste failed: only one instance of a particular published sequence or page is allowed within each course.');
+                    return (&mt('Paste failed: only one instance of a particular published sequence or page is allowed within each course.'));
                 }
             }
         }
@@ -874,7 +1032,7 @@
                 $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x;
                 $title=&mt('Copy of').' '.$title;
             } else {
-                return &mt('Paste failed: An error occurred when copying the simple page.');
+                return (&mt('Paste failed: An error occurred when copying the simple page.'));
             }
 	}
     }
@@ -882,33 +1040,34 @@
     my $ext='false';
     if ($url=~m{^http(|s)://}) { $ext='true'; }
     $url       = &LONCAPA::map::qtunescape($url);
-# Now insert the URL at the bottom
-    my $newidx = &LONCAPA::map::getresidx($url);
 
 # For uploaded files (excluding pages/sequences) path in copied file is changed
 # if paste is from Main to Supplemental (or vice versa), or if pasting between
 # courses.
 
+    my $newidx;
     unless ($is_map) {
+# Now insert the URL at the bottom
+        $newidx = &LONCAPA::map::getresidx($url);
         if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(.+)$}) {
             my $relpath = $1;
             if ($relpath ne '') {
                 my ($prefix,$subdir,$rem) = ($relpath =~ m{^(default|\d+)/(\d+)/(.+)$});
-                my ($newloc,$newsubdir) = ($folder =~ /^(default|supplemental)_?(\d*)/);
+                my ($newloc,$newdocsdir) = ($folder =~ /^(default|supplemental)_?(\d*)/);
                 my $newprefix = $newloc;
                 if ($newloc eq 'default') {
                     $newprefix = 'docs';
                 }
-                if ($newsubdir eq '') {
-                    $newsubdir = 'default';
+                if ($newdocsdir eq '') {
+                    $newdocsdir = 'default';
                 }
                 if (($prefixchg) || ($srcdom ne $coursedom) || ($srcnum ne $coursenum)) {
-                    my $newpath = "$newprefix/$newsubdir/$newidx/$rem";
+                    my $newpath = "$newprefix/$newdocsdir/$newidx/$rem";
                     $url =
                         &Apache::lonclonecourse::writefile($env{'request.course.id'},$newpath,
                                                            &Apache::lonnet::getfile($oldurl));
                     if ($url eq '/adm/notfound.html') {
-                        return &mt('Paste failed: an error occurred saving the file.');
+                        return (&mt('Paste failed: an error occurred saving the file.'));
                     } else {
                         my ($newsubpath) = ($newpath =~ m{^(.*/)[^/]*$});
                         $newsubpath =~ s{/+$}{/};
@@ -918,15 +1077,29 @@
             }
         }
     }
-    my $result =
-        &apply_fixups($is_map,$prefixchg,$coursedom,$coursenum,$oldurl,$url,
-                      \%removefrommap,\%rewrites,\%retitles,\%copies,\%dbcopies,
-                      \%zombies,\%params,\%docmoves,\%mapmoves,$errors,\%before,\%after);
+# Apply any changes to maps, or copy dependencies for uploaded HTML pages 
+    my ($result,$save_err);
+    $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);
     if ($result eq 'ok') {
+        if ($is_map) { 
+            my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
+                                            $folder.'.'.$container);
+            return $errtext if ($fatal);
+
+            if ($#LONCAPA::map::order<1) {
+                my $idx=&LONCAPA::map::getresidx();
+                if ($idx<=0) { $idx=1; }
+                $LONCAPA::map::order[0]=$idx;
+                $LONCAPA::map::resources[$idx]='';
+            }
+            $newidx = &LONCAPA::map::getresidx($url);
+        }
         if ($env{'docs.markedcopy_supplemental'}) {
-            if ($folder =~ /^supplemental/) {
-                $title = $env{'docs.markedcopy_supplemental'};
-            } else {
+            if ($folder !~ /^supplemental/) {
                 (undef,undef,$title) =
                     &Apache::loncommon::parse_supplemental_title($env{'docs.markedcopy_supplemental'});
             }
@@ -938,8 +1111,81 @@
         }
         $LONCAPA::map::resources[$newidx]= 	$title.':'.$url.':'.$ext.':normal:res';
         push(@LONCAPA::map::order, $newidx);
+
+# Store the result
+        my ($errtext,$fatal) = 
+            &storemap($coursenum,$coursedom,$folder.'.'.$container,1);
+        if ($fatal) {
+            $save_err = $errtext;
+        }
+    }
+   
+    if ($env{'form.docs.markedcopy_options'} eq 'move') {
+        &Apache::lonnet::delenv('docs.markedcopy');
+        &Apache::lonnet::delenv('docs.markedcopy_nested');
+        &Apache::lonnet::delenv('docs.markedcopy_nestednames');
+    }
+    return ($result,$save_err);
+}
+
+sub get_newmap_url {
+    my ($url,$folder,$prefixchg,$coursedom,$coursenum,$srcdom,$srcnum,
+        $titleref,$allmaps,$newurls) = @_;
+    my $newurl;
+    if ($url=~ m{^/uploaded/}) {
+        $$titleref=&mt('Copy of').' '.$$titleref;
+    }
+    my $now = time;
+    my $suffix=$$.int(rand(100)).$now;
+    my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/);
+    if ($oldid =~ m{^(/uploaded/$match_domain/$match_courseid/)(\D+)(\d+)$}) {
+        my $path = $1;
+        my $prefix = $2;
+        my $ancestor = $3;
+        if (length($ancestor) > 10) {
+            $ancestor = substr($ancestor,-10,10);
+        }
+        my $newid;
+        if ($prefixchg) {
+            if ($folder =~ /^supplemental/) {
+                $prefix =~ s/^default/supplemental/;
+            } else {
+                $prefix =~ s/^supplemental/default/;
+            }
+        }
+        if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) {
+            $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext;
+        } else {
+            $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$now.'.'.$ext;
+        }
+        my $counter = 0;
+        my $is_unique = &uniqueness_check($newurl);
+        if ($folder =~ /^default/) {
+            if ($allmaps->{$newurl}) {
+                $is_unique = 0;
+            }
+        }
+        while ((!$is_unique || $allmaps->{$newurl} || $newurls->{$newurl}) && ($counter < 100)) {
+            $counter ++;
+            $suffix ++;
+            if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) {
+                $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext;
+            } else {
+                $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$ancestor.$suffix.'.'.$ext;
+            }
+            $is_unique = &uniqueness_check($newurl);
+        }
+        if ($is_unique) {
+            $newurls->{$newurl} = 1;
+        } else {
+            if ($url=~/\.page$/) {
+                return (undef,&mt('Paste failed: an error occurred creating a unique URL for the composite page'));
+            } else {
+                return (undef,&mt('Paste failed: an error occurred creating a unique URL for the folder'));
+            }
+        }
     }
-    return $result;
+    return ($newurl);
 }
 
 sub dbcopy {
@@ -974,7 +1220,8 @@
 }
 
 sub contained_map_check {
-    my ($url,$folder,$removefrommap,$addedmaps) = @_;
+    my ($url,$folder,$removefrommap,$removeparam,$addedmaps,$hierarchy,$titles,
+        $allmaps) = @_;
     my $content = &Apache::lonnet::getfile($url);
     unless ($content eq '-1') {
         my $parser = HTML::TokeParser->new(\$content);
@@ -986,21 +1233,33 @@
                 my $ressrc = $token->[2]->{'src'};
                 if ($folder =~ /^supplemental/) {
                     unless (&supp_pasteable($ressrc)) {
-                        $removefrommap->{$url}{$token->[2]->{'id'}};
+                        $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
                         next;
                     }
                 }
-                if ($ressrc =~ /\.(sequence|page)$/) {
-                    if (ref($addedmaps->{$ressrc}) eq 'ARRAY') {
-                        push(@{$addedmaps->{$ressrc}},$url);
+                if ($ressrc =~ m{^/(res|uploaded)/.+\.(sequence|page)$}) {
+                    if ($1 eq 'uploaded') {
+                        $hierarchy->{$url}{$token->[2]->{'id'}} = $ressrc;
+                        $titles->{$url}{$token->[2]->{'id'}} = $token->[2]->{'title'};
                     } else {
-                        $addedmaps->{$ressrc} = [$url];
+                        if ($allmaps->{$ressrc}) {
+                            $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; 
+                        } elsif (ref($addedmaps->{$ressrc}) eq 'ARRAY') {
+                            $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc;
+                        } else {
+                            $addedmaps->{$ressrc} = [$url];
+                        }
                     }
-                    &contained_map_check($ressrc,$folder,$removefrommap,$addedmaps);
+                    &contained_map_check($ressrc,$folder,$removefrommap,$removeparam,
+                                         $addedmaps,$hierarchy,$titles,$allmaps);
                 }
-            } elsif ($token->[1] !~ /^resource|map|link$/) {
+            } elsif ($token->[1] eq 'param') {
                 if ($folder =~ /^supplemental/) {
-                    $removefrommap->{$url}{$token->[1]};
+                    if (ref($removeparam->{$url}{$token->[2]->{'to'}}) eq 'ARRAY') {
+                        push(@{$removeparam->{$url}{$token->[2]->{'to'}}},$token->[2]->{'name'});
+                    } else {
+                        $removeparam->{$url}{$token->[2]->{'to'}} = [$token->[2]->{'name'}]; 
+                    }
                 }
             }
         }
@@ -1018,13 +1277,20 @@
 }
 
 sub url_paste_fixups {
-    my ($oldurl,$prefixchg,$cdom,$cnum,$allmaps,$rewrites,$retitles,$copies,
-        $dbcopies,$zombies,$params,$mapmoves,$mapchanges) = @_;
+    my ($oldurl,$folder,$prefixchg,$cdom,$cnum,$allmaps,$rewrites,$retitles,$copies,
+        $dbcopies,$zombies,$params,$mapmoves,$mapchanges,$tomove,$newsubdir,$newurls) = @_;
     my $checktitle;
     if (($prefixchg) &&
-        ($oldurl =~ m{^/uploaded/($match_domain)/($match_courseid)/supplemental})) {
+        ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/supplemental})) {
         $checktitle = 1;
     }
+    my $skip;
+    if ($oldurl =~ m{^\Q/uploaded/$cdom/$cnum/\E(default|supplemental)(_?\d*)\.(?:page|sequence)$}) {
+        my $mapid = $1.$2;
+        if ($tomove->{$mapid}) {
+            $skip = 1;
+        }
+    }
     my $file = &Apache::lonnet::getfile($oldurl);
     return if ($file eq '-1');
     my $parser = HTML::TokeParser->new(\$file);
@@ -1036,29 +1302,54 @@
             my $ressrc = $token->[2]->{'src'};
             next if ($ressrc eq '');
             my $id = $token->[2]->{'id'};
+            my $title = $token->[2]->{'title'};
             if ($checktitle) {
-                my $title = $token->[2]->{'title'};
                 if ($title =~ m{\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) {
                     $retitles->{$oldurl}{$ressrc} = $id;
-
                 }
             }
             next if ($token->[2]->{'type'} eq 'external');
             if ($token->[2]->{'type'} eq 'zombie') {
+                next if ($skip);  
                 $zombies->{$oldurl}{$ressrc} = $id;
                 $changed = 1;
             } elsif ($ressrc =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)$}) {
-                my $srccdom = $1;
-                my $srccnum = $2;
+                my $srcdom = $1;
+                my $srcnum = $2;
                 my $rem = $3;
-                if (($srccdom ne $cdom) || ($srccnum ne $cnum) || ($prefixchg) ||
-                    ($mapchanges->{$oldurl})) {
+                my $newurl;
+                my $mapname;
+                if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) {
+                    my $prefix = $1;
+                    $mapname = $prefix.$2;
+                    if ($tomove->{$mapname}) {
+                        &url_paste_fixups($ressrc,$folder,$prefixchg,$cdom,$cnum,$allmaps,
+                                          $rewrites,$retitles,$copies,$dbcopies,$zombies,
+                                          $params,$mapmoves,$mapchanges,$tomove,$newsubdir,
+                                          $newurls);
+                        next;
+                    } else {
+                        ($newurl,my $error) =
+                            &get_newmap_url($ressrc,$folder,$prefixchg,$cdom,$cnum,
+                                            $srcdom,$srcnum,\$title,$allmaps,$newurls);
+                        if ($newurl =~ /(?:default|supplemental)_(\d+)\.(?:sequence|page)$/) {
+                            $newsubdir->{$ressrc} = $1;
+                        }
+                        if ($error) {
+                            next;
+                        }
+                    }
+                }
+                if (($srcdom ne $cdom) || ($srcnum ne $cnum) || ($prefixchg) ||
+                    ($mapchanges->{$oldurl}) || (($newurl ne '') && ($newurl ne $oldurl))) {
+                   
                     if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) {
                         $rewrites->{$oldurl}{$ressrc} = $id;
                         $mapchanges->{$ressrc} = 1;
-                        unless (&url_paste_fixups($ressrc,$prefixchg,$cdom,$cnum,$allmaps,
+                        unless (&url_paste_fixups($ressrc,$folder,$prefixchg,$cdom,$cnum,$allmaps,
                                                   $rewrites,$retitles,$copies,$dbcopies,$zombies,
-                                                  $params,$mapmoves,$mapchanges)) {
+                                                  $params,$mapmoves,$mapchanges,$tomove,$newsubdir,
+                                                  $newurls)) {
                             $mapmoves->{$ressrc} = 1;
                         }
                         $changed = 1;
@@ -1069,27 +1360,30 @@
                     }
                 }
             } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) {
-                my $srccdom = $1;
-                my $srccnum = $2;
-                if (($srccdom ne $cdom) || ($srccnum ne $cnum)) {
+                next if ($skip);  
+                my $srcdom = $1;
+                my $srcnum = $2;
+                if (($srcdom ne $cdom) || ($srcnum ne $cnum)) {
                     $rewrites->{$oldurl}{$ressrc} = $id;
                     $dbcopies->{$oldurl}{$ressrc} = $id;
                     $changed = 1;
                 }
             } elsif ($ressrc =~ m{^/public/($match_domain)/($match_courseid)/(.+)$}) {
-                my $srccdom = $1;
-                my $srccnum = $2;
-                if (($srccdom ne $cdom) || ($srccnum ne $cnum)) {
+                next if ($skip);
+                my $srcdom = $1;
+                my $srcnum = $2;
+                if (($srcdom ne $cdom) || ($srcnum ne $cnum)) {
                     $rewrites->{$oldurl}{$ressrc} = $id;
                     $dbcopies->{$oldurl}{$ressrc} = $id;
                     $changed = 1;
                 }
             }
         } elsif ($token->[1] eq 'param') {
+            next if ($skip);
             my $to = $token->[2]->{'to'}; 
             if ($to ne '') {
                 if (ref($params->{$oldurl}{$to}) eq 'ARRAY') {
-                    push (@{$params->{$oldurl}{$to}},$token->[2]->{'name'});
+                    push(@{$params->{$oldurl}{$to}},$token->[2]->{'name'});
                 } else {
                     @{$params->{$oldurl}{$to}} = ($token->[2]->{'name'});
                 }
@@ -1100,25 +1394,9 @@
 }
 
 sub apply_fixups {
-    my ($is_map,$prefixchg,$cdom,$cnum,$oldurl,$url,$removefrommap,$rewrites,
-        $retitles,$copies,$dbcopies,$zombies,$params,$docmoves,$mapmoves,$errors,
-        $before,$after) = @_;
-    my ($oldsubdir,$newsubdir,$subdirchg);
-    if ($is_map) {
-        ($oldsubdir) =
-            ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_?(\d*)});
-        if ($oldsubdir eq '') {
-            $oldsubdir = 'default';
-        }
-        ($newsubdir) =
-            ($url =~ m{^/uploaded/$match_domain/$match_courseid/(?:default|supplemental)_?(\d*)});
-        if ($newsubdir eq '') {
-            $newsubdir = 'default';
-        }
-        if ($oldsubdir ne $newsubdir) {
-            $subdirchg = 1;
-        }
-    }
+    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 @allcopies;
         if (ref($copies->{$key}) eq 'HASH') {
@@ -1140,8 +1418,8 @@
         }
         if (@allcopies > 0) {
             foreach my $item (@allcopies) {
-                my ($relpath,$fname) = 
-                    ($item =~ m{^(/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(?:default|\d+)/.*/)([^/]+)$});
+                my ($relpath,$oldsubdir,$fname) = 
+                    ($item =~ m{^(/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(default|\d+)/.*/)([^/]+)$});
                 if ($fname ne '') {
                     my $content = &Apache::lonnet::getfile($item);
                     unless ($content eq '-1') {
@@ -1154,8 +1432,8 @@
                             if ($prefixchg) {
                                 $storefn =~ s/^\Q$before->{'doc'}\E/$after->{'doc'}/;
                             }
-                            if (($key eq $oldurl) && ($subdirchg)) {
-                                $storefn =~ s{^(docs|supplemental)/\Q$oldsubdir\E/}{$1/$newsubdir/};
+                            if ($newsubdir->{$key}) {
+                                $storefn =~ s#^(docs|supplemental)/\Q$oldsubdir\E/#$1/$newsubdir->{$key}#;
                             }
                         }
                         &copy_dependencies($item,$storefn,$relpath,$errors,\$content);
@@ -1180,6 +1458,9 @@
         if ($prefixchg) {
             $storefn =~ s/^\Q$before->{'map'}\E/$after->{'map'}/;
         }
+        if ($newsubdir->{$key}) {
+            $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir->{$key}/;
+        }
         my $mapcontent = &Apache::lonnet::getfile($key);
         if ($mapcontent eq '-1') {
             if (ref($errors) eq 'HASH') {
@@ -1199,22 +1480,25 @@
     my %updates;
     if ($is_map) {
         foreach my $key (keys(%{$rewrites})) {
-           $updates{$key} = 1;
+            $updates{$key} = 1;
         }
         foreach my $key (keys(%{$zombies})) {
-           $updates{$key} = 1;
+            $updates{$key} = 1;
         }
         foreach my $key (keys(%{$removefrommap})) {
-           $updates{$key} = 1;
-        } 
+            $updates{$key} = 1;
+        }
+        foreach my $key (keys(%{$removeparam})) {
+            $updates{$key} = 1;
+        }
         foreach my $key (keys(%{$dbcopies})) {
-           $updates{$key} = 1;
+            $updates{$key} = 1;
         }
         foreach my $key (keys(%{$retitles})) {
-           $updates{$key} = 1;
+            $updates{$key} = 1;
         }
         foreach my $key (keys(%updates)) {
-            my (%torewrite,%toretitle,%toremove,%zombie,%newdb);
+            my (%torewrite,%toretitle,%toremove,%remparam,%currparam,%zombie,%newdb);
             if (ref($rewrites->{$key}) eq 'HASH') {
                 %torewrite = %{$rewrites->{$key}};
             }
@@ -1224,6 +1508,9 @@
             if (ref($removefrommap->{$key}) eq 'HASH') {
                 %toremove = %{$removefrommap->{$key}};
             }
+            if (ref($removeparam->{$key}) eq 'HASH') {
+                %remparam = %{$removeparam->{$key}};
+            }
             if (ref($zombies->{$key}) eq 'HASH') {
                 %zombie = %{$zombies->{$key}};
             }
@@ -1232,69 +1519,72 @@
                     $newdb{$item} = &dbcopy($item);
                 }
             }
-            my $map = &Apache::lonnet::getfile($key);
-            my $newcontent;
-            if ($map eq '-1') {
-                return &mt('Paste failed: an error occurred reading a folder or page: [_1].',$key);
-            } else {
-                my $parser = HTML::TokeParser->new(\$map);
-                $parser->attr_encoded(1);
-                while (my $token = $parser->get_token) {
-                    if ($token->[0] eq 'S') {
-                        if ($token->[2]->{'type'} eq 'zombie') {
-                            next if (($token->[2]->{'src'} ne '') &&
-                                     ($zombie{$token->[2]->{'src'}} eq $token->[2]->{'id'}));
-                        }
-                        if ($token->[1] eq 'resource') {
-                            my $src = $token->[2]->{'src'};
-                            my $id = $token->[2]->{'id'};
-                            my $title = $token->[2]->{'title'};
-                            my $changed;
-                            if ((exists($toretitle{$src})) && ($toretitle{$src} eq $id)) {
-                                if ($title =~ m{^\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) {
-                                    $token->[2]->{'title'} = $1;
-                                    $changed = 1;
-                                }
+            if (ref($params->{$key}) eq 'HASH') {
+                %currparam = %{$params->{$key}};
+            }
+            my ($errtext,$fatal) = &LONCAPA::map::mapread($key);
+            if ($fatal) {
+                return $errtext;
+            }
+            for (my $i=0; $i<@LONCAPA::map::zombies; $i++) {
+                if (defined($LONCAPA::map::zombies[$i])) {
+                    my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::zombies[$i]);
+                    if ($zombie{$src} eq $i) {
+                        undef($LONCAPA::map::zombies[$i]);
+                    }
+                }
+            }
+            for (my $i=0; $i<@LONCAPA::map::resources; $i++) {
+                if (defined($LONCAPA::map::resources[$i])) {
+                    my $changed;
+                    my ($title,$src,$ext,$type)=split(/\:/,$LONCAPA::map::resources[$i]);
+                    if ($toremove{$src} eq $i) {
+                        splice(@LONCAPA::map::order,$i,1);
+                        if (ref($currparam{$i}) eq 'ARRAY') {
+                            foreach my $name (@{$currparam{$i}}) {
+                                &LONCAPA::map::delparameter($i,'parameter_'.$name);
                             }
-                            if ((exists($torewrite{$src})) && ($torewrite{$src} eq $id)) {
-                                $src =~ s{^/(uploaded|adm|public)/$match_domain/$match_courseid/}{/$1/$cdom/$cnum/};
-                                if ($src =~ m{^/uploaded/}) {
-                                    if ($prefixchg) {
-                                        if ($src =~ /\.(page|sequence)$/) {
-                                            $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'}#;
-                                        }
-                                    }
-                                    if (($key eq $oldurl) && ($src !~ /\.(page|sequence)$/) && ($subdirchg)) {
-                                        $src =~ s{^(/uploaded/$match_domain/$match_courseid/\w+/)\Q$oldsubdir\E}{$1$newsubdir};
-                                    }
+                        }
+                        next;
+                    }
+                    my $origsrc = $src;
+                    if ((exists($toretitle{$src})) && ($toretitle{$src} eq $i)) {
+                        if ($title =~ m{^\d+\Q___&&&___\E$match_username\Q___&&&___\E$match_domain\Q___&&&___\E(.+)$}) {
+                            $changed = 1;
+                        }
+                    }
+                    if ((exists($torewrite{$src})) && ($torewrite{$src} eq $i)) {
+                        $src =~ s{^/(uploaded|adm|public)/$match_domain/$match_courseid/}{/$1/$cdom/$cnum/};
+                        if ($origsrc =~ m{^/uploaded/}) {
+                            if ($prefixchg) {
+                                if ($src =~ /\.(page|sequence)$/) {
+                                    $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'}#;
                                 }
-                                $token->[2]->{'src'} = $src;
-                                $changed = 1;
-                            } elsif ($newdb{$src} ne '') {
-                                $token->[2]->{'src'} = $newdb{$src};
-                                $changed = 1;
                             }
-                            if ($changed) {
-                                $newcontent .= "<$token->[1]";
-                                foreach my $attr (@{$token->[3]}) {
-                                    if ($attr =~ /^\w+$/) {
-                                        $newcontent .=  ' '.$attr.'="'.$token->[2]->{$attr}.'"';
-                                    }
+                            if ($newsubdir->{$origsrc}) {
+                                if ($src =~ /\.(page|sequence)$/) {
+                                    $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}#;
                                 }
-                                $newcontent .= ' />'."\n";
-                            } else {
-                                $newcontent .= $token->[4]."\n";
                             }
-                        } elsif (($token->[2]->{'id'} ne '') &&
-                                 (exists($toremove{$token->[2]->{'id'}}))) {
-                            next;
-                        } else {
-                            $newcontent .= $token->[4]."\n";
                         }
-                    } elsif ($token->[0] eq 'E') {
-                        $newcontent .= $token->[2]."\n";
+                        $changed = 1;
+                    } elsif ($newdb{$src} ne '') {
+                        $src = $newdb{$src};
+                        $changed = 1;
+                    }
+                    if ($changed) {
+                        $LONCAPA::map::resources[$i] = join(':',($title,$src,$ext,$type));
+                    }
+                }
+            }
+            foreach my $idx (keys(%remparam)) {
+                if (ref($remparam{$idx}) eq 'ARRAY') {
+                    foreach my $name (@{$remparam{$idx}}) {   
+                        &LONCAPA::map::delparameter($idx,'parameter_'.$name);
                     }
                 }
             }
@@ -1308,11 +1598,17 @@
                 if ($prefixchg) {
                     $storefn =~ s/^\Q$before->{'map'}\E/$after->{'map'}/;
                 }
+                if ($newsubdir->{$key}) {
+                    $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir->{$key}/;
+                }
             }
-            my $newmapurl =
-                &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,
-                                                   $newcontent);
-            if ($newmapurl eq '/adm/notfound.html') {
+            my $report;
+            if ($folder !~ /^supplemental/) {
+                $report = 1;
+            }
+            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.');
             }
         }
@@ -1496,13 +1792,13 @@
 
 	if ($env{'form.pastemarked'}) {
             my %paste_errors;
-            my $paste_res =
-                &do_paste_from_buffer($coursenum,$coursedom,$folder,\%paste_errors);
-            if ($paste_res eq 'ok') {
-# Store the result
-                ($errtext,$fatal) = &storemap($coursenum,$coursedom,$folder.'.'.$container);
-                return $errtext if ($fatal);
-            } elsif ($paste_res ne '') {
+            my ($paste_res,$save_error) =
+                &do_paste_from_buffer($coursenum,$coursedom,$folder,$container,
+                                      \%paste_errors);
+                if ($save_error ne '') {
+                    return $save_error; 
+                }
+            if ($paste_res ne 'ok') {
                 $r->print('<p><span class="LC_error">'.$paste_res.'</span></p>');
             }
             if (keys(%paste_errors) > 0) {
@@ -1519,7 +1815,11 @@
 	$r->print($upload_output);
 
 	if (&handle_edit_cmd()) {
-	    ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
+            my $contentchg;
+            if ($env{'form.cmd'} =~ /^(del|cut)_/) {
+                $contentchg = 1;
+            }
+	    ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container,$contentchg);
 	    return $errtext if ($fatal);
 	}
 # Group import/search
@@ -1546,7 +1846,7 @@
 		    $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx;
 		}
 		($errtext,$fatal)=&storemap($coursenum,$coursedom,
-					    $folder.'.'.$container);
+					    $folder.'.'.$container,1);
 		return $errtext if ($fatal);
 	    } else {
 		$r->print('<p><span class="LC_error">'.&mt('No map selected.').'</span></p>');
@@ -1638,7 +1938,7 @@
         my $readfile="/uploaded/$coursedom/$coursenum/$folder.$container";
         $r->print(&generate_edit_table($tid,$orderhash,$to_show,$iconpath,$jumpto,
                                        $readfile));
-        &print_paste_buffer($r,$container,$folder);
+        &print_paste_buffer($r,$container,$folder,$coursedom,$coursenum);
     } else {
         if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) {
             #Function Box for Supplemental Content for users with mdc priv.
@@ -1726,7 +2026,7 @@
 	    $comment.':'.$url.':'.$ext.':normal:res';
         $LONCAPA::map::order[$#LONCAPA::map::order+1]= $newidx;
         ($errtext,$fatal)=&storemap($coursenum,$coursedom,
-				    $folder.'.'.$container);
+				    $folder.'.'.$container,1);
         if ($fatal) {
             $$upload_output = '<div class="LC_error" id="uploadfileresult">'.$errtext.'</div>';
             return;
@@ -1884,19 +2184,9 @@
 		'cp' => 'Copy');
 	my $nocopy=0;
         my $nocut=0;
-        if ($url=~/\.(page|sequence)$/) {
-	    if ($url =~ m{/res/}) {
-		# no copy for published maps
-		$nocopy = 1;
-	    } else {
-		foreach my $item (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$url),1)) {
-		    my ($title,$url,$ext,$type)=split(/\:/,$item);
-		    if (($url=~/\.(page|sequence)/) && ($type ne 'zombie')) {
-			$nocopy=1;
-			last;
-		    }
-		}
-	    }
+        if ($url=~ m{^/res/.+\.(page|sequence)$}) {
+	    # no copy for published maps
+	    $nocopy=1;
 	}
         if ($url=~/^\/res\/lib\/templates\//) {
            $nocopy=1;
@@ -3047,6 +3337,9 @@
                             onload   => "javascript:resize_scrollbox('contentscroll','1','1');",
                           };
         }
+        if ($env{'docs.markedcopy_url'}) {
+            $script .= &paste_popup_js(); 
+        }
     }
 # -------------------------------------------------------------------- Body tag
     $script = '<script type="text/javascript">'."\n"
@@ -3234,7 +3527,11 @@
 
 
     if ($allowed) {
-	&update_paste_buffer($coursenum,$coursedom);
+        my $folder = $env{'form.folder'};
+        if ($folder eq '') {
+            $folder='default';
+        }
+	&update_paste_buffer($coursenum,$coursedom,$folder);
 	$r->print(<<HIDDENFORM);
 	<form name="renameform" method="post" action="/adm/coursedocs">
    <input type="hidden" name="title" />
@@ -3758,7 +4055,7 @@
             my ($title,$url, at rrest) = 
                 split(/:/,$LONCAPA::map::resources[$LONCAPA::map::order[$position]]);
             if (&handle_edit_cmd($docuname,$docudom)) {
-                ($errtext,$fatal) = &storemap($docuname,$docudom,$map);
+                ($errtext,$fatal) = &storemap($docuname,$docudom,$map,1);
                 if ($fatal) {
                     if ($container eq 'page') {
                         $delwarning = &mt('An error occurred updating the contents of the current page.');
@@ -4474,6 +4771,22 @@
 
 =item do_paste_from_buffer()
 
+=item get_newmap_url()
+
+=item dbcopy()
+
+=item uniqueness_check()
+
+=item contained_map_check()
+
+=item reinit_role()
+
+=item url_paste_fixups()
+
+=item apply_fixups()
+
+=item copy_dependencies()
+
 =item update_parameter()
 
 =item handle_edit_cmd()


More information about the LON-CAPA-cvs mailing list