--- loncom/interface/lonmeta.pm 2001/12/24 21:09:08 1.11 +++ loncom/interface/lonmeta.pm 2006/08/08 19:35:53 1.165 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Metadata display handler # -# $Id: lonmeta.pm,v 1.11 2001/12/24 21:09:08 www Exp $ +# $Id: lonmeta.pm,v 1.165 2006/08/08 19:35:53 banghart Exp $ # # Copyright Michigan State University Board of Trustees # @@ -17,243 +17,1323 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ -# -# (TeX Content Handler -# -# 05/29/00,05/30,10/11 Gerd Kortemeyer) -# -# 10/19,10/21,10/23,11/27,08/09/01,12/22,12/24 Gerd Kortemeyer + package Apache::lonmeta; use strict; +use LONCAPA::lonmetadata(); use Apache::Constants qw(:common); -use Apache::lonnet(); +use Apache::lonnet; use Apache::loncommon(); +use Apache::lonhtmlcommon(); +use Apache::lonmsg; +use Apache::lonpublisher; +use Apache::lonlocal; +use Apache::lonmysql; +use Apache::lonmsg; +use lib '/home/httpd/lib/perl/'; +use LONCAPA; + + +############################################################ +############################################################ +## +## &get_dynamic_metadata_from_sql($url) +## +## Queries sql database for dynamic metdata +## Returns a hash of hashes, with keys of urls which match $url +## Returned fields are given below. +## +## Examples: +## +## %DynamicMetadata = &Apache::lonmeta::get_dynmaic_metadata_from_sql +## ('/res/msu/korte/'); +## +## $DynamicMetadata{'/res/msu/korte/example.problem'}->{$field} +## +############################################################ +############################################################ +sub get_dynamic_metadata_from_sql { + my ($url) = shift(); + my ($authordom,$author)=($url=~m:^/res/(\w+)/(\w+)/:); + if (! defined($authordom)) { + $authordom = shift(); + } + if (! defined($author)) { + $author = shift(); + } + if (! defined($authordom) || ! defined($author)) { + return (); + } + my $query = 'SELECT * FROM metadata WHERE url LIKE "'.$url.'%"'; + my $server = &Apache::lonnet::homeserver($author,$authordom); + my $reply = &Apache::lonnet::metadata_query($query,undef,undef, + ,[$server]); + return () if (! defined($reply) || ref($reply) ne 'HASH'); + my $filename = $reply->{$server}; + if (! defined($filename) || $filename =~ /^error/) { + return (); + } + my $max_time = time + 10; # wait 10 seconds for results at most + my %ReturnHash; + # + # Look for results + my $finished = 0; + while (! $finished && time < $max_time) { + my $datafile=$Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/'.$filename; + if (! -e "$datafile.end") { next; } + my $fh; + if (!($fh=Apache::File->new($datafile))) { next; } + while (my $result = <$fh>) { + chomp($result); + next if (! $result); + my %hash=&LONCAPA::lonmetadata::metadata_col_to_hash(map { &unescape($_) } split(/\,/,$result)); + foreach my $key (keys(%hash)) { + $ReturnHash{$hash{'url'}}->{$key}=$hash{$key}; + } + } + $finished = 1; + } + # + return %ReturnHash; +} -# ----------------------------------------- Fetch and evaluate dynamic metadata +# Fetch and evaluate dynamic metadata sub dynamicmeta { my $url=&Apache::lonnet::declutter(shift); $url=~s/\.meta$//; my ($adomain,$aauthor)=($url=~/^(\w+)\/(\w+)\//); - my $regexp=&Apache::lonnet::escape($url); + my $regexp=$url; $regexp=~s/(\W)/\\$1/g; $regexp='___'.$regexp.'___'; - my %evaldata=&Apache::lonnet::dump - ('resevaldata',$adomain,$aauthor,$regexp); - my %sum; - my %cnt; - my %listitems=('count' => 'add', - 'course' => 'add', - 'avetries' => 'avg', - 'stdno' => 'add', - 'difficulty' => 'avg', - 'clear' => 'avg', - 'technical' => 'avg', - 'helpful' => 'avg', - 'correct' => 'avg', - 'depth' => 'avg', - 'comments' => 'app', - 'usage' => 'cnt' - ); - foreach (keys %evaldata) { - $_=~/___(\w+)$/; - if (defined($cnt{$1})) { $cnt{$1}++; } else { $cnt{$1}=1; } - unless ($listitems{$1} eq 'app') { - if (defined($sum{$1})) { - $sum{$1}+=$evaldata{$_}; - } else { - $sum{$1}=$evaldata{$_}; - } + my %evaldata=&Apache::lonnet::dump('nohist_resevaldata',$adomain, + $aauthor,$regexp); + my %DynamicData = &LONCAPA::lonmetadata::process_reseval_data(\%evaldata); + my %Data = &LONCAPA::lonmetadata::process_dynamic_metadata($url, + \%DynamicData); + # + # Deal with 'count' separately + $Data{'count'} = &access_count($url,$aauthor,$adomain); + # + # Debugging code I will probably need later + if (0) { + &Apache::lonnet::logthis('Dynamic Metadata'); + while(my($k,$v)=each(%Data)){ + &Apache::lonnet::logthis(' "'.$k.'"=>"'.$v.'"'); + } + &Apache::lonnet::logthis('-------------------'); + } + return %Data; +} + +sub access_count { + my ($src,$author,$adomain) = @_; + my %countdata=&Apache::lonnet::dump('nohist_accesscount',$adomain, + $author,$src); + if (! exists($countdata{$src})) { + return &mt('Not Available'); + } else { + return $countdata{$src}; + } +} + +# Try to make an alt tag if there is none +sub alttag { + my ($base,$src)=@_; + my $fullpath=&Apache::lonnet::hreflocation($base,$src); + my $alttag=&Apache::lonnet::metadata($fullpath,'title').' '. + &Apache::lonnet::metadata($fullpath,'subject').' '. + &Apache::lonnet::metadata($fullpath,'abstract'); + $alttag=~s/\s+/ /gs; + $alttag=~s/\"//gs; + $alttag=~s/\'//gs; + $alttag=~s/\s+$//gs; + $alttag=~s/^\s+//gs; + if ($alttag) { + return $alttag; + } else { + return &mt('No information available'); + } +} + +# Author display +sub authordisplay { + my ($aname,$adom)=@_; + return &Apache::loncommon::aboutmewrapper + (&Apache::loncommon::plainname($aname,$adom), + $aname,$adom,'preview').' ['.$aname.':'.$adom.']'; +} + +# Pretty display +sub evalgraph { + my $value=shift; + if (! $value) { + return ''; + } + my $val=int($value*10.+0.5)-10; + my $output='
  | '; + } else { + $output.=''. + ' | '; + } + $output.=' | '; + if ($val>20) { + $output.=' | '. + ' | '; + } else { + $output.=' |   | '; + } + $output.='('.sprintf("%5.2f",$value).') |
'; } else { - if (defined($sum{$1})) { - if ($evaldata{$_}) { - $sum{$1}.=' | '; } } - my %returnhash=(); - foreach (keys %cnt) { - if ($listitems{$_} eq 'avg') { - $returnhash{$_}=int(($sum{$_}/$cnt{$_})*100.0+0.5)/100.0; - } elsif ($listitems{$_} eq 'cnt') { - $returnhash{$_}=$cnt{$_}; - } else { - $returnhash{$_}=$sum{$_}; - } + $output.=' | ('.sprintf("%3.2f",$value).') |
Author(s) | -$content{'author'} | ||
Subject | -$content{'subject'} | ||
Keyword(s) | -$content{'keywords'} | ||
Notes | -$content{'notes'} | ||
Abstract | -$content{'abstract'} | ||
MIME Type | -$mime ($content{'mime'}) | ||
Language | -$language | ||
Creation Date | -$creationdate | ||
-Last Revision Date | $lastrevisiondate | ||
Publisher/Owner | -$content{'owner'} | ||
Copyright/Distribution | -$content{'copyright'}
+ my ($port_path,$group);
+ if ($uri =~ m{^/editupload/\Q$cdom\E/\Q$cnum\E/groups/}) {
+ $group = (split('/',$uri))[5];
+ $port_path = '/adm/coursegrp_portfolio';
+ } else {
+ $port_path = '/adm/portfolio';
+ }
+ if ($env{'form.group'} ne $group) {
+ $env{'form.group'} = $group;
+ }
+ return ($port_path,$group);
+}
+
+sub portfolio_display_uri {
+ my ($uri,$as_links)=@_;
+
+ my ($port_path,$group) = &get_port_path_and_group($uri);
+
+ $uri =~ s|.*/(portfolio/.*)$|$1|;
+ my ($res_uri,$meta_uri) = ($uri,$uri);
+ if ($uri =~ /\.meta$/) {
+ $res_uri =~ s/\.meta//;
+ } else {
+ $meta_uri .= '.meta';
+ }
+
+ my ($path) = ($res_uri =~ m|^portfolio(.*/)[^/]*$|);
+ if ($as_links) {
+ $res_uri = &portfolio_linked_path($res_uri,$group,$port_path);
+ $meta_uri = &portfolio_linked_path($meta_uri,$group,$port_path);
+ }
+ return ($res_uri,$meta_uri,$path);
+}
+
+sub pre_select_course {
+ my ($r,$uri) = @_;
+ my $output;
+ my $fn=&Apache::lonnet::filelocation('',$uri);
+ my ($res_uri,$meta_uri,$path) = &portfolio_display_uri($uri);
+ %Apache::lonpublisher::metadatafields=();
+ %Apache::lonpublisher::metadatakeys=();
+ my $result=&Apache::lonnet::getfile($fn);
+ if ($result == -1){
+ $r->print(&mt('Creating new file [_1]'),$meta_uri);
+ } else {
+ &Apache::lonpublisher::metaeval($result);
+ }
+ $r->print(' '); + + my ($port_path,$group) = &get_port_path_and_group($uri); + $r->print(' '); + + return; +} +sub select_course { + my $output=$/; + my $current_restriction= + $Apache::lonpublisher::metadatafields{'courserestricted'}; + my $selected = ($current_restriction eq 'none' ? 'selected="selected"' + : ''); + + $output .= ' '; + return ($output); +} +# Pretty printing of metadata field + +sub prettyprint { + my ($type,$value,$target,$prefix,$form,$noformat)=@_; +# $target,$prefix,$form are optional and for filecrumbs only + if (! defined($value)) { + return ' '; + } + # Title + if ($type eq 'title') { + return ''.$value.''; + } + # Dates + if (($type eq 'creationdate') || + ($type eq 'lastrevisiondate')) { + return ($value?&Apache::lonlocal::locallocaltime( + &Apache::lonmysql::unsqltime($value)): + &mt('not available')); + } + # Language + if ($type eq 'language') { + return &Apache::loncommon::languagedescription($value); + } + # Copyright + if ($type eq 'copyright') { + return &Apache::loncommon::copyrightdescription($value); + } + # Copyright + if ($type eq 'sourceavail') { + return &Apache::loncommon::source_copyrightdescription($value); + } + # MIME + if ($type eq 'mime') { + return ' '. + &Apache::loncommon::filedescription($value); + } + # Person + if (($type eq 'author') || + ($type eq 'owner') || + ($type eq 'modifyinguser') || + ($type eq 'authorspace')) { + $value=~s/(\w+)(\:|\@)(\w+)/&authordisplay($1,$3)/gse; + return $value; + } + # Gradelevel + if (($type eq 'lowestgradelevel') || + ($type eq 'highestgradelevel')) { + return &Apache::loncommon::gradeleveldescription($value); + } + # Only for advance users below + if (! $env{'user.adv'}) { + return '- '.&mt('not displayed').' -'; + } + # File + if (($type eq 'customdistributionfile') || + ($type eq 'obsoletereplacement') || + ($type eq 'goto_list') || + ($type eq 'comefrom_list') || + ($type eq 'sequsage_list') || + ($type eq 'dependencies')) { + return '
'.&Apache::lonnet::clutter($uri).''); + my ($domain,$author)=($uri=~/^(\w+)\/(\w+)\//); + if (&Apache::loncacc::constructaccess('/~'.$author.'/',$domain)) { + if ($env{'form.clearbombs'}) { + &Apache::lonmsg::clear_author_res_msg($uri); + } + my $clear=&mt('Clear all Messages in Subdirectory'); + $r->print(<'); + } + } + } else { + $r->print(&mt('Not authorized')); + } + return; +} + +##################################################### +##################################################### +### ### +### Uneditable Metadata Display ### +### ### +##################################################### +##################################################### +sub present_uneditable_metadata { + my ($r,$uri) = @_; + # + my $uploaded = ($uri =~ m|/uploaded/|); + my %content=(); + # Read file + foreach (split(/\,/,&Apache::lonnet::metadata($uri,'keys'))) { + $content{$_}=&Apache::lonnet::metadata($uri,$_); + } + # Render Output + # displayed url + my ($thisversion)=($uri=~/\.(\d+)\.(\w+)\.meta$/); + $uri=~s/\.meta$//; + my $disuri=&Apache::lonnet::clutter($uri); + $disuri=~s/^\/adm\/wrapper//; + # version + my $versiondisplay=''; + if (!$uploaded) { + my $currentversion=&Apache::lonnet::getversion($disuri); + if ($thisversion) { + $versiondisplay=&mt('Version').': '.$thisversion. + ' ('.&mt('most recent version').': '. + ($currentversion>0 ? + $currentversion : + &mt('information not available')).')'; + } else { + $versiondisplay='Version: '.$currentversion; + } + } + # crumbify displayed URL uri target prefix form size + $disuri=&Apache::lonhtmlcommon::crumbs($disuri,undef, undef, undef,'+1'); + $disuri =~ s: ::g; + # obsolete + my $obsolete=$content{'obsolete'}; + my $obsoletewarning=''; + if (($obsolete) && ($env{'user.adv'})) { + $obsoletewarning=' '. + &mt('This resource has been marked obsolete by the author(s)'). + ' '; + } + # + my %lt=&fieldnames(); + my $table=''; + my $title = $content{'title'}; + if (! defined($title)) { + $title = 'Untitled Resource'; + } + my @fields; + if ($uploaded) { + @fields = ('title','author','subject','keywords','notes','abstract', + 'lowestgradelevel','highestgradelevel','standards','mime', + 'owner'); + } else { + @fields = ('title', + 'author', + 'subject', + 'keywords', + 'notes', + 'abstract', + 'lowestgradelevel', + 'highestgradelevel', + 'standards', + 'mime', + 'language', + 'creationdate', + 'lastrevisiondate', + 'owner', + 'copyright', + 'customdistributionfile', + 'sourceavail', + 'sourcerights', + 'obsolete', + 'obsoletereplacement'); + } + foreach my $field (@fields) { + $table.=''.$lt{$field}.
+ ' | '.
+ &prettyprint($field,$content{$field}).' |
+$disuri Dynamic Metadata (updated periodically)'); - my %items=( - 'count' => 'Network-wide number of accesses (hits)', - 'course' => 'Network-wide number of courses using resource', - 'usage' => 'Number of resources using or importing resource', - 'clear' => 'Material presented in clear way', - 'depth' => 'Material covered with sufficient depth', - 'helpful' => 'Material is helpful', - 'correct' => 'Material appears to be correct', - 'technical' => 'Resource is technically correct', - 'avetries' => 'Average number of tries till solved', - 'stdno' => 'Total number of students who have worked on this problem', - 'difficulty' => 'Degree of difficulty'); - my %dynmeta=&dynamicmeta($uri); - $r->print( -' |
'.$items{$_}.' | '. -$dynmeta{$_}." |
'.$items{$_}.' | '. -$dynmeta{$_}." |
'.$items{$_}.' | '. -$dynmeta{$_}." |
'.$dynmeta{'comments'}.''); - } -# ------------------------------------------------------------- All other stuff - $r->print( - '