--- loncom/interface/londocs.pm 2013/03/17 14:27:34 1.537
+++ loncom/interface/londocs.pm 2013/04/02 20:33:41 1.542
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Documents
#
-# $Id: londocs.pm,v 1.537 2013/03/17 14:27:34 raeburn Exp $
+# $Id: londocs.pm,v 1.542 2013/04/02 20:33:41 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -323,10 +323,9 @@ sub group_import {
}
my $ext = 'false';
if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; }
- $url = &LONCAPA::map::qtunescape($url);
$name = &LONCAPA::map::qtunescape($name);
if ($name eq '') {
- $name = &mt('Web Page');
+ $name = &LONCAPA::map::qtunescape(&mt('Web Page'));
}
if ($url =~ m{^/uploaded/$coursedom/$coursenum/((?:docs|supplemental)/(?:default|\d+))/new\.html$}) {
my $filepath = $1;
@@ -367,6 +366,7 @@ END
return (&mt('Failed to save new web page.'),1);
}
}
+ $url = &LONCAPA::map::qtunescape($url);
$LONCAPA::map::resources[$residx] =
join(':', ($name, $url, $ext, 'normal', 'res'));
}
@@ -490,7 +490,7 @@ sub docs_change_log {
}
my $folderpath=$env{'form.folderpath'};
if ($folderpath eq '') {
- $folderpath = 'default&'.&escape(&mt('Main '.$crstype.' Documents').':::::');
+ $folderpath = 'default&'.&escape(&mt('Main '.$crstype.' Content').':::::');
}
$pathitem = '';
@@ -655,57 +655,115 @@ sub docs_change_log {
sub update_paste_buffer {
my ($coursenum,$coursedom,$folder) = @_;
+ my (@possibles,%removals,%cuts);
+ if ($env{'form.multiremove'}) {
+ $env{'form.multiremove'} =~ s/,$//;
+ map { $removals{$_} = 1; } split(/,/,$env{'form.multiremove'});
+ }
+ if (($env{'form.multicopy'}) || ($env{'form.multicut'})) {
+ if ($env{'form.multicut'}) {
+ $env{'form.multicut'} =~ s/,$//;
+ foreach my $item (split(/,/,$env{'form.multicut'})) {
+ unless ($removals{$item}) {
+ $cuts{$item} = 1;
+ push(@possibles,$item.':cut');
+ }
+ }
+ }
+ if ($env{'form.multicopy'}) {
+ $env{'form.multicopy'} =~ s/,$//;
+ foreach my $item (split(/,/,$env{'form.multicopy'})) {
+ unless ($removals{$item} || $cuts{$item}) {
+ push(@possibles,$item.':copy');
+ }
+ }
+ }
+ } elsif ($env{'form.markcopy'}) {
+ @possibles = split(/,/,$env{'form.markcopy'});
+ }
- return if (!defined($env{'form.markcopy'}));
+ return if (@possibles == 0);
return if (!defined($env{'form.copyfolder'}));
- return if ($env{'form.markcopy'} < 0);
my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
$env{'form.copyfolder'});
-
return if ($fatal);
-# Mark for copying
- my ($title,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$env{'form.markcopy'}]]);
- if (&is_supplemental_title($title)) {
- &Apache::lonnet::appenv({'docs.markedcopy_supplemental' => $title});
- ($title) = &Apache::loncommon::parse_supplemental_title($title);
- } elsif ($env{'docs.markedcopy_supplemental'}) {
- &Apache::lonnet::delenv('docs.markedcopy_supplemental');
- }
- $url=~s{http(:|:)//https(:|:)//}{https$2//};
-
- (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;
+ my %curr_groups = &Apache::longroup::coursegroups();
+
+# Retrieve current paste buffer suffixes.
+ my @currpaste = split(/,/,$env{'docs.markedcopies'});
+ my (%pasteurls,@newpaste);
+
+# Construct identifiers for current contents of user's paste buffer
+ if (@currpaste) {
+ foreach my $suffix (@currpaste) {
+ my $cid = $env{'docs.markedcopy_crs_'.$suffix};
+ my $url = $env{'docs.markedcopy_url_'.$suffix};
+ if (($cid =~ /^$match_domain(?:_)$match_courseid$/) &&
+ ($url ne '')) {
+ $pasteurls{$cid.'_'.$url};
+ }
+ }
+ }
+
+# Mark items for copying (skip any items already in user's paste buffer)
+ my %addtoenv;
+
+ foreach my $item (@possibles) {
+ my ($orderidx,$cmd) = split(/:/,$item);
+ next if ($orderidx =~ /\D/);
+ next unless (($cmd eq 'cut') || ($cmd eq 'copy') || ($cmd eq 'remove'));
+ my ($title,$url)=split(':',$LONCAPA::map::resources[$orderidx]);
+ my %denied = &action_restrictions($coursenum,$coursedom,
+ &LONCAPA::map::qtescape($url),
+ $env{'form.folderpath'},\%curr_groups);
+ next if ($denied{'copy'});
+ $url=~s{http(:|:)//https(:|:)//}{https$2//};
+ next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$url}));
+ my ($suffix,$errortxt,$locknotfreed) =
+ &new_timebased_suffix($env{'user.domain'},$env{'user.name'},'paste');
+ push(@newpaste,$suffix);
+ if ($locknotfreed) {
+ return $locknotfreed;
+ last;
+ }
+ if (&is_supplemental_title($title)) {
+ &Apache::lonnet::appenv({'docs.markedcopy_supplemental_'.$suffix => $title});
+ ($title) = &Apache::loncommon::parse_supplemental_title($title);
+ }
+
+ $addtoenv{'docs.markedcopy_title_'.$suffix} = $title,
+ $addtoenv{'docs.markedcopy_url_'.$suffix} = $url,
+ $addtoenv{'docs.markedcopy_cmd_'.$suffix} = $cmd,
+ $addtoenv{'docs.markedcopy_crs_'.$suffix} = $env{'request.course.id'};
+
+ if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(default|supplemental)_?(\d*)\.(page|sequence)$}) {
+ my $prefix = $1;
+ my $subdir =$2;
+ if ($subdir eq '') {
+ $subdir = $prefix;
}
- if ($nestednames ne '') {
- $addtoenv{'docs.markedcopy_nestednames'} = $nestednames;
+ 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_'.$suffix} = $nested;
+ }
+ if ($nestednames ne '') {
+ $addtoenv{'docs.markedcopy_nestednames_'.$suffix} = $nestednames;
+ }
}
}
}
+ if (@newpaste) {
+ $addtoenv{'docs.markedcopies'} = join(',',(@currpaste,@newpaste));
+ }
&Apache::lonnet::appenv(\%addtoenv);
delete($env{'form.markcopy'});
}
@@ -737,155 +795,200 @@ sub recurse_uploaded_maps {
sub print_paste_buffer {
my ($r,$container,$folder,$coursedom,$coursenum) = @_;
- return if (!defined($env{'docs.markedcopy_url'}));
+ return if (!defined($env{'docs.markedcopies'}));
- 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;
+ unless (($env{'form.pastemarked'}) || ($env{'form.clearmarked'})) {
+ return if ($env{'docs.markedcopies'} eq '');
}
- my ($canpaste,$nopaste,$othercrs,$areachange);
- if ($folder =~ /^supplemental/) {
- $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 @currpaste = split(/,/,$env{'docs.markedcopies'});
+ my ($pasteitems,@pasteable);
- if ($canpaste) {
- 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 = '
'.&mt('(from another course).');
- }
- } else {
- $canpaste = 0;
- $nopaste = &mt('Paste from another course unavailable.')
- }
+# Construct identifiers for current contents of user's paste buffer
+ foreach my $suffix (@currpaste) {
+ next if ($suffix =~ /\D/);
+ my $cid = $env{'docs.markedcopy_crs_'.$suffix};
+ my $url = $env{'docs.markedcopy_url_'.$suffix};
+ if (($cid =~ /^$match_domain\_$match_courseid$/) &&
+ ($url ne '')) {
+ my ($is_external,$othercourse,$fromsupp,$is_uploaded_map,$parent,
+ $canpaste,$nopaste,$othercrs,$areachange);
+ my $extension = (split(/\./,$env{'docs.markedcopy_url_'.$suffix}))[-1];
+ if ($url =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) {
+ $is_external = 1;
}
- if ($rem =~ m{^(default|supplemental)_?(\d*)\.(?:page|sequence)$}) {
- my $prefix = $1;
- $parent = $2;
- if ($folder !~ /^\Q$prefix\E/) {
- $areachange = 1;
+ if ($folder =~ /^supplemental/) {
+ $canpaste = &supp_pasteable($env{'docs.markedcopy_url_'.$suffix});
+ unless ($canpaste) {
+ $nopaste = &mt('Paste into Supplemental Content unavailable.');
}
- $is_uploaded_map = 1;
+ } else {
+ $canpaste = 1;
}
- }
- }
-
- $r->print('
'.
- join('
',@{$pastemsgarray}).
- '
'. - $lockerror. + if (ref($pastemsgarray) eq 'ARRAY') { + if (@{$pastemsgarray} > 0) { + $r->print('
'.
+ join('
',@{$pastemsgarray}).
'
'. + $lockerror. + '
'); + } + if ($save_error ne '') { + return $save_error; + } + if ($paste_res) { + my %errortext = &Apache::lonlocal::texthash ( + fail => 'Storage of folder contents failed', + failread => 'Reading folder contents failed', + failstore => 'Storage of folder contents failed', + ); + if ($errortext{$paste_res}) { + $r->print(''.$errortext{$paste_res}.'
'); } - if ($paste_res ne 'ok') { - $r->print(''.$paste_res.'
'); } if (keys(%paste_errors) > 0) { - $r->print(''."\n". + $r->print('
'."\n". &mt('The following files are either dependencies of a web page or references within a folder and/or composite page which could not be copied during the paste operation:')."\n". '
'.$output.'
'); + } + } $r->print($upload_output); +# Rename, cut, copy or remove a single resource if (&handle_edit_cmd()) { my $contentchg; - if ($env{'form.cmd'} =~ /^(del|cut)_/) { + if ($env{'form.cmd'} =~ m{^(del|cut)_}) { $contentchg = 1; } ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container,$contentchg); return $errtext if ($fatal); } + +# Cut, copy and/or remove multiple resources + if ($env{'form.multichange'}) { + my %allchecked = ( + cut => {}, + remove => {}, + ); + my $needsupdate; + foreach my $which (keys(%allchecked)) { + $env{'form.multi'.$which} =~ s/,$//; + if ($env{'form.multi'.$which}) { + map { $allchecked{$which}{$_} = 1; } split(/,/,$env{'form.multi'.$which}); + if (ref($allchecked{$which}) eq 'HASH') { + $needsupdate += scalar(keys(%{$allchecked{$which}})); + } + } + } + if ($needsupdate) { + my $haschanges = 0; + my %curr_groups = &Apache::longroup::coursegroups(); + my $total = scalar(@LONCAPA::map::order) - 1; + for (my $i=$total; $i>=0; $i--) { + my $res = $LONCAPA::map::order[$i]; + my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]); + $name=&LONCAPA::map::qtescape($name); + $url=&LONCAPA::map::qtescape($url); + next unless ($name && $url); + my %denied = + &action_restrictions($coursenum,$coursedom,$url, + $env{'form.folderpath'},\%curr_groups); + foreach my $which (keys(%allchecked)) { + next if ($denied{$which}); + next unless ($allchecked{$which}{$res}); + if ($which eq 'remove') { + if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) && + ($url!~/$LONCAPA::assess_page_seq_re/)) { + &Apache::lonnet::removeuploadedurl($url); + } else { + &LONCAPA::map::makezombie($res); + } + splice(@LONCAPA::map::order,$i,1); + $haschanges ++; + } elsif ($which eq 'cut') { + &LONCAPA::map::makezombie($res); + splice(@LONCAPA::map::order,$i,1); + $haschanges ++; + } + } + } + if ($haschanges) { + ($errtext,$fatal) = + &storemap($coursenum,$coursedom,$folder.'.'.$container,1); + return $errtext if ($fatal); + } + } + } + # Group import/search if ($env{'form.importdetail'}) { my @imports; @@ -2237,8 +2595,13 @@ sub editor { $r->print(''); } - my ($to_show,$output,@allidx,@allmapidx); - + my ($to_show,$output,@allidx,@allmapidx,%filters,%lists,%curr_groups); + %filters = ( + canremove => [], + cancut => [], + cancopy => [], + ); + %curr_groups = &Apache::longroup::coursegroups(); &Apache::loncommon::start_data_table_count(); #setup a row counter foreach my $res (@LONCAPA::map::order) { my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]); @@ -2252,12 +2615,14 @@ sub editor { } $output .= &entryline($idx,$name,$url,$folder,$allowed,$res, $coursenum,$coursedom,$crstype, - $pathitem,$supplementalflag,$container); + $pathitem,$supplementalflag,$container, + \%filters,\%curr_groups); $idx++; $shown++; } &Apache::loncommon::end_data_table_count(); + my $need_save; if (($allowed) || ($supplementalflag && $folder eq 'supplemental')) { my $toolslink = '' .&Apache::loncommon::help_open_menu('Navigation Screen', @@ -2275,50 +2640,41 @@ sub editor { .&Apache::loncommon::start_data_table(undef,'contentlist') .&Apache::loncommon::start_data_table_header_row() .' | '.&mt('Move').' | ' - .''.&mt('Actions').' | ' - .''.&mt('Document').' | '; + .''.&mt('Actions').' | ' + .''.&mt('Document').' | '; if ($folder !~ /^supplemental/) { $to_show .= ''.&mt('Settings').' | '; } $to_show .= &Apache::loncommon::end_data_table_header_row(); if ($folder !~ /^supplemental/) { - my $idxlist = join(',',@allidx); - my $mapidxlist = join(',',@allmapidx); + $lists{'canhide'} = join(',',@allidx); + $lists{'canrandomlyorder'} = join(',',@allmapidx); + foreach my $item ('canremove','cancut','cancopy') { + if (ref($filters{$item}) eq 'ARRAY') { + $lists{$item} = join(',',@{$filters{$item}}); + } + } if (@allidx > 0) { my $path; if ($env{'form.folderpath'}) { $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); } - $to_show .= - &Apache::loncommon::continue_data_table_row(). - ''. - ' | '. - ''. - ' | '. - &Apache::loncommon::end_data_table_row(); + if (@allidx > 1) { + $to_show .= + &Apache::loncommon::continue_data_table_row(). + ' '. - - ''. + ' | '. + &multiple_check_form('actions',\%lists). + ' | '. + ''. + ' | '. + ' | '. + &multiple_check_form('settings',\%lists). + ' | '. + &Apache::loncommon::end_data_table_row(); + $need_save = 1; + } } } $to_show .= $output.' ' @@ -2360,8 +2716,8 @@ sub editor { } if ($allowed) { my $readfile="/uploaded/$coursedom/$coursenum/$folder.$container"; - $r->print(&generate_edit_table($tid,$orderhash,$to_show,$iconpath,$jumpto, - $readfile)); + $r->print(&generate_edit_table($tid,$orderhash,$to_show,$iconpath, + $jumpto,$readfile,$need_save,"$folder.$container")); &print_paste_buffer($r,$container,$folder,$coursedom,$coursenum); } else { $r->print($to_show); @@ -2369,6 +2725,67 @@ sub editor { return; } +sub multiple_check_form { + my ($caller,$listsref) = @_; + return unless (ref($listsref) eq 'HASH'); + my $output = + ''. + ' '; + return $output; +} + sub process_file_upload { my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd) = @_; # upload a file, if present @@ -2528,7 +2945,7 @@ sub is_supplemental_title { sub entryline { my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$coursedom, - $crstype,$pathitem,$supplementalflag,$container)=@_; + $crstype,$pathitem,$supplementalflag,$container,$filtersref,$currgroups)=@_; my ($foldertitle,$renametitle); if (&is_supplemental_title($title)) { ($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title); @@ -2544,7 +2961,7 @@ sub entryline { $renametitle=~s/\"\;/\\\"/g; $renametitle=~s/ /%20/g; my $line=&Apache::loncommon::start_data_table_row(); - my ($form_start,$form_end,$form_common); + my ($form_start,$form_end,$form_common,$form_param); # Edit commands my ($esc_path, $path, $symb); if ($env{'form.folderpath'}) { @@ -2568,8 +2985,25 @@ sub entryline { &Apache::lonnet::declutter($currurl)); } } - my ($renamelink,%lt); + my ($renamelink,%lt,$ishash); + if (ref($filtersref) eq 'HASH') { + $ishash = 1; + } + if ($allowed) { + $form_start = ' + '; + my $incindex=$index+1; my $selectbox=''; if (($#LONCAPA::map::order>0) && @@ -2605,66 +3039,9 @@ sub entryline { 'ul' => 'URL', 'ti' => 'Title', ); - my $nocopy=0; - my $nocut=0; - my $noremove=0; - if ($url=~ m{^/res/.+\.(page|sequence)$}) { - # no copy for published maps - $nocopy=1; - } - if ($url=~/^\/res\/lib\/templates\//) { - $nocopy=1; - $nocut=1; - } - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - if ($url eq "/uploaded/$cdom/$cnum/group_allfolders.sequence") { - if ($env{'form.folderpath'} =~ /^default&[^\&]+$/) { - my %curr_groups = &Apache::longroup::coursegroups(); - if (keys(%curr_groups) > 0) { - $noremove=1; - } - $nocut=1; - $nocopy=1; - } - } elsif ($url =~ m{^\Q/uploaded/$cdom/$cnum/group_folder_\E(\w+)\.sequence$}) { - my $group = $1; - if ($env{'form.folderpath'} =~ /^default&[^\&]+\&group_allfolders\&[^\&]+$/) { - my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group); - if (keys(%curr_group) > 0) { - $noremove=1; - } - } - $nocut=1; - $nocopy=1; - } elsif ($url =~ m{^\Q/adm/$cdom/$cnum/\E(\w+)/smppg$}) { - my $group = $1; - if ($env{'form.folderpath'} =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&\Qgroup_folder_$group\E\&[^\&]+$/) { - my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group); - my %groupsettings = &Apache::longroup::get_group_settings($curr_group{$group}); - if (keys(%groupsettings) > 0) { - $noremove=1; - } - $nocut=1; - $nocopy=1; - } - } elsif ($env{'form.folderpath'} =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&group_folder_(\w+)\&/) { - my $group = $1; - my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group); - if ($url =~ /group_boards_\Q$group\E/) { - my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group); - my %groupsettings = &Apache::longroup::get_group_settings($curr_group{$group}); - if (keys(%groupsettings) > 0) { - if (ref($groupsettings{'functions'}) eq 'HASH') { - if ($groupsettings{'functions'}{'discussion'} eq 'on') { - $noremove=1; - } - } - } - $nocut=1; - $nocopy=1; - } - } + my %denied = &action_restrictions($coursenum,$coursedom,$url, + $env{'form.folderpath'}, + $currgroups); my ($copylink,$cutlink,$removelink); my $skip_confirm = 0; if ( $folder =~ /^supplemental/ @@ -2678,48 +3055,64 @@ sub entryline { $skip_confirm = 1; } - if ($nocopy) { + if ($denied{'copy'}) { $copylink=(<
---|