'.
- &mt('Dump '.$type.
- ' DOCS to Construction Space: available on other servers');
- }
-}
sub clean {
my ($title)=@_;
$title=~s/[^\w\/\!\$\%\^\*\-\_\=\+\;\:\,\\\|\`\~]+/\_/gs;
- return $title;
+ return $title;
}
-# -------------------------------------------------------- Actually dump course
+
+
sub dumpcourse {
my ($r) = @_;
- my $type = &Apache::loncommon::course_type();
- $r->print(&Apache::loncommon::start_page('Dump '.$type.' DOCS to Construction Space').
- '');
+ '');
}
+ $r->print(&endContentScreen());
}
-# ------------------------------------------------------ Generate "export" button
+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)$})
+ && ($caller eq 'londocs')
+ && (!&Apache::lonnet::stat_file($url))) {
-sub exportbutton {
- my $type = &Apache::loncommon::course_type();
- return '
'.
- ''.
- &Apache::loncommon::help_open_topic('Docs_Export_Course_Docs');
+ my $errtext = '';
+ my $fatal = 0;
+ my $newmapstr = '';
+ $env{'form.output'}=$newmapstr;
+ my $result=&Apache::lonnet::finishuserfileupload($coursenum,$coursedom,
+ 'output',$1.$2);
+ if ($result !~ m{^/uploaded/}) {
+ $errtext.='Map not saved: A network error occurred when trying to save the new map. ';
+ $fatal = 2;
+ }
+ if ($fatal) {
+ return ($errtext,$fatal);
+ }
+ }
+ if ($url) {
+ if (($caller eq 'londocs') &&
+ ($folder =~ /^default/)) {
+ if (($url =~ /\.(page|sequence)$/) && (!$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);
+ push(@LONCAPA::map::order, $residx);
+ }
+ my $ext = 'false';
+ if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; }
+ $name = &LONCAPA::map::qtunescape($name);
+ if ($name eq '') {
+ $name = &LONCAPA::map::qtunescape(&mt('Web Page'));
+ }
+ if ($url =~ m{^/uploaded/$coursedom/$coursenum/((?:docs|supplemental)/(?:default|\d+))/new\.html$}) {
+ my $filepath = $1;
+ my $fname = $name;
+ if ($fname =~ /^\W+$/) {
+ $fname = 'web';
+ } else {
+ $fname =~ s/\W/_/g;
+ }
+ if (length($fname > 15)) {
+ $fname = substr($fname,0,14);
+ }
+ my $initialtext = &mt('Replace with your own content.');
+ my $newhtml = <
+
+
+
+$name
+
+
+$initialtext
+
+
+END
+ $env{'form.output'}=$newhtml;
+ my $result =
+ &Apache::lonnet::finishuserfileupload($coursenum,$coursedom,
+ 'output',
+ "$filepath/$residx/$fname.html");
+ if ($result =~ m{^/uploaded/}) {
+ $url = $result;
+ if ($filepath =~ /^supplemental/) {
+ $name = time.'___&&&___'.$env{'user.name'}.'___&&&___'.
+ $env{'user.domain'}.'___&&&___'.$name;
+ }
+ } else {
+ return (&mt('Failed to save new web page.'),1);
+ }
+ }
+ $url = &LONCAPA::map::qtunescape($url);
+ $LONCAPA::map::resources[$residx] =
+ join(':', ($name, $url, $ext, 'normal', 'res'));
+ }
+ }
+ if ($importuploaded) {
+ my %import_errors;
+ my %updated = (
+ removefrommap => \%removefrommap,
+ removeparam => \%removeparam,
+ );
+ my ($result,$msgsarray,$lockerror) =
+ &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".
+ '
';
+ }
+ }
+ my ($errtext,$fatal) =
+ &storemap($coursenum, $coursedom, $folder.'.'.$container,1);
+ return ($errtext,$fatal,$fixuperrors);
+}
+
+sub log_docs {
+ return &Apache::lonnet::write_log('course','docslog',@_);
+}
+
+{
+ my @oldresources=();
+ my @oldorder=();
+ my $parmidx;
+ my %parmaction=();
+ my %parmvalue=();
+ my $changedflag;
+
+ sub snapshotbefore {
+ @oldresources=@LONCAPA::map::resources;
+ @oldorder=@LONCAPA::map::order;
+ $parmidx=undef;
+ %parmaction=();
+ %parmvalue=();
+ $changedflag=0;
+ }
+
+ sub remember_parms {
+ my ($idx,$parameter,$action,$value)=@_;
+ $parmidx=$idx;
+ $parmaction{$parameter}=$action;
+ $parmvalue{$parameter}=$value;
+ $changedflag=1;
+ }
+
+ sub log_differences {
+ my ($plain)=@_;
+ my %storehash=('folder' => $plain,
+ 'currentfolder' => $env{'form.folder'});
+ if ($parmidx) {
+ $storehash{'parameter_res'}=$oldresources[$parmidx];
+ foreach my $parm (keys(%parmaction)) {
+ $storehash{'parameter_action_'.$parm}=$parmaction{$parm};
+ $storehash{'parameter_value_'.$parm}=$parmvalue{$parm};
+ }
+ }
+ my $maxidx=$#oldresources;
+ if ($#LONCAPA::map::resources>$#oldresources) {
+ $maxidx=$#LONCAPA::map::resources;
+ }
+ for (my $idx=0; $idx<=$maxidx; $idx++) {
+ if ($LONCAPA::map::resources[$idx] ne $oldresources[$idx]) {
+ $storehash{'before_resources_'.$idx}=$oldresources[$idx];
+ $storehash{'after_resources_'.$idx}=$LONCAPA::map::resources[$idx];
+ $changedflag=1;
+ }
+ if ($LONCAPA::map::order[$idx] ne $oldorder[$idx]) {
+ $storehash{'before_order_res_'.$idx}=$oldresources[$oldorder[$idx]];
+ $storehash{'after_order_res_'.$idx}=$LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
+ $changedflag=1;
+ }
+ }
+ $storehash{'maxidx'}=$maxidx;
+ if ($changedflag) { &log_docs(\%storehash); }
+ }
}
-sub exportcourse {
- my $r=shift;
- my $type = &Apache::loncommon::course_type();
- my %discussiontime = &Apache::lonnet::dump('discussiontimes',
- $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'});
- my $numdisc = keys %discussiontime;
- my $navmap = Apache::lonnavmaps::navmap->new();
- my $it=$navmap->getIterator(undef,undef,undef,1,undef,undef);
- my $curRes;
- my $outcome;
-
- &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
- ['finishexport']);
- if ($env{'form.finishexport'}) {
- &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
- ['archive','discussion']);
-
- my @exportitems = &Apache::loncommon::get_env_multiple('form.archive');
- my @discussions = &Apache::loncommon::get_env_multiple('form.discussion');
- if (@exportitems == 0 && @discussions == 0) {
- $outcome = ' As you did not select any content items or discussions for export, an IMS package has not been created. Please go back to select either content items or discussions for export';
- } else {
- my $now = time;
- my %symbs;
- my $manifestok = 0;
- my $imsresources;
- my $tempexport;
- my $copyresult;
- my $ims_manifest = &create_ims_store($now,\$manifestok,\$outcome,\$tempexport);
- if ($manifestok) {
- &build_package($now,$navmap,\@exportitems,\@discussions,\$outcome,$tempexport,\$copyresult,$ims_manifest);
- close($ims_manifest);
-
-#Create zip file in prtspool
- my $imszipfile = '/prtspool/'.
- $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
- time.'_'.rand(1000000000).'.zip';
- my $cwd = &Cwd::getcwd();
- my $imszip = '/home/httpd/'.$imszipfile;
- chdir $tempexport;
- open(OUTPUT, "zip -r $imszip * 2> /dev/null |");
- close(OUTPUT);
- chdir $cwd;
- $outcome .= &mt('Download the zip file from IMS '.lc($type).' archive ',$imszipfile,);
- if ($copyresult) {
- $outcome .= 'The following errors occurred during export - '.$copyresult;
- }
- } else {
- $outcome = ' Unfortunately you will not be able to retrieve an IMS archive of this posts at this time, because there was a problem creating a manifest file. ';
- }
- }
- $r->print(&Apache::loncommon::start_page('Export '.lc($type).' to IMS content package'));
- $r->print($outcome);
- $r->print(&Apache::loncommon::end_page());
- } else {
- my $display;
- $display = ''.
- &Apache::loncommon::end_page());
- }
-}
-
-sub create_ims_store {
- my ($now,$manifestok,$outcome,$tempexport) = @_;
- $$tempexport = $Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/ims_exports';
- my $ims_manifest;
- if (!-e $$tempexport) {
- mkdir($$tempexport,0700);
- }
- $$tempexport .= '/'.$now;
- if (!-e $$tempexport) {
- mkdir($$tempexport,0700);
- }
- $$tempexport .= '/'.$env{'user.domain'}.'_'.$env{'user.name'};
- if (!-e $$tempexport) {
- mkdir($$tempexport,0700);
- }
- if (!-e "$$tempexport/resources") {
- mkdir("$$tempexport/resources",0700);
- }
-# open manifest file
- my $manifest = '/imsmanifest.xml';
- my $manifestfilename = $$tempexport.$manifest;
- if ($ims_manifest = Apache::File->new('>'.$manifestfilename)) {
- $$manifestok=1;
- print $ims_manifest
-''."\n".
-''."\n".
-'
-
-
-
- '.$env{'request.course.id'}.'
-
- '.$env{'course.'.$env{'request.course.id'}.'.description'}.'
-
-
-
- '."\n".
-' '."\n".
-' '."\n".
-' '.$env{'course.'.$env{'request.course.id'}.'.description'}.''
- } else {
- $$outcome .= 'An error occurred opening the IMS manifest file. '
-;
- }
- return $ims_manifest;
-}
-
-sub build_package {
- my ($now,$navmap,$exportitems,$discussions,$outcome,$tempexport,$copyresult,$ims_manifest) = @_;
-# first iterator to look for dependencies
- my $it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
- my $curRes;
- my $count = 0;
- my $depth = 0;
- my $lastcontainer = 0;
- my %parent = ();
- my @dependencies = ();
- my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
- my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
- while ($curRes = $it->next()) {
- if (ref($curRes)) {
- $count ++;
- }
- if ($curRes == $it->BEGIN_MAP()) {
- $depth++;
- $parent{$depth} = $lastcontainer;
+function showOptions(caller,suffix) {
+ if (document.getElementById('pasteoptionstext_'+suffix)) {
+ if (caller.checked) {
+ document.getElementById('pasteoptionstext_'+suffix).innerHTML =' $lt{'show'}';
+ } else {
+ document.getElementById('pasteoptionstext_'+suffix).innerHTML ='';
}
- if ($curRes == $it->END_MAP()) {
- $depth--;
- $lastcontainer = $parent{$depth};
+ if (document.getElementById('pasteoptions_'+suffix)) {
+ document.getElementById('pasteoptions_'+suffix).style.display='none';
}
- if (ref($curRes)) {
- if ($curRes->is_sequence() || $curRes->is_page()) {
- $lastcontainer = $count;
- }
- if (grep/^$count$/,@$exportitems) {
- &get_dependencies($exportitems,\%parent,$depth,\@dependencies);
+ }
+ return;
+}
+
+END
+
+}
+
+
+sub do_paste_from_buffer {
+ my ($coursenum,$coursedom,$folder,$container,$errors) = @_;
+
+# Array of items in paste buffer
+ my (@currpaste,%pastebuffer,%allerrors);
+ @currpaste = split(/,/,$env{'docs.markedcopies'});
+
+# Early out if paste buffer is empty
+ if (@currpaste == 0) {
+ return ();
+ }
+ map { $pastebuffer{$_} = 1; } @currpaste;
+
+# Array of items selected items to paste
+ my @reqpaste = &Apache::loncommon::get_env_multiple('form.pasting');
+
+# Early out if nothing selected to paste
+ if (@reqpaste == 0) {
+ return();
+ }
+ my @topaste;
+ foreach my $suffix (@reqpaste) {
+ next if ($suffix =~ /\D/);
+ next unless (exists($pastebuffer{$suffix}));
+ push(@topaste,$suffix);
+ }
+
+# Early out if nothing available to paste
+ if (@topaste == 0) {
+ return();
+ }
+
+ my (%msgs,%before,%after,@dopaste,%is_map,%notinsupp,%notincrs,%duplicate,
+ %prefixchg,%srcdom,%srcnum,%marktomove,$save_err,$lockerrors,$allresult,
+ %msgs);
+
+ foreach my $suffix (@topaste) {
+ my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url_'.$suffix});
+# 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($url)) {
+ $notinsupp{$suffix} = 1;
+ next;
}
}
- }
-# second iterator to build manifest and store resources
- $it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
- $depth = 0;
- my $prevdepth;
- $count = 0;
- my $imsresources;
- my $pkgdepth;
- while ($curRes = $it->next()) {
- if ($curRes == $it->BEGIN_MAP()) {
- $prevdepth = $depth;
- $depth++;
+ if ($url =~ m{^/uploaded/($match_domain)/($match_courseid)/}) {
+ my $srcd = $1;
+ my $srcn = $2;
+# 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 (($srcd ne $coursedom) || ($srcn ne $coursenum)) {
+ unless ($env{"user.priv.cm./$srcd/$srcn"} =~ /\Q:mdc&F\E/) {
+ $notincrs{$suffix} = 1;
+ next;
+ }
+ }
+ $srcdom{$suffix} = $srcd;
+ $srcnum{$suffix} = $srcn;
}
- if ($curRes == $it->END_MAP()) {
- $prevdepth = $depth;
- $depth--;
+
+ push(@dopaste,$suffix);
+ if ($url=~/\.(page|sequence)$/) {
+ $is_map{$suffix} = 1;
}
- if (ref($curRes)) {
- $count ++;
- if ((grep/^$count$/,@$exportitems) || (grep/^$count$/,@dependencies)) {
- my $symb = $curRes->symb();
- my $isvisible = 'true';
- my $resourceref;
- if ($curRes->randomout()) {
- $isvisible = 'false';
- }
- unless ($curRes->is_sequence()) {
- $resourceref = 'identifierref="RES-'.$env{'request.course.id'}.'-'.$count.'"';
- }
- my $step = $prevdepth - $depth;
- if (($step >= 0) && ($count > 1)) {
- while ($step >= 0) {
- print $ims_manifest "\n".' '."\n";
- $step --;
- }
- }
- $prevdepth = $depth;
-
- my $itementry =
- ''.
- ''.$curRes->title().'';
- print $ims_manifest "\n".$itementry;
-
- unless ($curRes->is_sequence()) {
- my $content_file;
- my @hrefs = ();
- &process_content($count,$curRes,$cdom,$cnum,$symb,\$content_file,\@hrefs,$copyresult,$tempexport);
- if ($content_file) {
- $imsresources .= "\n".
- ' '."\n".
- ' '."\n";
- foreach (@hrefs) {
- $imsresources .=
- ' '."\n";
- }
- if (grep/^$count$/,@$discussions) {
- my $ressymb = $symb;
- my $mode;
- if ($ressymb =~ m|adm/(\w+)/(\w+)/(\d+)/bulletinboard$|) {
- unless ($ressymb =~ m|adm/wrapper/adm|) {
- $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard';
- }
- $mode = 'board';
- }
- my %extras = (
- caller => 'imsexport',
- tempexport => $tempexport.'/resources',
- count => $count
- );
- my $discresult = &Apache::lonfeedback::list_discussion($mode,undef,$ressymb,\%extras);
- }
- $imsresources .= ' '."\n";
- }
- }
- $pkgdepth = $depth;
- }
- }
- }
- while ($pkgdepth > 0) {
- print $ims_manifest " \n";
- $pkgdepth --;
- }
- my $resource_text = qq|
-
-
-
- $imsresources
-
-
- |;
- print $ims_manifest $resource_text;
-}
-
-sub get_dependencies {
- my ($exportitems,$parent,$depth,$dependencies) = @_;
- if ($depth > 1) {
- if ((!grep/^$$parent{$depth}$/,@$exportitems) && (!grep/^$$parent{$depth}$/,@$dependencies)) {
- push @$dependencies, $$parent{$depth};
- if ($depth > 2) {
- &get_dependencies($exportitems,$parent,$depth-1,$dependencies);
+ if ($url =~ m{^/uploaded/$match_domain/$match_courseid/([^/]+)}) {
+ my $oldprefix = $1;
+# 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{$suffix} = 'docstosupp';
+ } elsif (($folder =~ /^default/) && ($oldprefix =~ /^supplemental/)) {
+ $prefixchg{$suffix} = 'supptodocs';
+ }
+
+# If pasting an uploaded map, get list of contained uploaded maps.
+ if ($env{'docs.markedcopy_nested_'.$suffix}) {
+ my @nested;
+ my ($type) = ($oldprefix =~ /^(default|supplemental)/);
+ my @items = split(/\&/,$env{'docs.markedcopy_nested_'.$suffix});
+ 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_'.$suffix.'_'.$item} eq 'move') {
+ push(@{$marktomove{$suffix}},$type.'_'.$item);
+ }
+ }
}
}
}
-}
-sub process_content {
- my ($count,$curRes,$cdom,$cnum,$symb,$content_file,$href,$copyresult,$tempexport) = @_;
- my $content_type;
- my $message;
- my @uploads = ();
- if ($curRes->is_sequence()) {
- $content_type = 'sequence';
- } elsif ($curRes->is_page()) {
- $content_type = 'page'; # need to handle individual items in pages.
- } elsif ($symb =~ m-public/$cdom/$cnum/syllabus$-) {
- $content_type = 'syllabus';
- my $contents = &Apache::imsexport::templatedpage($content_type);
- if ($contents) {
- $$content_file = &store_template($contents,$tempexport,$count,$content_type);
- }
- } elsif ($symb =~ m-\.sequence___\d+___ext-) {
- $content_type = 'external';
- my $title = $curRes->title;
- my $contents = &Apache::imsexport::external($symb,$title);
- if ($contents) {
- $$content_file = &store_template($contents,$tempexport,$count,$content_type);
- }
- } elsif ($symb =~ m-adm/navmaps$-) {
- $content_type = 'navmap';
- } elsif ($symb =~ m-adm/[^/]+/[^/]+/(\d+)/smppg$-) {
- $content_type = 'simplepage';
- my $contents = &Apache::imsexport::templatedpage($content_type,$1,$count,\@uploads);
- if ($contents) {
- $$content_file = &store_template($contents,$tempexport,$count,$content_type);
- }
- } elsif ($symb =~ m-lib/templates/simpleproblem\.problem$-) {
- $content_type = 'simpleproblem';
- my $contents = &Apache::imsexport::simpleproblem($symb);
- if ($contents) {
- $$content_file = &store_template($contents,$tempexport,$count,$content_type);
- }
- } elsif ($symb =~ m-lib/templates/examupload\.problem$-) {
- $content_type = 'examupload';
- } elsif ($symb =~ m-adm/(\w+)/(\w+)/(\d+)/bulletinboard$-) {
- $content_type = 'bulletinboard';
- my $contents = &Apache::imsexport::templatedpage($content_type,$3,$count,\@uploads,$1,$2);
- if ($contents) {
- $$content_file = &store_template($contents,$tempexport,$count,$content_type);
- }
- } elsif ($symb =~ m-adm/([^/]+)/([^/]+)/aboutme$-) {
- $content_type = 'aboutme';
- my $contents = &Apache::imsexport::templatedpage($content_type,undef,$count,\@uploads,$1,$2);
- if ($contents) {
- $$content_file = &store_template($contents,$tempexport,$count,$content_type);
- }
- } elsif ($symb =~ m-\.(sequence|page)___\d+___uploaded/$cdom/$cnum/-) {
- $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'uploaded');
- } elsif ($symb =~ m-\.(sequence|page)___\d+___([^/]+)/([^/]+)-) {
- my $canedit = 0;
- if ($2 eq $env{'user.domain'} && $3 eq $env{'user.name'}) {
- $canedit= 1;
- }
-# only include problem code where current user is author
- if ($canedit) {
- $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'resource');
- } else {
- $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'noedit');
- }
- } elsif ($symb =~ m-uploaded/$cdom/$cnum-) {
- $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'uploaded');
- }
- if (@uploads > 0) {
- foreach my $item (@uploads) {
- my $uploadmsg = '';
- &replicate_content($cdom,$cnum,$tempexport,$item,$count,\$uploadmsg,$href,'templateupload');
- if ($uploadmsg) {
- $$copyresult .= $uploadmsg."\n";
- }
- }
- }
- if ($message) {
- $$copyresult .= $message."\n";
- }
-}
-
-sub replicate_content {
- my ($cdom,$cnum,$tempexport,$symb,$count,$message,$href,$caller) = @_;
- my ($map,$ind,$url);
- if ($caller eq 'templateupload') {
- $url = $symb;
- $url =~ s#//#/#g;
- } else {
- ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
+# Early out if nothing available to paste
+ if (@dopaste == 0) {
+ return ();
+ }
+
+# Populate message hash and hashes used for main content <=> supplemental content
+# changes
+
+ %msgs = &Apache::lonlocal::texthash (
+ notinsupp => 'Paste failed: content type is not supported within Supplemental Content',
+ notincrs => 'Paste failed: Item is from a different course which you do not have rights to edit.',
+ duplicate => 'Paste failed: only one instance of a particular published sequence or page is allowed within each course.',
+ );
+
+ %before = (
+ docstosupp => {
+ map => 'default',
+ doc => 'docs',
+ },
+ supptodocs => {
+ map => 'supplemental',
+ doc => 'supplemental',
+ },
+ );
+
+ %after = (
+ docstosupp => {
+ map => 'supplemental',
+ doc => 'supplemental'
+ },
+ supptodocs => {
+ map => 'default',
+ doc => 'docs',
+ },
+ );
+
+# Retrieve information about all course maps in main content area
+
+ my $allmaps = {};
+ if ($folder =~ /^default/) {
+ $allmaps =
+ &Apache::loncommon::allmaps_incourse($coursedom,$coursenum,
+ $env{"course.$env{'request.course.id'}.home"},
+ $env{'request.course.id'});
}
- my $content;
- my $filename;
- my $repstatus;
- my $content_name;
- if ($url =~ m-/([^/]+)$-) {
- $filename = $1;
- if (!-e $tempexport.'/resources') {
- mkdir($tempexport.'/resources',0700);
- }
- if (!-e $tempexport.'/resources/'.$count) {
- mkdir($tempexport.'/resources/'.$count,0700);
- }
- my $destination = $tempexport.'/resources/'.$count.'/'.$filename;
- my $copiedfile;
- if ($copiedfile = Apache::File->new('>'.$destination)) {
- my $content;
- if ($caller eq 'resource') {
- my $respath = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res';
- my $filepath = &Apache::lonnet::filelocation($respath,$url);
- $content = &Apache::lonnet::getfile($filepath);
- if ($content eq -1) {
- $$message = 'Could not copy file '.$filename;
- } else {
- &extract_media($url,$cdom,$cnum,\$content,$count,$tempexport,$href,$message,'resource');
- $repstatus = 'ok';
+
+ my (@toclear,%mapurls,%lockerrs,%msgerrs,%results);
+
+# Loop over the items to paste
+ foreach my $suffix (@dopaste) {
+# Maps need to be copied first
+ my (%removefrommap,%removeparam,%addedmaps,%rewrites,%retitles,%copies,
+ %dbcopies,%zombies,%params,%docmoves,%mapmoves,%mapchanges,%newsubdir,
+ %newurls,%tomove);
+ if (ref($marktomove{$suffix}) eq 'ARRAY') {
+ map { $tomove{$_} = 1; } @{$marktomove{$suffix}};
+ }
+ my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url_'.$suffix});
+ my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title_'.$suffix});
+ my $oldurl = $url;
+ if ($is_map{$suffix}) {
+# If pasting a map, check if map contains other maps
+ my (%hierarchy,%titles);
+ &contained_map_check($url,$folder,\%removefrommap,\%removeparam,
+ \%addedmaps,\%hierarchy,\%titles,$allmaps);
+ if ($url=~ m{^/uploaded/}) {
+ my $newurl;
+ unless ($env{'form.docs.markedcopy_options_'.$suffix} eq 'move') {
+ ($newurl,my $error) =
+ &get_newmap_url($url,$folder,$prefixchg{$suffix},$coursedom,
+ $coursenum,$srcdom{$suffix},$srcnum{$suffix},
+ \$title,$allmaps,\%newurls);
+ if ($error) {
+ $allerrors{$suffix} = $error;
+ next;
+ }
+ if ($newurl ne '') {
+ if ($newurl ne $url) {
+ if ($newurl =~ /(?:default|supplemental)_(\d+).(?:sequence|page)$/) {
+ $newsubdir{$url} = $1;
+ }
+ $mapchanges{$url} = 1;
+ }
+ }
}
- } elsif ($caller eq 'uploaded' || $caller eq 'templateupload') {
- my $rtncode;
- $repstatus = &Apache::lonnet::getuploaded('GET',$url,$cdom,$cnum,\$content,$rtncode);
- if ($repstatus eq 'ok') {
- if ($url =~ /\.html?$/i) {
- &extract_media($url,$cdom,$cnum,\$content,$count,$tempexport,$href,$message,'uploaded');
+ if (($srcdom{$suffix} ne $coursedom) ||
+ ($srcnum{$suffix} ne $coursenum) ||
+ ($prefixchg{$suffix}) || (($newurl ne '') && ($newurl ne $url))) {
+ unless (&url_paste_fixups($url,$folder,$prefixchg{$suffix},
+ $coursedom,$coursenum,$srcdom{$suffix},
+ $srcnum{$suffix},$allmaps,\%rewrites,
+ \%retitles,\%copies,\%dbcopies,
+ \%zombies,\%params,\%mapmoves,
+ \%mapchanges,\%tomove,\%newsubdir,
+ \%newurls)) {
+ $mapmoves{$url} = 1;
}
+ $url = $newurl;
+ } elsif ($env{'docs.markedcopy_nested_'.$suffix}) {
+ &url_paste_fixups($url,$folder,$prefixchg{$suffix},$coursedom,
+ $coursenum,$srcdom{$suffix},$srcnum{$suffix},
+ $allmaps,\%rewrites,\%retitles,\%copies,\%dbcopies,
+ \%zombies,\%params,\%mapmoves,\%mapchanges,
+ \%tomove,\%newsubdir,\%newurls);
+ }
+ } elsif ($url=~m {^/res/}) {
+# published map can only exists once, so remove from paste buffer when done
+ push(@toclear,$suffix);
+# if pasting published map (main content area only) check map not already in course
+ if ($folder =~ /^default/) {
+ if ((ref($allmaps) eq 'HASH') && ($allmaps->{$url})) {
+ $duplicate{$suffix} = 1;
+ next;
+ }
+ }
+ }
+ }
+ if ($url=~ m{/(bulletinboard|smppg)$}) {
+ my $prefix = $1;
+ #need to copy the db contents to a new one, unless this is a move.
+ my %info = (
+ src => $url,
+ cdom => $coursedom,
+ cnum => $coursenum,
+ );
+ unless ($env{'form.docs.markedcopy_options_'.$suffix} eq 'move') {
+ my (%lockerr,$msg);
+ my ($newurl,$result,$errtext) =
+ &dbcopy(\%info,$coursedom,$coursenum,\%lockerr);
+ if ($result eq 'ok') {
+ $url = $newurl;
+ $title=&mt('Copy of').' '.$title;
} else {
- $$message = 'Could not render '.$url.' server message - '.$rtncode." \n";
+ if ($prefix eq 'smppg') {
+ $msg = &mt('Paste failed: An error occurred when copying the simple page.').' '.$errtext;
+ } elsif ($prefix eq 'bulletinboard') {
+ $msg = &mt('Paste failed: An error occurred when copying the bulletin board.').' '.$errtext;
+ }
+ $results{$suffix} = $result;
+ $msgerrs{$suffix} = $msg;
+ $lockerrs{$suffix} = $lockerr{$prefix};
+ next;
+ }
+ if ($lockerr{$prefix}) {
+ $lockerrs{$suffix} = $lockerr{$prefix};
}
- } elsif ($caller eq 'noedit') {
-# Need to render the resource without the LON-CAPA Internal header and the Post discussion footer, and then set $content equal to this.
- $repstatus = 'ok';
- $content = 'Not the owner of this resource';
}
- if ($repstatus eq 'ok') {
- print $copiedfile $content;
+ }
+ $title = &LONCAPA::map::qtunescape($title);
+ my $ext='false';
+ if ($url=~m{^http(|s)://}) { $ext='true'; }
+ if ($env{'docs.markedcopy_supplemental_'.$suffix}) {
+ if ($folder !~ /^supplemental/) {
+ (undef,undef,$title) =
+ &Apache::loncommon::parse_supplemental_title($env{'docs.markedcopy_supplemental_'.$suffix});
}
- close($copiedfile);
} else {
- $$message = 'Could not open destination file for '.$filename." \n";
+ if ($folder=~/^supplemental/) {
+ $title=time.'___&&&___'.$env{'user.name'}.'___&&&___'.
+ $env{'user.domain'}.'___&&&___'.$title;
+ }
+ }
+
+# 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.
+
+ unless ($is_map{$suffix}) {
+ my $newidx;
+# Now insert the URL at the bottom
+ $newidx = &LONCAPA::map::getresidx(&LONCAPA::map::qtunescape($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,$newdocsdir) = ($folder =~ /^(default|supplemental)_?(\d*)/);
+ my $newprefix = $newloc;
+ if ($newloc eq 'default') {
+ $newprefix = 'docs';
+ }
+ if ($newdocsdir eq '') {
+ $newdocsdir = 'default';
+ }
+ if (($prefixchg{$suffix}) ||
+ ($srcdom{$suffix} ne $coursedom) ||
+ ($srcnum{$suffix} ne $coursenum) ||
+ ($env{'form.docs.markedcopy_options_'.$suffix} ne 'move')) {
+ 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') {
+ $msgs{$suffix} = &mt('Paste failed: an error occurred saving the file.');
+ next;
+ } else {
+ my ($newsubpath) = ($newpath =~ m{^(.*/)[^/]*$});
+ $newsubpath =~ s{/+$}{/};
+ $docmoves{$oldurl} = $newsubpath;
+ }
+ }
+ }
+ }
+ $LONCAPA::map::resources[$newidx]=$title.':'.&LONCAPA::map::qtunescape($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;
+ $allresult = 'fail';
+ }
+ }
+
+# Apply any changes to maps, or copy dependencies for uploaded HTML pages
+ unless ($allresult eq 'fail') {
+ my %updated = (
+ rewrites => \%rewrites,
+ zombies => \%zombies,
+ removefrommap => \%removefrommap,
+ removeparam => \%removeparam,
+ dbcopies => \%dbcopies,
+ retitles => \%retitles,
+ );
+ my %info = (
+ newsubdir => \%newsubdir,
+ params => \%params,
+ );
+ if ($prefixchg{$suffix}) {
+ $info{'before'} = $before{$prefixchg{$suffix}};
+ $info{'after'} = $after{$prefixchg{$suffix}};
+ }
+ my %moves = (
+ copies => \%copies,
+ docmoves => \%docmoves,
+ mapmoves => \%mapmoves,
+ );
+ (my $result,$msgs{$suffix},my $lockerror) =
+ &apply_fixups($folder,$is_map{$suffix},$coursedom,$coursenum,$errors,
+ \%updated,\%info,\%moves,$prefixchg{$suffix},$oldurl,
+ $url,'paste');
+ $lockerrors .= $lockerror;
+ if ($result eq 'ok') {
+ if ($is_map{$suffix}) {
+ my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
+ $folder.'.'.$container);
+ if ($fatal) {
+ $allresult = 'failread';
+ } else {
+ if ($#LONCAPA::map::order<1) {
+ my $idx=&LONCAPA::map::getresidx();
+ if ($idx<=0) { $idx=1; }
+ $LONCAPA::map::order[0]=$idx;
+ $LONCAPA::map::resources[$idx]='';
+ }
+ my $newidx = &LONCAPA::map::getresidx(&LONCAPA::map::qtunescape($url));
+ $LONCAPA::map::resources[$newidx]=$title.':'.&LONCAPA::map::qtunescape($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;
+ $allresult = 'failstore';
+ }
+ }
+ }
+ if ($env{'form.docs.markedcopy_options_'.$suffix} eq 'move') {
+ push(@toclear,$suffix);
+ }
+ }
}
- } else {
- $$message = 'Could not determine name of file for '.$symb." \n";
}
- if ($repstatus eq 'ok') {
- $content_name = 'resources/'.$count.'/'.$filename;
+ &clear_from_buffer(\@toclear,\@currpaste);
+ my $msgsarray;
+ foreach my $suffix (keys(%msgs)) {
+ if (ref($msgs{$suffix}) eq 'ARRAY') {
+ $msgsarray .= join(',',@{$msgs{$suffix}});
+ }
+ }
+ return ($allresult,$save_err,$msgsarray,$lockerrors);
+}
+
+sub do_buffer_empty {
+ my @currpaste = split(/,/,$env{'docs.markedcopies'});
+ if (@currpaste == 0) {
+ return &mt('Clipboard is already empty');
+ }
+ my @toclear = &Apache::loncommon::get_env_multiple('form.pasting');
+ if (@toclear == 0) {
+ return &mt('Nothing selected to clear from clipboard');
+ }
+ my $numdel = &clear_from_buffer(\@toclear,\@currpaste);
+ if ($numdel) {
+ return &mt('[quant,_1,item] cleared from clipboard',$numdel);
+ } else {
+ return &mt('Clipboard unchanged');
}
- return $content_name;
+ return;
}
-sub extract_media {
- my ($url,$cdom,$cnum,$content,$count,$tempexport,$href,$message,$caller) = @_;
- my ($dirpath,$container);
- my %allfiles = ();
- my %codebase = ();
- if ($url =~ m-(.*/)([^/]+)$-) {
- $dirpath = $1;
- $container = $2;
- } else {
- $dirpath = $url;
- $container = '';
- }
- &Apache::lonnet::extract_embedded_items(undef,undef,\%allfiles,\%codebase,$content);
- foreach my $embed_file (keys(%allfiles)) {
- my $filename;
- if ($embed_file =~ m#([^/]+)$#) {
- $filename = $1;
- } else {
- $filename = $embed_file;
+sub clear_from_buffer {
+ my ($toclear,$currpaste) = @_;
+ return unless ((ref($toclear) eq 'ARRAY') && (ref($currpaste) eq 'ARRAY'));
+ my %pastebuffer;
+ map { $pastebuffer{$_} = 1; } @{$currpaste};
+ my $numdel = 0;
+ foreach my $suffix (@{$toclear}) {
+ next if ($suffix =~ /\D/);
+ next unless (exists($pastebuffer{$suffix}));
+ my $regexp = 'docs.markedcopy_[a-z]+_'.$suffix;
+ if (&Apache::lonnet::delenv($regexp,1) eq 'ok') {
+ delete($pastebuffer{$suffix});
+ $numdel ++;
+ }
+ }
+ my $newbuffer = join(',',sort(keys(%pastebuffer)));
+ &Apache::lonnet::appenv({'docs.markedcopies' => $newbuffer});
+ return $numdel;
+}
+
+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/;
+ }
}
- my $newname = 'res/'.$filename;
- my ($rtncode,$embed_content,$repstatus);
- my $embed_url;
- if ($embed_file =~ m-^/-) {
- $embed_url = $embed_file; # points to absolute path
+ if (($srcdom eq $coursedom) && ($srcnum eq $coursenum)) {
+ $newurl = $path.$prefix.$ancestor.$suffix.'.'.$ext;
} else {
- if ($embed_file =~ m-https?://-) {
- next; # points to url
+ $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 {
- $embed_url = $dirpath.$embed_file; # points to relative path
+ $newurl = "/uploaded/$coursedom/$coursenum/$prefix".$ancestor.$suffix.'.'.$ext;
}
+ $is_unique = &uniqueness_check($newurl);
}
- if ($caller eq 'resource') {
- my $respath = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res';
- my $embed_path = &Apache::lonnet::filelocation($respath,$embed_url);
- $embed_content = &Apache::lonnet::getfile($embed_path);
- unless ($embed_content eq -1) {
- $repstatus = 'ok';
+ 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'));
}
- } elsif ($caller eq 'uploaded') {
-
- $repstatus = &Apache::lonnet::getuploaded('GET',$embed_url,$cdom,$cnum,\$embed_content,$rtncode);
}
- if ($repstatus eq 'ok') {
- my $destination = $tempexport.'/resources/'.$count.'/res';
- if (!-e "$destination") {
- mkdir($destination,0755);
- }
- $destination .= '/'.$filename;
- my $copiedfile;
- if ($copiedfile = Apache::File->new('>'.$destination)) {
- print $copiedfile $embed_content;
- push @{$href}, 'resources/'.$count.'/res/'.$filename;
- my $attrib_regexp = '';
- if (@{$allfiles{$embed_file}} > 1) {
- $attrib_regexp = join('|',@{$allfiles{$embed_file}});
+ }
+ return ($newurl);
+}
+
+sub dbcopy {
+ my ($dbref,$coursedom,$coursenum,$lockerrorsref) = @_;
+ my ($url,$result,$errtext);
+ my $url = $dbref->{'src'};
+ if (ref($dbref) eq 'HASH') {
+ if ($url =~ m{/(smppg|bulletinboard)$}) {
+ my $prefix = $1;
+ if (($dbref->{'cdom'} =~ /^$match_domain$/) &&
+ ($dbref->{'cnum'} =~ /^$match_courseid$/)) {
+ my $db_name;
+ my $marker = (split(m{/},$url))[4];
+ $marker=~s/\D//g;
+ if ($dbref->{'src'} =~ m{/smppg$}) {
+ $db_name =
+ &Apache::lonsimplepage::get_db_name($url,$marker,
+ $dbref->{'cdom'},
+ $dbref->{'cnum'});
+ } else {
+ $db_name = 'bulletinpage_'.$marker;
+ }
+ my ($suffix,$freedlock,$error) =
+ &Apache::lonnet::get_timebased_id($prefix,'num','templated',
+ $coursedom,$coursenum,
+ 'concat');
+ if (!$suffix) {
+ if ($prefix eq 'smppg') {
+ $errtext = &mt('Failed to acquire a unique timestamp-based suffix when copying a simple page [_1].',$url);
+ } else {
+ $errtext = &mt('Failed to acquire a unique timestamp-based suffix when copying a bulletin board [_1].',$url);
+ }
+ if ($error) {
+ $errtext .= ' '.$error;
+ }
} else {
- $attrib_regexp = $allfiles{$embed_file}[0];
+ #need to copy the db contents to a new one.
+ my %contents=&Apache::lonnet::dump($db_name,
+ $dbref->{'cdom'},
+ $dbref->{'cnum'});
+ if (exists($contents{'uploaded.photourl'})) {
+ my $photo = $contents{'uploaded.photourl'};
+ my ($subdir,$fname) =
+ ($photo =~ m{^/uploaded/$match_domain/$match_courseid/+(bulletin|simplepage)/(?:|\d+/)([^/]+)$});
+ my $newphoto;
+ if ($fname ne '') {
+ my $content = &Apache::lonnet::getfile($photo);
+ unless ($content eq '-1') {
+ $env{'form.'.$suffix.'.photourl'} = $content;
+ $newphoto =
+ &Apache::lonnet::finishuserfileupload($coursenum,$coursedom,$suffix.'.photourl',"$subdir/$suffix/$fname");
+ delete($env{'form.'.$suffix.'.photourl'});
+ }
+ }
+ if ($newphoto =~ m{^/uploaded/}) {
+ $contents{'uploaded.photourl'} = $newphoto;
+ }
+ }
+ $db_name =~ s{_\d*$ }{_$suffix}x;
+ $result=&Apache::lonnet::put($db_name,\%contents,
+ $coursedom,$coursenum);
+ if ($result eq 'ok') {
+ $url =~ s{/(\d*)/(smppg|bulletinboard)$}{/$suffix/$2}x;
+ }
}
- $$content =~ s#($attrib_regexp\s*=\s*['"]?)\Q$embed_file\E(['"]?)#$1$newname$2#gi;
- if ($caller eq 'resource' && $container =~ /\.(problem|library)$/) {
- $$content =~ s#\Q$embed_file\E#$newname#gi;
+ if (($freedlock ne 'ok') && (ref($lockerrorsref) eq 'HASH')) {
+ $lockerrorsref->{$prefix} =
+ '
'.
+ &mt('There was a problem removing a lockfile.');
+ if ($prefix eq 'smppg') {
+ $lockerrorsref->{$prefix} .=
+ &mt('This will prevent creation of additional simple pages in this course.');
+ } else {
+ $lockerrorsref->{$prefix} .= &mt('This will prevent creation of additional bulletin boards in this course.');
+ }
+ $lockerrorsref->{$prefix} .= &mt('Please contact the domain coordinator for your LON-CAPA domain.').'
');
- } else {
+
+ 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]='';
+ }
+
# ------------------------------------------------------------ Process commands
# ---------------- if they are for this folder and user allowed to make changes
- if (($allowed) && ($env{'form.folder'} eq $folder)) {
+ if (($allowed) && ($env{'form.folder'} eq $folder)) {
# set parameters and change order
- if (defined($env{'form.setparms'})) {
- my $idx=$env{'form.setparms'};
-# set parameters
- if ($env{'form.randpick_'.$idx}) {
- &Apache::lonratedt::storeparameter($idx,'parameter_randompick',$env{'form.randpick_'.$idx},'int_pos');
- } else {
- &Apache::lonratedt::delparameter($idx,'parameter_randompick');
- }
- if ($env{'form.hidprs_'.$idx}) {
- &Apache::lonratedt::storeparameter($idx,'parameter_hiddenresource','yes','string_yesno');
- } else {
- &Apache::lonratedt::delparameter($idx,'parameter_hiddenresource');
- }
- if ($env{'form.encprs_'.$idx}) {
- &Apache::lonratedt::storeparameter($idx,'parameter_encrypturl','yes','string_yesno');
- } else {
- &Apache::lonratedt::delparameter($idx,'parameter_encrypturl');
- }
+ &snapshotbefore();
- if ($env{'form.newpos'}) {
+ if (&update_parameter()) {
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
+ return $errtext if ($fatal);
+ }
+
+ if ($env{'form.newpos'} && $env{'form.currentpos'}) {
# change order
+ my $res = splice(@LONCAPA::map::order,$env{'form.currentpos'}-1,1);
+ splice(@LONCAPA::map::order,$env{'form.newpos'}-1,0,$res);
- my $newpos=$env{'form.newpos'}-1;
- my $currentpos=$env{'form.currentpos'}-1;
- my $i;
- my @neworder=();
- if ($newpos>$currentpos) {
-# moving stuff up
- for ($i=0;$i<$currentpos;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i];
- }
- for ($i=$currentpos;$i<$newpos;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i+1];
- }
- $neworder[$newpos]=$Apache::lonratedt::order[$currentpos];
- for ($i=$newpos+1;$i<=$#Apache::lonratedt::order;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i];
- }
- } else {
-# moving stuff down
- for ($i=0;$i<$newpos;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i];
- }
- $neworder[$newpos]=$Apache::lonratedt::order[$currentpos];
- for ($i=$newpos+1;$i<$currentpos+1;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i-1];
- }
- for ($i=$currentpos+1;$i<=$#Apache::lonratedt::order;$i++) {
- $neworder[$i]=$Apache::lonratedt::order[$i];
- }
- }
- @Apache::lonratedt::order=@neworder;
- }
-# store the changed version
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
+ return $errtext if ($fatal);
+ }
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
-
- }
- if ($env{'form.pastemarked'}) {
-# paste resource to end of list
- my $url=$env{'form.markedcopy_url'};
- my $title=$env{'form.markedcopy_title'};
-# Maps need to be copied first
- if (($url=~/\.(page|sequence)$/) || ($url=~/^\/uploaded\//)) {
- $title=&mt('Copy of').' '.$title;
- my $newid=$$.time;
- $url=~/^(.+)\.(\w+)$/;
- my $newurl=$1.$newid.'.'.$2;
- my $storefn=$newurl;
- $storefn=~s/^\/\w+\/\w+\/\w+\///;
- &Apache::loncreatecourse::writefile
- ($env{'request.course.id'},$storefn,
- &Apache::lonnet::getfile($url));
- $url=$newurl;
- }
- $title=~s/\\<\;/g;
- $title=~s/\>/\>\;/g;
- $title=~s/\:/\:/g;
- my $ext='false';
- if ($url=~/^http\:\/\//) { $ext='true'; }
- $url=~s/\:/\:/g;
-# Now insert the URL at the bottom
- my $newidx=&Apache::lonratedt::getresidx($url);
- $Apache::lonratedt::resources[$newidx]=
- $title.':'.$url.':'.$ext.':normal:res';
- $Apache::lonratedt::order[1+$#Apache::lonratedt::order]=$newidx;
-# Store the result
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
+ if ($env{'form.pastemarked'}) {
+ my %paste_errors;
+ my ($paste_res,$save_error,$pastemsgarray,$lockerror) =
+ &do_paste_from_buffer($coursenum,$coursedom,$folder,$container,
+ \%paste_errors);
+ if (ref($pastemsgarray) eq 'ARRAY') {
+ if (@{$pastemsgarray} > 0) {
+
+ $r->print('
'.
+ join(' ',@{$pastemsgarray}).
+ '
');
+ }
+ }
+ if ($lockerror) {
+ $r->print('
'.
+ $lockerror.
+ '
');
+ }
+ if ($save_error ne '') {
+ return $save_error;
+ }
+ if ($paste_res ne 'ok') {
+ $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".
+ '
'."\n");
+ foreach my $key (sort(keys(%paste_errors))) {
+ $r->print('
'.$key.'
'."\n");
+ }
+ $r->print('
'."\n");
+ }
+ } elsif ($env{'form.clearmarked'}) {
+ my $output = &do_buffer_empty();
+ if ($output) {
+ $r->print('
'.$output.'
');
+ }
+ }
- }
- $r->print($upload_output);
- if ($env{'form.cmd'}) {
- my ($cmd,$idx)=split(/\_/,$env{'form.cmd'});
- if ($cmd eq 'del') {
- my (undef,$url)=split(':',$Apache::lonratedt::resources[$Apache::lonratedt::order[$idx]]);
- if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) &&
- ($url!~/\.(page|sequence|problem|exam|quiz|assess|survey|form|library|task)$/)) {
- &Apache::lonnet::removeuploadedurl($url);
- } else {
- &Apache::lonratedt::makezombie($Apache::lonratedt::order[$idx]);
- }
- for (my $i=$idx;$i<$#Apache::lonratedt::order;$i++) {
- $Apache::lonratedt::order[$i]=
- $Apache::lonratedt::order[$i+1];
- }
- $#Apache::lonratedt::order--;
- } elsif ($cmd eq 'cut') {
- my (undef,$url)=split(':',$Apache::lonratedt::resources[$Apache::lonratedt::order[$idx]]);
- &Apache::lonratedt::makezombie($Apache::lonratedt::order[$idx]);
- for (my $i=$idx;$i<$#Apache::lonratedt::order;$i++) {
- $Apache::lonratedt::order[$i]=
- $Apache::lonratedt::order[$i+1];
- }
- $#Apache::lonratedt::order--;
- } elsif ($cmd eq 'up') {
- if (($idx) && (defined($Apache::lonratedt::order[$idx-1]))) {
- my $i=$Apache::lonratedt::order[$idx-1];
- $Apache::lonratedt::order[$idx-1]=
- $Apache::lonratedt::order[$idx];
- $Apache::lonratedt::order[$idx]=$i;
- }
- } elsif ($cmd eq 'down') {
- if (defined($Apache::lonratedt::order[$idx+1])) {
- my $i=$Apache::lonratedt::order[$idx+1];
- $Apache::lonratedt::order[$idx+1]=
- $Apache::lonratedt::order[$idx];
- $Apache::lonratedt::order[$idx]=$i;
- }
- } elsif ($cmd eq 'rename') {
- my $ratstr = $Apache::lonratedt::resources[$Apache::lonratedt::order[$idx]];
- my ($rtitle,@rrest)=split(/\:/,
- $Apache::lonratedt::resources[
- $Apache::lonratedt::order[$idx]]);
- my $comment=
- &HTML::Entities::decode($env{'form.title'});
- $comment=~s/\\<\;/g;
- $comment=~s/\>/\>\;/g;
- $comment=~s/\:/\:/g;
- if ($comment=~/\S/) {
- $Apache::lonratedt::resources[
- $Apache::lonratedt::order[$idx]]=
- $comment.':'.join(':',@rrest);
- }
+ $r->print($upload_output);
+
+# Rename, cut, copy or remove a single resource
+ if (&handle_edit_cmd()) {
+ my $contentchg;
+ 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}}));
+ }
}
-# Store the changed version
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,
- $folder.'.'.$container);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
}
+ 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;
- foreach (split(/\&/,$env{'form.importdetail'})) {
- if (defined($_)) {
- my ($name,$url)=split(/\=/,$_);
- $name=&unescape($name);
- $url=&unescape($url);
- push @imports, $name, $url;
- }
- }
-# Store the changed version
- ($errtext,$fatal)=group_import($coursenum, $coursedom, $folder,
- $container,'londocs',@imports);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
+ if ($env{'form.importdetail'}) {
+ my @imports;
+ foreach my $item (split(/\&/,$env{'form.importdetail'})) {
+ if (defined($item)) {
+ my ($name,$url,$residx)=
+ map { &unescape($_); } split(/\=/,$item);
+ if ($url =~ m{^\Q/uploaded/$coursedom/$coursenum/\E(default|supplemental)_new\.(sequence|page)$}) {
+ my ($suffix,$errortxt,$locknotfreed) =
+ &new_timebased_suffix($coursedom,$coursenum,'map',$1,$2);
+ if ($locknotfreed) {
+ $r->print($locknotfreed);
+ }
+ if ($suffix) {
+ $url =~ s/_new\./_$suffix./;
+ } else {
+ return $errortxt;
+ }
+ } elsif ($url =~ m{^/adm/$match_domain/$match_username/new/(smppg|bulletinboard)$}) {
+ my $type = $1;
+ my ($suffix,$errortxt,$locknotfreed) =
+ &new_timebased_suffix($coursedom,$coursenum,$type);
+ if ($locknotfreed) {
+ $r->print($locknotfreed);
+ }
+ if ($suffix) {
+ $url =~ s{^(/adm/$match_domain/$match_username)/new}{$1/$suffix};
+ } else {
+ return $errortxt;
+ }
+ } elsif ($url =~ m{^/uploaded/$coursedom/$coursenum/(docs|supplemental)/(default|\d+)/new.html$}) {
+ if ($supplementalflag) {
+ next unless ($1 eq 'supplemental');
+ if ($folder eq 'supplemental') {
+ next unless ($2 eq 'default');
+ } else {
+ next unless ($folder eq 'supplemental_'.$2);
+ }
+ } else {
+ next unless ($1 eq 'docs');
+ if ($folder eq 'default') {
+ next unless ($2 eq 'default');
+ } else {
+ next unless ($folder eq 'default_'.$2);
+ }
+ }
+ }
+ push(@imports, [$name, $url, $residx]);
}
+ }
+ ($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'}) {
- if ($env{'form.importmap'}=~/\w/) {
- foreach (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$env{'form.importmap'}))) {
- my ($title,$url,$ext,$type)=split(/\:/,$_);
- my $idx=&Apache::lonratedt::getresidx($url);
- $Apache::lonratedt::resources[$idx]=$_;
- $Apache::lonratedt::order
- [$#Apache::lonratedt::order+1]=$idx;
- }
-# Store the changed version
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,
- $folder.'.'.$container);
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
- } else {
- $r->print('
'.&mt('No map selected.').'
');
- }
- }
- }
-# ---------------------------------------------------------------- End commands
-# ---------------------------------------------------------------- Print screen
- my $idx=0;
- my $shown=0;
- $r->print('
':'').
+ '');
+ if ($randompick>=0) {
+ $r->print('
'
+ .&mt('Caution: this folder is set to randomly pick a subset'
+ .' of resources. Adding or removing resources from this'
+ .' folder will change the set of resources that the'
+ .' students see, resulting in spurious or missing credit'
+ .' for completed problems, not limited to ones you'
+ .' modify. Do not modify the contents of this folder if'
+ .' it is in active student use.')
+ .'
'
+ .&mt('Caution: this folder is set to randomly order its'
+ .' contents. Adding or removing resources from this folder'
+ .' will change the order of resources shown.')
+ .'
';
+ return $output;
}
sub process_file_upload {
my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd) = @_;
# upload a file, if present
- my $parseaction;
- if ($env{'form.parserflag'}) {
+ my ($parseaction,$showupload,$nextphase,$mimetype);
+ if ($env{'form.parserflag'}) {
$parseaction = 'parse';
}
- my $phase_status;
my $folder=$env{'form.folder'};
if ($folder eq '') {
$folder='default';
@@ -1271,17 +2770,14 @@ sub process_file_upload {
my $errtext='';
my $fatal=0;
my $container='sequence';
- if ($env{'form.pagepath'}) {
+ if ($env{'form.folderpath'} =~ /:1$/) {
$container='page';
}
($errtext,$fatal)=
- &mapread($coursenum,$coursedom,$folder.'.'.$container);
- if ($#Apache::lonratedt::order<1) {
- $Apache::lonratedt::order[0]=1;
- $Apache::lonratedt::resources[1]='';
- }
- if ($fatal) {
- return 'failed';
+ &mapread($coursenum,$coursedom,$folder.'.'.$container);
+ if ($#LONCAPA::map::order<1) {
+ $LONCAPA::map::order[0]=1;
+ $LONCAPA::map::resources[1]='';
}
my $destination = 'docs/';
if ($folder =~ /^supplemental/) {
@@ -1292,361 +2788,654 @@ sub process_file_upload {
} elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
$destination .= $2.'/';
}
-# this is for a course, not a user, so set coursedoc flag
-# probably the only place in the system where this should be "1"
- my $newidx=&Apache::lonratedt::getresidx();
+ if ($fatal) {
+ $$upload_output = '
'.&mt('The uploaded file has not been stored as an error occurred reading the contents of the current folder.').'
';
+ return;
+ }
+# this is for a course, not a user, so set context to coursedoc.
+ my $newidx=&LONCAPA::map::getresidx();
$destination .= $newidx;
- my $url=&Apache::lonnet::userfileupload('uploaddoc',1,$destination,
+ my $url=&Apache::lonnet::userfileupload('uploaddoc','coursedoc',$destination,
$parseaction,$allfiles,
- $codebase);
+ $codebase,undef,undef,undef,undef,
+ undef,undef,\$mimetype);
+ if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E.*/([^/]+)$}) {
+ my $stored = $1;
+ $showupload = '
';
+ return;
} else {
- if ($parseaction eq 'parse') {
- my $total_embedded = keys(%{$allfiles});
+ if ($parseaction eq 'parse' && $mimetype eq 'text/html') {
+ $$upload_output = $showupload;
+ my $total_embedded = scalar(keys(%{$allfiles}));
if ($total_embedded > 0) {
- my $num = 0;
- $$upload_output .= 'This file contains embedded multimedia objects, which need to be uploaded to LON-CAPA.
- ';
+ } else {
+ $$upload_output .= &mt('Embedded item(s) already present, so no additional upload(s) required').' ';
+ }
} else {
- $$upload_output .= 'No embedded items identified ';
+ $$upload_output .= &mt('No embedded items identified').' ';
}
+ $$upload_output = '
'.$$upload_output.'
';
+ } elsif (&Apache::loncommon::is_archive_file($mimetype)) {
+ $nextphase = 'decompress_uploaded';
+ my $position = scalar(@LONCAPA::map::order)-1;
+ my $noextract = &return_to_editor();
+ my $archiveurl = &HTML::Entities::encode($url,'<>&"');
+ my %archiveitems = (
+ folderpath => $env{'form.folderpath'},
+ cmd => $nextphase,
+ newidx => $newidx,
+ position => $position,
+ phase => $nextphase,
+ comment => $comment,
+ );
+ my ($destination,$dir_root) = &embedded_destination($coursenum,$coursedom);
+ my @current = &get_dir_list($url,$coursenum,$coursedom,$newidx);
+ $$upload_output = $showupload.
+ &Apache::loncommon::decompress_form($mimetype,
+ $archiveurl,'/adm/coursedocs',$noextract,
+ \%archiveitems,\@current);
}
}
}
- return $phase_status;
+ return $nextphase;
}
-sub process_secondary_uploads {
- my ($upload_output,$coursedom,$coursenum,$formname,$num,$newidx) = @_;
- my $folder=$env{'form.folder'};
- my $destination = 'docs/';
- if ($folder =~ /^supplemental/) {
- $destination = 'supplemental/';
- }
- if (($folder eq 'default') || ($folder eq 'supplemental')) {
- $destination .= 'default/';
- } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
- $destination .= $2.'/';
+sub get_dir_list {
+ my ($url,$coursenum,$coursedom,$newidx) = @_;
+ my ($destination,$dir_root) = &embedded_destination();
+ my ($dirlistref,$listerror) =
+ &Apache::lonnet::dirlist("$dir_root/$destination/$newidx",$coursedom,$coursenum,1);
+ my @dir_lines;
+ my $dirptr=16384;
+ if (ref($dirlistref) eq 'ARRAY') {
+ foreach my $dir_line (sort
+ {
+ my ($afile)=split('&',$a,2);
+ my ($bfile)=split('&',$b,2);
+ return (lc($afile) cmp lc($bfile));
+ } (@{$dirlistref})) {
+ my ($filename,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef)=split(/\&/,$dir_line,16);
+ $filename =~ s/\s+$//;
+ next if ($filename =~ /^\.\.?$/);
+ my $isdir = 0;
+ if ($dirptr&$testdir) {
+ $isdir = 1;
+ }
+ push(@dir_lines, [$filename,$dom,$isdir,$size,$mtime,$obs]);
+ }
}
- $destination .= $newidx;
- my ($url,$filename);
- $url=&Apache::lonnet::userfileupload($formname.$num,1,$destination);
- ($filename) = ($url =~ m-^/uploaded/$coursedom/$coursenum/$destination/(.+)$-);
- return $filename;
+ return @dir_lines;
+}
+
+sub is_supplemental_title {
+ my ($title) = @_;
+ return scalar($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/);
}
# --------------------------------------------------------------- An entry line
sub entryline {
- my ($index,$title,$url,$folder,$allowed,$residx,$coursenum)=@_;
- $title=~s/\&colon\;/\:/g;
- $title=&HTML::Entities::encode(&HTML::Entities::decode(
- &unescape($title)),'"<>&\'');
- my $renametitle=$title;
- my $foldertitle=$title;
- my $pagetitle=$title;
- my $orderidx=$Apache::lonratedt::order[$index];
- if ($title=~ /^(\d+)___&&&___(\w+)___&&&___(\w+)___&&&___(.*)$/ ) {
- $foldertitle=&Apache::lontexconvert::msgtexconverted($4);
- $renametitle=$4;
- $title=''.&Apache::lonlocal::locallocaltime($1).' '.
- &Apache::loncommon::plainname($2,$3).': '.
- $foldertitle;
+ my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$coursedom,
+ $crstype,$pathitem,$supplementalflag,$container,$filtersref,$currgroups)=@_;
+ my ($foldertitle,$renametitle);
+ if (&is_supplemental_title($title)) {
+ ($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title);
+ } else {
+ $title=&HTML::Entities::encode($title,'"<>&\'');
+ $renametitle=$title;
+ $foldertitle=$title;
}
+
+ my $orderidx=$LONCAPA::map::order[$index];
+
$renametitle=~s/\\/\\\\/g;
$renametitle=~s/\"\;/\\\"/g;
- my $line='
';
+ $renametitle=~s/ /%20/g;
+ my $line=&Apache::loncommon::start_data_table_row();
+ my ($form_start,$form_end,$form_common,$form_param);
# Edit commands
- my $container;
- my $folderpath;
+ my ($esc_path, $path, $symb);
if ($env{'form.folderpath'}) {
- $container = 'sequence';
- $folderpath=&escape($env{'form.folderpath'});
+ $esc_path=&escape($env{'form.folderpath'});
+ $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
# $htmlfoldername=&HTML::Entities::encode($env{'form.foldername'},'<>&"');
}
- my ($pagepath,$pagesymb);
- if ($env{'form.pagepath'}) {
- $container = 'page';
- $pagepath=&escape($env{'form.pagepath'});
- $pagesymb=&escape($env{'form.pagesymb'});
- }
- my $cpinfo='';
- if ($env{'form.markedcopy_url'}) {
- $cpinfo='&markedcopy_url='.
- &escape($env{'form.markedcopy_url'}).
- '&markedcopy_title='.
- &escape($env{'form.markedcopy_title'});
+ my $isexternal;
+ if ($residx) {
+ my $currurl = $url;
+ $currurl =~ s{^http(|s)(:|:)//}{/adm/wrapper/ext/};
+ if ($currurl =~ m{^/adm/wrapper/ext/}) {
+ $isexternal = 1;
+ }
+ if (!$supplementalflag) {
+ my $path = 'uploaded/'.
+ $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'.
+ $env{'course.'.$env{'request.course.id'}.'.num'}.'/';
+ $symb = &Apache::lonnet::encode_symb($path.$folder.".$container",
+ $residx,
+ &Apache::lonnet::declutter($currurl));
+ }
+ }
+ my ($renamelink,%lt,$ishash);
+ if (ref($filtersref) eq 'HASH') {
+ $ishash = 1;
}
+
if ($allowed) {
+ $form_start = '
+ ';
+
my $incindex=$index+1;
my $selectbox='';
- if (($folder!~/^supplemental/) &&
- ($#Apache::lonratedt::order>0) &&
+ if (($#LONCAPA::map::order>0) &&
((split(/\:/,
- $Apache::lonratedt::resources[$Apache::lonratedt::order[0]]))[1]
- ne '') &&
+ $LONCAPA::map::resources[$LONCAPA::map::order[0]]))[1]
+ ne '') &&
((split(/\:/,
- $Apache::lonratedt::resources[$Apache::lonratedt::order[1]]))[1]
+ $LONCAPA::map::resources[$LONCAPA::map::order[1]]))[1]
ne '')) {
$selectbox=
''.
- '
";
+ $line.=&Apache::loncommon::end_data_table_row();
return $line;
}
-# ---------------------------------------------------------------- tie the hash
+sub action_restrictions {
+ my ($cnum,$cdom,$url,$folderpath,$currgroups) = @_;
+ my %denied = (
+ cut => 0,
+ copy => 0,
+ remove => 0,
+ );
+ if ($url=~ m{^/res/.+\.(page|sequence)$}) {
+ # no copy for published maps
+ $denied{'copy'} = 1;
+ } elsif ($url=~m{^/res/lib/templates/}) {
+ $denied{'copy'} = 1;
+ $denied{'cut'} = 1;
+ } elsif ($url eq "/uploaded/$cdom/$cnum/group_allfolders.sequence") {
+ if ($folderpath =~ /^default&[^\&]+$/) {
+ if ((ref($currgroups) eq 'HASH') && (keys(%{$currgroups}) > 0)) {
+ $denied{'remove'} = 1;
+ }
+ $denied{'cut'} = 1;
+ $denied{'copy'} = 1;
+ }
+ } elsif ($url =~ m{^\Q/uploaded/$cdom/$cnum/group_folder_\E(\w+)\.sequence$}) {
+ my $group = $1;
+ if ($folderpath =~ /^default&[^\&]+\&group_allfolders\&[^\&]+$/) {
+ if ((ref($currgroups) eq 'HASH') && (exists($currgroups->{$group}))) {
+ $denied{'remove'} = 1;
+ }
+ }
+ $denied{'cut'} = 1;
+ $denied{'copy'} = 1;
+ } elsif ($url =~ m{^\Q/adm/$cdom/$cnum/\E(\w+)/smppg$}) {
+ my $group = $1;
+ if ($folderpath =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&\Qgroup_folder_$group\E\&[^\&]+$/) {
+ if ((ref($currgroups) eq 'HASH') && (exists($currgroups->{$group}))) {
+ my %groupsettings = &Apache::longroup::get_group_settings($currgroups->{$group});
+ if (keys(%groupsettings) > 0) {
+ $denied{'remove'} = 1;
+ }
+ $denied{'cut'} = 1;
+ $denied{'copy'} = 1;
+ }
+ }
+ } elsif ($folderpath =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&group_folder_(\w+)\&/) {
+ my $group = $1;
+ if ($url =~ /group_boards_\Q$group\E/) {
+ if ((ref($currgroups) eq 'HASH') && (exists($currgroups->{$group}))) {
+ my %groupsettings = &Apache::longroup::get_group_settings($currgroups->{$group});
+ if (keys(%groupsettings) > 0) {
+ if (ref($groupsettings{'functions'}) eq 'HASH') {
+ if ($groupsettings{'functions'}{'discussion'} eq 'on') {
+ $denied{'remove'} = 1;
+ }
+ }
+ }
+ $denied{'cut'} = 1;
+ $denied{'copy'} = 1;
+ }
+ }
+ }
+ return %denied;
+}
+
+sub new_timebased_suffix {
+ my ($dom,$num,$type,$area,$container) = @_;
+ my ($prefix,$namespace,$idtype,$errtext,$locknotfreed);
+ if ($type eq 'paste') {
+ $prefix = $type;
+ $namespace = 'courseeditor';
+ } elsif ($type eq 'map') {
+ $prefix = 'docs';
+ if ($area eq 'supplemental') {
+ $prefix = 'supp';
+ }
+ $prefix .= $container;
+ $namespace = 'uploadedmaps';
+ } else {
+ $prefix = $type;
+ $namespace = 'templated';
+ }
+ $idtype = 'concat';
+ my ($suffix,$freedlock,$error) =
+ &Apache::lonnet::get_timebased_id($prefix,'num',$namespace,$dom,$num);
+ if (!$suffix) {
+ if ($type eq 'paste') {
+ $errtext = &mt('Failed to acquire a unique timestamp-based suffix when adding to the paste buffer.');
+ } elsif ($type eq 'map') {
+ $errtext = &mt('Failed to acquire a unique timestamp-based suffix for the new folder/page.');
+ } elsif ($type eq 'smppg') {
+ $errtext = &mt('Failed to acquire a unique timestamp-based suffix for the new simple page.');
+ } else {
+ $errtext = &mt('Failed to acquire a unique timestamp-based suffix for the new bulletin board.');
+ }
+ if ($error) {
+ $errtext .= ' '.$error;
+ }
+ }
+ if ($freedlock ne 'ok') {
+ $locknotfreed =
+ '
'.
+ &mt('There was a problem removing a lockfile.').' ';
+ if ($type eq 'paste') {
+ &mt('This will prevent use of the paste buffer until th next log-in.');
+ } elsif ($type eq 'map') {
+ &mt('This will prevent creation of additional folders or composite pages in this course.');
+ } elsif ($type eq 'smppg') {
+ $locknotfreed .=
+ &mt('This will prevent creation of additional simple pages in this course.');
+ } else {
+ $locknotfreed .=
+ &mt('This will prevent creation of additional bulletin boards in this course.');
+ }
+ unless ($type eq 'paste') {
+ $locknotfreed .=
+ ' '.&mt('Please contact the domain coordinator for your LON-CAPA domain.');
+ }
+ $locknotfreed .= '
';
+ }
+ return ($suffix,$errtext,$locknotfreed);
+}
+
+=pod
+
+=item tiehash()
+
+tie the hash
+
+=cut
sub tiehash {
my ($mode)=@_;
@@ -1663,7 +3452,7 @@ sub tiehash {
$hashtied=1;
}
}
- }
+ }
}
sub untiehash {
@@ -1672,7 +3461,8 @@ sub untiehash {
return OK;
}
-# --------------------------------------------------------------- check on this
+
+
sub checkonthis {
my ($r,$url,$level,$title)=@_;
@@ -1681,6 +3471,9 @@ sub checkonthis {
$r->rflush();
if (($url) && ($url!~/^\/uploaded\//) && ($url!~/\*$/)) {
$r->print("\n ");
+ if ($level==0) {
+ $r->print(" ");
+ }
for (my $i=0;$i<=$level*5;$i++) {
$r->print(' ');
}
@@ -1690,7 +3483,7 @@ sub checkonthis {
my $result=&Apache::lonnet::repcopy(
&Apache::lonnet::filelocation('',$url));
if ($result eq 'ok') {
- $r->print(''.&mt('ok').'');
+ $r->print(''.&mt('ok').'');
$r->rflush();
&Apache::lonnet::countacc($url);
$url=~/\.(\w+)$/;
@@ -1700,7 +3493,7 @@ sub checkonthis {
for (my $i=0;$i<=$level*5;$i++) {
$r->print(' ');
}
- $r->print('- '.&mt('Rendering').': ');
+ $r->print('- '.&mt('Rendering:').' ');
my ($errorcount,$warningcount)=split(/:/,
&Apache::lonnet::ssi_body($url,
('grade_target'=>'web',
@@ -1708,94 +3501,120 @@ sub checkonthis {
if (($errorcount) ||
($warningcount)) {
if ($errorcount) {
- $r->print(''.
- $errorcount.' '.
- &mt('error(s)').' ');
+ $r->print(''.
+ &mt('[quant,_1,error]',$errorcount).'');
}
if ($warningcount) {
- $r->print(''.
- $warningcount.' '.
- &mt('warning(s)').'');
+ $r->print(''.
+ &mt('[quant,_1,warning]',$warningcount).'');
}
} else {
- $r->print(''.&mt('ok').'');
+ $r->print(''.&mt('ok').'');
}
$r->rflush();
}
my $dependencies=
&Apache::lonnet::metadata($url,'dependencies');
- foreach (split(/\,/,$dependencies)) {
- if (($_=~/^\/res\//) && (!$alreadyseen{$_})) {
- &checkonthis($r,$_,$level+1);
+ foreach my $dep (split(/\,/,$dependencies)) {
+ if (($dep=~/^\/res\//) && (!$alreadyseen{$dep})) {
+ &checkonthis($r,$dep,$level+1);
}
}
} elsif ($result eq 'unavailable') {
- $r->print(''.&mt('connection down').'');
+ $r->print(''.&mt('connection down').'');
} elsif ($result eq 'not_found') {
unless ($url=~/\$/) {
- $r->print(''.&mt('not found').'');
+ $r->print(''.&mt('not found').'');
} else {
- $r->print(''.&mt('unable to verify variable URL').'');
+ $r->print(''.&mt('unable to verify variable URL').'');
}
} else {
- $r->print(''.&mt('access denied').'');
+ $r->print(''.&mt('access denied').'');
}
- }
- }
+ }
+ }
}
-#
-# ----------------------------------------------------------------- List Symbs
-#
+
+=pod
+
+=item list_symbs()
+
+List Content Identifiers
+
+=cut
+
sub list_symbs {
my ($r) = @_;
- $r->print(&Apache::loncommon::start_page('Symb List'));
+ my $crstype = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page('List of Content Identifiers'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content Identifiers'));
+ $r->print(&startContentScreen('tools'));
my $navmap = Apache::lonnavmaps::navmap->new();
- $r->print("
\n");
- foreach my $res ($navmap->retrieveResources()) {
- $r->print($res->compTitle()."\t".$res->symb()."\n");
+ if (!defined($navmap)) {
+ $r->print('
'.&mt('Retrieval of List Failed').'
'.
+ '
'.
+ &mt('Unable to retrieve information about course contents').
+ '
');
+ &Apache::lonnet::logthis('Symb list failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
+ } else {
+ $r->print('
\n");
- $r->print(''.&mt('Return to DOCS').'');
+ $r->print(&endContentScreen());
}
-#
-# -------------------------------------------------------------- Verify Content
-#
sub verifycontent {
my ($r) = @_;
- my $type = &Apache::loncommon::course_type();
- my $loaderror=&Apache::lonnet::overloaderror($r);
- if ($loaderror) { return $loaderror; }
- $r->print(&Apache::loncommon::start_page('Verify '.$type.' Documents'));
+ my $crstype = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Documents'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Documents'));
+ $r->print(&startContentScreen('tools'));
+ $r->print('
'.&mt($crstype.' content verification').'
');
$hashtied=0;
undef %alreadyseen;
%alreadyseen=();
&tiehash();
- foreach (keys %hash) {
- if ($hash{$_}=~/\.(page|sequence)$/) {
- if (($_=~/^src_/) && ($alreadyseen{&unescape($hash{$_})})) {
- $r->print(''.
- &mt('The following sequence or page is included more than once in your '.$type.': ').
- &unescape($hash{$_}).' '.
- &mt('Note that grading records for problems included in this sequence or folder will overlap.'));
+
+ foreach my $key (keys(%hash)) {
+ if ($hash{$key}=~/\.(page|sequence)$/) {
+ if (($key=~/^src_/) && ($alreadyseen{&unescape($hash{$key})})) {
+ $r->print(''.
+ &mt('The following sequence or page is included more than once in your '.$crstype.':').' '.
+ &unescape($hash{$key}).' '.
+ &mt('Note that grading records for problems included in this sequence or folder will overlap.').'');
}
}
- if (($_=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$_})})) {
- &checkonthis($r,$hash{$_},0,$hash{'title_'.$1});
+ if (($key=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$key})})) {
+ &checkonthis($r,$hash{$key},0,$hash{'title_'.$1});
}
}
&untiehash();
- $r->print('
');
+ $r->print(&endContentScreen());
}
-# -------------------------------------------------------------- Check Versions
-
sub devalidateversioncache {
my $src=shift;
&Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
@@ -1804,8 +3623,11 @@ sub devalidateversioncache {
sub checkversions {
my ($r) = @_;
- my $type = &Apache::loncommon::course_type();
- $r->print(&Apache::loncommon::start_page("Check $type Document Versions"));
+ my $crstype = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page("Check $crstype Document Versions"));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs("Check $crstype Document Versions"));
+ $r->print(&startContentScreen('tools'));
+
my $header='';
my $startsel='';
my $monthsel='';
@@ -1824,16 +3646,16 @@ sub checkversions {
my %newsetversions=();
if ($env{'form.setmostrecent'}) {
$haschanged=1;
- foreach (keys %hash) {
- if ($_=~/^ids\_(\/res\/.+)$/) {
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
$newsetversions{$1}='mostrecent';
&devalidateversioncache($1);
}
}
} elsif ($env{'form.setcurrent'}) {
$haschanged=1;
- foreach (keys %hash) {
- if ($_=~/^ids\_(\/res\/.+)$/) {
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
my $getvers=&Apache::lonnet::getversion($1);
if ($getvers>0) {
$newsetversions{$1}=$getvers;
@@ -1843,11 +3665,11 @@ sub checkversions {
}
} elsif ($env{'form.setversions'}) {
$haschanged=1;
- foreach (keys %env) {
- if ($_=~/^form\.set_version_(.+)$/) {
+ foreach my $key (keys(%env)) {
+ if ($key=~/^form\.set_version_(.+)$/) {
my $src=$1;
- if (($env{$_}) && ($env{$_} ne $setversions{$src})) {
- $newsetversions{$src}=$env{$_};
+ if (($env{$key}) && ($env{$key} ne $setversions{$src})) {
+ $newsetversions{$src}=$env{$key};
&devalidateversioncache($src);
}
}
@@ -1856,20 +3678,22 @@ sub checkversions {
if ($haschanged) {
if (&Apache::lonnet::put('resourceversions',\%newsetversions,
$env{'course.'.$env{'request.course.id'}.'.domain'},
- $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') {
- $r->print('
'.&mt('Your Version Settings have been Stored').'
');
+ $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') {
+ $r->print(&Apache::loncommon::confirmwrapper(
+ &Apache::lonhtmlcommon::confirm_success(&mt('Your Version Settings have been Saved'))));
} else {
- $r->print('
'.&mt('An Error Occured while Attempting to Store your Version Settings').'
');
+ $r->print(&Apache::loncommon::confirmwrapper(
+ &Apache::lonhtmlcommon::confirm_success(&mt('An Error Occured while Attempting to Save your Version Settings'),1)));
}
&mark_hash_old();
}
&changewarning($r,'');
if ($env{'form.timerange'} eq 'all') {
# show all documents
- $header=&mt('All Documents in '.$type);
- $allsel=1;
- foreach (keys %hash) {
- if ($_=~/^ids\_(\/res\/.+)$/) {
+ $header=&mt('All Documents in '.$crstype);
+ $allsel=' selected="selected"';
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
my $src=$1;
$changes{$src}=1;
}
@@ -1879,7 +3703,7 @@ sub checkversions {
%changes=&Apache::lonnet::dump
('versionupdate',$env{'course.'.$env{'request.course.id'}.'.domain'},
$env{'course.'.$env{'request.course.id'}.'.num'});
- my $firstkey=(keys %changes)[0];
+ my $firstkey=(keys(%changes))[0];
unless ($firstkey=~/^error\:/) {
unless ($env{'form.timerange'}) {
$env{'form.timerange'}=604800;
@@ -1888,19 +3712,19 @@ sub checkversions {
.&mt('seconds');
if ($env{'form.timerange'}==-1) {
$seltext='since start of course';
- $startsel='selected';
+ $startsel=' selected="selected"';
$env{'form.timerange'}=time;
}
$starttime=time-$env{'form.timerange'};
if ($env{'form.timerange'}==2592000) {
$seltext=&mt('during the last month').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
- $monthsel='selected';
+ $monthsel=' selected="selected"';
} elsif ($env{'form.timerange'}==604800) {
$seltext=&mt('during the last week').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
- $weeksel='selected';
+ $weeksel=' selected="selected"';
} elsif ($env{'form.timerange'}==86400) {
$seltext=&mt('since yesterday').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
- $daysel='selected';
+ $daysel=' selected="selected"';
}
$header=&mt('Content changed').' '.$seltext;
} else {
@@ -1911,139 +3735,140 @@ sub checkversions {
$env{'course.'.$env{'request.course.id'}.'.domain'},
$env{'course.'.$env{'request.course.id'}.'.num'});
my %lt=&Apache::lonlocal::texthash
- ('st' => 'Version changes since start of '.$type,
+ ('st' => 'Version changes since start of '.$crstype,
'lm' => 'Version changes since last Month',
'lw' => 'Version changes since last Week',
'sy' => 'Version changes since Yesterday',
'al' => 'All Resources (possibly large output)',
+ 'cd' => 'Change display',
'sd' => 'Display',
'fi' => 'File',
'md' => 'Modification Date',
'mr' => 'Most recently published Version',
- 've' => 'Version used in '.$type,
- 'vu' => 'Set Version to be used in '.$type,
-'sv' => 'Set Versions to be used in '.$type.' according to Selections below',
+ 've' => 'Version used in '.$crstype,
+ 'vu' => 'Set Version to be used in '.$crstype,
+'sv' => 'Set Versions to be used in '.$crstype.' according to Selections below',
'sm' => 'Keep all Resources up-to-date with most recent Versions (default)',
'sc' => 'Set all Resource Versions to current Version (Fix Versions)',
- 'di' => 'Differences');
+ 'di' => 'Differences',
+ 'save' => 'Save changes',
+ 'vers' => 'Version choice(s) for specific resources',
+ 'act' => 'Actions');
$r->print(<$header