--- loncom/publisher/lonpublisher.pm 2014/12/12 18:27:34 1.294 +++ loncom/publisher/lonpublisher.pm 2024/12/30 17:13:26 1.295.2.4 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Publication Handler # -# $Id: lonpublisher.pm,v 1.294 2014/12/12 18:27:34 raeburn Exp $ +# $Id: lonpublisher.pm,v 1.295.2.4 2024/12/30 17:13:26 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -318,8 +318,12 @@ string which presents the form field (fo =item B<textfield> +=item B<text_with_browse_field> + =item B<hiddenfield> +=item B<checkbox> + =item B<selectbox> =back @@ -367,7 +371,7 @@ sub hiddenfield { sub checkbox { my ($name,$text)=@_; - return "\n<br /><label><input type='checkbox' name='$name' /> ". + return "\n<label><input type='checkbox' name='$name' /> ". &mt($text)."</label>"; } @@ -399,6 +403,58 @@ sub select_level_form { if (!defined($value)) { $env{'form.'.$name}=0; } return &Apache::loncommon::select_level_form($value,$name); } + +sub common_access { + my ($name,$text,$options)=@_; + return unless (ref($options) eq 'ARRAY'); + my $formname = 'pubdirpref'; + my $chkname = 'common'.$name; + my $chkid = 'LC_'.$chkname; + my $divid = $chkid.'div'; + my $customdivid = 'LC_customfile'; + my $selname = $chkname.'select'; + my $selid = $chkid.'select'; + my $selonchange; + if ($name eq 'dist') { + $selonchange = ' onchange="showHideCustom(this,'."'$customdivid'".');"'; + } + 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 = <<"END"; +<span class="LC_nobreak"> +<label> +<input type="checkbox" name="commonaccess" value="$name" id="$chkid" +onclick="showHideAccess(this,'$divid');" /> +$text</label></span> +<div id="$divid" style="padding:0;clear:both;margin:0;border:0;display:none"> +<select name="$selname" id="$selid" $selonchange> +<option value="" selected="selected">$lt{'sel'}</option> +END + foreach my $val (@{$options}) { + $output .= '<option value="'.$val.'">'.$lt{$val}.'</option>'."\n"; + } + $output .= ' +</select>'; + if ($name eq 'dist') { + $output .= <<"END"; +<div id="$customdivid" style="padding:0;clear:both;margin:0;border:0;display:none"> +<input type="text" name="commoncustomrights" size="60" value="" /> +<a href="javascript:openbrowser('$formname','commoncustomrights','rights');"> +$lt{'sel'}</a></div> +END + } + $output .= ' +</div> +'; +} + ######################################### ######################################### @@ -1629,7 +1685,33 @@ sub phasetwo { %metadatakeys=(); &metaeval(&unescape($env{'form.allmeta'})); - + + if ($batch) { + my %commonaccess; + map { $commonaccess{$_} = 1; } &Apache::loncommon::get_env_multiple('form.commonaccess'); + if ($commonaccess{'dist'}) { + unless ($style eq 'prv') { + if ($env{'form.commondistselect'} eq 'custom') { + unless ($source =~ /\.rights$/) { + if ($env{'form.commoncustomrights'} =~ m{^/res/.+\.rights$}) { + $env{'form.customdistributionfile'} = $env{'form.commoncustomrights'}; + $env{'form.copyright'} = $env{'form.commondistselect'}; + } + } + } elsif ($env{'form.commondistselect'} =~ /^default|domain|public$/) { + $env{'form.copyright'} = $env{'form.commondistselect'}; + } + } + } + unless ($style eq 'prv') { + if ($commonaccess{'source'}) { + if (($env{'form.commonsourceselect'} eq 'open') || ($env{'form.commonsourceselect'} eq 'closed')) { + $env{'form.sourceavail'} = $env{'form.commonsourceselect'}; + } + } + } + } + $metadatafields{'title'}=$env{'form.title'}; $metadatafields{'author'}=$env{'form.author'}; $metadatafields{'subject'}=$env{'form.subject'}; @@ -1842,11 +1924,7 @@ sub phasetwo { # ------------------------------------------------------------- Trigger updates push(@{$modified_urls},[$target,$source]); - unless ($registered_cleanup) { - my $handlers = $r->get_handlers('PerlCleanupHandler'); - $r->set_handlers('PerlCleanupHandler' => [\¬ify,@{$handlers}]); - $registered_cleanup=1; - } + ¬ify_in_cleanup($r); # ---------------------------------------------------------- Clear local caches my $thisdistarget=$target; @@ -1882,39 +1960,51 @@ sub phasetwo { return 1; } +sub notify_in_cleanup { + my ($r) = @_; + unless ($registered_cleanup) { + my $handlers = $r->get_handlers('PerlCleanupHandler'); + $r->set_handlers('PerlCleanupHandler' => [\¬ify,@{$handlers}]); + $registered_cleanup=1; + } +} + # =============================================================== Notifications sub notify { # --------------------------------------------------- Send update notifications - foreach my $targetsource (@{$modified_urls}){ - my ($target,$source)=@{$targetsource}; - my $logfile=Apache::File->new('>>'.$source.'.log'); - print $logfile "\nCleanup phase: Notifications\n"; - my @subscribed=&get_subscribed_hosts($target); - foreach my $subhost (@subscribed) { - print $logfile "\nNotifying host ".$subhost.':'; - my $reply=&Apache::lonnet::critical('update:'.$target,$subhost); - print $logfile $reply; - } + if (ref($modified_urls) eq 'ARRAY') { + foreach my $targetsource (@{$modified_urls}){ + my ($target,$source)=@{$targetsource}; + my $logfile=Apache::File->new('>>'.$source.'.log'); + print $logfile "\nCleanup phase: Notifications\n"; + my @subscribed=&get_subscribed_hosts($target); + foreach my $subhost (@subscribed) { + print $logfile "\nNotifying host ".$subhost.':'; + my $reply=&Apache::lonnet::critical('update:'.$target,$subhost); + print $logfile $reply; + } # ---------------------------------------- Send update notifications, meta only - my @subscribedmeta=&get_subscribed_hosts("$target.meta"); - foreach my $subhost (@subscribedmeta) { - print $logfile "\nNotifying host for metadata only ".$subhost.':'; - my $reply=&Apache::lonnet::critical('update:'.$target.'.meta', - $subhost); - print $logfile $reply; - } + my @subscribedmeta=&get_subscribed_hosts("$target.meta"); + foreach my $subhost (@subscribedmeta) { + print $logfile "\nNotifying host for metadata only ".$subhost.':'; + my $reply=&Apache::lonnet::critical('update:'.$target.'.meta', + $subhost); + print $logfile $reply; + } # --------------------------------------------------- Notify subscribed courses - my %courses=&coursedependencies($target); - my $now=time; - foreach my $course (keys(%courses)) { - print $logfile "\nNotifying course ".$course.':'; - my ($cdom,$cname)=split(/\_/,$course); - my $reply=&Apache::lonnet::cput - ('versionupdate',{$target => $now},$cdom,$cname); - print $logfile $reply; - } - print $logfile "\n============ Done ============\n"; - $logfile->close(); + my %courses=&coursedependencies($target); + my $now=time; + foreach my $course (keys(%courses)) { + print $logfile "\nNotifying course ".$course.':'; + my ($cdom,$cname)=split(/\_/,$course); + my $reply=&Apache::lonnet::cput + ('versionupdate',{$target => $now},$cdom,$cname); + print $logfile $reply; + } + print $logfile "\n============ Done ============\n"; + $logfile->close(); + } + $modified_urls = []; } if ($lock) { &Apache::lonnet::remove_lock($lock); } return OK; @@ -1981,19 +2071,39 @@ sub publishdirectory { .&Apache::lonhtmlcommon::row_title(&mt('Target')) .'<span class="LC_filename">'.$thisdisresdir.'</span>' ); + my %reasons = &Apache::lonlocal::texthash( + mod => 'Authoring Space file postdates published file', + modmeta => 'Authoring Space metadata file postdates published file', + unpub => 'Resource is unpublished', + ); my $dirptr=16384; # Mask indicating a directory in stat.cmode. unless ($env{'form.phase'} eq 'two') { # ask user what they want $r->print(&Apache::lonhtmlcommon::row_closure() - .&Apache::lonhtmlcommon::row_title(&mt('Options')) - ); + .&Apache::lonhtmlcommon::row_title(&mt('Options') + .&Apache::loncommon::help_open_topic('Publishing_Directory_Options'))); $r->print(&hiddenfield('phase','two'). &hiddenfield('filename',$env{'form.filename'}). - &checkbox('pubrec','include subdirectories'). - &checkbox('forcerepub','force republication of previously published files'). - &checkbox('obsolete','make file(s) obsolete'). - &checkbox('forceoverride','force directory level metadata over existing') + '<fieldset><legend>'.&mt('Recurse').'</legend>'. + &checkbox('pubrec','include subdirectories'). + '</fieldset>'. + '<fieldset><legend>'.&mt('Force').'</legend>'. + &checkbox('forcerepub','force republication of previously published files').'<br />'. + &checkbox('forceoverride','force directory level metadata over existing'). + '</fieldset>'. + '<fieldset><legend>'.&mt('Exclude').'</legend>'. + &checkbox('excludeunpub','exclude currently unpublished files').'<br />'. + &checkbox('excludemod','exclude modified files').'<br />'. + &checkbox('excludemodmeta','exclude files with modified metadata'). + '</fieldset>'. + '<fieldset><legend>'.&mt('Actions').'</legend>'. + &checkbox('obsolete','make file(s) obsolete').'<br />'. + &common_access('dist',&mt('apply common copyright/distribution'), + ['default','domain','public','custom']).'<br />'. + &common_access('source',&mt('apply common source availability'), + ['closed','open']). + '</fieldset>' ); $r->print(&Apache::lonhtmlcommon::row_closure(1) .&Apache::lonhtmlcommon::end_pick_box() @@ -2004,7 +2114,12 @@ sub publishdirectory { $r->print(&Apache::lonhtmlcommon::row_closure(1) .&Apache::lonhtmlcommon::end_pick_box() ); + my %commonaccess; + map { $commonaccess{$_} = 1; } &Apache::loncommon::get_env_multiple('form.commonaccess'); unless ($lock) { $lock=&Apache::lonnet::set_lock(&mt('Publishing [_1]',$fn)); } + if ($lock) { + ¬ify_in_cleanup($r); + } # actually publish things opendir(DIR,$fn); my @files=sort(readdir(DIR)); @@ -2013,7 +2128,7 @@ sub publishdirectory { $cuid,$cgid,$crdev,$csize, $catime,$cmtime,$cctime, $cblksize,$cblocks)=stat($fn.'/'.$filename); - + my $extension=''; if ($filename=~/\.(\w+)$/) { $extension=$1; } if ($cmode&$dirptr) { @@ -2022,8 +2137,9 @@ sub publishdirectory { } } elsif ((&Apache::loncommon::fileembstyle($extension) ne 'hdn') && ($filename!~/^[\#\.]/) && ($filename!~/\~$/)) { -# find out publication status and/or exiting metadata +# find out publication status and/or existing metadata my $publishthis=0; + my $skipthis; if (-e $resdir.'/'.$filename) { my ($rdev,$rino,$rmode,$rnlink, $ruid,$rgid,$rrdev,$rsize, @@ -2031,22 +2147,72 @@ sub publishdirectory { $rblksize,$rblocks)=stat($resdir.'/'.$filename); if (($rmtime<$cmtime) || ($env{'form.forcerepub'})) { # previously published, modified now - $publishthis=1; - } - my $meta_cmtime = (stat($fn.'/'.$filename.'.meta'))[9]; - my $meta_rmtime = (stat($resdir.'/'.$filename.'.meta'))[9]; - if ( $meta_rmtime<$meta_cmtime ) { - $publishthis=1; + if ($env{'form.excludemod'}) { + $skipthis='mod'; + } else { + $publishthis=1; + } } + unless ($skipthis) { + my $meta_cmtime = (stat($fn.'/'.$filename.'.meta'))[9]; + my $meta_rmtime = (stat($resdir.'/'.$filename.'.meta'))[9]; + if ( $meta_rmtime<$meta_cmtime ) { + if ($env{'form.excludemodmeta'}) { + $skipthis='modmeta'; + $publishthis=0; + } else { + $publishthis=1; + } + } else { + unless (&Apache::loncommon::fileembstyle($extension) eq 'prv') { + if ($commonaccess{'dist'}) { + my ($currdist,$currdistfile,$currsourceavail); + my $currdist = &Apache::lonnet::metadata($thisdisresdir.'/'.$filename,'copyright'); + if ($currdist eq 'custom') { + $currdistfile = &Apache::lonnet::metadata($thisdisresdir.'/'.$filename,'customdistributionfile'); + } + if ($env{'form.commondistselect'} eq 'custom') { + if ($env{'form.commoncustomrights'} =~ m{^/res/.+\.rights$}) { + if ($currdist eq 'custom') { + unless ($env{'form.commoncustomrights'} eq $currdistfile) { + $publishthis=1; + } + } else { + $publishthis=1; + } + } + } elsif ($env{'form.commondistselect'} =~ /^default|domain|public$/) { + unless ($currdist eq $env{'form.commondistselect'}) { + $publishthis=1; + } + } + } + } + } + } } else { # never published - $publishthis=1; + if ($env{'form.excludeunpub'}) { + $skipthis='unpub'; + } else { + $publishthis=1; + } } if ($publishthis) { &batchpublish($r,$fn.'/'.$filename,$resdir.'/'.$filename); } else { - $r->print('<br />'.&mt('Skipping').' '.$filename.'<br />'); + my $reason; + if ($skipthis) { + $reason = $reasons{$skipthis}; + } else { + $reason = &mt('No changes needed to published resource or metadata'); + } + $r->print('<br />'.&mt('Skipping').' '.$filename); + if ($reason) { + $r->print(' ('.$reason.')'); + } + $r->print('<br />'); } $r->rflush(); } @@ -2247,7 +2413,53 @@ sub handler { my $js='<script type="text/javascript">'. &Apache::loncommon::browser_and_searcher_javascript(). '</script>'; - $r->print(&Apache::loncommon::start_page('Resource Publication',$js) + my $startargs = {}; + if ($fn=~/\/$/) { + unless ($env{'form.phase'} eq 'two') { + $startargs->{'add_entries'} = { onload => 'javascript:setDefaultAccess();' }; + $js .= <<"END"; +<script type="text/javascript"> +// <![CDATA[ +function showHideAccess(caller,div) { + if (document.getElementById(div)) { + if (caller.checked) { + document.getElementById(div).style.display='inline-block'; + } else { + document.getElementById(div).style.display='none'; + } + } +} + +function showHideCustom(caller,divid) { + if (document.getElementById(divid)) { + if (caller.options[caller.selectedIndex].value == 'custom') { + document.getElementById(divid).style.display="inline-block"; + } else { + document.getElementById(divid).style.display="none"; + } + } +} +function setDefaultAccess() { + var chkids = Array('LC_commondist','LC_commonsource'); + for (var i=0; i<chkids.length; i++) { + if (document.getElementById(chkids[i])) { + document.getElementById(chkids[i]).checked = false; + } + if (document.getElementById(chkids[i]+'select')) { + document.getElementById(chkids[i]+'select').selectedIndex = 0; + } + if (document.getElementById(chkids[i]+'div')) { + document.getElementById(chkids[i]+'div').style.display = 'none'; + } + } +} +// ]]> +</script> + +END + } + } + $r->print(&Apache::loncommon::start_page('Resource Publication',$js,$startargs) .&Apache::lonhtmlcommon::breadcrumbs() .&Apache::loncommon::head_subbox( &Apache::loncommon::CSTR_pageheader($docroot.$fn))