--- loncom/publisher/lonpublisher.pm 2016/03/22 16:41:10 1.295 +++ loncom/publisher/lonpublisher.pm 2025/01/04 21:23:33 1.307 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Publication Handler # -# $Id: lonpublisher.pm,v 1.295 2016/03/22 16:41:10 raeburn Exp $ +# $Id: lonpublisher.pm,v 1.307 2025/01/04 21:23:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -128,13 +128,9 @@ use Apache::lonlocal; use Apache::loncfile; use LONCAPA::lonmetadata; use Apache::lonmsg; -use vars qw(%metadatafields %metadatakeys); +use vars qw(%metadatafields %metadatakeys %addid $readit); use LONCAPA qw(:DEFAULT :match); - -my %addid; -my %nokey; - my $docroot; my $cuname; @@ -333,7 +329,7 @@ string which presents the form field (fo ######################################### ######################################### sub textfield { - my ($title,$name,$value,$noline)=@_; + my ($title,$name,$value,$noline,$readonly)=@_; $value=~s/^\s+//gs; $value=~s/\s+$//gs; $value=~s/\s+/ /gs; @@ -345,22 +341,31 @@ sub textfield { } sub text_with_browse_field { - my ($title,$name,$value,$restriction,$noline)=@_; + my ($title,$name,$value,$restriction,$noline,$readonly)=@_; $value=~s/^\s+//gs; $value=~s/\s+$//gs; $value=~s/\s+/ /gs; $title=&mt($title); $env{'form.'.$name}=$value; - return "\n".&Apache::lonhtmlcommon::row_title($title) - .'' - .'' + my $disabled; + if ($readonly) { + $disabled = ' disabled="disabled"'; + } + my $output = + "\n".&Apache::lonhtmlcommon::row_title($title) + .''; + unless ($readonly) { + $output .= + '' .'' .&mt('Select') .' ' .'' .&mt('Search') - .'' - .&Apache::lonhtmlcommon::row_closure($noline); + .''; + } + $output .= &Apache::lonhtmlcommon::row_closure($noline); + return $output; } sub hiddenfield { @@ -371,12 +376,12 @@ sub hiddenfield { sub checkbox { my ($name,$text)=@_; - return "\n ". + return "\n ". &mt($text).""; } sub selectbox { - my ($title,$name,$value,$functionref,@idlist)=@_; + my ($title,$name,$value,$readonly,$functionref,@idlist)=@_; $title=&mt($title); $value=(split(/\s*,\s*/,$value))[-1]; if (defined($value)) { @@ -391,6 +396,9 @@ sub selectbox { if ($id eq $value) { $selout.=' selected="selected"'; } + if ($readonly) { + $selout .= ' disabled="disabled"'; + } $selout.='>'.&{$functionref}($id).''; } $selout.=''.&Apache::lonhtmlcommon::row_closure(); @@ -420,7 +428,7 @@ sub common_access { } 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 domai', + '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', @@ -428,7 +436,6 @@ sub common_access { 'sel' => 'Select', ); my $output = <<"END"; - ######################################### sub publish { - my ($source,$target,$style,$batch)=@_; + my ($source,$target,$style,$batch,$nokeyref)=@_; my $logfile; my $scrout=''; my $allmeta=''; @@ -1204,6 +1211,20 @@ sub publish { $content=$outstring; } + +# ----------------------------------------------------- Course Authoring Space. + my ($courseauthor,$crsaurights,$readonly); + if ($env{'request.course.id'}) { + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'}; + if ($source =~ m{^\Q$docroot/priv/$cdom/$cnum/\E}) { + $courseauthor = $cnum.':'.$cdom; + $crsaurights = "/res/$cdom/$cnum/default.rights"; + $readonly = 1; + } + } + # -------------------------------------------- Initial step done, now metadata. # --------------------------------------- Storage for metadata keys and fields. @@ -1347,7 +1368,7 @@ sub publish { $textonly=~s/[^a-z^ü^ä^ö^ß\s]//g; #dont delete german "Umlaute" foreach ($textonly=~m/[^\s]+/g) { #match all but whitespaces - unless ($nokey{$_}) { + unless ($nokeyref->{$_}) { $keywords{$_}=1; } } @@ -1490,7 +1511,7 @@ END $defaultlanguage =~ s/,\s*$//g; $intr_scrout.=&selectbox('Language','language', - $defaultlanguage, + $defaultlanguage,'', \&Apache::loncommon::languagedescription, (&Apache::loncommon::languageids), ); @@ -1507,8 +1528,11 @@ END if ($style eq 'prv') { $pubowner_last = 1; } + if ($courseauthor) { + $metadatafields{'owner'} = $courseauthor; + } $intr_scrout.=&textfield('Publisher/Owner','owner', - $metadatafields{'owner'},$pubowner_last); + $metadatafields{'owner'},$pubowner_last,$readonly); # ---------------------------------------------- Retrofix for unused copyright if ($metadatafields{'copyright'} eq 'free') { @@ -1521,6 +1545,10 @@ END # ------------------------------------------------ Dial in reasonable defaults my $defaultoption=$metadatafields{'copyright'}; unless ($defaultoption) { $defaultoption='default'; } + if ($courseauthor) { + $defaultoption='custom'; + $metadatafields{'customdistributionfile'}=$crsaurights; + } my $defaultsourceoption=$metadatafields{'sourceavail'}; unless ($defaultsourceoption) { $defaultsourceoption='closed'; } unless ($style eq 'prv') { @@ -1532,12 +1560,12 @@ END $defaultoption='default'; } $intr_scrout.=&selectbox('Copyright/Distribution','copyright', - $defaultoption, + $defaultoption,$readonly, \&Apache::loncommon::copyrightdescription, (grep !/^(public|priv)$/,(&Apache::loncommon::copyrightids))); } else { $intr_scrout.=&selectbox('Copyright/Distribution','copyright', - $defaultoption, + $defaultoption,$readonly, \&Apache::loncommon::copyrightdescription, (grep !/^priv$/,(&Apache::loncommon::copyrightids))); } @@ -1546,9 +1574,9 @@ END my $replace=&mt('Copyright/Distribution:'); $intr_scrout =~ s/$replace/$replace.' '.$copyright_help/ge; - $intr_scrout.=&text_with_browse_field('Custom Distribution File','customdistributionfile',$metadatafields{'customdistributionfile'},'rights'); + $intr_scrout.=&text_with_browse_field('Custom Distribution File','customdistributionfile',$metadatafields{'customdistributionfile'},'rights','',$readonly); $intr_scrout.=&selectbox('Source Distribution','sourceavail', - $defaultsourceoption, + $defaultsourceoption,'', \&Apache::loncommon::source_copyrightdescription, (&Apache::loncommon::source_copyrightids)); # $intr_scrout.=&text_with_browse_field('Source Custom Distribution File','sourcerights',$metadatafields{'sourcerights'},'rights'); @@ -1598,6 +1626,18 @@ END return($scrout,0); } +sub getnokey { + my ($includedir) = @_; + my $nokey={}; + my $fh=Apache::File->new($includedir.'/un_keyword.tab'); + while (<$fh>) { + my $word=$_; + chomp($word); + $nokey->{$word}=1; + } + return $nokey; +} + ######################################### ######################################### @@ -1620,13 +1660,21 @@ Parameters: =item I<$distarget> +=item I<$batch> + +=item I<$usebuffer> + =back Returns: =over 4 -=item integer +=item integer or array + +if $userbuffer arg is true, and if caller wants an array +then the array ($output,$rtncode) will be returned, otherwise +just the $rtncode will be returned. $rtncode is an integer: 0: fail 1: success @@ -1640,26 +1688,54 @@ Returns: ######################################### sub phasetwo { - my ($r,$source,$target,$style,$distarget,$batch)=@_; + my ($r,$source,$target,$style,$distarget,$batch,$usebuffer)=@_; $source=~s/\/+/\//g; $target=~s/\/+/\//g; # # Unless trying to get rid of something, check name validity # + my $output; unless ($env{'form.obsolete'}) { if ($target=~/(\_\_\_|\&\&\&|\:\:\:)/) { - $r->print(''. + $output = ''. &mt('Unsupported character combination [_1] in filename, FAIL.',"'.$1.'"). - ''); - return 0; + ''; + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } } unless ($target=~/\.(\w+)$/) { - $r->print(''.&mt('No valid extension found in filename, FAIL').''); - return 0; + $output = ''.&mt('No valid extension found in filename, FAIL').''; + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } } if ($target=~/\.(\d+)\.(\w+)$/) { - $r->print(''.&mt('Filename of resource contains internal version number. Cannot publish such resources, FAIL').''); - return 0; + $output = ''.&mt('Filename of resource contains internal version number. Cannot publish such resources, FAIL').''; + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } } } @@ -1669,14 +1745,25 @@ sub phasetwo { $distarget=~s/\/+/\//g; my $logfile; unless ($logfile=Apache::File->new('>>'.$source.'.log')) { - $r->print( - ''. - &mt('No write permission to user directory, FAIL').''); - return 0; + $output = ''. + &mt('No write permission to user directory, FAIL').''; + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + return 0; + } } if ($source =~ /\.rights$/) { - $r->print(''.&mt('Warning: It can take up to 1 hour for rights changes to fully propagate.').''); + $output = ''.&mt('Warning: It can take up to 1 hour for rights changes to fully propagate.').''; + unless ($usebuffer) { + $r->print($output); + $output = ''; + } } print $logfile @@ -1738,7 +1825,21 @@ sub phasetwo { $env{'user.domain'}; $metadatafields{'authorspace'}=$cuname.':'.$cudom; $metadatafields{'domain'}=$cudom; - + + my $crsauthor; + if ($env{'request.course.id'}) { + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + if ($distarget =~ m{^/res/$cdom/$cnum}) { + $crsauthor = 1; + my $default_rights = "/res/$cdom/$cnum/default.rights"; + unless ($distarget eq $default_rights) { + $metadatafields{'copyright'} = 'custom'; + $metadatafields{'customdistributionfile'} = $default_rights; + } + } + } + my $allkeywords=$env{'form.addkey'}; if (exists($env{'form.keywords'})) { if (ref($env{'form.keywords'})) { @@ -1758,20 +1859,36 @@ sub phasetwo { if ($metadatafields{'copyright'} eq 'custom') { my $file=$metadatafields{'customdistributionfile'}; unless ($file=~/\.rights$/) { - $r->print( - ''.&mt('No valid custom distribution rights file specified, FAIL'). - ''); - return 0; + $output .= ''.&mt('No valid custom distribution rights file specified, FAIL'). + ''; + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } } } { print $logfile "\nWrite metadata file for ".$source; my $mfh; unless ($mfh=Apache::File->new('>'.$source.'.meta')) { - $r->print( - ''.&mt('Could not write metadata, FAIL'). - ''); - return 0; + $output .= ''.&mt('Could not write metadata, FAIL'). + ''; + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } } foreach my $field (sort(keys(%metadatafields))) { unless ($field=~/\./) { @@ -1790,7 +1907,12 @@ sub phasetwo { .''.$tag.'>'; } } - $r->print(''.&mt('Wrote Metadata').''); + + $output .= ''.&mt('Wrote Metadata').''; + unless ($usebuffer) { + $r->print($output); + $output = ''; + } print $logfile "\nWrote metadata"; } @@ -1799,17 +1921,27 @@ sub phasetwo { $metadatafields{'url'} = $distarget; $metadatafields{'version'} = 'current'; - my ($error,$success) = &store_metadata(%metadatafields); - if ($success) { - $r->print(''.&mt('Synchronized SQL metadata database').''); - print $logfile "\nSynchronized SQL metadata database"; - } else { - $r->print($error); - print $logfile "\n".$error; + unless ($crsauthor) { + my ($error,$success) = &store_metadata(%metadatafields); + if ($success) { + $output .= ''.&mt('Synchronized SQL metadata database').''; + print $logfile "\nSynchronized SQL metadata database"; + } else { + $output .= $error; + print $logfile "\n".$error; + } + unless ($usebuffer) { + $r->print($output); + $output = ''; + } } # --------------------------------------------- Delete author resource messages my $delresult=&Apache::lonmsg::del_url_author_res_msg($target); - $r->print(''.&mt('Removing error messages:').' '.$delresult.''); + $output .= ''.&mt('Removing error messages:').' '.$delresult.''; + unless ($usebuffer) { + $r->print($output); + $output = ''; + } print $logfile "\nRemoving error messages: $delresult"; # ----------------------------------------------------------- Copy old versions @@ -1823,9 +1955,18 @@ sub phasetwo { my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'}; unless ($srcd=~/^\Q$docroot\E\/res/) { print $logfile "\nPANIC: Target dir is ".$srcd; - $r->print( - "".&mt('Invalid target directory, FAIL').""); - return 0; + $output .= + "".&mt('Invalid target directory, FAIL').""; + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } } opendir(DIR,$srcd); while ($filename=readdir(DIR)) { @@ -1840,18 +1981,35 @@ sub phasetwo { } closedir(DIR); $maxversion++; - $r->print(''.&mt('Creating old version [_1]',$maxversion).''); + $output .= ''.&mt('Creating old version [_1]',$maxversion).''; + unless ($usebuffer) { + $r->print($output); + $output = ''; + } print $logfile "\nCreating old version ".$maxversion."\n"; my $copyfile=$srcd.'/'.$srcf.'.'.$maxversion.'.'.$srct; if (copy($target,$copyfile)) { print $logfile "Copied old target to ".$copyfile."\n"; - $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('Copied old target file'))); + $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Copied old target file')); + unless ($usebuffer) { + $r->print($output); + $output = ''; + } } else { print $logfile "Unable to write ".$copyfile.':'.$!."\n"; - $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('Failed to copy old target').", $!",1)); - return 0; + $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Failed to copy old target').", $!",1); + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } } # --------------------------------------------------------------- Copy Metadata @@ -1860,19 +2018,34 @@ sub phasetwo { if (copy($target.'.meta',$copyfile)) { print $logfile "Copied old target metadata to ".$copyfile."\n"; - $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('Copied old metadata'))); + $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Copied old metadata')); + unless ($usebuffer) { + $r->print($output); + $output = ''; + } } else { print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n"; if (-e $target.'.meta') { - $r->print(&Apache::lonhtmlcommon::confirm_success( - &mt('Failed to write old metadata copy').", $!",1)); - return 0; + $output .= &Apache::lonhtmlcommon::confirm_success( + &mt('Failed to write old metadata copy').", $!",1); + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } } } - - } else { - $r->print(''.&mt('Initial version').''); + $output .= ''.&mt('Initial version').''; + unless ($usebuffer) { + $r->print($output); + $output = ''; + } print $logfile "\nInitial version"; } @@ -1888,22 +2061,38 @@ sub phasetwo { if ((-e $path)!=1) { print $logfile "\nCreating directory ".$path; mkdir($path,0777); - $r->print('' - .&mt('Created directory [_1]' - ,''.$parts[$count].'') - .'' - ); + $output .= '' + .&mt('Created directory [_1]' + ,''.$parts[$count].'') + .''; + unless ($usebuffer) { + $r->print($output); + $output = ''; + } } } if (copy($source,$copyfile)) { print $logfile "\nCopied original source to ".$copyfile."\n"; - $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('Copied source file'))); + $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Copied source file')); + unless ($usebuffer) { + $r->print($output); + $output = ''; + } } else { print $logfile "\nUnable to write ".$copyfile.':'.$!."\n"; - $r->print(&Apache::lonhtmlcommon::confirm_success( - &mt('Failed to copy source').", $!",1)); - return 0; + $output .= &Apache::lonhtmlcommon::confirm_success( + &mt('Failed to copy source').", $!",1); + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } } # ---------------------------------------------- Delete local tmp-preview files @@ -1914,22 +2103,33 @@ sub phasetwo { if (copy($source.'.meta',$copyfile)) { print $logfile "\nCopied original metadata to ".$copyfile."\n"; - $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('Copied metadata'))); + $output .= &Apache::lonhtmlcommon::confirm_success(&mt('Copied metadata')); + unless ($usebuffer) { + $r->print($output); + $output = ''; + } } else { print $logfile "\nUnable to write metadata ".$copyfile.':'.$!."\n"; - $r->print(&Apache::lonhtmlcommon::confirm_success( - &mt('Failed to write metadata copy').", $!",1)); - return 0; + $output .= &Apache::lonhtmlcommon::confirm_success( + &mt('Failed to write metadata copy').", $!",1); + if ($usebuffer) { + if (wantarray) { + return ($output,0); + } else { + return 0; + } + } else { + $r->print($output); + return 0; + } + } + unless ($usebuffer) { + $r->rflush; } - $r->rflush; # ------------------------------------------------------------- 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; @@ -1940,7 +2140,11 @@ sub phasetwo { # ------------------------------------------------------------- Everything done $logfile->close(); - $r->print(''.&mt('Done').''); + $output .= ''.&mt('Done').''; + unless ($usebuffer) { + $r->print($output); + $output = ''; + } # ------------------------------------------------ Provide link to new resource unless ($batch) { @@ -1949,7 +2153,7 @@ sub phasetwo { my $thissrcdir=$thissrc; $thissrcdir=~s/\/[^\/]+$/\//; - $r->print( + $output .= &Apache::lonhtmlcommon::actionbox([ ''. &mt('View Published Version'). @@ -1959,45 +2163,73 @@ sub phasetwo { '', ''. &mt('Back to Source Directory'). - '']) - ); + '']); + unless ($usebuffer) { + $r->print($output); + $output = ''; + } + } + + if ($usebuffer) { + if (wantarray) { + return ($output,1); + } else { + return 1; + } + } else { + if (wantarray) { + return ('',1); + } else { + 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; } - return 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; @@ -2006,12 +2238,11 @@ sub notify { ######################################### sub batchpublish { - my ($r,$srcfile,$targetfile)=@_; + my ($r,$srcfile,$targetfile,$nokeyref,$usebuffer)=@_; #publication pollutes %env with form.* values my %oldenv=%env; $srcfile=~s/\/+/\//g; $targetfile=~s/\/+/\//g; - $srcfile=~s/\/+/\//g; my $docroot=$r->dir_config('lonDocRoot'); my $thisdistarget=$targetfile; @@ -2023,34 +2254,65 @@ sub batchpublish { $srcfile=~/\.(\w+)$/; my $thistype=$1; +# +# If lonpublisher::batchpublish() is called directly from another package +# instead of via a call to lonpublisher::handler(), need to set the package +# scalars: $cuname and $cudom, and will unset when done. +# + my $clearvars; + if (($cuname eq '') && ($cudom eq '')) { + ($cuname,$cudom) = &Apache::lonnet::constructaccess($srcfile); + unless (($cuname eq '') && ($cudom eq '')) { + $clearvars = 1; + } + } my $thisembstyle=&Apache::loncommon::fileembstyle($thistype); - $r->print('' + my $output = '' .&mt('Publishing [_1]',&Apache::loncfile::display($srcfile)) - .'' - ); + .''; + unless ($usebuffer) { + $r->print($output); + $output = ''; + } # phase one takes # my ($source,$target,$style,$batch)=@_; - my ($outstring,$error)=&publish($srcfile,$targetfile,$thisembstyle,1); - $r->print(''.$outstring.''); + my ($outstring,$error)=&publish($srcfile,$targetfile,$thisembstyle,1,$nokeyref); + + if ($usebuffer) { + $output .= ''.$outstring.''; + } else { + $r->print(''.$outstring.''); + } # phase two takes # my ($source,$target,$style,$distarget,batch)=@_; # $env{'form.allmeta'},$env{'form.title'},$env{'form.author'},... if (!$error) { - $r->print(''); - &phasetwo($r,$srcfile,$targetfile,$thisembstyle,$thisdistarget,1); - $r->print(''); + if ($usebuffer) { + my ($result,$error) = &phasetwo($r,$srcfile,$targetfile,$thisembstyle,$thisdistarget,1,$usebuffer); + $output .= ''.$result.''; + } else { + &phasetwo($r,$srcfile,$targetfile,$thisembstyle,$thisdistarget,1); + } } %env=%oldenv; - return ''; + if ($clearvars) { + undef($cuname); + undef($cudom); + } + if ($usebuffer) { + return $output; + } else { + return ''; + } } ######################################### sub publishdirectory { - my ($r,$fn,$thisdisfn)=@_; + my ($r,$fn,$thisdisfn,$nokeyref,$crsauthor)=@_; $fn=~s/\/+/\//g; $thisdisfn=~s/\/+/\//g; my $thisdisresdir=$thisdisfn; @@ -2064,23 +2326,41 @@ sub publishdirectory { .&Apache::lonhtmlcommon::row_title(&mt('Target')) .''.$thisdisresdir.'' ); + 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'). - &common_access('dist',&mt('apply common copyright/distribution'), - ['default','domain','custom']). - &common_access('source',&mt('apply common source availability'), - ['closed','open']) + ''.&mt('Recurse').''. + &checkbox('pubrec','include subdirectories'). + ''. + ''.&mt('Force').''. + &checkbox('forcerepub','force republication of previously published files').''. + &checkbox('forceoverride','force directory level metadata over existing'). + ''. + ''.&mt('Exclude').''. + &checkbox('excludeunpub','exclude currently unpublished files').''. + &checkbox('excludemod','exclude modified files').''. + &checkbox('excludemodmeta','exclude files with modified metadata'). + ''. + ''.&mt('Actions').''. + &checkbox('obsolete','make file(s) obsolete').''); + unless ($crsauthor) { + $r->print(&common_access('dist',&mt('apply common copyright/distribution'), + ['default','domain','public','custom']).''); + } + $r->print(&common_access('source',&mt('apply common source availability'), + ['closed','open']). + '' ); $r->print(&Apache::lonhtmlcommon::row_closure(1) .&Apache::lonhtmlcommon::end_pick_box() @@ -2091,7 +2371,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)); @@ -2100,17 +2385,18 @@ sub publishdirectory { $cuid,$cgid,$crdev,$csize, $catime,$cmtime,$cctime, $cblksize,$cblocks)=stat($fn.'/'.$filename); - + my $extension=''; if ($filename=~/\.(\w+)$/) { $extension=$1; } if ($cmode&$dirptr) { if (($filename!~/^\./) && ($env{'form.pubrec'})) { - &publishdirectory($r,$fn.'/'.$filename,$thisdisfn.'/'.$filename); + &publishdirectory($r,$fn.'/'.$filename,$thisdisfn.'/'.$filename,$nokeyref,$crsauthor); } } 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, @@ -2118,22 +2404,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); + &batchpublish($r,$fn.'/'.$filename,$resdir.'/'.$filename,$nokeyref); } else { - $r->print(''.&mt('Skipping').' '.$filename.''); + my $reason; + if ($skipthis) { + $reason = $reasons{$skipthis}; + } else { + $reason = &mt('No changes needed to published resource or metadata'); + } + $r->print(''.&mt('Skipping').' '.$filename); + if ($reason) { + $r->print(' ('.$reason.')'); + } + $r->print(''); } $r->rflush(); } @@ -2293,38 +2629,27 @@ sub handler { return HTTP_NOT_FOUND; } -# -------------------------------- File is there and owned, init lookup tables. - - %addid=(); - - { - my $fh=Apache::File->new($r->dir_config('lonTabDir').'/addid.tab'); - while (<$fh>=~/(\w+)\s+(\w+)/) { - $addid{$1}=$2; - } - } - - %nokey=(); - - { - my $fh=Apache::File->new($r->dir_config('lonIncludes').'/un_keyword.tab'); - while (<$fh>) { - my $word=$_; - chomp($word); - $nokey{$word}=1; - } - } - -# ---------------------------------------------------------- Start page output. +# --------------------------------- File is there and owned, start page output &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; - + # Breadcrumbs &Apache::lonhtmlcommon::clear_breadcrumbs(); + my $crumbtext = 'Authoring Space'; + my $crumbhref = &Apache::loncommon::authorspace($fn); + my $crsauthor; + if ($env{'request.course.id'}) { + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + if ($crumbhref eq "/priv/$cdom/$cnum/") { + $crumbtext = 'Course Authoring Space'; + $crsauthor = 1; + } + } &Apache::lonhtmlcommon::add_breadcrumb({ - 'text' => 'Authoring Space', - 'href' => &Apache::loncommon::authorspace($fn), + 'text' => $crumbtext, + 'href' => $crumbhref, }); &Apache::lonhtmlcommon::add_breadcrumb({ 'text' => 'Resource Publication', @@ -2390,10 +2715,11 @@ END my $thistarget=$fn; $thistarget=~s/^\/priv\//\/res\//; my $thisdistarget=&HTML::Entities::encode($thistarget,'<>&"'); + my $nokeyref = &getnokey($r->dir_config('lonIncludes')); if ($fn=~/\/$/) { # -------------------------------------------------------- This is a directory - &publishdirectory($r,$docroot.$fn,$thisdisfn); + &publishdirectory($r,$docroot.$fn,$thisdisfn,$nokeyref,$crsauthor); $r->print( ''. &Apache::lonhtmlcommon::actionbox([ @@ -2466,7 +2792,7 @@ ENDDIFF } unless ($errorcount) { my ($outstring,$error)= - &publish($docroot.$fn,$docroot.$thistarget,$thisembstyle); + &publish($docroot.$fn,$docroot.$thistarget,$thisembstyle,undef,$nokeyref); $r->print($outstring); } else { $r->print(''. @@ -2474,7 +2800,9 @@ ENDDIFF ''); } } else { - &phasetwo($r,$docroot.$fn,$docroot.$thistarget,$thisembstyle,$thisdistarget); + my ($output,$error) = &phasetwo($r,$docroot.$fn,$docroot.$thistarget, + $thisembstyle,$thisdistarget); + $r->print($output); } } $r->print(&Apache::loncommon::end_page()); @@ -2482,6 +2810,24 @@ ENDDIFF return OK; } +BEGIN { + +# ----------------------------------- Read addid.tab + unless ($readit) { + %addid=(); + + { + my $tabdir = $Apache::lonnet::perlvar{'lonTabDir'}; + my $fh=Apache::File->new($tabdir.'/addid.tab'); + while (<$fh>=~/(\w+)\s+(\w+)/) { + $addid{$1}=$2; + } + } + } + $readit=1; +} + + 1; __END__
'.&mt('Warning: It can take up to 1 hour for rights changes to fully propagate.').'
'.&mt('Wrote Metadata').'
'.&mt('Synchronized SQL metadata database').'
'.&mt('Removing error messages:').' '.$delresult.'
'.&mt('Creating old version [_1]',$maxversion).'
'.&mt('Initial version').'
' - .&mt('Created directory [_1]' - ,''.$parts[$count].'') - .'
' + .&mt('Created directory [_1]' + ,''.$parts[$count].'') + .'
'.&mt('Done').'
'.$outstring.'
'); - &phasetwo($r,$srcfile,$targetfile,$thisembstyle,$thisdistarget,1); - $r->print('
'.$result.'