'.
- &mt('Dump Course DOCS to Construction Space: available on other servers');
+ return '
'.
+ &mt('Dump '.$type.
+ ' DOCS to Construction Space: available on other servers').
+ '
';
}
}
-# -------------------------------------------------------- Actually dump course
+sub clean {
+ my ($title)=@_;
+ $title=~s/[^\w\/\!\$\%\^\*\-\_\=\+\;\:\,\\\|\`\~]+/\_/gs;
+ return $title;
+}
+
+
sub dumpcourse {
- my $r=shift;
- $r->print('Dump DOCS'.
- &Apache::loncommon::bodytag('Dump Course DOCS to Construction Space').
- '');
+ '');
+ }
+}
+
+
+
+sub exportbutton {
+ my $type = &Apache::loncommon::course_type();
+ return "".&mt('IMS Export')."".
+ &Apache::loncommon::help_open_topic('Docs_Export_Course_Docs').' ';
+}
+
+
+
+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();
+ if (!defined($navmap)) {
+ $r->print(&Apache::loncommon::start_page('Export '.$type.' to IMS Package').
+ '
'.&mt('IMS Export Failed').'
'.
+ '
'.
+ &mt('Unable to retrieve information about course contents').
+ '
'.&mt('Return to Course Editor').'');
+ &Apache::lonnet::logthis('IMS export failed - could not create navmap object in '.lc($type).':'.$env{'request.course.id'});
+ return;
+ }
+ 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 =
+ '
'
+ .&mt('As you did not select any content items or discussions'
+ .' for export, an IMS package has not been created.')
+ .'
'
+ .'
'
+ .&mt('Please [_1]go back[_2] 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;
+ if ($copyresult) {
+ $outcome .= '
'
+ .&mt('The following errors occurred during export - [_1]'
+ ,$copyresult)
+ .'
';
+ }
+ $outcome .= '
'
+ .&mt('[_1]Your IMS package[_2] is ready for download.'
+ ,'','')
+ .'
';
+ } else {
+ $outcome = '
'
+ .&mt('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 '.$type.' to IMS Package'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('IMS Export'));
+ $r->print($outcome);
+ $r->print(&Apache::loncommon::end_page());
+ } else {
+ my $display;
+ $display = '');
+ }
+}
+
+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;
+ }
+ if ($curRes == $it->END_MAP()) {
+ $depth--;
+ $lastcontainer = $parent{$depth};
+ }
+ if (ref($curRes)) {
+ if ($curRes->is_sequence() || $curRes->is_page()) {
+ $lastcontainer = $count;
+ }
+ if (grep(/^$count$/,@$exportitems)) {
+ &get_dependencies($exportitems,\%parent,$depth,\@dependencies);
+ }
+ }
+ }
+# 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 ($curRes == $it->END_MAP()) {
+ $prevdepth = $depth;
+ $depth--;
+ }
+
+ 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 my $item (@hrefs) {
+ $imsresources .=
+ ' '."\n";
+ }
+ if (grep(/^$count$/,@$discussions)) {
+ my $ressymb = $symb;
+ my $mode;
+ if ($ressymb =~ m|adm/($match_domain)/($match_username)/(\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);
+ }
+ }
+ }
+}
+
+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/($match_domain)/($match_username)/(\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);
+ }
+ 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';
+ }
+ } 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');
+ }
+ } else {
+ $$message = 'Could not render '.$url.' server message - '.$rtncode." \n";
+ }
+ } 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;
+ }
+ close($copiedfile);
+ } else {
+ $$message = 'Could not open destination file for '.$filename." \n";
+ }
+ } else {
+ $$message = 'Could not determine name of file for '.$symb." \n";
+ }
+ if ($repstatus eq 'ok') {
+ $content_name = 'resources/'.$count.'/'.$filename;
+ }
+ return $content_name;
+}
+
+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,\%allfiles,\%codebase,$content);
+ foreach my $embed_file (keys(%allfiles)) {
+ my $filename;
+ if ($embed_file =~ m#([^/]+)$#) {
+ $filename = $1;
+ } else {
+ $filename = $embed_file;
+ }
+ my $newname = 'res/'.$filename;
+ my ($rtncode,$embed_content,$repstatus);
+ my $embed_url;
+ if ($embed_file =~ m-^/-) {
+ $embed_url = $embed_file; # points to absolute path
+ } else {
+ if ($embed_file =~ m-https?://-) {
+ next; # points to url
+ } else {
+ $embed_url = $dirpath.$embed_file; # points to relative path
+ }
+ }
+ 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';
+ }
+ } 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}});
+ } else {
+ $attrib_regexp = $allfiles{$embed_file}[0];
+ }
+ $$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;
+ }
+ }
+ } else {
+ $$message .= 'replication of embedded file - '.$embed_file.' in '.$url.' failed, reason -'.$rtncode." \n";
+ }
+ }
+ return;
+}
+
+sub store_template {
+ my ($contents,$tempexport,$count,$content_type) = @_;
+ if ($contents) {
+ if ($tempexport) {
+ if (!-e $tempexport.'/resources') {
+ mkdir($tempexport.'/resources',0700);
+ }
+ if (!-e $tempexport.'/resources/'.$count) {
+ mkdir($tempexport.'/resources/'.$count,0700);
+ }
+ my $destination = $tempexport.'/resources/'.$count.'/'.$content_type.'.xml';
+ my $storetemplate;
+ if ($storetemplate = Apache::File->new('>'.$destination)) {
+ print $storetemplate $contents;
+ close($storetemplate);
+ }
+ if ($content_type eq 'external') {
+ return 'resources/'.$count.'/'.$content_type.'.html';
+ } else {
+ return 'resources/'.$count.'/'.$content_type.'.xml';
+ }
+ }
}
}
-# Imports the given (name, url) resources into the course
-# coursenum, coursedom, and folder must precede the list
sub group_import {
- my $coursenum = shift;
- my $coursedom = shift;
- my $folder = shift;
- while (@_) {
- my $name = shift;
- my $url = shift;
+ my ($coursenum, $coursedom, $folder, $container, $caller, @files) = @_;
+
+ 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))) {
+
+ 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) {
- my $idx = $#Apache::lonratedt::resources + 1;
- $Apache::lonratedt::order[$#Apache::lonratedt::order+1]=$idx;
+ if (!$residx
+ || defined($LONCAPA::map::zombies[$residx])) {
+ $residx = &LONCAPA::map::getresidx($url,$residx);
+ push(@LONCAPA::map::order, $residx);
+ }
my $ext = 'false';
- if ($url=~/^http:\/\//) { $ext = 'true'; }
- $url =~ s/:/\:/g;
- $name =~ s/:/\:/g;
- $Apache::lonratedt::resources[$idx] =
- join ':', ($name, $url, $ext, 'normal', 'res');
+ if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; }
+ $url = &LONCAPA::map::qtunescape($url);
+ $name = &LONCAPA::map::qtunescape($name);
+ $LONCAPA::map::resources[$residx] =
+ join(':', ($name, $url, $ext, 'normal', 'res'));
}
}
- return &storemap($coursenum, $coursedom, $folder.'.sequence');
+ return &storemap($coursenum, $coursedom, $folder.'.'.$container);
}
-sub editor {
- my ($r,$coursenum,$coursedom,$folder,$allowed)=@_;
- if ($ENV{'form.foldername'}) {
- $r->print('
Folder: '.$ENV{'form.foldername'}.'
');
- }
- my $errtext='';
- my $fatal=0;
- ($errtext,$fatal)=
- &mapread($coursenum,$coursedom,$folder.'.sequence');
- if ($#Apache::lonratedt::order<1) {
- $Apache::lonratedt::order[0]=1;
- $Apache::lonratedt::resources[1]='';
- }
- if ($fatal) {
- $r->print('
'.$errtext.'
');
+sub breadcrumbs {
+ my ($where,$allowed,$type)=@_;
+ &Apache::lonhtmlcommon::clear_breadcrumbs();
+ my (@folders);
+ if ($env{'form.pagepath'}) {
+ @folders = split('&',$env{'form.pagepath'});
} else {
-# ------------------------------------------------------------ Process commands
-# ---------------- if they are for this folder and user allowed to make changes
- if (($allowed) && ($ENV{'form.folder'} eq $folder)) {
-# upload a file, if present
- if (($ENV{'form.uploaddoc.filename'}) &&
- ($ENV{'form.cmd'}=~/^upload_(\w+)/)) {
- if ($folder=~/^$1/) {
-# 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 $url=&Apache::lonnet::userfileupload('uploaddoc',1);
- my $ext='false';
- if ($url=~/^http\:\/\//) { $ext='true'; }
- $url=~s/\:/\:/g;
- my $comment=$ENV{'form.comment'};
- $comment=~s/\\<\;/g;
- $comment=~s/\>/\>\;/g;
- $comment=~s/\:/\:/g;
- if ($folder=~/^supplemental/) {
- $comment=time.'___&&&___'.$ENV{'user.name'}.'___&&&___'.
- $ENV{'user.domain'}.'___&&&___'.$comment;
- }
- my $newidx=$#Apache::lonratedt::resources+1;
- $Apache::lonratedt::resources[$newidx]=
- $comment.':'.$url.':'.$ext.':normal:res';
- $Apache::lonratedt::order[$#Apache::lonratedt::order+1]=
- $newidx;
-
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.sequence');
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
- }
- }
+ @folders=split('&',$env{'form.folderpath'});
+ }
+ my $folderpath;
+ my $cpinfo='';
+ my $plain='';
+ my $randompick=-1;
+ my $isencrypted=0;
+ my $ishidden=0;
+ my $is_random_order=0;
+ while (@folders) {
+ my $folder=shift(@folders);
+ my $foldername=shift(@folders);
+ if ($folderpath) {$folderpath.='&';}
+ $folderpath.=$folder.'&'.$foldername;
+ my $url='/adm/coursedocs?folderpath='.
+ &escape($folderpath);
+ my $name=&unescape($foldername);
+# randompick number, hidden, encrypted, random order, is appended with ":"s to the foldername
+ $name=~s/\:(\d*)\:(\w*)\:(\w*):(\d*)$//;
+ if ($1 ne '') {
+ $randompick=$1;
+ } else {
+ $randompick=-1;
}
- if ($ENV{'form.cmd'}) {
- my ($cmd,$idx)=split(/\_/,$ENV{'form.cmd'});
- if ($cmd eq 'del') {
- 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 ($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;
- $Apache::lonratedt::resources[
- $Apache::lonratedt::order[$idx]]=
- $comment.':'.join(':',@rrest);
-
+ if ($2) { $ishidden=1; }
+ if ($3) { $isencrypted=1; }
+ if ($4 ne '') { $is_random_order = 1; }
+ if ($folder eq 'supplemental') {
+ if ($allowed) {
+ $name = &mt('Supplemental '.$type.' Documents');
+ } else {
+ $name = &mt($type.' Documents');
}
-# Store the changed version
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,
- $folder.'.sequence');
- if ($fatal) {
- $r->print('
'.$errtext.'
');
- return;
+ }
+ &Apache::lonhtmlcommon::add_breadcrumb(
+ {'href'=>$url.$cpinfo,
+ 'title'=>$name,
+ 'text'=>$name,
+ 'no_mt'=>1,
+ });
+ $plain.=$name.' > ';
+ }
+ $plain=~s/\>\;\s*$//;
+ return (&Apache::lonhtmlcommon::breadcrumbs(undef,undef,0,'nohelp',
+ undef, undef, 1 ),$randompick,$ishidden,$isencrypted,$plain,$is_random_order);
+}
+
+sub log_docs {
+ return &Apache::lonnet::instructor_log('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 docs_change_log {
+ my ($r)=@_;
+ my $folder=$env{'form.folder'};
+ $r->print(&Apache::loncommon::start_page('Course Document Change Log'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Document Change Log'));
+ my %docslog=&Apache::lonnet::dump('nohist_docslog',
+ $env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
+
+ if ((keys(%docslog))[0]=~/^error\:/) { undef(%docslog); }
+
+ $r->print('');
+ $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
+ '
'.&mt('Time').'
'.&mt('User').'
'.&mt('Folder').'
'.&mt('Before').'
'.
+ &mt('After').'
'.
+ &Apache::loncommon::end_data_table_header_row());
+ my $shown=0;
+ foreach my $id (sort { $docslog{$b}{'exe_time'}<=>$docslog{$a}{'exe_time'} } (keys(%docslog))) {
+ if ($env{'form.displayfilter'} eq 'currentfolder') {
+ if ($docslog{$id}{'logentry'}{'currentfolder'} ne $folder) { next; }
+ }
+ my @changes=keys(%{$docslog{$id}{'logentry'}});
+ if ($env{'form.displayfilter'} eq 'containing') {
+ my $wholeentry=$docslog{$id}{'exe_uname'}.':'.$docslog{$id}{'exe_udom'}.':'.
+ &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},$docslog{$id}{'exe_udom'});
+ foreach my $key (@changes) {
+ $wholeentry.=':'.$docslog{$id}{'logentry'}{$key};
+ }
+ if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
+ }
+ my $count = 0;
+ my $time =
+ &Apache::lonlocal::locallocaltime($docslog{$id}{'exe_time'});
+ my $plainname =
+ &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},
+ $docslog{$id}{'exe_udom'});
+ my $about_me_link =
+ &Apache::loncommon::aboutmewrapper($plainname,
+ $docslog{$id}{'exe_uname'},
+ $docslog{$id}{'exe_udom'});
+ my $send_msg_link='';
+ if ((($docslog{$id}{'exe_uname'} ne $env{'user.name'})
+ || ($docslog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
+ $send_msg_link =' '.
+ &Apache::loncommon::messagewrapper(&mt('Send message'),
+ $docslog{$id}{'exe_uname'},
+ $docslog{$id}{'exe_udom'});
+ }
+ $r->print(&Apache::loncommon::start_data_table_row());
+ $r->print('
');
+# Before
+ for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
+ my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0];
+ my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0];
+ if ($oldname ne $newname) {
+ $r->print(&LONCAPA::map::qtescape($oldname));
+ }
+ }
+ $r->print('
');
+ for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
+ if ($docslog{$id}{'logentry'}{'before_order_res_'.$idx}) {
+ $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.')
+ .'
+ '.($url?"":'').$title.($url?'':' '.&mt('(re-initialize course to access)').'').$external."
+
";
+ if (($allowed) && ($folder!~/^supplemental/)) {
+ my %lt=&Apache::lonlocal::texthash(
+ 'hd' => 'Hidden',
+ 'ec' => 'URL hidden');
+ my $enctext=
+ ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i?' checked="checked"':'');
+ my $hidtext=
+ ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i?' checked="checked"':'');
+ $line.=(<
+ $form_start
+
+ $form_end
+
+
+ $form_start
+
+ $form_end
+
+
$form_start $rand_order_text $form_end
+
$form_start $parameterset $form_end
+ENDPARMS
+ }
+ $line.=&Apache::loncommon::end_data_table_row();
return $line;
}
-# ---------------------------------------------------------------- tie the hash
+=pod
+
+=item tiehash()
+
+tie the hash
+
+=cut
sub tiehash {
+ my ($mode)=@_;
$hashtied=0;
- if ($ENV{'request.course.fn'}) {
- if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db",
- &GDBM_READER(),0640)) {
+ if ($env{'request.course.fn'}) {
+ if ($mode eq 'write') {
+ if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
+ &GDBM_WRCREAT(),0640)) {
+ $hashtied=2;
+ }
+ } else {
+ if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
+ &GDBM_READER(),0640)) {
$hashtied=1;
- }
- }
+ }
+ }
+ }
}
sub untiehash {
if ($hashtied) { untie %hash; }
$hashtied=0;
+ return OK;
}
-# --------------------------------------------------------------- check on this
+
+
sub checkonthis {
my ($r,$url,$level,$title)=@_;
+ $url=&unescape($url);
$alreadyseen{$url}=1;
$r->rflush();
if (($url) && ($url!~/^\/uploaded\//) && ($url!~/\*$/)) {
- $r->print(' ');
+ $r->print("\n ");
+ if ($level==0) {
+ $r->print(" ");
+ }
for (my $i=0;$i<=$level*5;$i++) {
$r->print(' ');
}
@@ -511,8 +2143,8 @@ sub checkonthis {
if ($url=~/^\/res\//) {
my $result=&Apache::lonnet::repcopy(
&Apache::lonnet::filelocation('',$url));
- if ($result==OK) {
- $r->print(''.&mt('ok').'');
+ if ($result eq 'ok') {
+ $r->print(''.&mt('ok').'');
$r->rflush();
&Apache::lonnet::countacc($url);
$url=~/\.(\w+)$/;
@@ -522,83 +2154,123 @@ sub checkonthis {
for (my $i=0;$i<=$level*5;$i++) {
$r->print(' ');
}
- $r->print('- '.&mt('Rendering').': ');
- my $oldpath=$ENV{'request.filename'};
- $ENV{'request.filename'}=&Apache::lonnet::filelocation('',$url);
- &Apache::lonxml::xmlparse($r,'web',
- &Apache::lonnet::getfile(
- &Apache::lonnet::filelocation('',$url)));
- undef($Apache::lonhomework::parsing_a_problem);
- $ENV{'request.filename'}=$oldpath;
- if (($Apache::lonxml::errorcount) ||
- ($Apache::lonxml::warningcount)) {
- if ($Apache::lonxml::errorcount) {
- $r->print(''.
- $Apache::lonxml::errorcount.' '.
- &mt('error(s)').' ');
+ $r->print('- '.&mt('Rendering:').' ');
+ my ($errorcount,$warningcount)=split(/:/,
+ &Apache::lonnet::ssi_body($url,
+ ('grade_target'=>'web',
+ 'return_only_error_and_warning_counts' => 1)));
+ if (($errorcount) ||
+ ($warningcount)) {
+ if ($errorcount) {
+ $r->print(''.
+ &mt('[quant,_1,error]',$errorcount).'');
}
- if ($Apache::lonxml::warningcount) {
- $r->print(''.
- $Apache::lonxml::warningcount.' '.
- &mt('warning(s)').'');
+ if ($warningcount) {
+ $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==HTTP_SERVICE_UNAVAILABLE) {
- $r->print(''.&mt('connection down').'');
- } elsif ($result==HTTP_NOT_FOUND) {
+ } elsif ($result eq 'unavailable') {
+ $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').'');
}
- }
- }
+ }
+ }
+}
+
+
+
+=pod
+
+=item list_symbs()
+
+List Symbs
+
+=cut
+
+sub list_symbs {
+ my ($r) = @_;
+
+ my $type = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page('Symb List'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Symb List'));
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ 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($type).':'.$env{'request.course.id'});
+ } else {
+ $r->print("
\n");
+ }
+ $r->print(''.&mt('Return to DOCS').'');
}
-#
-# -------------------------------------------------------------- Verify Content
-#
sub verifycontent {
- my $r=shift;
+ my ($r) = @_;
+ my $type = &Apache::loncommon::course_type();
my $loaderror=&Apache::lonnet::overloaderror($r);
if ($loaderror) { return $loaderror; }
-
- $r->print('Verify Content'.
- &Apache::loncommon::bodytag('Verify Course Documents'));
+ $r->print(&Apache::loncommon::start_page('Verify '.$type.' Documents'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$type.' Documents'));
$hashtied=0;
undef %alreadyseen;
%alreadyseen=();
&tiehash();
- foreach (keys %hash) {
- if (($_=~/^src\_(.+)$/) && (!$alreadyseen{$hash{$_}})) {
- &checkonthis($r,$hash{$_},0,$hash{'title_'.$1});
+ 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 '.$type.': ').
+ &unescape($hash{$key}).' '.
+ &mt('Note that grading records for problems included in this sequence or folder will overlap.'));
+ }
+ }
+ if (($key=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$key})})) {
+ &checkonthis($r,$hash{$key},0,$hash{'title_'.$1});
}
}
&untiehash();
- $r->print('
'.&mt('Done').'.
');
+ $r->print('
'.&mt('Done').'.
'.''.
+ &mt('Return to DOCS').'');
}
-# -------------------------------------------------------------- Check Versions
+
+sub devalidateversioncache {
+ my $src=shift;
+ &Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
+ &Apache::lonnet::clutter($src));
+}
sub checkversions {
- my $r=shift;
- $r->print('Check Versions'.
- &Apache::loncommon::bodytag('Check Course Document Versions'));
+ my ($r) = @_;
+ my $type = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page("Check $type Document Versions"));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs("Check $type Document Versions"));
my $header='';
my $startsel='';
my $monthsel='';
@@ -609,57 +2281,60 @@ sub checkversions {
my $starttime=0;
my $haschanged=0;
my %setversions=&Apache::lonnet::dump('resourceversions',
- $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
- $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+ $env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
$hashtied=0;
&tiehash();
my %newsetversions=();
- if ($ENV{'form.setmostrecent'}) {
+ 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'}) {
+ } 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;
+ &devalidateversioncache($1);
}
}
}
- } elsif ($ENV{'form.setversions'}) {
+ } 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;
- &Apache::lonnet::logthis('Found: '.$1.' '.$ENV{$_});
- if (($ENV{$_}) && ($ENV{$_} ne $setversions{$src})) {
- $newsetversions{$src}=$ENV{$_};
+ if (($env{$key}) && ($env{$key} ne $setversions{$src})) {
+ $newsetversions{$src}=$env{$key};
+ &devalidateversioncache($src);
}
}
}
}
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('An Error Occured while Attempting to Store your Version Settings').'
');
+ $r->print('
'.&mt('An Error Occured while Attempting to Save your Version Settings').'
');
}
- &changewarning($r,'');
+ &mark_hash_old();
}
- if ($ENV{'form.timerange'} eq 'all') {
+ &changewarning($r,'');
+ if ($env{'form.timerange'} eq 'all') {
# show all documents
- $header=&mt('All Documents in Course');
+ $header=&mt('All Documents in '.$type);
$allsel=1;
- foreach (keys %hash) {
- if ($_=~/^ids\_(\/res\/.+)$/) {
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
my $src=$1;
$changes{$src}=1;
}
@@ -667,28 +2342,28 @@ sub checkversions {
} else {
# show documents which changed
%changes=&Apache::lonnet::dump
- ('versionupdate',$ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
- $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
- my $firstkey=(keys %changes)[0];
+ ('versionupdate',$env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
+ my $firstkey=(keys(%changes))[0];
unless ($firstkey=~/^error\:/) {
- unless ($ENV{'form.timerange'}) {
- $ENV{'form.timerange'}=604800;
+ unless ($env{'form.timerange'}) {
+ $env{'form.timerange'}=604800;
}
- my $seltext=&mt('during the last').' '.$ENV{'form.timerange'}.' '
+ my $seltext=&mt('during the last').' '.$env{'form.timerange'}.' '
.&mt('seconds');
- if ($ENV{'form.timerange'}==-1) {
+ if ($env{'form.timerange'}==-1) {
$seltext='since start of course';
$startsel='selected';
- $ENV{'form.timerange'}=time;
+ $env{'form.timerange'}=time;
}
- $starttime=time-$ENV{'form.timerange'};
- if ($ENV{'form.timerange'}==2592000) {
+ $starttime=time-$env{'form.timerange'};
+ if ($env{'form.timerange'}==2592000) {
$seltext=&mt('during the last month').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
$monthsel='selected';
- } elsif ($ENV{'form.timerange'}==604800) {
+ } elsif ($env{'form.timerange'}==604800) {
$seltext=&mt('during the last week').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
$weeksel='selected';
- } elsif ($ENV{'form.timerange'}==86400) {
+ } elsif ($env{'form.timerange'}==86400) {
$seltext=&mt('since yesterday').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
$daysel='selected';
}
@@ -698,10 +2373,10 @@ sub checkversions {
}
}
%setversions=&Apache::lonnet::dump('resourceversions',
- $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
- $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+ $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 Course',
+ ('st' => 'Version changes since start of '.$type,
'lm' => 'Version changes since last Month',
'lw' => 'Version changes since last Week',
'sy' => 'Version changes since Yesterday',
@@ -710,9 +2385,9 @@ sub checkversions {
'fi' => 'File',
'md' => 'Modification Date',
'mr' => 'Most recently published Version',
- 've' => 'Version used in Course',
- 'vu' => 'Set Version to be used in Course',
-'sv' => 'Set Versions to be used in Course according to Selections below',
+ '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',
'sm' => 'Keep all Resources up-to-date with most recent Versions (default)',
'sc' => 'Set all Resource Versions to current Version (Fix Versions)',
'di' => 'Differences');
@@ -733,14 +2408,14 @@ sub checkversions {
ENDHEADERS
- foreach (sort keys %changes) {
- if ($changes{$_}>$starttime) {
- my ($root,$extension)=($_=~/^(.*)\.(\w+)$/);
- my $currentversion=&Apache::lonnet::getversion($_);
+ foreach my $key (sort(keys(%changes))) {
+ if ($changes{$key}>$starttime) {
+ my ($root,$extension)=($key=~/^(.*)\.(\w+)$/);
+ my $currentversion=&Apache::lonnet::getversion($key);
if ($currentversion<0) {
$currentversion=&mt('Could not be determined.');
}
- my $linkurl=&Apache::lonnet::clutter($_);
+ my $linkurl=&Apache::lonnet::clutter($key);
$r->print(
'
');
my $lastold=1;
for (my $prevvers=1;$prevvers<$currentversion;$prevvers++) {
my $url=$root.'.'.$prevvers.'.'.$extension;
@@ -785,7 +2462,7 @@ ENDHEADERS
$lastold=$prevvers;
}
}
- #
+ #
# Code to figure out how many version entries should go in
# each of the four columns
my $entries_per_col = 0;
@@ -796,11 +2473,11 @@ ENDHEADERS
$entries_per_col = $num_entries/4 + 1;
}
my $entries_count = 0;
- $r->print('
');
+ $r->print('
');
my $cols_output = 1;
for (my $prevvers=$lastold;$prevvers<$currentversion;$prevvers++) {
my $url=$root.'.'.$prevvers.'.'.$extension;
- $r->print(''.&mt('Version').' '.$prevvers.' ('.
&Apache::lonlocal::locallocaltime(
&Apache::lonnet::metadata($url,
@@ -813,7 +2490,7 @@ ENDHEADERS
'&versionone='.$prevvers.
'">'.&mt('Diffs').'');
}
- $r->print(' ');
+ $r->print(' ');
if (++$entries_count % $entries_per_col == 0) {
$r->print('
');
if ($cols_output != 4) {
@@ -834,34 +2511,96 @@ ENDHEADERS
&untiehash();
}
+sub mark_hash_old {
+ my $retie_hash=0;
+ if ($hashtied) {
+ $retie_hash=1;
+ &untiehash();
+ }
+ &tiehash('write');
+ $hash{'old'}=1;
+ &untiehash();
+ if ($retie_hash) { &tiehash(); }
+}
+
+sub is_hash_old {
+ my $untie_hash=0;
+ if (!$hashtied) {
+ $untie_hash=1;
+ &tiehash();
+ }
+ my $return=$hash{'old'};
+ if ($untie_hash) { &untiehash(); }
+ return $return;
+}
+
sub changewarning {
- my ($r,$postexec)=@_;
- $r->print(
-''.
-'');
+ my ($r,$postexec,$message,$url)=@_;
+ if (!&is_hash_old()) { return; }
+ my $pathvar='folderpath';
+ my $path=&escape($env{'form.folderpath'});
+ if (!defined($url)) {
+ if (defined($env{'form.pagepath'})) {
+ $pathvar='pagepath';
+ $path=&escape($env{'form.pagepath'});
+ $path.='&pagesymb='.&escape($env{'form.pagesymb'});
+ }
+ $url='/adm/coursedocs?'.$pathvar.'='.$path;
+ }
+ my $course_type = &Apache::loncommon::course_type();
+ if (!defined($message)) {
+ $message='Changes will become active for your current session after [_1], or the next time you log in.';
+ }
+ $r->print("\n\n".
+''."\n".
+''."\n\n");
}
-# ================================================================ Main Handler
+
+sub init_breadcrumbs {
+ my ($form,$text)=@_;
+ &Apache::lonhtmlcommon::clear_breadcrumbs();
+ &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs",
+ text=>"Edit ".&Apache::loncommon::course_type(),
+ faq=>273,
+ bug=>'Instructor Interface',
+ help => 'Docs_Adding_Course_Doc'});
+ &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?".$form.'=1',
+ text=>$text,
+ faq=>273,
+ bug=>'Instructor Interface'});
+}
+
+
+
+
sub handler {
my $r = shift;
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
return OK if $r->header_only;
+ my $type = &Apache::loncommon::course_type();
+
# --------------------------------------------- Initialize help topics for this
- foreach ('Adding_Course_Doc','Main_Course_Documents',
- 'Adding_External_Resource','Navigate_Content',
- 'Adding_Folders','Docs_Overview', 'Load_Map',
- 'Supplemental', 'Score_Upload_Form',
- 'Importing_LON-CAPA_Resource','Uploading_From_Harddrive') {
- $help{$_}=&Apache::loncommon::help_open_topic('Docs_'.$_);
- }
+ foreach my $topic ('Adding_Course_Doc','Main_Course_Documents',
+ 'Adding_External_Resource','Navigate_Content',
+ 'Adding_Folders','Docs_Overview', 'Load_Map',
+ 'Supplemental','Score_Upload_Form','Adding_Pages',
+ 'Importing_LON-CAPA_Resource','Uploading_From_Harddrive',
+ 'Check_Resource_Versions','Verify_Content') {
+ $help{$topic}=&Apache::loncommon::help_open_topic('Docs_'.$topic);
+ }
# Composite help files
$help{'Syllabus'} = &Apache::loncommon::help_open_topic(
'Docs_About_Syllabus,Docs_Editing_Templated_Pages');
@@ -871,508 +2610,1259 @@ sub handler {
'Option_Response_Simple');
$help{'Bulletin Board'} = &Apache::loncommon::help_open_topic(
'Docs_About_Bulletin_Board,Docs_Editing_Templated_Pages');
- $help{'My Personal Info'} = &Apache::loncommon::help_open_topic(
+ $help{'My Personal Information Page'} = &Apache::loncommon::help_open_topic(
'Docs_About_My_Personal_Info,Docs_Editing_Templated_Pages');
+ $help{'Group Portfolio'} = &Apache::loncommon::help_open_topic('Docs_About_Group_Files');
$help{'Caching'} = &Apache::loncommon::help_open_topic('Caching');
-
- if ($ENV{'form.verify'}) {
+
+# does this user have privileges to modify docs
+ my $allowed=&Apache::lonnet::allowed('mdc',$env{'request.course.id'});
+ if ($allowed && $env{'form.verify'}) {
+ &init_breadcrumbs('verify','Verify Content');
&verifycontent($r);
- } elsif ($ENV{'form.versions'}) {
+ } elsif ($allowed && $env{'form.listsymbs'}) {
+ &init_breadcrumbs('listsymbs','List Symbs');
+ &list_symbs($r);
+ } elsif ($allowed && $env{'form.docslog'}) {
+ &init_breadcrumbs('docslog','Show Log');
+ &docs_change_log($r);
+ } elsif ($allowed && $env{'form.versions'}) {
+ &init_breadcrumbs('versions','Check/Set Resource Versions');
&checkversions($r);
- } elsif ($ENV{'form.dumpcourse'}) {
+ } elsif ($allowed && $env{'form.dumpcourse'}) {
+ &init_breadcrumbs('dumpcourse','Dump '.&Apache::loncommon::course_type().' DOCS to Construction Space');
&dumpcourse($r);
+ } elsif ($allowed && $env{'form.exportcourse'}) {
+ &init_breadcrumbs('exportcourse','IMS Export');
+ &exportcourse($r);
} else {
# is this a standard course?
- my $standard=($ENV{'request.course.uri'}=~/^\/uploaded\//);
- my $forcestandard;
+ my $standard=($env{'request.course.uri'}=~/^\/uploaded\//);
+ my $forcestandard = 0;
my $forcesupplement;
my $script='';
- my $allowed;
- my $events='';
my $showdoc=0;
+ my $containertag;
+ my $uploadtag;
+
+
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
- ['folder','foldername']);
+ ['folderpath','pagepath',
+ 'pagesymb']);
+# No folderpath, no pagepath, see if we have something stored
+ if ((!$env{'form.folderpath'}) && (!$env{'form.pagepath'})) {
+ &Apache::loncommon::restore_course_settings('docs_folderpath',
+ {'folderpath' => 'scalar'});
+ }
+ if (!$env{'form.folderpath'}) {
+ &Apache::loncommon::restore_course_settings('docs_folderpath',
+ {'pagepath' => 'scalar'});
+ }
+ if ($env{'form.pagepath'}) {
+ $env{'form.folderpath'}='';
+ }
+ if ($env{'form.folderpath'} =~ /^supplemental_\d+/) {
+ $env{'form.folderpath'} = 'supplemental&'.
+ &escape(&mt('Supplemental '.$type.' Documents')).'&'.
+ $env{'form.folderpath'};
+ }
+ &Apache::loncommon::store_course_settings('docs_folderpath',
+ {'pagepath' => 'scalar',
+ 'folderpath' => 'scalar'});
+ if ($env{'form.folderpath'}) {
+ my (@folderpath)=split('&',$env{'form.folderpath'});
+ $env{'form.foldername'}=&unescape(pop(@folderpath));
+ $env{'form.folder'}=pop(@folderpath);
+ }
+ if ($env{'form.pagepath'}) {
+ my (@pagepath)=split('&',$env{'form.pagepath'});
+ $env{'form.pagename'}=&unescape(pop(@pagepath));
+ $env{'form.folder'}=pop(@pagepath);
+ $containertag = ''.
+ '';
+ $uploadtag = ''.
+ '';
+ }
if ($r->uri=~/^\/adm\/coursedocs\/showdoc\/(.*)$/) {
- $showdoc=$1;
+ $showdoc='/'.$1;
}
unless ($showdoc) { # got called from remote
- $forcestandard=($ENV{'form.folder'}=~/^default_/);
- $forcesupplement=($ENV{'form.folder'}=~/^supplemental_/);
+ if (($env{'form.folder'}=~/^(?:group|default)_/) ||
+ ($env{'form.folder'} =~ m:^\d+/(pages|sequences)/:)) {
+ $forcestandard = 1;
+ }
+ $forcesupplement=($env{'form.folder'}=~/^supplemental_/);
-# does this user have privileges to post, etc?
- $allowed=&Apache::lonnet::allowed('mdc',$ENV{'request.course.id'});
- if ($allowed) {
+ if ($allowed) {
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['cmd']);
- $script=&Apache::lonratedt::editscript('simple');
+ $script=&Apache::lonratedt::editscript('simple');
}
} else { # got called in sequence from course
$allowed=0;
- $script=''.&Apache::lonmenu::registerurl(1,undef).''."\n";
+
+ # Breadcrumbs
+ &Apache::lonhtmlcommon::clear_breadcrumbs();
+ &Apache::lonhtmlcommon::add_breadcrumb({
+ href=>"/adm/createuser",text=>"$type Documents"});
+
+ $r->print(&Apache::loncommon::start_page("$type Documents", $script,
+ {'force_register' => $showdoc,})
+ .&Apache::loncommon::help_open_menu('','',273,'RAT')
+ .&Apache::lonhtmlcommon::breadcrumbs(
+ 'Editing the Table of Contents for your '.$type,
+ 'Docs_Adding_Course_Doc')
+ );
+
+ my %allfiles = ();
+ my %codebase = ();
+ my ($upload_result,$upload_output);
+ if ($allowed) {
+ if (($env{'form.uploaddoc.filename'}) &&
+ ($env{'form.cmd'}=~/^upload_(\w+)/)) {
+# Process file upload - phase one - upload and parse primary file.
+ undef($hadchanges);
+ $upload_result = &process_file_upload(\$upload_output,$coursenum,
+ $coursedom,\%allfiles,
+ \%codebase,$1);
+ if ($hadchanges) {
+ &mark_hash_old();
+ }
+ if ($upload_result eq 'phasetwo') {
+ $r->print($upload_output);
+ }
+ } elsif ($env{'form.phasetwo'}) {
+ my %newname = ();
+ my %origname = ();
+ my %attribs = ();
+ my $updateflag = 0;
+ my $residx = $env{'form.newidx'};
+ my $primary_url = &unescape($env{'form.primaryurl'});
+# Process file upload - phase two - gather secondary files.
+ for (my $i=0; $i<$env{'form.phasetwo'}; $i++) {
+ if ($env{'form.embedded_item_'.$i.'.filename'}) {
+ my $javacodebase;
+ $newname{$i} = &process_secondary_uploads(\$upload_output,$coursedom,$coursenum,'embedded_item_',$i,$residx);
+ $origname{$i} = &unescape($env{'form.embedded_orig_'.$i});
+ if (exists($env{'form.embedded_codebase_'.$i})) {
+ $javacodebase = &unescape($env{'form.embedded_codebase_'.$i});
+ $origname{$i} =~ s#^\Q$javacodebase\E/##;
+ }
+ my @attributes = ();
+ if ($env{'form.embedded_attrib_'.$i} =~ /:/) {
+ @attributes = split(/:/,$env{'form.embedded_attrib_'.$i});
+ } else {
+ @attributes = ($env{'form.embedded_attrib_'.$i});
+ }
+ foreach my $attr (@attributes) {
+ push(@{$attribs{$i}},&unescape($attr));
+ }
+ if ($javacodebase) {
+ $codebase{$i} = $javacodebase;
+ $codebase{$i} =~ s#/$##;
+ $updateflag = 1;
+ }
+ }
+ unless ($newname{$i} eq $origname{$i}) {
+ $updateflag = 1;
+ }
+ }
+# Process file upload - phase three - modify primary file
+ if ($updateflag) {
+ my ($content,$rtncode);
+ my $updateflag = 0;
+ my $getstatus = &Apache::lonnet::getuploaded('GET',$primary_url,$coursedom,$coursenum,\$content,\$rtncode);
+ if ($getstatus eq 'ok') {
+ foreach my $item (keys(%newname)) {
+ if ($newname{$item} ne $origname{$item}) {
+ my $attrib_regexp = '';
+ if (@{$attribs{$item}} > 1) {
+ $attrib_regexp = join('|',@{$attribs{$item}});
+ } else {
+ $attrib_regexp = $attribs{$item}[0];
+ }
+ if ($content =~ m#($attrib_regexp\s*=\s*['"]?)\Q$origname{$item}\E(['"]?)#) {
+ }
+ $content =~ s#($attrib_regexp\s*=\s*['"]?)\Q$origname{$item}\E(['"]?)#$1$newname{$item}$2#gi;
+ }
+ if (exists($codebase{$item})) {
+ $content =~ s/(codebase\s*=\s*["']?)\Q$codebase{$item}\E(["']?)/$1.$2/i; #' stupid emacs
+ }
+ }
+# Save edited file.
+ my $saveresult;
+ my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
+ my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $url = &Apache::lonnet::store_edited_file($primary_url,$content,$docudom,$docuname,\$saveresult);
+ } else {
+ &Apache::lonnet::logthis('retrieval of uploaded file - '.$primary_url.' - for editing, failed: '.$getstatus);
+ }
+ }
+ }
+ }
-# print screen
- $r->print(<
-
-The LearningOnline Network with CAPA
-
-ENDDOCUMENT
- if ($allowed) {
- $r->print(<
+ unless ($showdoc || $upload_result eq 'phasetwo') {
+# -----------------------------------------------------------------------------
+ my %lt=&Apache::lonlocal::texthash(
+ 'uplm' => 'Upload a new main '.lc($type).' document',
+ 'upls' => 'Upload a new supplemental '.lc($type).' document',
+ 'impp' => 'Import a document',
+ 'copm' => 'All documents out of a published map into this folder',
+ 'upld' => 'Upload Document',
+ 'srch' => 'Search',
+ 'impo' => 'Import',
+ 'book' => 'Import Bookmarks',
+ 'selm' => 'Select Map',
+ 'load' => 'Load Map',
+ 'reco' => 'Recover Deleted Resources',
+ 'newf' => 'New Folder',
+ 'newp' => 'New Composite Page',
+ 'extr' => 'External Resource',
+ 'syll' => 'Syllabus',
+ 'navc' => 'Navigate Contents',
+ 'sipa' => 'Simple Course Page',
+ 'sipr' => 'Simple Problem',
+ 'drbx' => 'Drop Box',
+ 'scuf' => 'Score Upload Form',
+ 'bull' => 'Discussion Board',
+ 'mypi' => 'My Personal Information Page',
+ 'grpo' => 'Group Portfolio',
+ 'rost' => 'Course Roster',
+ 'abou' => 'Personal Information Page for a User',
+ 'imsf' => 'IMS Import',
+ 'imsl' => 'Import IMS package',
+ 'file' => 'File',
+ 'title' => 'Title',
+ 'comment' => 'Comment',
+ 'parse' => 'Upload embedded images/multimedia files if HTML file!',
+ 'nd' => 'Upload Document',
+ 'pm' => 'Published Map',
+ 'sd' => 'Special Document',
+ 'mo' => 'More Options',
+ );
+# -----------------------------------------------------------------------------
+ my $fileupload=(<
+
+FIUP
+
+ my $checkbox=(<$lt{'parse'}?
+
+ -->
+
+CHBO
+
+ my @fileuploada = (
+ { '' => " $help{'Uploading_From_Harddrive'}" },
+ );
+ my $fileuploadform=(<
+
+ $fileupload
+
+ $lt{'title'}:
+
+ $uploadtag
+
+
+
+ $checkbox
+
+FUFORM
+ $fileuploadform .= create_form_ul(create_list_elements(@fileuploada));
+ $fileuploadform .= (<
+FUFORM
+
+ my $simpleeditdefaultform=(<
+
+SEDFFORM
+ my @simpleeditdefaultforma = (
+ { '' => "$uploadtag$lt{'srch'}" },
+ { '' => "$lt{'impo'}$help{'Importing_LON-CAPA_Resource'}" },
+ { '' => "$lt{'book'}" },
+ );
+ $simpleeditdefaultform .= create_form_ul(create_list_elements(@simpleeditdefaultforma));
+ $simpleeditdefaultform .=(<
+