--- loncom/publisher/lonpublisher.pm 2002/08/09 17:59:14 1.90 +++ loncom/publisher/lonpublisher.pm 2002/09/16 13:05:50 1.95 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Publication Handler # -# $Id: lonpublisher.pm,v 1.90 2002/08/09 17:59:14 matthew Exp $ +# $Id: lonpublisher.pm,v 1.95 2002/09/16 13:05:50 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -67,28 +67,42 @@ =pod -=head1 Name +=head1 NAME lonpublisher - LON-CAPA publishing handler -=head1 Synopsis +=head1 SYNOPSIS -lonpublisher takes the proper steps to add resources to the LON-CAPA +B is used by B inside B. This is the +invocation by F: + + + PerlAccessHandler Apache::lonacc + SetHandler perl-script + PerlHandler Apache::lonpublisher + ErrorDocument 403 /adm/login + ErrorDocument 404 /adm/notfound.html + ErrorDocument 406 /adm/unauthorized.html + ErrorDocument 500 /adm/errorhandler + + +=head1 DESCRIPTION + +B takes the proper steps to add resources to the LON-CAPA digital library. This includes updating the metadata table in the LON-CAPA database. -=head1 Description - -lonpublisher is many things to many people. -To all people it is woefully documented. -This documentation conforms to this standard. +B is many things to many people. This module publishes a file. This involves gathering metadata, versioning the file, copying file from construction space to publication space, and copying metadata from construction space to publication space. -=head2 Internal Functions +=head2 SUBROUTINES + +Many of the undocumented subroutines implement various magical +parsing shortcuts. =over 4 @@ -130,9 +144,26 @@ my $cudom; =pod -=item metaeval +=item B + +Evaluates a string that contains metadata. This subroutine +stores values inside I<%metadatafields> and I<%metadatakeys>. +The hash key is a I<$unikey> corresponding to a unique id +that is descriptive of the parser location inside the XML tree. + +Parameters: + +=over 4 + +=item I<$metastring> + +A string that contains metadata. -Evaluate string with metadata +=back + +Returns: + +nothing =cut @@ -185,10 +216,34 @@ sub metaeval { =pod -=item metaread +=item B Read a metadata file +Parameters: + +=over + +=item I<$logfile> + +File output stream to output errors and warnings to. + +=item I<$fn> + +File name (including path). + +=back + +Returns: + +=over 4 + +=item Scalar string (if successful) + +XHTML text that indicates successful reading of the metadata. + +=back + =cut ######################################### @@ -196,10 +251,10 @@ Read a metadata file sub metaread { my ($logfile,$fn)=@_; unless (-e $fn) { - print $logfile 'No file '.$fn."\n"; + print($logfile 'No file '.$fn."\n"); return '
No file: '.$fn.''; } - print $logfile 'Processing '.$fn."\n"; + print($logfile 'Processing '.$fn."\n"); my $metastring; { my $metafh=Apache::File->new($fn); @@ -214,10 +269,30 @@ sub metaread { =pod -=item sqltime +=item B Convert 'time' format into a datetime sql format +Parameters: + +=over 4 + +=item I<$timef> + +Seconds since 00:00:00 UTC, January 1, 1970. + +=back + +Returns: + +=over 4 + +=item Scalar string + +MySQL-compatible datetime string. + +=back + =cut ######################################### @@ -236,15 +311,21 @@ sub sqltime { =pod -=item Form field generating functions +=item Form-field-generating subroutines. + +For input parameters, these subroutines take in values +such as I<$name>, I<$value> and other form field metadata. +The output (scalar string that is returned) is an XHTML +string which presents the form field (foreseeably inside +
tags). =over 4 -=item textfield +=item B -=item hiddenfield +=item B -=item selectbox +=item B =back @@ -255,12 +336,12 @@ sub sqltime { sub textfield { my ($title,$name,$value)=@_; return "\n

$title:
". - ''; + ''; } sub hiddenfield { my ($name,$value)=@_; - return "\n".''; + return "\n".''; } sub selectbox { @@ -283,7 +364,7 @@ sub selectbox { =pod -=item urlfixup +=item B Fix up a url? First step of publication @@ -316,9 +397,9 @@ sub urlfixup { =pod -=item absoluteurl +=item B -Currently undocumented +Currently undocumented. =cut @@ -339,7 +420,7 @@ sub absoluteurl { =pod -=item set_allow +=item B Currently undocumented @@ -370,7 +451,7 @@ sub set_allow { =pod -=item get_subscribed_hosts +=item B Currently undocumented @@ -404,7 +485,7 @@ sub get_subscribed_hosts { } } } else { - &Apache::lonnet::logthis("Un able to open $target.subscription"); + &Apache::lonnet::logthis("Unable to open $target.subscription"); } &Apache::lonnet::logthis("Got list of ".join(':',@subscribed)); return @subscribed; @@ -416,7 +497,7 @@ sub get_subscribed_hosts { =pod -=item get_max_ids_indices +=item B Currently undocumented @@ -460,7 +541,7 @@ sub get_max_ids_indices { =pod -=item get_all_text_unbalanced +=item B Currently undocumented @@ -502,7 +583,7 @@ sub get_all_text_unbalanced { =pod -=item fix_ids_and_indices +=item B Currently undocumented @@ -654,7 +735,7 @@ sub fix_ids_and_indices { =pod -=item store_metadata +=item B Store the metadata in the metadata table in the loncapa database. Uses lonmysql to access the database. @@ -710,9 +791,13 @@ sub store_metadata { =pod -=item publish +=item B + +This is the workhorse function of this module. This subroutine generates +backup copies, performs any automatic processing (prior to publication, +especially for rat and ssi files), -Currently undocumented. This is the workhorse function of this module. +I =cut @@ -769,15 +854,16 @@ sub publish { if ( &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.'/'. $thisdep.'.meta') eq '-1') { - $scrout.= - ' - Currently not available'; + $scrout.= ' - Currently not available'. + ''; } else { my %temphash=(&Apache::lonnet::declutter($target).'___'. &Apache::lonnet::declutter($thisdep).'___usage' => time); $thisdep=~/^\/res\/(\w+)\/(\w+)\//; if ((defined($1)) && (defined($2))) { - &Apache::lonnet::put('resevaldata',\%temphash,$1,$2); + &Apache::lonnet::put('nohist_resevaldata',\%temphash, + $1,$2); } } } @@ -786,23 +872,24 @@ sub publish { #Encode any High ASCII characters $outstring=&HTML::Entities::encode($outstring,"\200-\377"); -# ------------------------------------------------------------- Write modified +# ------------------------------------------------------------- Write modified. { my $org; unless ($org=Apache::File->new('>'.$source)) { print $logfile "No write permit to $source\n"; return - "No write permission to $source, FAIL"; + 'No write permission to '.$source. + ', FAIL'; } - print $org $outstring; + print($org $outstring); } $content=$outstring; } -# --------------------------------------------- Initial step done, now metadata +# -------------------------------------------- Initial step done, now metadata. -# ---------------------------------------- Storage for metadata keys and fields +# --------------------------------------- Storage for metadata keys and fields. %metadatafields=(); %metadatakeys=(); @@ -1013,8 +1100,8 @@ END $scrout.=&textfield('Publisher/Owner','owner', $metadatafields{'owner'}); -# --------------------------------------------------- Correct copyright for rat +# -------------------------------------------------- Correct copyright for rat. if ($style eq 'rat') { if ($metadatafields{'copyright'} eq 'public') { delete $metadatafields{'copyright'}; @@ -1031,10 +1118,11 @@ END (&Apache::loncommon::copyrightids)); } - my $copyright_help = Apache::loncommon::help_open_topic("Publishing_Copyright"); + my $copyright_help = + Apache::loncommon::help_open_topic('Publishing_Copyright'); $scrout =~ s/DISTRIBUTION:/'DISTRIBUTION: ' . $copyright_help/ge; return $scrout. - '

'; + '

'; } ######################################### @@ -1042,11 +1130,34 @@ END =pod -=item phasetwo +=item B Render second interface showing status of publication steps. This is publication step two. +Parameters: + +=over 4 + +=item I<$source> + +=item I<$target> + +=item I<$style> + +=item I<$distarget> + +=back + +Returns: + +=over 4 + +=item Scalar string + +String contains status (errors and warnings) and information associated with +the server's attempts at publication. + =cut ######################################### @@ -1075,17 +1186,20 @@ sub phasetwo { $metadatafields{'abstract'}=$ENV{'form.abstract'}; $metadatafields{'mime'}=$ENV{'form.mime'}; $metadatafields{'language'}=$ENV{'form.language'}; - $metadatafields{'creationdate'}=$ENV{'form.creationdate'}; - $metadatafields{'lastrevisiondate'}=$ENV{'form.lastrevisiondate'}; + $metadatafields{'creationdate'}= + &sqltime($ENV{'form.creationdate'}); + $metadatafields{'lastrevisiondate'}= + &sqltime($ENV{'form.lastrevisiondate'}); $metadatafields{'owner'}=$ENV{'form.owner'}; $metadatafields{'copyright'}=$ENV{'form.copyright'}; $metadatafields{'dependencies'}=$ENV{'form.dependencies'}; my $allkeywords=$ENV{'form.addkey'}; - if (exists($ENV{'form.keywords'}) && (ref($ENV{'form.keywords'}))) { - my @Keywords = @{$ENV{'form.keywords'}}; - foreach (@Keywords) { - $allkeywords.=','.$_; + if (exists($ENV{'form.keywords'})) { + if (ref($ENV{'form.keywords'})) { + $allkeywords .= ','.join(',',@{$ENV{'form.keywords'}}); + } else { + $allkeywords .= ','.$ENV{'form.keywords'}; } } $allkeywords=~s/\W+/\,/; @@ -1126,7 +1240,7 @@ sub phasetwo { $metadatafields{'version'} = 'current'; unless ($metadatafields{'copyright'} eq 'priv') { my ($error,$success) = &store_metadata(\%metadatafields); - if (! $success) { + if ($success) { $scrout.='

Synchronized SQL metadata database'; print $logfile "\nSynchronized SQL metadata database"; } else { @@ -1266,36 +1380,87 @@ if (-e $target) { return $warning.$scrout. - '


View Published Version'. + '
'. + 'View Published Version'. '

Back to Source'. '

Back to Source Directory'; + '">Back to Source Directory'; } +######################################### + +sub batchpublish { + my ($r,$srcfile)=@_; + my $thisdisfn=$srcfile; + $thisdisfn=~s/\/home\/korte\/public_html\///; + $srcfile=~s/\/+/\//g; + $r->print('

Publishing '.$thisdisfn.'

'); +} ######################################### + +sub publishdirectory { + my ($r,$fn,$thisdisfn)=@_; + $r->print('

Directory '.$thisdisfn.'/

'); + + my $dirptr=16384; # Mask indicating a directory in stat.cmode. + + opendir(DIR,$fn); + my @files=sort(readdir(DIR)); + foreach my $filename (@files) { + my ($cdev,$cino,$cmode,$cnlink, + $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); + } + } elsif ((&Apache::loncommon::fileembstyle($extension) ne 'hdn') && + ($filename!~/^[\#\.]/) && ($filename!~/\~$/)) { + &batchpublish($r,$fn.'/'.$filename); + $r->rflush(); + } + } + closedir(DIR); +} ######################################### =pod -=item handler +=item B A basic outline of the handler subroutine follows. =over 4 -=item Get query string for limited number of parameters +=item * + +Get query string for limited number of parameters. + +=item * -=item Check filename +Check filename. -=item File is there and owned, init lookup tables +=item * -=item Start page output +File is there and owned, init lookup tables. -=item Individual file +=item * -=item publish from $thisfn to $thistarget with $thisembstyle +Start page output. + +=item * + +Evaluate individual file, and then output information. + +=item * + +Publishing from $thisfn to $thistarget with $thisembstyle. =back @@ -1374,7 +1539,7 @@ sub handler { unless ($ENV{'form.phase'} eq 'two') { -# --------------------------------- File is there and owned, init lookup tables +# -------------------------------- File is there and owned, init lookup tables. %addid=(); @@ -1398,56 +1563,61 @@ unless ($ENV{'form.phase'} eq 'two') { } -# ----------------------------------------------------------- Start page output +# ---------------------------------------------------------- Start page output. $r->content_type('text/html'); $r->send_http_header; $r->print('LON-CAPA Publishing'); - $r->print( - ''); + $r->print(&Apache::loncommon::bodytag('Resource Publication')); my $thisfn=$fn; - -# ------------------------------------------------------------- Individual file - { - $thisfn=~/\.(\w+)$/; - my $thistype=$1; - my $thisembstyle=&Apache::loncommon::fileembstyle($thistype); - my $thistarget=$thisfn; + my $thistarget=$thisfn; - $thistarget=~s/^\/home/$targetdir/; - $thistarget=~s/\/public\_html//; + $thistarget=~s/^\/home/$targetdir/; + $thistarget=~s/\/public\_html//; + + my $thisdistarget=$thistarget; + $thisdistarget=~s/^$docroot//; - my $thisdistarget=$thistarget; - $thisdistarget=~s/^$docroot//; + my $thisdisfn=$thisfn; + $thisdisfn=~s/^\/home\/$cuname\/public_html\///; - my $thisdisfn=$thisfn; - $thisdisfn=~s/^\/home\/$cuname\/public_html\///; + if ($fn=~/\/$/) { +# -------------------------------------------------------- This is a directory + &publishdirectory($r,$fn,$thisdisfn); + + } else { +# ---------------------- Evaluate individual file, and then output information. + $thisfn=~/\.(\w+)$/; + my $thistype=$1; + my $thisembstyle=&Apache::loncommon::fileembstyle($thistype); $r->print('

Publishing '. &Apache::loncommon::filedescription($thistype).' '. - $thisdisfn.'

Target: '.$thisdistarget.'

'); + ''.$thisdisfn. + 'Target: '.$thisdistarget.'

'); - if (($cuname ne $ENV{'user.name'}) || ($cudom ne $ENV{'user.domain'})) { - $r->print('

Co-Author: '.$cuname.' at '.$cudom. - '

'); + if (($cuname ne $ENV{'user.name'}) || ($cudom ne $ENV{'user.domain'})) { + $r->print('

Co-Author: '.$cuname.' at '.$cudom. + '

'); } if (&Apache::loncommon::fileembstyle($thistype) eq 'ssi') { - $r->print('
Diffs with Current Version

'); + '&versionone=priv" target="cat">Diffs with Current Version

'); } -# ------------ We are publishing from $thisfn to $thistarget with $thisembstyle +# ------------------ Publishing from $thisfn to $thistarget with $thisembstyle. unless ($ENV{'form.phase'} eq 'two') { $r->print( - '


'.&publish($thisfn,$thistarget,$thisembstyle)); + '
'.&publish($thisfn,$thistarget,$thisembstyle)); } else { $r->print( - '
'.&phasetwo($thisfn,$thistarget,$thisembstyle,$thisdistarget)); + '
'.&phasetwo($thisfn,$thistarget, + $thisembstyle,$thisdistarget)); } }