');
+# 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('
':'').
+ '');
+ 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.')
+ .'
'.
+ &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");
+ }
+}
+
+
+sub verifycontent {
+ my ($r) = @_;
+ my $crstype = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Documents'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Documents'));
+ &startContentScreen($r,'tools');
+ $hashtied=0;
+ undef %alreadyseen;
+ %alreadyseen=();
+ &tiehash();
+ 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 (($key=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$key})})) {
+ &checkonthis($r,$hash{$key},0,$hash{'title_'.$1});
+ }
+ }
+ &untiehash();
+ $r->print('
'.&mt('Done').'
');
+}
+
+
+sub devalidateversioncache {
+ my $src=shift;
+ &Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
+ &Apache::lonnet::clutter($src));
+}
+
+sub checkversions {
+ my ($r) = @_;
+ 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"));
+ &startContentScreen($r,'tools');
+
+ my $header='';
+ my $startsel='';
+ my $monthsel='';
+ my $weeksel='';
+ my $daysel='';
+ my $allsel='';
+ my %changes=();
+ 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'});
+
+ $hashtied=0;
+ &tiehash();
+ my %newsetversions=();
+ if ($env{'form.setmostrecent'}) {
+ $haschanged=1;
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
+ $newsetversions{$1}='mostrecent';
+ &devalidateversioncache($1);
+ }
+ }
+ } elsif ($env{'form.setcurrent'}) {
+ $haschanged=1;
+ 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'}) {
+ $haschanged=1;
+ foreach my $key (keys(%env)) {
+ if ($key=~/^form\.set_version_(.+)$/) {
+ my $src=$1;
+ 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('Your Version Settings have been Saved').'
');
+ } else {
+ $r->print('
'.&mt('An Error Occured while Attempting to Save your Version Settings').'
');
+ }
+ &mark_hash_old();
+ }
+ &changewarning($r,'');
+ if ($env{'form.timerange'} eq 'all') {
+# show all documents
+ $header=&mt('All Documents in '.$crstype);
+ $allsel=1;
+ foreach my $key (keys(%hash)) {
+ if ($key=~/^ids\_(\/res\/.+)$/) {
+ my $src=$1;
+ $changes{$src}=1;
+ }
+ }
+ } 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];
+ unless ($firstkey=~/^error\:/) {
+ unless ($env{'form.timerange'}) {
+ $env{'form.timerange'}=604800;
+ }
+ my $seltext=&mt('during the last').' '.$env{'form.timerange'}.' '
+ .&mt('seconds');
+ if ($env{'form.timerange'}==-1) {
+ $seltext='since start of course';
+ $startsel='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';
+ } elsif ($env{'form.timerange'}==604800) {
+ $seltext=&mt('during the last week').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
+ $weeksel='selected';
+ } elsif ($env{'form.timerange'}==86400) {
+ $seltext=&mt('since yesterday').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
+ $daysel='selected';
+ }
+ $header=&mt('Content changed').' '.$seltext;
+ } else {
+ $header=&mt('No content modifications yet.');
+ }
+ }
+ %setversions=&Apache::lonnet::dump('resourceversions',
+ $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 '.$crstype,
+ 'lm' => 'Version changes since last Month',
+ 'lw' => 'Version changes since last Week',
+ 'sy' => 'Version changes since Yesterday',
+ 'al' => 'All Resources (possibly large output)',
+ 'sd' => 'Display',
+ 'fi' => 'File',
+ 'md' => 'Modification Date',
+ 'mr' => 'Most recently published Version',
+ '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');
+ $r->print(<
+
+
+
+
+
+
$header
+
+
+ENDHEADERS
+ 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($key);
+ $r->print(
+ '
');
+ my $lastold=1;
+ for (my $prevvers=1;$prevvers<$currentversion;$prevvers++) {
+ my $url=$root.'.'.$prevvers.'.'.$extension;
+ if (&Apache::lonnet::metadata($url,'lastrevisiondate')<
+ $starttime) {
+ $lastold=$prevvers;
+ }
+ }
+ #
+ # Code to figure out how many version entries should go in
+ # each of the four columns
+ my $entries_per_col = 0;
+ my $num_entries = ($currentversion-$lastold);
+ if ($num_entries % 4 == 0) {
+ $entries_per_col = $num_entries/4;
+ } else {
+ $entries_per_col = $num_entries/4 + 1;
+ }
+ my $entries_count = 0;
+ $r->print('
');
+}
+
+#
+# End tabs
+#
+
+sub endContentScreen {
+ my ($r)=@_;
+ $r->print('
');
+}
+
+sub supplemental_base {
+ return 'supplemental&'.&escape(&mt('Supplemental '.&Apache::loncommon::course_type().' Content'));
+}
+
sub handler {
my $r = shift;
- $r->content_type('text/html');
+ &Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
return OK if $r->header_only;
+ my $crstype = &Apache::loncommon::course_type();
-# is this a standard course?
+#
+# --------------------------------------------- Initialize help topics for this
+ 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');
+ $help{'Simple Page'} = &Apache::loncommon::help_open_topic(
+ 'Docs_About_Simple_Page,Docs_Editing_Templated_Pages');
+ $help{'Simple Problem'} = &Apache::loncommon::help_open_topic(
+ 'Option_Response_Simple');
+ $help{'Bulletin Board'} = &Apache::loncommon::help_open_topic(
+ 'Docs_About_Bulletin_Board,Docs_Editing_Templated_Pages');
+ $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');
+
+
+ my $allowed;
+# URI is /adm/supplemental when viewing supplemental docs in non-edit mode.
+ unless ($r->uri eq '/adm/supplemental') {
+ # does this user have privileges to modify content.
+ $allowed = &Apache::lonnet::allowed('mdc',$env{'request.course.id'});
+ }
- &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['folder']);
- my $standard=($ENV{'request.course.uri'}=~/^\/uploaded\//);
- my $forcestandard=($ENV{'form.folder'}=~/^default_/);
- my $forcesupplement=($ENV{'form.folder'}=~/^supplement_/);
+ if ($allowed && $env{'form.verify'}) {
+ &init_breadcrumbs('verify','Verify Content');
+ &verifycontent($r);
+ } 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 ($allowed && $env{'form.dumpcourse'}) {
+ &init_breadcrumbs('dumpcourse','Dump '.&Apache::loncommon::course_type().' Documents to Construction Space');
+ &dumpcourse($r);
+ } elsif ($allowed && $env{'form.exportcourse'}) {
+ &init_breadcrumbs('exportcourse','IMS Export');
+ &Apache::imsexport::exportcourse($r);
+ } else {
+#
+# Done catching special calls
+# The whole rest is for course and supplemental documents
+# Get the parameters that may be needed
+#
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
+ ['folderpath','pagepath',
+ 'pagesymb','forcesupplement','forcestandard',
+ 'symb','command']);
+
+# standard=1: this is a "new-style" course with an uploaded map as top level
+# standard=2: this is a "old-style" course, and there is nothing we can do
+
+ my $standard=($env{'request.course.uri'}=~/^\/uploaded\//);
+
+# Decide whether this should display supplemental or main content
+# supplementalflag=1: show supplemental documents
+# supplementalflag=0: show standard documents
+
+
+ my $supplementalflag=($env{'form.folderpath'}=~/^supplemental/);
+ if (($env{'form.folderpath'}=~/^default/) || $env{'form.folderpath'} eq "" || ($env{'form.pagepath'})) {
+ $supplementalflag=0;
+ }
+ if ($env{'form.forcesupplement'}) { $supplementalflag=1; }
+ if ($env{'form.forcestandard'}) { $supplementalflag=0; }
+ unless ($allowed) { $supplementalflag=1; }
+ unless ($standard) { $supplementalflag=1; }
-# does this user have privileges to post, etc?
- my $allowed=&Apache::lonnet::allowed('srm',$ENV{'request.course.id'});
my $script='';
- if ($allowed) {
- &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['cmd']);
- $script=&Apache::lonratedt::editscript('docs');
+ my $showdoc=0;
+ my $addentries = {};
+ my $container;
+ my $containertag;
+ my $uploadtag;
+
+# Do we directly jump somewhere?
+
+ if ($env{'form.command'} eq 'direct') {
+ my ($mapurl,$id,$resurl);
+ if ($env{'form.symb'} ne '') {
+ ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($env{'form.symb'});
+ if ($resurl=~/\.(sequence|page)$/) {
+ $mapurl=$resurl;
+ } elsif ($resurl eq 'adm/navmaps') {
+ $mapurl=$env{'course.'.$env{'request.course.id'}.'.url'};
+ }
+ my $mapresobj;
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ $mapresobj = $navmap->getResourceByUrl($mapurl);
+ }
+ $mapurl=~s{^.*/([^/]+)\.(\w+)$}{$1};
+ my $type=$2;
+ my $path;
+ if (ref($mapresobj)) {
+ my $pcslist = $mapresobj->map_hierarchy();
+ if ($pcslist ne '') {
+ foreach my $pc (split(/,/,$pcslist)) {
+ next if ($pc <= 1);
+ my $res = $navmap->getByMapPc($pc);
+ if (ref($res)) {
+ my $thisurl = $res->src();
+ $thisurl=~s{^.*/([^/]+)\.\w+$}{$1};
+ my $thistitle = $res->title();
+ $path .= '&'.
+ &Apache::lonhtmlcommon::entity_encode($thisurl).'&'.
+ &Apache::lonhtmlcommon::entity_encode($thistitle).
+ ':'.$res->randompick().
+ ':'.$res->randomout().
+ ':'.$res->encrypted().
+ ':'.$res->randomorder();
+ }
+ }
+ }
+ $path .= '&'.&Apache::lonhtmlcommon::entity_encode($mapurl).'&'.
+ &Apache::lonhtmlcommon::entity_encode($mapresobj->title()).
+ ':'.$mapresobj->randompick().
+ ':'.$mapresobj->randomout().
+ ':'.$mapresobj->encrypted().
+ ':'.$mapresobj->randomorder();
+ } else {
+ my $maptitle = &Apache::lonnet::gettitle($mapurl);
+ $path = '&default&...::::'.
+ '&'.&Apache::lonhtmlcommon::entity_encode($mapurl).'&'.
+ &Apache::lonhtmlcommon::entity_encode($maptitle).'::::';
+ }
+ $path = 'default&'.
+ &Apache::lonhtmlcommon::entity_encode('Main Course Documents').
+ $path;
+ if ($type eq 'sequence') {
+ $env{'form.folderpath'}=$path;
+ $env{'form.pagepath'}='';
+ } else {
+ $env{'form.pagepath'}=$path;
+ $env{'form.folderpath'}='';
+ }
+ } elsif ($env{'form.supppath'} ne '') {
+ $env{'form.folderpath'}=$env{'form.supppath'};
+ }
+ } elsif ($env{'form.command'} eq 'editdocs') {
+ $env{'form.folderpath'} = 'default&'.
+ &Apache::lonhtmlcommon::entity_encode('Main Course Content');
+ $env{'form.pagepath'}='';
+ } elsif ($env{'form.command'} eq 'editsupp') {
+ $env{'form.folderpath'} = 'default&'.
+ &Apache::lonhtmlcommon::entity_encode('Supplemental Content');
+ $env{'form.pagepath'}='';
+ }
+
+# Where do we store these for when we come back?
+ my $stored_folderpath='docs_folderpath';
+ if ($supplementalflag) {
+ $stored_folderpath='docs_sup_folderpath';
+ }
+
+# No folderpath, no pagepath, see if we have something stored
+ if ((!$env{'form.folderpath'}) && (!$env{'form.pagepath'})) {
+ &Apache::loncommon::restore_course_settings($stored_folderpath,
+ {'folderpath' => 'scalar'});
+ }
+
+# If we are not allowed to make changes, all we can see are supplemental docs
+ if (!$allowed) {
+ $env{'form.pagepath'}='';
+ unless ($env{'form.folderpath'} =~ /^supplemental/) {
+ $env{'form.folderpath'} = &supplemental_base();
+ }
+ }
+# If we still not have a folderpath, see if we can resurrect at pagepath
+ if (!$env{'form.folderpath'} && $allowed) {
+ &Apache::loncommon::restore_course_settings($stored_folderpath,
+ {'pagepath' => 'scalar'});
+ }
+# Make the zeroth entry in supplemental docs page paths, so we can get to top level
+ if ($env{'form.folderpath'} =~ /^supplemental_\d+/) {
+ $env{'form.folderpath'} = &supplemental_base()
+ .'&'.
+ $env{'form.folderpath'};
+ }
+# If after all of this, we still don't have any paths, make them
+ unless (($env{'form.pagepath'}) || ($env{'form.folderpath'})) {
+ if ($supplementalflag) {
+ $env{'form.folderpath'}=&supplemental_base();
+ } else {
+ $env{'form.folderpath'}='default';
+ }
+ }
+
+# Store this
+ &Apache::loncommon::store_course_settings($stored_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);
+ $container='sequence';
+ }
+ if ($env{'form.pagepath'}) {
+ my (@pagepath)=split('&',$env{'form.pagepath'});
+ $env{'form.pagename'}=&unescape(pop(@pagepath));
+ $env{'form.folder'}=pop(@pagepath);
+ $container='page';
+ $containertag = ''.
+ '';
+ $uploadtag =
+ ''.
+ ''.
+ '';
+ } else {
+ my $folderpath=$env{'form.folderpath'};
+ if (!$folderpath) {
+ if ($env{'form.folder'} eq '' ||
+ $env{'form.folder'} eq 'supplemental') {
+ $folderpath='default&'.
+ &escape(&mt('Main '.$crstype.' Documents'));
+ }
+ }
+ $containertag = '';
+ $uploadtag = '';
+ }
+ if ($r->uri=~/^\/adm\/coursedocs\/showdoc\/(.*)$/) {
+ $showdoc='/'.$1;
+ }
+ if ($showdoc) { # got called in sequence from course
+ $allowed=0;
+ } else {
+ if ($allowed) {
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['cmd']);
+ $script=&Apache::lonratedt::editscript('simple');
+ }
}
# get course data
- my $coursenum=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};
- my $coursedom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
+ my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
+ my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
+
+# get personal data
+ my $uname=$env{'user.name'};
+ my $udom=$env{'user.domain'};
+ my $plainname=&escape(&Apache::loncommon::plainname($uname,$udom));
# graphics settings
- $iconpath = $r->dir_config('lonIconsURL') . "/";
+ $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL') . "/");
-# upload a file, if present
- if (($ENV{'form.uploaddoc.filename'}) && ($allowed)) {
-# 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 $comment=$ENV{'form.comment'};
- $comment=~s/\\<\;/g;
- $comment=~s/\>/\>\;/g;
- }
-
-# print screen
- $r->print(<
-
-The LearningOnline Network with CAPA
-
-
-ENDDOCUMENT
-$r->print(&Apache::loncommon::bodytag('Course Documents'));
-# --------------------------------------------------0------ Standard documents
- if (($standard) && ($allowed) && (!$forcesupplement)) {
- $r->print('
Main Course Documents
');
- my $folder=$ENV{'form.folder'};
- unless ($folder) { $folder='default'; }
- &editor($r,$coursenum,$coursedom,$folder,$allowed);
- $r->print(<Post a new main course document
-
-ENDFORM
- $r->print('');
- }
-# ----------------------------------------------------- Supplemental documents
- if (!$forcestandard) {
- $r->print('