--- loncom/interface/londocs.pm 2006/07/20 01:46:14 1.239 +++ loncom/interface/londocs.pm 2007/08/29 00:52:36 1.296 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.239 2006/07/20 01:46:14 www Exp $ +# $Id: londocs.pm,v 1.296 2007/08/29 00:52:36 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -33,17 +33,16 @@ use Apache::Constants qw(:common :http); use Apache::imsexport; use Apache::lonnet; use Apache::loncommon; -use Apache::lonratedt; -use Apache::lonratsrv; +use LONCAPA::map(); +use Apache::lonratedt(); use Apache::lonxml; -use Apache::loncreatecourse; +use Apache::lonclonecourse; use Apache::lonnavmaps; use HTML::Entities; use GDBM_File; use Apache::lonlocal; use Cwd; -use lib '/home/httpd/lib/perl/'; -use LONCAPA; +use LONCAPA qw(:DEFAULT :match); my $iconpath; @@ -58,7 +57,7 @@ my $hadchanges; my %help=(); -# Mapread read maps into lonratedt::global arrays +# Mapread read maps into LONCAPA::map:: global arrays # @order and @resources, determines status # sets @order - pointer to resources in right order # sets @resources - array with the resources with correct idx @@ -67,15 +66,15 @@ my %help=(); sub mapread { my ($coursenum,$coursedom,$map)=@_; return - &Apache::lonratedt::mapread('/uploaded/'.$coursedom.'/'.$coursenum.'/'. - $map); + &LONCAPA::map::mapread('/uploaded/'.$coursedom.'/'.$coursenum.'/'. + $map); } sub storemap { my ($coursenum,$coursedom,$map)=@_; my ($outtext,$errtext)= - &Apache::lonratedt::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'. - $map,1); + &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'. + $map,1); if ($errtext) { return ($errtext,2); } $hadchanges=1; @@ -100,7 +99,7 @@ sub authorhosts { $ca=$env{'user.name'}; $cd=$env{'user.domain'}; } else { - ($cd,$ca)=($realm=~/^\/(\w+)\/(\w+)$/); + ($cd,$ca)=($realm=~/^\/($match_domain)\/($match_username)$/); } my $allowed=0; my $myhome=&Apache::lonnet::homeserver($ca,$cd); @@ -123,16 +122,17 @@ sub dumpbutton { my ($home,$other,%outhash)=&authorhosts(); my $type = &Apache::loncommon::course_type(); if ($home+$other==0) { return ''; } - my $output=''; if ($home) { - return ''. + return '
'. ''. - &Apache::loncommon::help_open_topic('Docs_Dump_Course_Docs'); + &Apache::loncommon::help_open_topic('Docs_Dump_Course_Docs'). + '
'; } else { - return''. + return '
'. &mt('Dump '.$type. - ' DOCS to Construction Space: available on other servers'); + ' DOCS to Construction Space: available on other servers'). + '
'; } } @@ -148,6 +148,7 @@ sub dumpcourse { my $type = &Apache::loncommon::course_type(); $r->print(&Apache::loncommon::start_page('Dump '.$type.' DOCS to Construction Space'). '
'); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Dump '.$type.' DOCS to Construction Space')); my ($home,$other,%outhash)=&authorhosts(); unless ($home) { return ''; } my $origcrsid=$env{'request.course.id'}; @@ -186,22 +187,22 @@ sub dumpcourse { $r->print('
'.$_.' => '.$newfilename.': '); if (my $fh=Apache::File->new('>'.$path.'/'.$newfilename)) { if ($_=~/\.(sequence|page|html|htm|xml|xhtml)$/) { - print $fh &Apache::loncreatecourse::rewritefile( - &Apache::loncreatecourse::readfile($env{'request.course.id'},$_), + print $fh &Apache::lonclonecourse::rewritefile( + &Apache::lonclonecourse::readfile($env{'request.course.id'},$_), (%replacehash,$crs => '') ); } else { print $fh - &Apache::loncreatecourse::readfile($env{'request.course.id'},$_); + &Apache::lonclonecourse::readfile($env{'request.course.id'},$_); } $fh->close(); } else { $fail=1; } if ($fail) { - $r->print('fail'); + $r->print(''.&mt('fail').''); } else { - $r->print('ok'); + $r->print(''.&mt('ok').''); } } } else { @@ -230,12 +231,11 @@ sub dumpcourse { $r->print('

'.&mt('Folder in Construction Space').'


'); &tiehash(); $r->print('

'.&mt('Filenames in Construction Space').'

'); - foreach (&Apache::loncreatecourse::crsdirlist($origcrsid,'userfiles')) { + foreach (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) { $r->print(''); my ($ext)=($_=~/\.(\w+)$/); my $title=$hash{'title_'.$hash{ 'ids_/uploaded/'.$origcrsdata{'domain'}.'/'.$origcrsdata{'num'}.'/'.$_}}; - $title=~s/:/:/g; $r->print(''); if (!$title) { $title=$_; @@ -258,10 +258,10 @@ sub dumpcourse { sub exportbutton { my $type = &Apache::loncommon::course_type(); - return '
'.&mt('Internal Filename').''.&mt('Title').''.&mt('Save as ...').'
'.$_.''.($title?$title:' ').''. + return '
'. ''. - &Apache::loncommon::help_open_topic('Docs_Export_Course_Docs'); + &Apache::loncommon::help_open_topic('Docs_Export_Course_Docs').'
'; } sub exportcourse { @@ -316,6 +316,7 @@ sub exportcourse { } } $r->print(&Apache::loncommon::start_page('Export '.lc($type).' to IMS content package')); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Export '.lc($type).' to IMS content package')); $r->print($outcome); $r->print(&Apache::loncommon::end_page()); } else { @@ -365,7 +366,7 @@ sub exportcourse { if (ref($curRes)) { my $symb = $curRes->symb(); my $ressymb = $symb; - if ($ressymb =~ m|adm/(\w+)/(\w+)/(\d+)/bulletinboard$|) { + 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'; } @@ -379,7 +380,7 @@ sub exportcourse { } $display .= ' />'."\n"; for (my $i=0; $i<$depth; $i++) { - $display .= ''."\n"; + $display .= ''."\n"; } if ($curRes->is_sequence()) { $display .= ' '."\n"; @@ -457,6 +458,7 @@ function containerCheck(item) { |; $r->print(&Apache::loncommon::start_page('Export '.lc($type).' to IMS content package', $scripttag)); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Export '.lc($type).' to IMS content package')); $r->print($display.'
'. '

'. '$url.$cpinfo, - 'title'=>&unescape($foldername), + 'title'=>$name, 'text'=>''. - &unescape($foldername).'' + $name.'', + 'no_mt'=>1, }); - - + $plain.=$name.' > '; + } + $plain=~s/\>\;\s*$//; + return (&Apache::lonhtmlcommon::breadcrumbs(undef,undef,0,'nohelp', + 'LC_docs_path'),$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); } } - return &Apache::lonhtmlcommon::breadcrumbs(undef,undef,0,'nohelp', - 'LC_docs_path'); } -sub editor { - my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output)=@_; - my $errtext=''; - my $fatal=0; - my $container='sequence'; - if ($env{'form.pagepath'}) { - $container='page'; - } - ($errtext,$fatal)= - &mapread($coursenum,$coursedom,$folder.'.'.$container); - if ($#Apache::lonratedt::order<1) { - my $idx=&Apache::lonratedt::getresidx(); - if ($idx<=0) { $idx=1; } - $Apache::lonratedt::order[0]=$idx; - $Apache::lonratedt::resources[$idx]=''; + +# +# Docs Change Log +# +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(''. + ''); + + my %saveable_parameters = ('show' => 'scalar',); + &Apache::loncommon::store_course_settings('docs_log', + \%saveable_parameters); + &Apache::loncommon::restore_course_settings('docs_log', + \%saveable_parameters); + if (!$env{'form.show'}) { $env{'form.show'}=10; } + my %lt=('hiddenresource' => 'Resources hidden', + 'encrypturl' => 'URL hidden', + 'randompick' => 'Randomly pick', + 'randomorder' => 'Randomly ordered', + 'set' => 'set to', + 'del' => 'deleted'); + $r->print(&Apache::loncommon::display_filter(). + ''. + '

'); + $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(''.$time.' + '.$about_me_link. + '
'.$docslog{$id}{'exe_uname'}. + ':'.$docslog{$id}{'exe_udom'}.''. + $send_msg_link.''. + $docslog{$id}{'logentry'}{'folder'}.''); +# 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(''); +# After + $r->print(''); + + 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 '' && $oldname ne $newname) { + $r->print(&LONCAPA::map::qtescape($newname)); + } + } + $r->print(''); + if ($docslog{$id}{'logentry'}{'parameter_res'}) { + $r->print(&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'}))[0]).':'); + } +# End + $r->print(''.&Apache::loncommon::end_data_table_row()); + $shown++; + if (!($env{'form.show'} eq &mt('all') + || $shown<=$env{'form.show'})) { last; } } - if (defined($env{'form.markcopy'})) { + $r->print(&Apache::loncommon::end_data_table()); +} + +sub update_paste_buffer { + my ($coursenum,$coursedom) = @_; + + return if (!defined($env{'form.markcopy'})); + return if (!defined($env{'form.copyfolder'})); + return if ($env{'form.markcopy'} < 0); + + my ($errtext,$fatal) = &mapread($coursenum,$coursedom, + $env{'form.copyfolder'}); + + return if ($fatal); + # Mark for copying - my ($title,$url)=split(':',$Apache::lonratedt::resources[$Apache::lonratedt::order[$env{'form.markcopy'}]]); - $env{'form.markedcopy_title'}=$title; - $env{'form.markedcopy_url'}=$url; - } - $r->print(&breadcrumbs($folder)); - if ($fatal) { - $r->print('

'.$errtext.'

'); + my ($title,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$env{'form.markcopy'}]]); + if (&is_supplemental_title($title)) { + ($title) = &parse_supplemental_title($title); + } + $url=~s{http(:|:)//https(:|:)//}{https$2//}; + + &Apache::lonnet::appenv('docs.markedcopy_title' => $title, + 'docs.markedcopy_url' => $url); + delete($env{'form.markcopy'}); +} + +sub print_paste_buffer { + my ($r,$container) = @_; + return if (!defined($env{'docs.markedcopy_url'})); + + $r->print(<

+ENDPASTE + $r->print(' '); + + my $type; + if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) { + $type = &mt('External Resource'); + $r->print($type.': '. + &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('. + &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')'); + } else { + my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1]; + my $type = &Apache::loncommon::filedescription($extension); + my $icon = ''; + $r->print($icon.$type.': '. &parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}))); + } + if ($container eq 'page') { + $r->print(' + + +'); + } else { + $r->print(' + +'); + } + $r->print('

'); +} + +sub do_paste_from_buffer { + my ($coursenum,$coursedom) = @_; + + return 0 if (!$env{'form.pastemarked'}); + +# paste resource to end of list + my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url'}); + my $title=&LONCAPA::map::qtescape($env{'docs.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+/$match_domain/$match_username/}{}; + &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn, + &Apache::lonnet::getfile($url)); + $url = $newurl; + } +# published maps can only exists once, so remove it from paste buffer when done + if (($url=~/\.(page|sequence)$/) && ($url=~m {^/res/})) { + &Apache::lonnet::delenv('docs\\.markedcopy'); + } + if ($url=~ m{/smppg$}) { + my $db_name = &Apache::lonsimplepage::get_db_name($url); + if ($db_name =~ /^smppage_/) { + #simple pages, need to copy the db contents to a new one. + my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum); + my $now = time(); + $db_name =~ s{_\d*$ }{_$now}x; + my $result=&Apache::lonnet::put($db_name,\%contents, + $coursedom,$coursenum); + $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x; + $title=&mt('Copy of').' '.$title; + } + } + $title = &LONCAPA::map::qtunescape($title); + my $ext='false'; + if ($url=~m{^http(|s)://}) { $ext='true'; } + $url = &LONCAPA::map::qtunescape($url); +# Now insert the URL at the bottom + my $newidx = &LONCAPA::map::getresidx($url); + $LONCAPA::map::resources[$newidx]= $title.':'.$url.':'.$ext.':normal:res'; + push(@LONCAPA::map::order, $newidx); +# Store the result +} + +my %parameter_type = ( 'randompick' => 'int_pos', + 'hiddenresource' => 'string_yesno', + 'encrypturl' => 'string_yesno', + 'randomorder' => 'string_yesno',); +my $valid_parameters_re = join('|',keys(%parameter_type)); +# set parameters +sub update_parameter { + + return 0 if ($env{'form.changeparms'} !~ /^($valid_parameters_re)$/); + + my $which = $env{'form.changeparms'}; + my $idx = $env{'form.setparms'}; + if ($env{'form.'.$which.'_'.$idx}) { + my $value = ($which eq 'randompick') ? $env{'form.'.$which.'_'.$idx} + : 'yes'; + &LONCAPA::map::storeparameter($idx, 'parameter_'.$which, $value, + $parameter_type{$which}); + &remember_parms($idx,$which,'set',$value); } else { + &LONCAPA::map::delparameter($idx,'parameter_'.$which); + + &remember_parms($idx,$which,'del'); + } + return 1; +} + + +sub handle_edit_cmd { + my ($coursenum,$coursedom) =@_; + + my ($cmd,$idx)=split('_',$env{'form.cmd'}); + + my $ratstr = $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]; + my ($title, $url, @rrest) = split(':', $ratstr); + + if ($cmd eq 'del') { + 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 { + &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]); + } + splice(@LONCAPA::map::order, $idx, 1); + + } elsif ($cmd eq 'cut') { + &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]); + splice(@LONCAPA::map::order, $idx, 1); + + } elsif ($cmd eq 'up' + && ($idx) && (defined($LONCAPA::map::order[$idx-1]))) { + @LONCAPA::map::order[$idx-1,$idx] = @LONCAPA::map::order[$idx,$idx-1]; + + } elsif ($cmd eq 'down' + && defined($LONCAPA::map::order[$idx+1])) { + @LONCAPA::map::order[$idx+1,$idx] = @LONCAPA::map::order[$idx,$idx+1]; + + } elsif ($cmd eq 'rename') { + + my $comment = &LONCAPA::map::qtunescape($env{'form.title'}); + if ($comment=~/\S/) { + $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]= + $comment.':'.join(':', $url, @rrest); + } +# Devalidate title cache + my $renamed_url=&LONCAPA::map::qtescape($url); + &Apache::lonnet::devalidate_title_cache($renamed_url); + } else { + return 0; + } + return 1; +} + +sub editor { + my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output,$which)=@_; + + my $container= ($env{'form.pagepath'}) ? 'page' + : 'sequence'; + + 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]=''; + } + + my ($breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain,$is_random_order)= + &breadcrumbs($folder); + $r->print($breadcrumbtrail); + # ------------------------------------------------------------ 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); + } + + if ($env{'form.pastemarked'}) { + &do_paste_from_buffer($coursenum,$coursedom); + ($errtext,$fatal) = &storemap($coursenum,$coursedom,$folder.'.'.$container); + return $errtext if ($fatal); + } + + $r->print($upload_output); - ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container); - if ($fatal) { - $r->print('

'.$errtext.'

'); - return; + if (&handle_edit_cmd()) { + ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container); + return $errtext if ($fatal); + } +# Group import/search + if ($env{'form.importdetail'}) { + my @imports; + foreach (split(/\&/,$env{'form.importdetail'})) { + if (defined($_)) { + my ($name,$url,$residx)= + map {&unescape($_)} split(/\=/,$_); + push(@imports, [$name, $url, $residx]); } - } - 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; - 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; + ($errtext,$fatal)=&group_import($coursenum, $coursedom, $folder, + $container,'londocs',@imports); + return $errtext if ($fatal); + } +# Loading a complete map + if ($env{'form.loadmap'}) { + if ($env{'form.importmap'}=~/\w/) { + foreach my $res (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$env{'form.importmap'}))) { + my ($title,$url,$ext,$type)=split(/\:/,$res); + my $idx=&LONCAPA::map::getresidx($url); + $LONCAPA::map::resources[$idx]=$res; + $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx; } - - } - $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; - if ($comment=~/\S/) { - $Apache::lonratedt::resources[ - $Apache::lonratedt::order[$idx]]= - $comment.':'.join(':',@rrest); - } -# Devalidate title cache - &Apache::lonnet::devalidate_title_cache(&unescape($rrest[0])); - } -# Store the changed version ($errtext,$fatal)=&storemap($coursenum,$coursedom, $folder.'.'.$container); - if ($fatal) { - $r->print('

'.$errtext.'

'); - return; - } - } -# Group import/search - if ($env{'form.importdetail'}) { - my @imports; - &Apache::lonnet::logthis("imp detail ".$env{'form.importdetail'}); - 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; - } - } -# 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(''); - foreach (@Apache::lonratedt::order) { - my ($name,$url)=split(/\:/,$Apache::lonratedt::resources[$_]); - $name=&Apache::lonratsrv::qtescape($name); - $url=&Apache::lonratsrv::qtescape($url); - unless ($name) { $name=(split(/\//,$url))[-1]; } - unless ($name) { $idx++; next; } - $r->print(&entryline($idx,$name,$url,$folder,$allowed,$_,$coursenum)); - $idx++; - $shown++; - } - unless ($shown) { - $r->print(''); - } - $r->print("\n
'.&mt('Currently no documents.').'
\n"); - if ($env{'form.markedcopy_url'}) { - $r->print(<
- - -ENDPASTE - $r->print( - ' '.&Apache::loncommon::filedescription( - (split(/\./,$env{'form.markedcopy_url'}))[-1]).': '. - $env{'form.markedcopy_title'}); - if ($container eq 'page') { - $r->print(< - -PAGEINFO - } else { - $r->print(< -FOLDERINFO + return $errtext if ($fatal); + } else { + $r->print('

'.&mt('No map selected.').'

'); + } - $r->print('

'); } + &log_differences($plain); } +# ---------------------------------------------------------------- End commands +# ---------------------------------------------------------------- Print screen + my $idx=0; + my $shown=0; + if (($ishidden) || ($isencrypted) || ($randompick>=0) || ($is_random_order)) { + $r->print('

'.&mt('Parameters').':

    '. + ($randompick>=0?'
  • '.&mt('randomly pick [_1] resources',$randompick).'
  • ':''). + ($ishidden?'
  • '.&mt('contents hidden').'
  • ':''). + ($isencrypted?'
  • '.&mt('URLs hidden').'
  • ':''). + '

'); + } + 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.').'

'); + } + if ($is_random_order) { + $r->print('

'.&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.').'

'); + } + $r->print(''); + foreach my $res (@LONCAPA::map::order) { + my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]); + $name=&LONCAPA::map::qtescape($name); + $url=&LONCAPA::map::qtescape($url); + unless ($name) { $name=(split(/\//,$url))[-1]; } + unless ($name) { $idx++; next; } + $r->print(&entryline($idx,$name,$url,$folder,$allowed,$res, + $coursenum)); + $idx++; + $shown++; + } + unless ($shown) { + $r->print(''); + } + $r->print("\n
'.&mt('Currently no documents.').'
\n"); + + &print_paste_buffer($r,$container); + return; } sub process_file_upload { @@ -1282,9 +1511,9 @@ sub process_file_upload { } ($errtext,$fatal)= &mapread($coursenum,$coursedom,$folder.'.'.$container); - if ($#Apache::lonratedt::order<1) { - $Apache::lonratedt::order[0]=1; - $Apache::lonratedt::resources[1]=''; + if ($#LONCAPA::map::order<1) { + $LONCAPA::map::order[0]=1; + $LONCAPA::map::resources[1]=''; } if ($fatal) { return 'failed'; @@ -1300,68 +1529,46 @@ sub process_file_upload { } # 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(); + my $newidx=&LONCAPA::map::getresidx(); $destination .= $newidx; my $url=&Apache::lonnet::userfileupload('uploaddoc',1,$destination, $parseaction,$allfiles, $codebase); my $ext='false'; - if ($url=~/^http\:\/\//) { $ext='true'; } - $url=~s/\:/\:/g; + if ($url=~m{^http://}) { $ext='true'; } + $url = &LONCAPA::map::qtunescape($url); my $comment=$env{'form.comment'}; - $comment=~s/\/\>\;/g; - $comment=~s/\:/\:/g; + $comment = &LONCAPA::map::qtunescape($comment); if ($folder=~/^supplemental/) { $comment=time.'___&&&___'.$env{'user.name'}.'___&&&___'. $env{'user.domain'}.'___&&&___'.$comment; } - $Apache::lonratedt::resources[$newidx]= - $comment.':'.$url.':'.$ext.':normal:res'; - $Apache::lonratedt::order[$#Apache::lonratedt::order+1]= $newidx; + $LONCAPA::map::resources[$newidx]= + $comment.':'.$url.':'.$ext.':normal:res'; + $LONCAPA::map::order[$#LONCAPA::map::order+1]= $newidx; ($errtext,$fatal)=&storemap($coursenum,$coursedom, $folder.'.'.$container); if ($fatal) { - $$upload_output .= '

'.$errtext.'

'; + $$upload_output .= '

'.$errtext.'

'; return 'failed'; } else { if ($parseaction eq 'parse') { my $total_embedded = 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.
-
- + my $state = ' + + '; - $$upload_output .= 'Upload embedded files:
- '; - foreach my $embed_file (keys(%{$allfiles})) { - $$upload_output .= ''; - $num ++; - } - $phase_status = 'phasetwo'; - $$upload_output .= '
'.$embed_file. - ' - '; - my $attrib; - if (@{$$allfiles{$embed_file}} > 1) { - $attrib = join(':',@{$$allfiles{$embed_file}}); - } else { - $attrib = $$allfiles{$embed_file}[0]; - } - $$upload_output .= - ''; - if (exists($$codebase{$embed_file})) { - $$upload_output .= - ''; - } - $$upload_output .= '

- -
'; + $phase_status = 'phasetwo'; + + $$upload_output .= + 'This file contains embedded multimedia objects, which need to be uploaded to LON-CAPA.
'. + &ask_for_embedded_content('/adm/coursedocs', + $state,$allfiles,$codebase); } else { $$upload_output .= 'No embedded items identified
'; } @@ -1371,6 +1578,55 @@ sub process_file_upload { return $phase_status; } +sub ask_for_embedded_content { + my ($actionurl,$state,$allfiles,$codebase,$args)=@_; + my $upload_output = ' +
'; + $upload_output .= $state; + $upload_output .= 'Upload embedded files:
'. + &Apache::loncommon::start_data_table(); + + my $num = 0; + foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%{$allfiles})) { + $upload_output .= &Apache::loncommon::start_data_table_row(). + ''.$embed_file.''; + if ($args->{'ignore_remote_references'} + && $embed_file =~ m{^\w+://}) { + $upload_output.=''.&mt("URL points to other server.").''; + } elsif ($args->{'error_on_invalid_names'} + && $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) { + + $upload_output.=''.&mt("Invalid characters").''; + + } else { + + $upload_output .=' + + '; + my $attrib = join(':',@{$$allfiles{$embed_file}}); + $upload_output .= + "\n\t\t". + ''; + if (exists($$codebase{$embed_file})) { + $upload_output .= + "\n\t\t". + ''; + } + } + $upload_output .= ''.&Apache::loncommon::end_data_table_row(); + $num++; + } + $upload_output .= &Apache::loncommon::end_data_table().'
+ + + '.&mt('(only files for which a location has been provided will be uploaded)').' +
'; + return $upload_output; +} + sub process_secondary_uploads { my ($upload_output,$coursedom,$coursenum,$formname,$num,$newidx) = @_; my $folder=$env{'form.folder'}; @@ -1386,67 +1642,92 @@ sub process_secondary_uploads { $destination .= $newidx; my ($url,$filename); $url=&Apache::lonnet::userfileupload($formname.$num,1,$destination); - ($filename) = ($url =~ m-^/uploaded/$coursedom/$coursenum/$destination/(.+)$-); + ($filename) = ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/\Q$destination\E/(.+)$}); return $filename; } +sub is_supplemental_title { + my ($title) = @_; + return scalar($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/); +} + +sub parse_supplemental_title { + my ($title) = @_; + + my ($foldertitle,$renametitle); + if ($title =~ /&&&/) { + $title = &HTML::Entites::decode($title); + } + if ($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/) { + $renametitle=$4; + my ($time,$uname,$udom) = ($1,$2,$3); + $foldertitle=&Apache::lontexconvert::msgtexconverted($4); + my $name = &Apache::loncommon::plainname($uname,$udom); + $name = &HTML::Entities::encode($name,'"<>&\''); + $title=''.&Apache::lonlocal::locallocaltime($time).' '. + $name.':
'.$foldertitle; + } + if (wantarray) { + return ($title,$foldertitle,$renametitle); + } + return $title; +} + # --------------------------------------------------------------- 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 ($foldertitle,$pagetitle,$renametitle); + if (&is_supplemental_title($title)) { + ($title,$foldertitle,$renametitle) = &parse_supplemental_title($title); + $pagetitle = $foldertitle; + } else { + $title=&HTML::Entities::encode($title,'"<>&\''); + $renametitle=$title; + $foldertitle=$title; + $pagetitle=$title; } + + my $orderidx=$LONCAPA::map::order[$index]; + + $renametitle=~s/\\/\\\\/g; $renametitle=~s/\"\;/\\\"/g; + $renametitle=~s/ /%20/g; my $line=''; + my ($form_start,$form_end); # Edit commands - my $container; - my $folderpath; + my ($container, $type, $esc_path, $path, $symb); if ($env{'form.folderpath'}) { + $type = 'folder'; $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'}); + $type = $container = 'page'; + $esc_path=&escape($path = $env{'form.pagepath'}); + $path = &HTML::Entities::encode($env{'form.pagepath'},'<>&"'); + $symb=&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'}); - } if ($allowed) { my $incindex=$index+1; my $selectbox=''; if (($folder!~/^supplemental/) && - ($#Apache::lonratedt::order>0) && + ($#LONCAPA::map::order>0) && ((split(/\:/, - $Apache::lonratedt::resources[$Apache::lonratedt::order[0]]))[1] + $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= ''. ' - - - - - - - -
- -$lt{
- -$lt{
-$selectbox - - -$lt{'rm'} - -$lt{'ct'} - -$lt{'rn'} -$copylink + } + if (!$nocut) { + $cutlink=(<$lt{'ct'} +ENDCUT + } + $form_start = (< + + + + END - } else { - unless ($nocopy) { - $copylink=(< -$lt{'cp'} -ENDCOPY - } - $line.=(< - - - - - - - -
- -$lt{
- -$lt{
-$selectbox - - -$lt{'rm'} - -$lt{'ct'} - -$lt{'rn'} + $form_end = ''; + $line.=(< + + + + + + + +
+ $lt{ +
+ $lt{ +
+ + + $form_start + $selectbox + $form_end + + + $lt{'rm'} +$cutlink + $lt{'rn'} $copylink + END - } + } # Figure out what kind of a resource this is my ($extension)=($url=~/\.(\w+)$/); @@ -1550,13 +1837,13 @@ END if ($uploaded) { if ($extension eq 'sequence') { $icon=$iconpath.'/folder_closed.gif'; - $url=~/$coursenum\/([\/\w]+)\.sequence$/; + $url=~/\Q$coursenum\E\/([\/\w]+)\.sequence$/; $url='/adm/coursedocs?'; $folderarg=$1; $isfolder=1; } elsif ($extension eq 'page') { $icon=$iconpath.'/page.gif'; - $url=~/$coursenum\/([\/\w]+)\.page$/; + $url=~/\Q$coursenum\E\/([\/\w]+)\.page$/; $pagearg=$1; $url='/adm/coursedocs?'; $ispage=1; @@ -1564,7 +1851,9 @@ END &Apache::lonnet::allowuploaded('/adm/coursedoc',$url); } } - $url=~s-^http(\&colon\;|:)//-/adm/wrapper/ext/-; + + my $orig_url = $url; + my $external = ($url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/}); if ((!$isfolder) && ($residx) && ($folder!~/supplemental/) && (!$ispage)) { my $symb=&Apache::lonnet::symbclean( &Apache::lonnet::declutter('uploaded/'. @@ -1587,8 +1876,13 @@ END } } elsif ($url=~m|^/ext/|) { $url='/adm/wrapper'.$url; + $external = 1; } - $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); + if (&Apache::lonnet::symbverify($symb,$url)) { + $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); + } else { + $url=''; + } if ($container eq 'page') { my $symb=$env{'form.pagesymb'}; @@ -1596,20 +1890,32 @@ END $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); } } - my $parameterset=' '; + my ($parameterset,$rand_order_text) = (' ', ' '); if ($isfolder || $extension eq 'sequence') { my $foldername=&escape($foldertitle); my $folderpath=$env{'form.folderpath'}; if ($folderpath) { $folderpath.='&' }; - $folderpath.=$folderarg.'&'.$foldername; +# Append randompick number, hidden, and encrypted with ":" to foldername, +# so it gets transferred between levels + $folderpath.=$folderarg.'&'.$foldername.':'.(&LONCAPA::map::getparameter($orderidx, + 'parameter_randompick'))[0] + .':'.((&LONCAPA::map::getparameter($orderidx, + 'parameter_hiddenresource'))[0]=~/^yes$/i) + .':'.((&LONCAPA::map::getparameter($orderidx, + 'parameter_encrypturl'))[0]=~/^yes$/i) + .':'.((&LONCAPA::map::getparameter($orderidx, + 'parameter_randomorder'))[0]=~/^yes$/i); $url.='folderpath='.&escape($folderpath).$cpinfo; $parameterset=''; - +''.&mt('Save').''; + my $ro_set= + ((&LONCAPA::map::getparameter($orderidx,'parameter_randomorder'))[0]=~/^yes$/i?' checked="checked"':''); + $rand_order_text =' +'; } if ($ispage) { my $pagename=&escape($pagetitle); @@ -1627,28 +1933,45 @@ END $path.$pagearg.'.page'); } $url.='pagepath='.&escape($pagepath). - '&pagesymb='.&escape($symb).$cpinfo; + '&pagesymb='.&escape($symb).$cpinfo; } - $line.=''. - "$title"; + if ($external) { + my $form = ($folder =~ /^default/)? 'newext' : 'supnewext'; + $external = ' '.&mt('Edit').''; + } else { + undef($external); + } + $line.=' + + '.($url?'':'').''.($url?'':'').' + + + '.($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= - ((&Apache::lonratedt::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i?' checked="1"':''); + ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i?' checked="1"':''); my $hidtext= - ((&Apache::lonratedt::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i?' checked="1"':''); + ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i?' checked="1"':''); $line.=(< - - - -$parameterset + + $form_start + + $form_end + + + $form_start + + $form_end + + $form_start $rand_order_text $form_end + $form_start $parameterset $form_end ENDPARMS } - $line.=""; + $line.=""; return $line; } @@ -1714,17 +2037,17 @@ sub checkonthis { if (($errorcount) || ($warningcount)) { if ($errorcount) { - $r->print(''. + $r->print(''. $errorcount.' '. - &mt('error(s)').' '); + &mt('error(s)').' '); } if ($warningcount) { - $r->print(''. + $r->print(''. $warningcount.' '. - &mt('warning(s)').''); + &mt('warning(s)').''); } } else { - $r->print(''.&mt('ok').''); + $r->print(''.&mt('ok').''); } $r->rflush(); } @@ -1736,15 +2059,15 @@ sub checkonthis { } } } 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').''); } } } @@ -1758,6 +2081,7 @@ sub list_symbs { my ($r) = @_; $r->print(&Apache::loncommon::start_page('Symb List')); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Symb List')); my $navmap = Apache::lonnavmaps::navmap->new(); $r->print("
\n");
     foreach my $res ($navmap->retrieveResources()) {
@@ -1777,6 +2101,7 @@ sub verifycontent {
    my $loaderror=&Apache::lonnet::overloaderror($r);
    if ($loaderror) { return $loaderror; }
    $r->print(&Apache::loncommon::start_page('Verify '.$type.' Documents'));
+   $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$type.' Documents'));
    $hashtied=0;
    undef %alreadyseen;
    %alreadyseen=();
@@ -1784,9 +2109,9 @@ sub verifycontent {
    foreach (keys %hash) {
        if ($hash{$_}=~/\.(page|sequence)$/) {
 	   if (($_=~/^src_/) && ($alreadyseen{&unescape($hash{$_})})) {
-	       $r->print('
'. + $r->print('
'. &mt('The following sequence or page is included more than once in your '.$type.': '). - &unescape($hash{$_}).'

'. + &unescape($hash{$_}).'
'. &mt('Note that grading records for problems included in this sequence or folder will overlap.
')); } } @@ -1812,6 +2137,7 @@ sub checkversions { 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=''; @@ -1863,9 +2189,9 @@ sub checkversions { 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').'

'); + $r->print('

'.&mt('Your Version Settings have been Saved').'

'); } else { - $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').'

'); } &mark_hash_old(); } @@ -1972,10 +2298,10 @@ ENDHEADERS 'lastrevisiondate') ). ''. - 'Most Recent: '. + 'Most Recent: '. ''.$currentversion.''. - ''. - 'In '.$type.': '. + ''. + 'In '.$type.': '. ''); # Used in course my $usedversion=$hash{'version_'.$linkurl}; @@ -1984,8 +2310,8 @@ ENDHEADERS } else { $r->print($currentversion); } - $r->print(''. - 'Use: '); + $r->print('
'. + 'Use: '); # Set version $r->print(&Apache::loncommon::select_form($setversions{$linkurl}, 'set_version_'.$linkurl, @@ -1994,7 +2320,7 @@ ENDHEADERS '' => '', 'mostrecent' => 'most recent', map {$_,$_} (1..$currentversion)))); - $r->print(''); + $r->print(''); my $lastold=1; for (my $prevvers=1;$prevvers<$currentversion;$prevvers++) { my $url=$root.'.'.$prevvers.'.'.$extension; @@ -2018,7 +2344,7 @@ ENDHEADERS 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, @@ -2031,7 +2357,7 @@ ENDHEADERS '&versionone='.$prevvers. '">'.&mt('Diffs').''); } - $r->print('
'); + $r->print('
'); if (++$entries_count % $entries_per_col == 0) { $r->print(''); if ($cols_output != 4) { @@ -2093,14 +2419,30 @@ sub changewarning { $message='Changes will become active for your current session after [_1], or the next time you log in.'; } $r->print("\n\n". -''."\n". +''."\n". '
'. '

'. +'" />

'. &mt($message,' '). -$help{'Caching'}.'

'."\n\n"); +$help{'Caching'}.'

'."\n\n"); +} + +# =========================================== Breadcrumbs for special functions + +sub init_breadcrumbs { + my ($form,$text)=@_; + &Apache::lonhtmlcommon::clear_breadcrumbs(); + &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs", + text=>&Apache::loncommon::course_type()." Documents", + 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'}); } # ================================================================ Main Handler @@ -2131,20 +2473,28 @@ sub handler { 'Docs_About_Bulletin_Board,Docs_Editing_Templated_Pages'); $help{'My Personal Info'} = &Apache::loncommon::help_open_topic( 'Docs_About_My_Personal_Info,Docs_Editing_Templated_Pages'); + $help{'Group Files'} = &Apache::loncommon::help_open_topic('Docs_About_Group_Files'); $help{'Caching'} = &Apache::loncommon::help_open_topic('Caching'); # 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 ($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().' DOCS to Construction Space'); &dumpcourse($r); } elsif ($allowed && $env{'form.exportcourse'}) { + &init_breadcrumbs('exportcourse','Export '.&Apache::loncommon::course_type().' to IMS'); &exportcourse($r); } else { # is this a standard course? @@ -2158,8 +2508,7 @@ sub handler { my $uploadtag; &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['folderpath','pagepath', - 'pagesymb','markedcopy_url', - 'markedcopy_title']); + 'pagesymb']); if ($env{'form.folderpath'}) { my (@folderpath)=split('&',$env{'form.folderpath'}); $env{'form.foldername'}=&unescape(pop(@folderpath)); @@ -2171,8 +2520,8 @@ sub handler { $env{'form.folder'}=pop(@pagepath); $containertag = ''. ''; - $uploadtag = ''. - ''; + $uploadtag = ''. + ''; } if ($r->uri=~/^\/adm\/coursedocs\/showdoc\/(.*)$/) { $showdoc='/'.$1; @@ -2199,8 +2548,7 @@ sub handler { # get personal data my $uname=$env{'user.name'}; my $udom=$env{'user.domain'}; - my $plainname=&escape( - &Apache::loncommon::plainname($uname,$udom)); + my $plainname=&escape(&Apache::loncommon::plainname($uname,$udom)); # graphics settings @@ -2219,7 +2567,8 @@ sub handler { my %codebase = (); my ($upload_result,$upload_output); if ($allowed) { - if (($env{'form.uploaddoc.filename'}) && ($env{'form.cmd'}=~/^upload_(\w+)/)) { + if (($env{'form.uploaddoc.filename'}) && + ($env{'form.cmd'}=~/^upload_(\w+)/)) { # Process file upload - phase one - upload and parse primary file. $upload_result = &process_file_upload(\$upload_output,$coursenum, $coursedom,\%allfiles, @@ -2324,6 +2673,8 @@ sub handler { 'scuf' => 'Score Upload Form', 'bull' => 'Bulletin Board', 'mypi' => 'My Personal Info', + 'grpo' => 'Group Files', + 'rost' => 'Course Roster', 'abou' => 'About User', 'imsf' => 'Import IMS package', 'file' => 'File', @@ -2333,12 +2684,14 @@ sub handler { ); # ----------------------------------------------------------------------------- if ($allowed) { + &update_paste_buffer($coursenum,$coursedom); my $dumpbut=&dumpbutton(); my $exportbut=&exportbutton(); my %lt=&Apache::lonlocal::texthash( 'vc' => 'Verify Content', 'cv' => 'Check/Set Resource Versions', 'ls' => 'List Symbs', + 'sl' => 'Show Log' ); my $folderpath=$env{'form.folderpath'}; @@ -2351,55 +2704,72 @@ sub handler { } unless ($env{'form.pagepath'}) { $containertag = ''; - $uploadtag = ''; + $uploadtag = ''; } $r->print(< - - - -$containertag + + + + + $containertag
- -$uploadtag + + $uploadtag
- -
-$help{'Verify_Content'} - - $help{'Check_Resource_Versions'} -$dumpbut -$exportbut - - -
+
+ +
+ $help{'Verify_Content'} +
+
+ $help{'Check_Resource_Versions'} +
+ $dumpbut + $exportbut +
+ +
+
+ + +
+
+
 
ENDCOURSEVERIFY $r->print(&Apache::loncommon::help_open_topic('Docs_Adding_Course_Doc', &mt('Editing the Table of Contents for your '.$type))); } # --------------------------------------------------------- Standard documents - $r->print(''); + $r->print('
'); + if (($standard) && ($allowed) && (!$forcesupplement)) { - $r->print(' - - - +
'); + $r->print('
'); # '

'.&mt('Main Course Documents'). # ($allowed?' '.$help{'Main_Course_Documents'}:'').'

'); my $folder=$env{'form.folder'}; if ($folder eq '' || $folder eq 'supplemental') { $folder='default'; $env{'form.folderpath'}='default&'.&escape(&mt('Main '.$type.' Documents')); + $uploadtag = ''; } my $postexec=''; if ($folder eq 'default') { - $r->print(''); + $r->print(''); } else { #$postexec='self.close();'; } $hadchanges=0; - &editor($r,$coursenum,$coursedom,$folder,$allowed,$upload_output); + my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed, + $upload_output); + if ($error) { + $r->print('

'.$error.'

'); + } if ($hadchanges) { &mark_hash_old() } @@ -2414,54 +2784,56 @@ ENDCOURSEVERIFY } my $readfile='/uploaded/'.$coursedom.'/'.$coursenum.'/'.$folder.'.'.$container; $r->print(<
$lt{'uplm'}$lt{'impp'}$lt{'spec'}
+ + + + - + - - - + my $folderseq= + '/uploaded/'.$coursedom.'/'.$coursenum.'/supplemental_'.time. + '.sequence'; + + my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); + $r->print(< + + - -
$lt{'uplm'}$lt{'impp'}$lt{'spec'}
+
$lt{'file'}:
- +
$lt{'title'}:
- + $uploadtag - +
- + - +

- - + + $help{'Uploading_From_Harddrive'} - +
+
$lt{'pubd'}
$uploadtag - +
- - + + $help{'Importing_LON-CAPA_Resource'} - +
- -

+


+

$lt{'copm'}
-
-
+ -$help{'Load_Map'}
+value="$lt{'selm'}" /> +$help{'Load_Map'}


@@ -2474,116 +2846,134 @@ ENDFORM
$uploadtag - - + + $help{'Adding_External_Resource'} - +

-
ENDFORM } - $r->print('
'); + $r->print(''); unless ($env{'form.pagepath'}) { + my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); $r->print(<
- - - + + + $help{'Adding_Folders'} - +

- - - + + + $help{'Adding_Pages'} - +

$uploadtag - - + + $help{'Syllabus'} - +

$uploadtag - - + + $help{'Navigate_Content'} - +

$uploadtag - - + + $help{'Simple Page'} - +

$uploadtag - - + + $help{'Simple Problem'} - +

$uploadtag - - + + - +

$uploadtag - - + + $help{'Score_Upload_Form'} - +

$uploadtag - - + + $help{'Bulletin Board'} - +

$uploadtag - - + + $help{'My Personal Info'} - +

$uploadtag - - + + - + +
+
+$uploadtag + + + +$help{'Group Files'} + +
+
+$uploadtag + + + +$help{'Course Roster'} +
ENDFORM } @@ -2591,20 +2981,20 @@ ENDFORM $r->print(< $uploadtag - - + + $help{'Simple Problem'} - +
$uploadtag - - + + $help{'Score_Upload_Form'} - +
ENDBLOCK } @@ -2614,7 +3004,7 @@ ENDBLOCK } # ----------------------------------------------------- Supplemental documents if (!$forcestandard) { - $r->print('
'); + $r->print('
'); # '

'.&mt('Supplemental Course Documents'). # ($allowed?' '.$help{'Supplemental'}:'').'

'); my $folder=$env{'form.folder'}; @@ -2626,93 +3016,103 @@ ENDBLOCK $env{'form.folderpath'}='supplemental&'. &escape(&mt('Supplemental '.$type.' Documents')); } - &editor($r,$coursenum,$coursedom,$folder,$allowed); + my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed); + if ($error) { + $r->print('

'.$error.'

'); + } if ($allowed) { - my $folderseq= - '/uploaded/'.$coursedom.'/'.$coursenum.'/supplemental_'.time. - '.sequence'; - - $r->print(<
$lt{'upls'}$lt{'spec'}
$lt{'upls'}$lt{'spec'}
+
- +

- + - +

$lt{'comment'}:

- - - - + + + + $help{'Uploading_From_Harddrive'} - +
+
- - - + + + $help{'Adding_Folders'} - +

- - - + + + $help{'Adding_External_Resource'} - +

- - - + + + $help{'Syllabus'} - +

- - - + + + $help{'My Personal Info'} - +
ENDSUPFORM } } + $r->print(''); if ($allowed) { - $r->print('
'); + $r->print(' +
+ + + + +
'); } - $r->print(''); } else { unless ($upload_result eq 'phasetwo') { # -------------------------------------------------------- This is showdoc mode $r->print("

".&mt('Uploaded Document').' - '. &Apache::lonnet::gettitle($r->uri).'

'. -&mt('It is recommended that you use an up-to-date virus scanner before handling this file.')."

". - &entryline(0,&mt("Click to download or use your browser's Save Link function"),$showdoc).'

'); +&mt('It is recommended that you use an up-to-date virus scanner before handling this file.')."

". + &entryline(0,&mt("Click to download or use your browser's Save Link function"),$showdoc).'
'); } } } @@ -2744,6 +3144,17 @@ function makenewpage(targetform,folderse function makenewext(targetname) { this.document.forms.extimport.useform.value=targetname; + this.document.forms.extimport.title.value=''; + this.document.forms.extimport.url.value=''; + this.document.forms.extimport.residx.value=''; + window.open('/adm/rat/extpickframe.html'); +} + +function edittext(targetname,residx,title,url) { + this.document.forms.extimport.useform.value=targetname; + this.document.forms.extimport.residx.value=residx; + this.document.forms.extimport.url.value=url; + this.document.forms.extimport.title.value=title; window.open('/adm/rat/extpickframe.html'); } @@ -2823,14 +3234,14 @@ function finishpick() { var title=this.document.forms.extimport.title.value; var url=this.document.forms.extimport.url.value; var form=this.document.forms.extimport.useform.value; - eval - ('this.document.forms.'+form+'.importdetail.value="'+title+'='+url+ - '";this.document.forms.'+form+'.submit();'); + var residx=this.document.forms.extimport.residx.value; + eval('this.document.forms.'+form+'.importdetail.value="'+title+'='+url+'='+residx+'";this.document.forms.'+form+'.submit();'); } function changename(folderpath,index,oldtitle,container,pagesymb) { var title=prompt('New Title',oldtitle); if (title) { + this.document.forms.renameform.markcopy.value=-1; this.document.forms.renameform.title.value=title; this.document.forms.renameform.cmd.value='rename_'+index; if (container == 'sequence') { @@ -2844,8 +3255,9 @@ function changename(folderpath,index,old } } -function removeres(folderpath,index,oldtitle,container,pagesymb) { - if (confirm('WARNING: Removing a resource makes associated grades and scores inaccessible!\\nRemove "'+oldtitle+'"?')) { +function removeres(folderpath,index,oldtitle,container,pagesymb,skip_confirm) { + if (skip_confirm || confirm('WARNING: Removing a resource makes associated grades and scores inaccessible!\\nRemove "'+oldtitle+'"?')) { + this.document.forms.renameform.markcopy.value=-1; this.document.forms.renameform.cmd.value='del_'+index; if (container == 'sequence') { this.document.forms.renameform.folderpath.value=folderpath; @@ -2858,10 +3270,11 @@ function removeres(folderpath,index,oldt } } -function cutres(folderpath,index,oldtitle,container,pagesymb) { - if (confirm('WARNING: Cutting a resource makes associated grades and scores inaccessible!\\nGrades remain inaccessible if resource is pasted into another folder.\\nCut "'+oldtitle+'"?')) { +function cutres(folderpath,index,oldtitle,container,pagesymb,folder,skip_confirm) { + if (skip_confirm || confirm('WARNING: Cutting a resource makes associated grades and scores inaccessible!\\nGrades remain inaccessible if resource is pasted into another folder.\\nCut "'+oldtitle+'"?')) { this.document.forms.renameform.cmd.value='cut_'+index; this.document.forms.renameform.markcopy.value=index; + this.document.forms.renameform.copyfolder.value=folder+'.'+container; if (container == 'sequence') { this.document.forms.renameform.folderpath.value=folderpath; } @@ -2873,8 +3286,9 @@ function cutres(folderpath,index,oldtitl } } -function markcopy(folderpath,index,oldtitle,container,pagesymb) { +function markcopy(folderpath,index,oldtitle,container,pagesymb,folder) { this.document.forms.renameform.markcopy.value=index; + this.document.forms.renameform.copyfolder.value=folder+'.'+container; if (container == 'sequence') { this.document.forms.renameform.folderpath.value=folderpath; }