--- loncom/interface/londocs.pm 2024/12/20 15:15:04 1.712 +++ loncom/interface/londocs.pm 2025/01/07 21:01:37 1.722 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.712 2024/12/20 15:15:04 raeburn Exp $ +# $Id: londocs.pm,v 1.722 2025/01/07 21:01:37 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -48,6 +48,7 @@ use Apache::lonpublisher(); use Apache::loncourserespicker(); use HTML::Entities; use HTML::TokeParser; +use HTML::LCParser; use GDBM_File; use File::MMagic; use File::Copy; @@ -578,7 +579,8 @@ $contents{webreferences}.' $title=~s/[\/\s]+/\_/gs; $title=&clean($title); my $formname = 'dumpdoc'; - my $preamble = &authorspace_selector($r,$formname,$home,$title,%outhash); + my $preamble = &authorspace_selector($r,$formname,$home,$title,%outhash). + '
'."\n"; my %uploadedfiles; &tiehash(); foreach my $file (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) { @@ -642,8 +644,8 @@ sub authorspace_selector { } $preamble .= '
'. '
'.&mt('Folder in Authoring Space').''. - ''."\n". - '
'."\n"; + ''."\n". + ''."\n"; return $preamble; } @@ -693,9 +695,70 @@ sub recurse_html { sub copycrsauthored { my ($r,$coursenum,$coursedom,$coursehome,$readonly) = @_; - my ($starthash,$js); + my ($starthash,$js,$title,$formname); + my %origcrsdata=&Apache::lonnet::coursedescription($env{'request.course.id'}); + $title=$origcrsdata{'description'}; + $title=~s/[\/\s]+/\_/gs; + $title=&clean($title); + my ($home,$other,%outhash)=&authorhosts(); unless (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) { - $js = <<"ENDJS"; + my %js_lt; + $formname = 'copycrsauthored'; + if ($home) { + %js_lt = + &Apache::lonlocal::texthash( + yomu => 'You must select an Authoring Space', + whco => 'When Copyright set to "custom", URL of a published rights file is needed.', + ); + &js_escape(\%js_lt); + } + if ($home > 1) { + $js = <<"ENDJS"; + + +ENDJS + } elsif ($home) { + $js = <<"ENDJS"; + + +ENDJS + } + $js .= <<"ENDJS"; ENDJS + + $js .= "\n".&Apache::lonhtmlcommon::scripttag(&Apache::loncommon::browser_and_searcher_javascript())."\n"; $starthash = { - add_entries => {'onload' => "hide_searching();"}, + add_entries => {'onload' => "hide_searching(); init_copycrs_form();"}, }; } $r->print(&Apache::loncommon::start_page('Copy from Course Authoring to User Authoring',$js,$starthash)."\n". &Apache::lonhtmlcommon::breadcrumbs('Copy from Course Authoring Space')."\n"); $r->print(&startContentScreen('tools')); - my ($home,$other,%outhash)=&authorhosts(); unless ($home) { $r->print('

'.&mt('No author or co-author roles on this server.').'

'); $r->print(&endContentScreen()); return ''; } - my %origcrsdata=&Apache::lonnet::coursedescription($env{'request.course.id'}); + my $docroot = $r->dir_config('lonDocRoot'); + my $is_course_home; + my @ids=&Apache::lonnet::current_machine_ids(); + if (($coursehome ne '') && (grep(/^\Q$coursehome\E$/,@ids))) { + $is_course_home = 1; + } my $exclude = &Apache::lonnet::priv_exclude(); my $srcurl = "/priv/$coursedom/$coursenum"; - my $srctop = $r->dir_config('lonDocRoot').$srcurl; + my $srctop = $docroot.$srcurl; + my $resurl = "/res/$coursedom/$coursenum"; + my $res_exclude = &Apache::lonnet::res_exclude(); if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) { $r->print('

'.&mt('Copying Files and/or Sub-directories').'

'); if ($readonly) { @@ -742,7 +824,8 @@ ENDJS } my ($ca,$cd)=split(/\:/,$env{'form.authorspace'}); my $desturl = "/priv/$cd/$ca"; - my $desttop = $r->dir_config('lonDocRoot').$desturl; + my $destresurl = "/res/$cd/$ca"; + my $desttop = $docroot.$desturl; my $subdir = &clean($env{'form.authorfolder'}); $subdir = &cleandir($subdir); if ($subdir eq '') { @@ -754,16 +837,11 @@ ENDJS &endContentScreen()); return ''; } - my $is_course_home; - my @ids=&Apache::lonnet::current_machine_ids(); - if (($coursehome ne '') && (grep(/^\Q$coursehome\E$/,@ids))) { - $is_course_home = 1; - } my (%tocopy,%dirs_to_make,%files_to_copy); map { $tocopy{&unescape($_)} = 1; } &Apache::loncommon::get_env_multiple('form.copytouser'); if (keys(%tocopy)) { my (%subdirs,%files); - &Apache::lonnet::recursedirs($home,1,undef,$exclude,0,0,$srcurl,'',\%subdirs,\%files); + &Apache::lonnet::recursedirs($is_course_home,1,undef,$exclude,0,0,$srcurl,'',\%subdirs,\%files); foreach my $possible (sort(keys(%tocopy))) { if ($possible =~ m{/$}) { my $possdir = $possible; @@ -804,112 +882,284 @@ ENDJS return ''; } if (keys(%tocopy)) { - my $mm = new File::MMagic; - my ($notopdir,%newdir,%newfile); + my (%resdirs,%resfiles); + &Apache::lonnet::recursedirs($is_course_home,1,undef,$res_exclude,0,0,$resurl,'',\%resdirs,\%resfiles); + my ($notopdir,%newdir,%newfile,%checkdeps,%newresfile); $r->print('

'.&mt('Copy to: [_1]', ''.$desturl.'/'.$subdir.''). '

'."\n"); - unless ($is_course_home) { - $r->print('

'. - &endContentScreen()); - return ''; - } if (keys(%dirs_to_make)) { - if ($is_course_home) { - unless (-e $desttop.'/'.$subdir) { - mkdir($desttop.'/'.$subdir,0755); - } - if (-e $desttop.'/'.$subdir) { - foreach my $dir (sort(keys(%dirs_to_make))) { - my @dirs=split(/\//,$dir); - my $path="$desttop/$subdir"; - my $makepath=$path; - my $fail; - for (my $i=0;$i<@dirs;$i++) { - $makepath.='/'.$dirs[$i]; - unless (-e $makepath) { - unless (mkdir($makepath,0755)) { - $fail = 1; - last; - } - if (($i == scalar(@dirs)-1) && (!$fail)) { - $newdir{$dir} = 1; - } + unless (-e $desttop.'/'.$subdir) { + mkdir($desttop.'/'.$subdir,0755); + } + if (-e $desttop.'/'.$subdir) { + foreach my $dir (sort(keys(%dirs_to_make))) { + my @dirs=split(/\//,$dir); + my $path="$desttop/$subdir"; + my $makepath=$path; + my $fail; + for (my $i=0;$i<@dirs;$i++) { + $makepath.='/'.$dirs[$i]; + unless (-e $makepath) { + unless (mkdir($makepath,0755)) { + $fail = 1; + last; + } + if (($i == scalar(@dirs)-1) && (!$fail)) { + $newdir{$dir} = 1; } - } - if ($fail) { - $r->print('

'.&mt('Target directory: [_1] does not exist, and could not be created.', - ''.$desturl.'/'.$subdir.'/'.$dir.''). - '

'."\n"); } } - } else { - $notopdir = 1; + if ($fail) { + $r->print('

'.&mt('Target directory: [_1] does not exist, and could not be created.', + ''.$desturl.'/'.$subdir.'/'.$dir.''). + '

'."\n"); + } } + } else { + $notopdir = 1; } } if (keys(%files_to_copy)) { - if ($is_course_home) { - unless (-e $desttop.'/'.$subdir) { - mkdir($desttop.'/'.$subdir,0755); - } - if (-e $desttop.'/'.$subdir) { - my $num = 0; - foreach my $file (keys(%files_to_copy)) { - my ($fail,$dup,$dir_is_file,$src,$dest,$path,$fname); - if ($file =~ m{/}) { - ($path,$fname) = ($file =~ m{^(.+)/([^/]+)$}); - if (-d "$desttop/$subdir/$path") { - if (-e "$desttop/$subdir/$path/$fname") { - $dup = 1; + unless (-e $desttop.'/'.$subdir) { + mkdir($desttop.'/'.$subdir,0755); + } + if (-e $desttop.'/'.$subdir) { + my $num = 0; + my ($copyright,$customdistfile); + if ($env{'form.copyright'} eq 'default' || $env{'form.copyright'} eq 'domain' || $env{'form.copyright'} eq 'public') { + $copyright = $env{'form.copyright'}; + } elsif ($env{'form.copyright'} eq 'custom') { + if ($env{'form.customrights'} =~ m{^/res/$match_domain/$match_username/.+\.rights$}) { + my ($rightsdom,$rightsuname) = ($1,$2); + my $rightshome = &Apache::lonnet::homeserver($rightsdom,$rightsuname); + if (($rightshome eq 'no_host') || ($rightshome eq '')) { + $copyright = 'default'; + } elsif (grep(/^\Q$rightshome\E$/,@ids)) { + if (-e $docroot.$env{'form.customrights'}) { + $copyright = 'custom'; + $customdistfile = $env{'form.customrights'}; + } else { + $copyright = 'default'; + } + } else { + my $rightsfile = &Apache::lonnet::filelocation('',$env{'form.customrights'}); + unless (&Apache::lonnet::getfile($rightsfile) eq '-1') { + $customdistfile = $env{'form.customrights'}; + } + } + } + } + my $sourceavail; + if ($env{'form.sourceavail'} =~ /^(open|closed)$/) { + $sourceavail = $env{'form.sourceavail'}; + } + my $respublish; + if ($env{'form.respublish'}) { + $respublish = 1; + } + my $nokeyref = &Apache::lonpublisher::getnokey($r->dir_config('lonIncludes')); + foreach my $file (keys(%files_to_copy)) { + my ($fail,$dup,$dir_is_file,$src,$dest,$path,$fname); + if ($file =~ m{/}) { + ($path,$fname) = ($file =~ m{^(.+)/([^/]+)$}); + if (-d "$desttop/$subdir/$path") { + if (-e "$desttop/$subdir/$path/$fname") { + $dup = 1; + } else { + $src = "$srctop/$path/$fname"; + $dest = "$desttop/$subdir/$path/$fname"; + } + } elsif (-f "$desttop/$subdir/$path") { + $dir_is_file = 1; + } else { + $fail = 1; + } + } elsif (-e "$desttop/$subdir/$file") { + $dup = 1; + } else { + $src = "$srctop/$file"; + $dest = "$desttop/$subdir/$file"; + $fname = $file; + } + if ($fail) { + $r->print('

'.&mt('Target directory: [_1] does not exist, and could not be created.', + ''.$desturl.'/'.$subdir.'/'.$path.''). + '

'."\n"); + } elsif ($dup) { + $r->print('

'.&mt('Target file: [_1] already exists -- not overwriting.', + ''.$desturl.'/'.$subdir.'/'.$file.''). + '

'."\n"); + } elsif ($dir_is_file) { + $r->print('

'.&mt('Target directory: [_1] name is already in a use for a file -- not overwriting.', + ''.$desturl.'/'.$subdir.'/'.$file.''). + '

'."\n"); + } elsif (($src ne '') && ($dest ne '')) { + my $ressrc = $docroot.$resurl.'/'.$file; + my $ressrcmeta = $ressrc.'.meta'; + my ($ext) = ($file =~ /\.(\w+)$/); + my $embstyle=&Apache::loncommon::fileembstyle($ext); + my ($getres,$getresmeta); + if ($respublish) { + if ($path eq '') { + if ((ref($resfiles{'/'}) eq 'HASH') && + (exists($resfiles{'/'}{$fname}))) { + $getres = 1; + $getresmeta = 1; + } + } elsif ((ref($resfiles{$path}) eq 'HASH') && + (exists($resfiles{$path}{$fname}))) { + $getres = 1; + $getresmeta = 1; + } + } + if ($is_course_home) { + my ($needpriv,$needprivmeta); + if ($respublish) { + if ($getres) { + if (&Apache::londiff::are_different_files($src,$ressrc)) { + $needpriv = 1; + if (&File::Copy::copy($ressrc,$dest)) { + if ($embstyle eq 'ssi') { + &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd); + } + } + } else { + if (&File::Copy::copy($src,$dest)) { + $newfile{$file} = $desturl.'/'.$subdir.'/'.$file; + if ($embstyle eq 'ssi') { + &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd,$subdir); + } + } + } } else { - $src = "$srctop/$path/$fname"; - $dest = "$desttop/$subdir/$path/$fname"; + $needpriv = 1; + } + if ($getresmeta) { + if ((-e $src.'.meta') && (!-e $dest.'.meta')) { + if (&Apache::londiff::are_different_files($src.'.meta',$ressrc.'.meta')) { + if (&File::Copy::copy($ressrc.'.meta',$dest.'.meta')) { + &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright, + $customdistfile,$sourceavail,\%checkdeps); + } + $needprivmeta = 1; + } else { + if (&File::Copy::copy($src.'.meta',$dest.'.meta')) { + &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright, + $customdistfile,$sourceavail,\%checkdeps); + } + } + } + } + if ($getres) { + my $destresfile = $docroot.$destresurl.'/'.$subdir.'/'.$file; + if (-e $dest) { + my $output = &Apache::lonpublisher::batchpublish($r,$dest,$destresfile,$nokeyref,1); + if (-e $destresfile) { + $newresfile{$file} = $destresurl.'/'.$subdir.'/'.$file; + } + } } - } elsif (-f "$desttop/$subdir/$path") { - $dir_is_file = 1; } else { - $fail = 1; + $needpriv = 1; + if ((-e $src.'.meta') && (!-e $dest.'.meta')) { + $needprivmeta = 1; + } + } + if ($needpriv) { + if (&File::Copy::copy($src,$dest)) { + $newfile{$file} = $desturl.'/'.$subdir.'/'.$file; + if ($embstyle eq 'ssi') { + &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd,$subdir); + } + } + } + if ($needprivmeta) { + if (&File::Copy::copy($src.'.meta',$dest.'.meta')) { + &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright, + $customdistfile,$sourceavail,\%checkdeps); + } } - } elsif (-e "$desttop/$subdir/$file") { - $dup = 1; } else { - $src = "$srctop/$file"; - $dest = "$desttop/$subdir/$file"; - $fname = $file; - } - if ($fail) { - $r->print('

'.&mt('Target directory: [_1] does not exist, and could not be created.', - ''.$desturl.'/'.$subdir.'/'.$path.''). - '

'."\n"); - } elsif ($dup) { - $r->print('

'.&mt('Target file: [_1] already exists -- not overwriting.', - ''.$desturl.'/'.$subdir.'/'.$file.''). - '

'."\n"); - } elsif ($dir_is_file) { - $r->print('

'.&mt('Target directory: [_1] name is already in a use for a file -- not overwriting.', - ''.$desturl.'/'.$subdir.'/'.$file.''). - '

'."\n"); - } elsif (($src ne '') && ($dest ne '')) { - if (&File::Copy::copy($src,$dest)) { - $newfile{$file} = 1; - if ((-e $src.'.meta') && (!-e $dest.'.meta')) { - if (&File::Copy::copy($src.'.meta',$dest.'.meta')) { -#FIXME set distribution/copyright to author's default instead of custom. set author to $ca:$cd instead of $cdom:$cnum + my ($needpriv,$needprivmeta); + if ($respublish) { + if ($getres) { + &Apache::lonnet::repcopy($docroot.$resurl.'/'.$file); + } + if ($getresmeta) { + &Apache::lonnet::repcopy($docroot.$resurl.'/'.$file.'.meta'); + } + if (-e $docroot.$resurl.'/'.$file) { + if (&Apache::lonnet::repcopy_crsprivfile($srcurl.'/'.$file,$dest) eq 'ok') { + if (&Apache::londiff::are_different_files($docroot.$resurl.'/'.$file,$dest)) { + $needpriv = 1; + if (&File::Copy::copy($docroot.$resurl.'/'.$file,$dest)) { + if ($embstyle eq 'ssi') { + &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd); + } + } + } else { + if ($embstyle eq 'ssi') { + &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd,$subdir); + } + $newfile{$file} = $desturl.'/'.$subdir.'/'.$file; + } } + } else { + $needpriv = 1; } - my ($ext) = ($file =~ /\.(\w+)$/); - my $embstyle=&Apache::loncommon::fileembstyle($ext); - if ($embstyle eq 'ssi') { -#FIXME in any src or href attributes replace /res/$coursedom/$coursenum/ with /res/$cd/$ca/$subdir + if (-e $docroot.$resurl.'/'.$file.'.meta') { + if (&Apache::lonnet::repcopy_crsprivfile($srcurl.'/'.$file.'.meta',$dest.'.meta') eq 'ok') { + if (&Apache::londiff::are_different_files($docroot.$resurl.'/'.$file.'.meta',$dest.'.meta')) { + $needprivmeta = 1; + if (&File::Copy::copy($docroot.$resurl.'/'.$file.'.meta',$dest.'.meta')) { + &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright, + $customdistfile,$sourceavail,\%checkdeps); + } + } else { + &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright, + $customdistfile,$sourceavail,\%checkdeps); + } + } + } else { + if (!-e $dest.'.meta') { + $needprivmeta = 1; + } + } + if ($getres) { + my $destresfile = $docroot.$destresurl.'/'.$subdir.'/'.$file; + if (-e $dest) { + my $output = &Apache::lonpublisher::batchpublish($r,$dest,$destresfile,$nokeyref,1); + if (-e $destresfile) { + $newresfile{$file} = $destresurl.'/'.$subdir.'/'.$file; + } + } + } + } else { + $needpriv = 1; + if (!-e $dest.'.meta') { + $needprivmeta = 1; + } + } + if ($needpriv) { + if (&Apache::lonnet::repcopy_crsprivfile($srcurl.'/'.$file,$dest) eq 'ok') { + if ($embstyle eq 'ssi') { + &crsres_fixup($dest,$coursenum,$coursedom,$ca,$cd,$subdir); + } + $newfile{$file} = $desturl.'/'.$subdir.'/'.$file; + } + } + if ($needprivmeta) { + if (&Apache::lonnet::repcopy_crsprivfile($srcurl.'/'.$file.'.meta',$dest.'.meta') eq 'ok') { + &crsres_fixup_meta($dest,$coursenum,$coursedom,$ca,$cd,$copyright, + $customdistfile,$sourceavail,\%checkdeps); } } } } - } else { - $notopdir = 1; } + } else { + $notopdir = 1; } } if ($notopdir) { @@ -927,6 +1177,30 @@ ENDJS $r->print('

'.&mt('Copied the following files to [_1]:',''.$desturl.'/'.$subdir.''). '

'."\n". '

'."\n"); + foreach my $file (keys(%newfile)) { + my %storehash = ( + 'priv' => $newfile{$file}, + 'who' => $env{'user.name'}.':'.$env{'user.domain'}, + ); + if (exists($newresfile{$file})) { + $storehash{'res'} = 1; + } + &Apache::lonnet::store_userdata(\%storehash,$file,'copycourseauthor',$coursedom,$coursenum); + } + } + if (keys(%checkdeps)) { + my %missingdep; + foreach my $depfile (sort(keys(%checkdeps))) { + unless (-e "$desttop/$depfile") { + $missingdep{$depfile} = 1; + } + } + if (keys(%missingdep)) { + $r->print('

'.&mt('You may also need to copy the following missing dependencies for files copied to [_1]:', + ''.$desturl.'/'.$subdir.''). + '

'."\n". + '

'."\n"); + } } } else { $r->print('

'.&mt('No currently existing files or directories in Course Authoring Space selected for copying').'

'); @@ -934,11 +1208,10 @@ ENDJS return ''; } } else { - my $formname = 'copycrsauthored'; my $chkname = 'copytouser'; my $context = 'crsauthored'; my (%subdirs,%files,@dirs_by_depth,@files_by_depth,%parent,%children,%hierarchy,@checked_maps); - &Apache::lonnet::recursedirs($home,1,undef,$exclude,0,0,$srcurl,'',\%subdirs,\%files); + &Apache::lonnet::recursedirs($is_course_home,1,undef,$exclude,0,0,$srcurl,'',\%subdirs,\%files,1); foreach my $key (keys(%subdirs)) { next if (($key eq '/') || ($key eq '')); my @items = split(/\//,$key); @@ -962,11 +1235,25 @@ ENDJS } if (ref($files{$path}) eq 'HASH') { foreach my $file (keys(%{$files{$path}})) { - $files_by_depth[$depth]{$path}{$file} = 1; + $files_by_depth[$depth]{$path}{$file} = $files{$path}{$file}; } } } my ($info,$display,$onsubmit,$togglebuttons,$disabled); + my (%resdirs,%resfiles); + &Apache::lonnet::recursedirs($is_course_home,1,undef,$res_exclude,0,0,$resurl,'',\%resdirs,\%resfiles); + my $numpub = 0; + if (keys(%resfiles)) { + foreach my $dir (keys(%resfiles)) { + if (ref($resfiles{$dir}) eq 'HASH') { + foreach my $file (keys(%{$resfiles{$dir}})) { + if (exists($files{$dir}{$file})) { + $numpub ++; + } + } + } + } + } if ($readonly) { $disabled = ' disabled="disabled"'; } @@ -978,11 +1265,10 @@ ENDJS '  '; } - my $title=$origcrsdata{'description'}; - $title=~s/[\/\s]+/\_/gs; - $title=&clean($title); - my $preamble = &authorspace_selector($r,$formname,$home,$title,%outhash); - my $display = '
'."\n". + my $preamble = &authorspace_selector($r,$formname,$home,$title,%outhash). + &courseresource_options($formname,$numpub). + '
'."\n"; + my $display = ''."\n". $preamble."\n". '
'."\n". '
'."\n". @@ -991,16 +1277,43 @@ ENDJS &mt('Choose the files and/or folders to copy from Course Authoring to User Authoring'). '

'."\n"; my $count = 0; - my $startcount = 4 + $home; +# +# Warning to developers: +# +# If you add or remove form elements which precede the table of items to copy +# you will need to modify the value for startcount. Form elements include both: +# and
tags. +# $startcount (set to 9) contains the following: +# fieldsets with following legends: (a) Folder in Authoring Space, (b) Distribution to set in metadata +# (c) Content to copy +# inputs: textbox for destination folder; dropdown lists: (a) Copyright, (b) Source +# hidden: customrights file; buttons: (a) check all, (b) uncheck all. +# authorspace: if more than 1: a fieldset with legend: Select the Authoring Space, +# or if 1: an input (hidden) with available author/coauthor role. +# if there are multiple possible author/coauthor roles (i.e., $home > 1), +# incerement startcount by 1 for the dropdown list uses to select the target. +# +# If there are published files, increment startcount by 3: +# fieldset (legend: Published Resources), and two radio buttons (Yes/No). +# + my $startcount = 9; + if ($home > 1) { + $startcount ++; + } + if ($numpub) { + $startcount += 3; + } my $lastcontainer = $startcount; $display .= &Apache::loncommon::start_data_table()."\n". &Apache::loncommon::start_data_table_header_row(). ''.&mt('Copy?').''. - ''.&mt('Title').''. + ''.&mt('Name').''. + ''.&mt('Last modified').''. + ''.&mt('Published?').''. &Apache::loncommon::end_data_table_header_row()."\n"; $count = &recurse_crsauthored(0,\@dirs_by_depth,\@files_by_depth,'/',$startcount, $count,\$display,\%parent,\%children,$readonly, - $formname,$chkname,\$lastcontainer); + $formname,$chkname,\$lastcontainer,\%resfiles); $display .= &Apache::loncommon::end_data_table().'
'; unless ($readonly) { $display .= '
'. @@ -1017,8 +1330,9 @@ ENDJS sub recurse_crsauthored { my ($currdepth,$dirs_by_depth,$files_by_depth,$currpath,$startcount,$count,$displayref, - $parent,$children,$readonly,$formname,$chkname,$lastcontainerref) = @_; - return $count unless ((ref($dirs_by_depth) eq 'ARRAY') && (ref($files_by_depth) eq 'ARRAY')); + $parent,$children,$readonly,$formname,$chkname,$lastcontainerref,$resfilesref) = @_; + return $count unless ((ref($dirs_by_depth) eq 'ARRAY') && (ref($files_by_depth) eq 'ARRAY') && + (ref($resfilesref) eq 'HASH')); my ($disabled,$hasdirs,$hasfiles,%unique,%dirs,%files); if ((ref($dirs_by_depth->[$currdepth]) eq 'HASH') && (ref($dirs_by_depth->[$currdepth]{$currpath}) eq 'HASH')) { @@ -1064,11 +1378,11 @@ sub recurse_crsauthored { for (my $i=0; $i<$currdepth; $i++) { $$displayref .= "$whitespace\n"; } - $$displayref .= ' '.$item.''. + $$displayref .= ' '.$item.'  '. &Apache::loncommon::end_data_table_row()."\n"; $count = &recurse_crsauthored($deeper,$dirs_by_depth,$files_by_depth,$newpath, $startcount,$count,$displayref,$parent,$children, - $readonly,$formname,$chkname,$lastcontainerref); + $readonly,$formname,$chkname,$lastcontainerref,$resfilesref); } if ($hasfiles && exists($files{$item})) { $count ++; @@ -1092,6 +1406,12 @@ sub recurse_crsauthored { } else { $showpath = "/$currpath/"; } + my ($published,$lastmod); + if ((ref($resfilesref->{$currpath})) && (exists($resfilesref->{$currpath}{$item}))) { + $published = ''.&mt('yes').''; + } else { + $published = ''.&mt('no').''; + } $$displayref .= &Apache::loncommon::start_data_table_row(). ' '.$item.''. + ''.&Apache::lonlocal::locallocaltime($files{$item}).''. + ''.$published.''. &Apache::loncommon::end_data_table_row()."\n"; } } @@ -1107,6 +1429,246 @@ sub recurse_crsauthored { return $count; } +sub courseresource_options { + my ($formname,$numpub) = @_; + my %lt = &Apache::lonlocal::texthash( + 'default' => 'System wide - can be used for any courses system wide', + 'domain' => 'Domain only - use limited to courses in the domain', + 'custom' => 'Customized right of use ...', + 'public' => 'Public - no authentication or authorization required for use', + 'closed' => 'Closed - XML source is closed to everyone', + 'open' => 'Open - XML source is open to people who want to use it', + 'sel' => 'Select', + ); + my $output; + if ($numpub) { + $output .= '
'. + '
'.&mt('Published Resources').''. + &mt('[quant,_1,file] in Course Authoring Space also exist in Resource Space.', + $numpub).'
'. + &mt('Publish copied files in selected Authoring Space?').': '."\n". + ''."\n". + ''."\n". + '
'."\n"; + } + $output .= '
'. + '
'.&mt('Distribution to set in metadata').''. + &mt('Copyright').': '. + '
'."\n". + &mt('Source').' :'. + '
'."\n". + '
'."\n"; + return $output; +} + +sub crsres_fixup_meta { + my ($dest,$coursenum,$coursedom,$ca,$cd,$copyright,$customdistfile,$sourceavail,$checkdeps) = @_; + return unless (ref($checkdeps) eq 'HASH'); + if (open(my $fh,'<',$dest.'.meta')) { + my ($output,$now,$setsourceavail); + $now = time; + if (($dest =~ /\.(xml|html|htm|xhtml|xhtm)$/i) || ($dest =~ /$LONCAPA::assess_re/)) { + $setsourceavail = 1; + } + while (my $line=<$fh>) { + chomp($line); + if ($line eq "$coursenum:$coursedom") { + $output .= "$ca:$cd\n"; + } elsif ($line eq 'custom') { + $output .= "$copyright\n"; + } elsif ($line =~ m{^\d+$}) { + $output .= "$now\n"; + } elsif ($line eq "/res/$coursedom/$coursenum/default.rights") { + $output .= "$customdistfile\n"; + } elsif ($line =~ m{^(open|closed)$}) { + if ($setsourceavail) { + $output .= "$sourceavail\n"; + } + } elsif ($line eq "$coursedom") { + $output .= "$cd\n"; + } elsif ($line =~ m{^\d+$}) { + $output .= "$now\n"; + } elsif ($line =~ m{^$match_username:$match_domain$}) { + $output .= "$env{'user.name'}:$env{'user.domain'}\n"; + } elsif ($line eq "$coursenum:$coursedom") { + $output .= "$ca:$cd\n"; + } elsif ($line =~ m{^(.+)$}) { + my @deps = split(/\s*,\s*/,$1); + my @newdeps; + my $changed = 0; + foreach my $dep (@deps) { + if ($dep =~ m{^/res/$coursedom/$coursenum/(.+)$}) { + my $rest = $1; + push(@newdeps,"/res/$cd/$ca/$rest"); + $checkdeps->{$rest} = 1; + $changed ++; + } else { + push(@newdeps,$dep); + } + } + if ($changed) { + $output .= ''.join(',',@newdeps).''."\n"; + } + } else { + $output .= "$line\n"; + } + } + close($fh); + if (open(my $fh,'>',$dest.'.meta')) { + print $fh $output; + close($fh); + } + } +} + +sub crsres_fixup { + my ($dest,$coursenum,$coursedom,$ca,$cd,$subdir) = @_; + my $outstring=''; + my $changes = 0; + my @parser; + $parser[0]=HTML::LCParser->new($dest); + $parser[-1]->xml_mode(1); + my $token; + while (@parser) { + while ($token=$parser[-1]->get_token) { + if ($token->[0] eq 'S') { + my $tag=$token->[1]; + my $lctag=lc($tag); + my %parms=%{$token->[2]}; + foreach my $type ('src','href','background','bgimg') { + foreach my $key (keys(%parms)) { + if ($key =~ /^$type$/i) { + next if (($lctag eq 'img') && ($type eq 'src') && + ($parms{$key} =~ m{^data\:image/gif;base64,})); + if ($parms{$key} =~ m{^\Q/res/$coursedom/$coursenum/\E}si) { + $parms{$key} =~ s{^\Q/res/$coursedom/$coursenum/\E}{/res/$cd/$ca/$subdir/}si; + $changes ++; + } + } + } + } + # probably a image type