--- loncom/publisher/lonpublisher.pm 2004/01/20 22:52:17 1.162 +++ loncom/publisher/lonpublisher.pm 2006/01/13 19:19:34 1.205 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Publication Handler # -# $Id: lonpublisher.pm,v 1.162 2004/01/20 22:52:17 albertel Exp $ +# $Id: lonpublisher.pm,v 1.205 2006/01/13 19:19:34 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -121,12 +121,12 @@ use HTML::LCParser; use Apache::lonxml; use Apache::loncacc; use DBI; -use Apache::lonnet(); +use Apache::lonnet; use Apache::loncommon(); use Apache::lonmysql; use Apache::lonlocal; use Apache::loncfile; -use Apache::lonmeta; +use LONCAPA::lonmetadata; use Apache::lonmsg; use vars qw(%metadatafields %metadatakeys); @@ -138,6 +138,9 @@ my $docroot; my $cuname; my $cudom; +my $registered_cleanup; +my $modified_urls; + =pod =item B @@ -199,7 +202,8 @@ sub metaeval { } } my $newentry=$parser->get_text('/'.$entry); - if ($entry eq 'customdistributionfile') { + if (($entry eq 'customdistributionfile') || + ($entry eq 'sourcerights')) { $newentry=~s/^\s*//; if ($newentry !~m|^/res|) { $newentry=$prefix.$newentry; } } @@ -322,20 +326,48 @@ sub textfield { $value=~s/\s+$//gs; $value=~s/\s+/ /gs; $title=&mt($title); + $env{'form.'.$name}=$value; return "\n

$title:". "


". ''; } +sub text_with_browse_field { + my ($title,$name,$value,$restriction)=@_; + $value=~s/^\s+//gs; + $value=~s/\s+$//gs; + $value=~s/\s+/ /gs; + $title=&mt($title); + $env{'form.'.$name}=$value; + return "\n

$title:". + "


". + ''. + 'Select '. + 'Search'; + +} + sub hiddenfield { my ($name,$value)=@_; + $env{'form.'.$name}=$value; return "\n".''; } +sub checkbox { + my ($name,$text)=@_; + return "\n
"; +} + sub selectbox { my ($title,$name,$value,$functionref,@idlist)=@_; $title=&mt($title); $value=(split(/\s*,\s*/,$value))[-1]; + if (defined($value)) { + $env{'form.'.$name}=$value; + } else { + $env{'form.'.$name}=$idlist[0]; + } my $selout="\n

$title:". '


'; } +sub select_level_form { + my ($value,$name)=@_; + $env{'form.'.$name}=$value; + if (!defined($value)) { $env{'form.'.$name}=0; } + return &Apache::loncommon::select_level_form($value,$name); +} ######################################### ######################################### @@ -458,7 +496,8 @@ sub get_subscribed_hosts { while ($filename=readdir(DIR)) { if ($filename=~/\Q$srcf\E\.(\w+)$/) { my $subhost=$1; - if (($subhost ne 'meta' && $subhost ne 'subscription') && + if (($subhost ne 'meta' && $subhost ne 'subscription' && + $subhost ne 'tmp') && ($subhost ne $Apache::lonnet::perlvar{'lonHostID'})) { push(@subscribed,$subhost); } @@ -469,7 +508,6 @@ sub get_subscribed_hosts { if ( $sh=Apache::File->new("$target.subscription") ) { &Apache::lonnet::logthis("opened $target.subscription"); while (my $subline=<$sh>) { - &Apache::lonnet::logthis("Trying $subline"); if ($subline =~ /(^\w+):/) { if ($1 ne $Apache::lonnet::perlvar{'lonHostID'}) { push(@subscribed,$1); @@ -515,7 +553,8 @@ sub get_max_ids_indices { my $counter; if ($counter=$addid{$token->[1]}) { if ($counter eq 'id') { - if (defined($token->[2]->{'id'})) { + if (defined($token->[2]->{'id'}) && + $token->[2]->{'id'} !~ /^\s*$/) { $maxid=($token->[2]->{'id'}>$maxid)?$token->[2]->{'id'}:$maxid; if (exists($allids{$token->[2]->{'id'}})) { $duplicateids=1; @@ -527,7 +566,8 @@ sub get_max_ids_indices { $needsfixup=1; } } else { - if (defined($token->[2]->{'index'})) { + if (defined($token->[2]->{'index'}) && + $token->[2]->{'index'} !~ /^\s*$/) { $maxindex=($token->[2]->{'index'}>$maxindex)?$token->[2]->{'index'}:$maxindex; } else { $needsfixup=1; @@ -569,11 +609,11 @@ sub get_all_text_unbalanced { } elsif ($token->[0] eq 'E') { $result.=$token->[2]; } - if ($result =~ /(.*)\Q$tag\E(.*)/s) { + if ($result =~ /\Q$tag\E/s) { + ($result,my $redo)=$result =~ /(.*)\Q$tag\E(.*)/is; #&Apache::lonnet::logthis('Got a winner with leftovers ::'.$2); #&Apache::lonnet::logthis('Result is :'.$1); - $result=$1; - my $redo=$tag.$2; + $redo=$tag.$redo; push (@$pars,HTML::LCParser->new(\$redo)); $$pars[-1]->xml_mode('1'); last; @@ -636,30 +676,37 @@ sub fix_ids_and_indices { $allow{$token->[2]->{'src'}}=1; next; } + if ($lctag eq 'base') { next; } my %parms=%{$token->[2]}; $counter=$addid{$tag}; if (!$counter) { $counter=$addid{$lctag}; } if ($counter) { if ($counter eq 'id') { - unless (defined($parms{'id'})) { + unless (defined($parms{'id'}) && + $parms{'id'}!~/^\s*$/) { $maxid++; $parms{'id'}=$maxid; - print $logfile 'ID: '.$tag.':'.$maxid."\n"; + print $logfile 'ID(new) : '.$tag.':'.$maxid."\n"; + } else { + print $logfile 'ID(kept): '.$tag.':'.$parms{'id'}."\n"; } } elsif ($counter eq 'index') { - unless (defined($parms{'index'})) { + unless (defined($parms{'index'}) && + $parms{'index'}!~/^\s*$/) { $maxindex++; $parms{'index'}=$maxindex; print $logfile 'Index: '.$tag.':'.$maxindex."\n"; } } } - foreach my $type ('src','href','background','bgimg') { - foreach my $key (keys(%parms)) { - if ($key =~ /^$type$/i) { - $parms{$key}=&set_allow(\%allow,$logfile, - $target,$tag, - $parms{$key}); + unless ($parms{'type'} eq 'zombie') { + foreach my $type ('src','href','background','bgimg') { + foreach my $key (keys(%parms)) { + if ($key =~ /^$type$/i) { + $parms{$key}=&set_allow(\%allow,$logfile, + $target,$tag, + $parms{$key}); + } } } } @@ -788,55 +835,56 @@ sub store_metadata { &Apache::lonnet::logthis($error); return ($error,undef); } + my $dbh = &Apache::lonmysql::get_dbh(); if (($metadata{'obsolete'}) || ($metadata{'copyright'} eq 'priv') || ($metadata{'copyright'} eq 'custom')) { -# remove this entry - $status=&Apache::lonmysql::remove_from_table - ('metadata','url',$metadata{'url'}); + # remove this entry + $status=&LONCAPA::lonmetadata::delete_metadata($dbh,undef, + $metadata{'url'}); } else { -# store new data -# adjust some values to metadatadatabase (e.g., "usage" is a reserved word) - $metadata{'creationdate'}= - &Apache::lonmysql::sqltime($metadata{'creationdate'}); - $metadata{'lastrevisiondate'}= - &Apache::lonmysql::sqltime($metadata{'lastrevisiondate'}); - $metadata{'sequsage'}=$metadata{'usage'}; - $metadata{'sequsage_list'}=$metadata{'usage_list'}; - my %newmetadata=(); -# see if we have old entries - my @oldmeta=&Apache::lonmysql::get_rows('metadata', - "url LIKE BINARY '". - $metadata{'url'}."'"); - if ($#oldmeta==0) { -# yes, there is one old entry, transfer to newmetadata - %newmetadata=&Apache::lonmeta::metadata_col_to_hash(@{$oldmeta[0]}); -# remove old entry - $status=&Apache::lonmysql::remove_from_table - ('metadata','url',$metadata{'url'}); - } elsif ($#oldmeta>0) { -# more than one entry fit - how did that happen? - $error='Error occured retrieving old values in '. - 'metadata table in LON-CAPA database: '.$#oldmeta. - ' matches'; - &Apache::lonnet::logthis($error); - return ($error,undef); - } -# store new data on top of it - foreach (keys %metadata) { - $newmetadata{$_}=$metadata{$_}; - } - $status = &Apache::lonmysql::store_row('metadata',\%newmetadata); + $status = &LONCAPA::lonmetadata::update_metadata($dbh,undef, + \%metadata); } - if (! defined($status)) { + if (defined($status) && $status ne '') { $error='Error occured storing new values in '. 'metadata table in LON-CAPA database'; &Apache::lonnet::logthis($error); + &Apache::lonnet::logthis($status); return ($error,undef); } return (undef,$status); } +# ========================================== Parse file for errors and warnings + +sub checkonthis { + my ($r,$source)=@_; + my $uri=&Apache::lonnet::hreflocation($source); + $uri=~s/\/$//; + my $result=&Apache::lonnet::ssi_body($uri, + ('grade_target'=>'web', + 'return_only_error_and_warning_counts' => 1)); + my ($errorcount,$warningcount)=split(':',$result); + if (($errorcount) || ($warningcount)) { + $r->print('
'.$uri.': '); + if ($errorcount) { + $r->print(''. + $errorcount.' '. + &mt('error(s)').' '); + } + if ($warningcount) { + $r->print(''. + $warningcount.' '. + &mt('warning(s)').''); + } + } else { + #$r->print(''.&mt('ok').''); + } + $r->rflush(); + return ($warningcount,$errorcount); +} + # ============================================== Parse file itself for metadata # # parses a file with target meta, sets global %metadatafields %metadatakeys @@ -890,7 +938,7 @@ sub publish { return (''.&mt('No write permission to user directory, FAIL').'',1); } print $logfile -"\n\n================= Publish ".localtime()." Phase One ================\n".$ENV{'user.name'}.'@'.$ENV{'user.domain'}."\n"; +"\n\n================= Publish ".localtime()." Phase One ================\n".$env{'user.name'}.'@'.$env{'user.domain'}."\n"; if (($style eq 'ssi') || ($style eq 'rat') || ($style eq 'prv')) { # ------------------------------------------------------- This needs processing @@ -920,11 +968,11 @@ sub publish { $allowstr.="\n".''; } $scrout.='
'; - unless ($thisdep=~/\*/) { + if ($thisdep!~/\*/ && $thisdep!~m|^/adm/|) { $scrout.=''; } $scrout.=''.$thisdep.''; - unless ($thisdep=~/\*/) { + if ($thisdep!~/\*/ && $thisdep!~m|^/adm/|) { $scrout.=''; if ( &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.'/'. @@ -943,13 +991,8 @@ sub publish { } } } - $outstring=~s/\n*(\<\/[^\>]+\>)\s*$/$allowstr\n$1\n/s; + $outstring=~s/\n*(\<\/[^\>]+\>[^<]*)$/$allowstr\n$1\n/s; -### FIXME: is this really what we want? -# I dont' think so, to will corrupt any UTF-8 resources at least, -# and any encoding other than ISO-8859-1 will probably break - #Encode any High ASCII characters - #$outstring=&HTML::Entities::encode($outstring,"\200-\377"); # ------------------------------------------------------------- Write modified. { @@ -982,11 +1025,11 @@ sub publish { } # ------------------------------------------------ First, check out environment - unless (-e $source.'.meta') { - $metadatafields{'author'}=$ENV{'environment.firstname'}.' '. - $ENV{'environment.middlename'}.' '. - $ENV{'environment.lastname'}.' '. - $ENV{'environment.generation'}; + if ((!(-e $source.'.meta')) || ($env{'form.forceoverride'})) { + $metadatafields{'author'}=$env{'environment.firstname'}.' '. + $env{'environment.middlename'}.' '. + $env{'environment.lastname'}.' '. + $env{'environment.generation'}; $metadatafields{'author'}=~s/\s+/ /g; $metadatafields{'author'}=~s/\s+$//; $metadatafields{'owner'}=$cuname.'@'.$cudom; @@ -1007,6 +1050,7 @@ sub publish { $scrout.=&metaread($logfile,$currentpath.'default.meta',$prefix); $prefix=~s|^\.\./||; } + # ----------------------------------------------------------- Parse file itself # read %metadatafields from file itself @@ -1031,10 +1075,18 @@ sub publish { delete $metadatafields{$_}; } } +# ------------------------------------------------------------- Save some stuff + my %savemeta=(); + foreach ('title') { + $savemeta{$_}=$metadatafields{$_}; + } # ------------------------------------------ See if anything new in file itself $allmeta=&parseformeta($source,$style); - +# ----------------------------------------------------------- Restore the stuff + foreach (keys %savemeta) { + $metadatafields{$_}=$savemeta{$_}; + } } @@ -1094,32 +1146,41 @@ sub publish { } - foreach (split(/\W+/,$metadatafields{'keywords'})) { - $keywords{$_}=1; + foreach my $addkey (split(/[\"\'\,\;]/,$metadatafields{'keywords'})) { + $addkey=~s/\s+/ /g; + $addkey=~s/^\s//; + $addkey=~s/\s$//; + if ($addkey=~/\w/) { + $keywords{$addkey}=1; + } } # --------------------------------------------------- Now we also have keywords # ============================================================================= -# INTERACTIVE MODE -# - unless ($batch) { - $scrout.= - '
'. - '

'. - &hiddenfield('phase','two'). - &hiddenfield('filename',$ENV{'form.filename'}). - &hiddenfield('allmeta',&Apache::lonnet::escape($allmeta)). - &hiddenfield('dependencies',join(',',keys %allow)). - &textfield('Title','title',$metadatafields{'title'}). - &textfield('Author(s)','author',$metadatafields{'author'}). - &textfield('Subject','subject',$metadatafields{'subject'}); - -# --------------------------------------------------- Scan content for keywords - - my $keywords_help = Apache::loncommon::help_open_topic("Publishing_Keywords"); - my $KEYWORDS=&mt('Keywords'); - my $CheckAll=&mt('check all'); - my $UncheckAll=&mt('uncheck all'); - my $keywordout=<<"END"; +# interactive mode html goes into $intr_scrout +# batch mode throws away this HTML +# additionally all of the field functions have a by product of setting +# $env{'from.'..} so that it can be used by the phase two handler in +# batch mode + + my $intr_scrout.= + ''. + '

'.($env{'form.makeobsolete'}?'':'').'

'. + &hiddenfield('phase','two'). + &hiddenfield('filename',$env{'form.filename'}). + &hiddenfield('allmeta',&Apache::lonnet::escape($allmeta)). + &hiddenfield('dependencies',join(',',keys %allow)); + unless ($env{'form.makeobsolete'}) { + $intr_scrout.= + &textfield('Title','title',$metadatafields{'title'}). + &textfield('Author(s)','author',$metadatafields{'author'}). + &textfield('Subject','subject',$metadatafields{'subject'}); + # --------------------------------------------------- Scan content for keywords + + my $keywords_help = Apache::loncommon::help_open_topic("Publishing_Keywords"); + my $KEYWORDS=&mt('Keywords'); + my $CheckAll=&mt('check all'); + my $UncheckAll=&mt('uncheck all'); + my $keywordout=<<"END"; '); $r->print(&Apache::loncommon::bodytag('Resource Publication')); @@ -1925,7 +2058,7 @@ sub handler { if ($fn=~/\/$/) { # -------------------------------------------------------- This is a directory &publishdirectory($r,$fn,$thisdisfn); - $r->print('
'.&mt('Done').'
'.&mt('Return to Directory').''); @@ -1935,6 +2068,7 @@ sub handler { $thisfn=~/\.(\w+)$/; my $thistype=$1; my $thisembstyle=&Apache::loncommon::fileembstyle($thistype); + if ($thistype eq 'page') { $thisembstyle = 'rat'; } $r->print('

'.&mt('Publishing').' '. &Apache::loncommon::filedescription($thistype).' '); @@ -1945,7 +2079,7 @@ ENDCAPTION $r->print('

'.&mt('Target').': '. $thisdistarget.'
'); - if (($cuname ne $ENV{'user.name'})||($cudom ne $ENV{'user.domain'})) { + if (($cuname ne $env{'user.name'})||($cudom ne $env{'user.domain'})) { $r->print('

'.&mt('Co-Author').': '. $cuname.&mt(' at ').$cudom.'

'); } @@ -1960,12 +2094,24 @@ ENDDIFF # ------------------ Publishing from $thisfn to $thistarget with $thisembstyle. - unless ($ENV{'form.phase'} eq 'two') { - my ($outstring,$error)=&publish($thisfn,$thistarget,$thisembstyle); - $r->print('
'.$outstring); + unless ($env{'form.phase'} eq 'two') { +# ---------------------------------------------------------- Parse for problems + my ($warningcount,$errorcount); + if ($thisembstyle eq 'ssi') { + ($warningcount,$errorcount)=&checkonthis($r,$thisfn); + } + unless ($errorcount) { + my ($outstring,$error)= + &publish($thisfn,$thistarget,$thisembstyle); + $r->print('
'.$outstring); + } else { + $r->print('

'. + &mt('The document contains errors and cannot be published.'). + '

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