# The LearningOnline Network with CAPA # Metadata display handler # # $Id: lonmeta.pm,v 1.148 2005/12/19 23:19:18 albertel Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # 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 # 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/ package Apache::lonmeta; use strict; use LONCAPA::lonmetadata(); use Apache::Constants qw(:common); use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon(); use Apache::lonmsg; use Apache::lonpublisher; use Apache::lonlocal; use Apache::lonmysql; use Apache::lonmsg; ############################################################ ############################################################ ## ## &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 @Fields = ('url','count','course', 'goto','goto_list', 'comefrom','comefrom_list', 'sequsage','sequsage_list', 'stdno','stdno_list', 'dependencies', 'avetries','avetries_list', 'difficulty','difficulty_list', 'disc','disc_list', 'clear','technical','correct', 'helpful','depth'); # my $query = 'SELECT '.join(',',@Fields). ' 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 @Data = map { &Apache::lonnet::unescape($_); } split(',',$result); my $url = $Data[0]; for (my $i=0;$i<=$#Fields;$i++) { $ReturnHash{$url}->{$Fields[$i]}=$Data[$i]; } } $finished = 1; } # return %ReturnHash; } # Fetch and evaluate dynamic metadata sub dynamicmeta { my $url=&Apache::lonnet::declutter(shift); $url=~s/\.meta$//; my ($adomain,$aauthor)=($url=~/^(\w+)\/(\w+)\//); my $regexp=$url; $regexp=~s/(\W)/\\$1/g; $regexp='___'.$regexp.'___'; 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=''; if ($val>=20) { $output.=''; } else { $output.=''. ''; } $output.=''; if ($val>20) { $output.=''. ''; } else { $output.=''; } $output.='
          ('.sprintf("%5.2f",$value).')
'; return $output; } sub diffgraph { my $value=shift; if (! $value) { return ''; } my $val=int(40.0*$value+0.5); my @colors=('#FF9933','#EEAA33','#DDBB33','#CCCC33', '#BBDD33','#CCCC33','#DDBB33','#EEAA33'); my $output=''; for (my $i=0;$i<8;$i++) { if ($val>$i*5) { $output.=''; } else { $output.=''; } } $output.='
   ('.sprintf("%3.2f",$value).')
'; return $output; } # The field names sub fieldnames { my $file_type=shift; my %fields = ('title' => 'Title', 'author' =>'Author(s)', 'authorspace' => 'Author Space', 'modifyinguser' => 'Last Modifying User', 'subject' => 'Subject', 'standards' => 'Standards', 'keywords' => 'Keyword(s)', 'notes' => 'Notes', 'abstract' => 'Abstract', 'lowestgradelevel' => 'Lowest Grade Level', 'highestgradelevel' => 'Highest Grade Level', 'courserestricted' => 'Course Restricting Metadata'); if (! defined($file_type) || $file_type ne 'portfolio') { %fields = (%fields, 'domain' => 'Domain', 'mime' => 'MIME Type', 'language' => 'Language', 'creationdate' => 'Creation Date', 'lastrevisiondate' => 'Last Revision Date', 'owner' => 'Publisher/Owner', 'copyright' => 'Copyright/Distribution', 'customdistributionfile' => 'Custom Distribution File', 'sourceavail' => 'Source Available', 'sourcerights' => 'Source Custom Distribution File', 'obsolete' => 'Obsolete', 'obsoletereplacement' => 'Suggested Replacement for Obsolete File', 'count' => 'Network-wide number of accesses (hits)', 'course' => 'Network-wide number of courses using resource', 'course_list' => 'Network-wide courses using resource', 'sequsage' => 'Number of resources using or importing resource', 'sequsage_list' => 'Resources using or importing resource', 'goto' => 'Number of resources that follow this resource in maps', 'goto_list' => 'Resources that follow this resource in maps', 'comefrom' => 'Number of resources that lead up to this resource in maps', 'comefrom_list' => 'Resources that lead up to this resource in maps', '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', 'disc' => 'Degree of discrimination', 'dependencies' => 'Resources used by this resource', ); } return &Apache::lonlocal::texthash(%fields); } sub portfolio_linked_path { my ($path) = @_; my $result = &Apache::portfolio::make_anchor('portfolio','/'); my $fullpath = '/'; my (undef,@tree) = split('/',$path); my $filename = pop(@tree); foreach my $dir (@tree) { $fullpath .= $dir.'/'; $result .= '/'; $result .= &Apache::portfolio::make_anchor($dir,$fullpath); } $result .= "/$filename"; return $result; } sub portfolio_display_uri { my ($uri,$as_links)=@_; $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); $meta_uri = &portfolio_linked_path($meta_uri); } 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('
'); $r->print('

'.&mt('If you would like to associate this resource ([_1]) with a current or previous course, please select one from the list below, otherwise select, \'None\'',''.$res_uri.'').'

'); $output = &select_course(); $r->print($output.'
'); $r->print('
'); $r->print('

'. ''. ''. '
'); return; } sub select_course { my %courses; my $output; my $selected; foreach my $key (keys(%env)) { if ($key =~ m/\.metadata\./) { $key =~ m/^course\.(.+)(\.metadata.+$)/; my $course = $1; my $coursekey = 'course.'.$course.'.description'; my $value = $env{$coursekey}; $courses{$coursekey} = $value; } } my $meta_not_found = 1; if ($Apache::lonpublisher::metadatafields{'courserestricted'} eq 'none') { $selected = ' SELECTED '; } else { $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 ''; } # Evaluations if (($type eq 'clear') || ($type eq 'depth') || ($type eq 'helpful') || ($type eq 'correct') || ($type eq 'technical')) { return &evalgraph($value); } # Difficulty if ($type eq 'difficulty' || $type eq 'disc') { return &diffgraph($value); } # List of courses if ($type=~/\_list/) { my @Courses = split(/\s*\,\s*/,$value); my $Str; foreach my $course (@Courses) { my %courseinfo = &Apache::lonnet::coursedescription($course); if (! exists($courseinfo{'num'}) || $courseinfo{'num'} eq '') { next; } if ($Str ne '') { $Str .= '
'; } $Str .= ''. $courseinfo{'description'}.''; } return $Str; } # No pretty print found return $value; } # Pretty input of metadata field sub direct { return shift; } sub selectbox { my ($name,$value,$functionref,@idlist)=@_; if (! defined($functionref)) { $functionref=\&direct; } my $selout=''; } sub relatedfield { my ($show,$relatedsearchflag,$relatedsep,$fieldname,$relatedvalue)=@_; if (! $relatedsearchflag) { return ''; } if (! defined($relatedsep)) { $relatedsep=' '; } if (! $show) { return $relatedsep.' '; } return $relatedsep.''; } sub prettyinput { my ($type,$value,$fieldname,$formname, $relatedsearchflag,$relatedsep,$relatedvalue,$size,$course_key)=@_; if (! defined($size)) { $size = 80; } my $output; if (defined($course_key)) { my $stu_add; my $only_one; my %meta_options; my @cur_values_inst; my $cur_values_stu; my $values = $env{$course_key.'.metadata.'.$type.'.values'}; if ($env{$course_key.'.metadata.'.$type.'.options'} =~ m/stuadd/) { $stu_add = 'true'; } if ($env{$course_key.'.metadata.'.$type.'.options'} =~ m/onlyone/) { $only_one = 'true'; } # need to take instructor values out of list where instructor and student # values may be mixed. if ($values) { foreach my $item (split(/,/,$values)) { $item =~ s/^\s+//; $meta_options{$item} = $item; } foreach my $item (split(/,/,$value)) { $item =~ s/^\s+//; if ($meta_options{$item}) { push(@cur_values_inst,$item); } else { $cur_values_stu .= $item.','; } } } else { $cur_values_stu = $value; } if ($type eq 'courserestricted') { return (&select_course()); # return (''); } if (($type eq 'keywords') || ($type eq 'subject') || ($type eq 'author')||($type eq 'notes') || ($type eq 'abstract')|| ($type eq 'title')|| ($type eq 'standards')) { if ($values) { if ($only_one) { $output .= (&Apache::loncommon::select_form($cur_values_inst[0],'new_'.$type,%meta_options)); } else { $output .= (&Apache::loncommon::multiple_select_form('new_'.$type,\@cur_values_inst,undef,\%meta_options)); } } if ($stu_add) { $output .= ''. &relatedfield(1,$relatedsearchflag,$relatedsep,$fieldname, $relatedvalue); } return ($output); } if (($type eq 'lowestgradelevel') || ($type eq 'highestgradelevel')) { return &Apache::loncommon::select_level_form($value,$fieldname). &relatedfield(0,$relatedsearchflag,$relatedsep); } return(); } # Language if ($type eq 'language') { return &selectbox($fieldname, $value, \&Apache::loncommon::languagedescription, (&Apache::loncommon::languageids)). &relatedfield(0,$relatedsearchflag,$relatedsep); } # Copyright if ($type eq 'copyright') { return &selectbox($fieldname, $value, \&Apache::loncommon::copyrightdescription, (&Apache::loncommon::copyrightids)). &relatedfield(0,$relatedsearchflag,$relatedsep); } # Source Copyright if ($type eq 'sourceavail') { return &selectbox($fieldname, $value, \&Apache::loncommon::source_copyrightdescription, (&Apache::loncommon::source_copyrightids)). &relatedfield(0,$relatedsearchflag,$relatedsep); } # Gradelevels if (($type eq 'lowestgradelevel') || ($type eq 'highestgradelevel')) { return &Apache::loncommon::select_level_form($value,$fieldname). &relatedfield(0,$relatedsearchflag,$relatedsep); } # Obsolete if ($type eq 'obsolete') { return ''. &relatedfield(0,$relatedsearchflag,$relatedsep); } # Obsolete replacement file if ($type eq 'obsoletereplacement') { return '".&mt('Select').''. &relatedfield(0,$relatedsearchflag,$relatedsep); } # Customdistribution file if ($type eq 'customdistributionfile') { return '".&mt('Select').''. &relatedfield(0,$relatedsearchflag,$relatedsep); } # Source Customdistribution file if ($type eq 'sourcerights') { return '".&mt('Select').''. &relatedfield(0,$relatedsearchflag,$relatedsep); } if ($type eq 'courserestricted') { return (&select_course()); #return (''); } # Dates if (($type eq 'creationdate') || ($type eq 'lastrevisiondate')) { return &Apache::lonhtmlcommon::date_setter($formname,$fieldname,$value). &relatedfield(0,$relatedsearchflag,$relatedsep); } # No pretty input found $value=~s/^\s+//gs; $value=~s/\s+$//gs; $value=~s/\s+/ /gs; $value=~s/\"/\"\;/gs; return ''. &relatedfield(1,$relatedsearchflag,$relatedsep,$fieldname, $relatedvalue); } # Main Handler sub handler { my $r=shift; # my $uri=$r->uri; # # Set document type &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK if $r->header_only; # my ($resdomain,$resuser)= (&Apache::lonnet::declutter($uri)=~/^(\w+)\/(\w+)\//); my $html=&Apache::lonxml::xmlbegin(); $r->print($html.''. 'Catalog Information'. ''); if ($uri=~m:/adm/bombs/(.*)$:) { $r->print(&Apache::loncommon::bodytag('Error Messages')); # Looking for all bombs? &report_bombs($r,$uri); } elsif ($uri=~/\/portfolio\//) { ($resdomain,$resuser)= (&Apache::lonnet::declutter($uri)=~m|^(\w+)/(\w+)/portfolio|); $r->print(&Apache::loncommon::bodytag ('Edit Portfolio File Information','','','',$resdomain)); if ($env{'form.store'}) { &present_editable_metadata($r,$uri,'portfolio'); } else { &pre_select_course($r,$uri); } } elsif ($uri=~/^\/\~/) { # Construction space $r->print(&Apache::loncommon::bodytag ('Edit Catalog Information','','','',$resdomain)); &present_editable_metadata($r,$uri); } else { $r->print(&Apache::loncommon::bodytag ('Catalog Information','','','',$resdomain)); &present_uneditable_metadata($r,$uri); } $r->print(''); return OK; } ##################################################### ##################################################### ### ### ### Report Bombs ### ### ### ##################################################### ##################################################### sub report_bombs { my ($r,$uri) = @_; # Set document type $uri =~ s:/adm/bombs/::; $uri = &Apache::lonnet::declutter($uri); $r->print('

'.&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(< ENDCLEAR my %brokenurls = &Apache::lonmsg::all_url_author_res_msg($author,$domain); foreach (sort(keys(%brokenurls))) { if ($_=~/^\Q$uri\E/) { $r->print (''.$_.''. &Apache::lonmsg::retrieve_author_res_msg($_). '
'); } } } else { $r->print(&mt('Not authorized')); } return; } ##################################################### ##################################################### ### ### ### Uneditable Metadata Display ### ### ### ##################################################### ##################################################### sub present_uneditable_metadata { my ($r,$uri) = @_; # 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); # version my $currentversion=&Apache::lonnet::getversion($disuri); my $versiondisplay=''; 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'; } foreach ('title', 'author', 'subject', 'keywords', 'notes', 'abstract', 'lowestgradelevel', 'highestgradelevel', 'standards', 'mime', 'language', 'creationdate', 'lastrevisiondate', 'owner', 'copyright', 'customdistributionfile', 'sourceavail', 'sourcerights', 'obsolete', 'obsoletereplacement') { $table.=''.$lt{$_}. ''. &prettyprint($_,$content{$_}).''; delete $content{$_}; } # $r->print(<$title

$disuri
$obsoletewarning $versiondisplay

$table
ENDHEAD if ($env{'user.adv'}) { &print_dynamic_metadata($r,$uri,\%content); } return; } sub print_dynamic_metadata { my ($r,$uri,$content) = @_; # my %content = %$content; my %lt=&fieldnames(); # my $description = 'Dynamic Metadata (updated periodically)'; $r->print('

'.&mt($description).'

'. &mt('Processing')); $r->rflush(); my %items=&fieldnames(); my %dynmeta=&dynamicmeta($uri); # # General Access and Usage Statistics if (exists($dynmeta{'count'}) || exists($dynmeta{'sequsage'}) || exists($dynmeta{'comefrom'}) || exists($dynmeta{'goto'}) || exists($dynmeta{'course'})) { $r->print('

'.&mt('Access and Usage Statistics').'

'. ''); foreach ('count', 'sequsage','sequsage_list', 'comefrom','comefrom_list', 'goto','goto_list', 'course','course_list') { $r->print(''. '\n"); } $r->print('
'.$lt{$_}.''. &prettyprint($_,$dynmeta{$_})."
'); } else { $r->print('

'.&mt('No Access or Usages Statistics are available for this resource.').'

'); } # # Assessment statistics if ($uri=~/\.(problem|exam|quiz|assess|survey|form)$/) { if (exists($dynmeta{'stdno'}) || exists($dynmeta{'avetries'}) || exists($dynmeta{'difficulty'}) || exists($dynmeta{'disc'})) { # This is an assessment, print assessment data $r->print('

'. &mt('Overall Assessment Statistical Data'). '

'. ''); $r->print(''. ''."\n"); foreach ('avetries','difficulty','disc') { $r->print(''. ''."\n"); } $r->print('
'.$lt{'stdno'}.''. &prettyprint('stdno',$dynmeta{'stdno'}). '
'.$lt{$_}.''. &prettyprint($_,sprintf('%5.2f',$dynmeta{$_})). '
'); } if (exists($dynmeta{'stats'})) { # # New assessment statistics $r->print('

'. &mt('Detailed Assessment Statistical Data'). '

'); my $table = ''. ''. ''. ''. ''. ''. ''. ''. ''. ''.$/; foreach my $identifier (sort(keys(%{$dynmeta{'stats'}}))) { my $data = $dynmeta{'stats'}->{$identifier}; my $course = $data->{'course'}; my %courseinfo = &Apache::lonnet::coursedescription($course); if (! exists($courseinfo{'num'}) || $courseinfo{'num'} eq '') { &Apache::lonnet::logthis('lookup for '.$course.' failed'); next; } $table .= ''; $table .= ''; $table .= ''; $table .= ''; foreach ('avetries','difficulty','disc') { $table .= ''; } $table .= ''; $table .= ''.$/; } $table .= '
CourseSection(s)Num StudentsMean TriesDegree of DifficultyDegree of DiscriminationTime of computation
'.$courseinfo{'description'}.''.$data->{'sections'}.''.$data->{'stdno'}.''; if (exists($data->{$_})) { $table .= sprintf('%.2f',$data->{$_}).' '; } else { $table .= ''; } $table .= ''. &Apache::lonlocal::locallocaltime($data->{'timestamp'}). '
'.$/; $r->print($table); } else { $r->print('No new dynamic data found.'); } } else { $r->print('

'. &mt('No Assessment Statistical Data is available for this resource'). '

'); } # # if (exists($dynmeta{'clear'}) || exists($dynmeta{'depth'}) || exists($dynmeta{'helpful'}) || exists($dynmeta{'correct'}) || exists($dynmeta{'technical'})){ $r->print('

'.&mt('Evaluation Data').'

'. ''); foreach ('clear','depth','helpful','correct','technical') { $r->print(''. '\n"); } $r->print('
'.$lt{$_}.''. &prettyprint($_,$dynmeta{$_})."
'); } else { $r->print('

'.&mt('No Evaluation Data is available for this resource.').'

'); } $uri=~/^\/res\/(\w+)\/(\w+)\//; if ((($env{'user.domain'} eq $1) && ($env{'user.name'} eq $2)) || ($env{'user.role.ca./'.$1.'/'.$2})) { if (exists($dynmeta{'comments'})) { $r->print('

'.&mt('Evaluation Comments').' ('. &mt('visible to author and co-authors only'). ')

'. '
'.$dynmeta{'comments'}.'
'); } else { $r->print('

'.&mt('There are no Evaluation Comments on this resource.').'

'); } my $bombs = &Apache::lonmsg::retrieve_author_res_msg($uri); if (defined($bombs) && $bombs ne '') { $r->print('

'.&mt('Error Messages').' ('. &mt('visible to author and co-authors only').')'. '

'.$bombs); } else { $r->print('

'.&mt('There are currently no Error Messages for this resource.').'

'); } } # # All other stuff $r->print('

'. &mt('Additional Metadata (non-standard, parameters, exports)'). '

'); foreach (sort(keys(%content))) { my $name=$_; if ($name!~/\.display$/) { my $display=&Apache::lonnet::metadata($uri, $name.'.display'); if (! $display) { $display=$name; }; my $otherinfo=''; foreach ('name','part','type','default') { if (defined(&Apache::lonnet::metadata($uri, $name.'.'.$_))) { $otherinfo.=' '.$_.'='. &Apache::lonnet::metadata($uri, $name.'.'.$_).'; '; } } $r->print('\n"); } } $r->print("
'.$display.''.$content{$name}); if ($otherinfo) { $r->print(' ('.$otherinfo.')'); } $r->print("
"); return; } ##################################################### ##################################################### ### ### ### Editable metadata display ### ### ### ##################################################### ##################################################### sub present_editable_metadata { my ($r,$uri, $file_type) = @_; # Construction Space Call # Header my $disuri=$uri; my $fn=&Apache::lonnet::filelocation('',$uri); $disuri=~s/^\/\~/\/priv\//; $disuri=~s/\.meta$//; my $meta_uri = $disuri; my $path; if ($disuri =~ m|/portfolio/|) { ($disuri, $meta_uri, $path) = &portfolio_display_uri($disuri,1); } my $target=$uri; $target=~s/^\/\~/\/res\/$env{'request.role.domain'}\//; $target=~s/\.meta$//; my $bombs=&Apache::lonmsg::retrieve_author_res_msg($target); if ($bombs) { my $showdel=1; if ($env{'form.delmsg'}) { if (&Apache::lonmsg::del_url_author_res_msg($target) eq 'ok') { $bombs=&mt('Messages deleted.'); $showdel=0; } else { $bombs=&mt('Error deleting messages'); } } if ($env{'form.clearmsg'}) { my $cleardir=$target; $cleardir=~s/\/[^\/]+$/\//; if (&Apache::lonmsg::clear_author_res_msg($cleardir) eq 'ok') { $bombs=&mt('Messages cleared.'); $showdel=0; } else { $bombs=&mt('Error clearing messages'); } } my $del=&mt('Delete Messages for this Resource'); my $clear=&mt('Clear all Messages in Subdirectory'); my $goback=&mt('Back to Source File'); $r->print(<$disuri
ENDBOMBS if ($showdel) { $r->print(< ENDDEL } else { $r->print(''.$goback.''); } $r->print('
'.$bombs); } else { my $displayfile='Catalog Information for '.$disuri; if ($disuri=~/\/default$/) { my $dir=$disuri; $dir=~s/default$//; $displayfile= &mt('Default Cataloging Information for Directory').' '. $dir; } %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(<$displayfile ENDEDIT $r->print(''); my %lt=&fieldnames($file_type); my $output; my @fields; if ($file_type eq 'portfolio') { @fields = ('author','title','subject','keywords','abstract','notes','lowestgradelevel', 'highestgradelevel','standards'); } else { @fields = ('author','title','subject','keywords','abstract','notes', 'copyright','customdistributionfile','language', 'standards', 'lowestgradelevel','highestgradelevel','sourceavail','sourcerights', 'obsolete','obsoletereplacement'); } if ((! $Apache::lonpublisher::metadatafields{'courserestricted'}) && (! $env{'form.new_courserestricted'})) { $Apache::lonpublisher::metadatafields{'courserestricted'}= 'none'; } elsif ($env{'form.new_courserestricted'}) { $Apache::lonpublisher::metadatafields{'courserestricted'}= $env{'form.new_courserestricted'}; } if (! $Apache::lonpublisher::metadatafields{'copyright'}) { $Apache::lonpublisher::metadatafields{'copyright'}= 'default'; } if ($Apache::lonpublisher::metadatafields{'courserestricted'} ne 'none') { $r->print(&mt('Associated with course [_1]',''.$env{$Apache::lonpublisher::metadatafields{'courserestricted'}.".description"}. '').'
'); } else { $r->print("This resource is not associated with a course.
"); } foreach my $field_name (@fields) { if (defined($env{'form.new_'.$field_name})) { $Apache::lonpublisher::metadatafields{$field_name}= join(',',&Apache::loncommon::get_env_multiple('form.new_'.$field_name)); } if ($Apache::lonpublisher::metadatafields{'courserestricted'} ne 'none') { # handle restrictions here if (($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.'.$field_name.'.options'} =~ m/active/) || ($field_name eq 'courserestricted')){ $output.=("\n".'

'.$lt{$field_name}.': '. &prettyinput($field_name, $Apache::lonpublisher::metadatafields{$field_name}, 'new_'.$field_name,'defaultmeta', undef,undef,undef,undef, $Apache::lonpublisher::metadatafields{'courserestricted'}).'

'."\n"); } } else { $output.=('

'.$lt{$field_name}.': '. &prettyinput($field_name, $Apache::lonpublisher::metadatafields{$field_name}, 'new_'.$field_name,'defaultmeta').'

'); } } if ($env{'form.store'}) { my $mfh; my $formname='store'; my $file_content; if (&Apache::loncommon::get_env_multiple('form.new_keywords')) { $Apache::lonpublisher::metadatafields{'keywords'} = join (',', &Apache::loncommon::get_env_multiple('form.new_keywords')); } foreach (sort keys %Apache::lonpublisher::metadatafields) { next if ($_ =~ /\./); my $unikey=$_; $unikey=~/^([A-Za-z]+)/; my $tag=$1; $tag=~tr/A-Z/a-z/; $file_content.= "\n\<$tag"; foreach (split(/\,/, $Apache::lonpublisher::metadatakeys{$unikey}) ) { my $value= $Apache::lonpublisher::metadatafields{$unikey.'.'.$_}; $value=~s/\"/\'\'/g; $file_content.=' '.$_.'="'.$value.'"' ; # print $mfh ' '.$_.'="'.$value.'"'; } $file_content.= '>'. &HTML::Entities::encode ($Apache::lonpublisher::metadatafields{$unikey}, '<>&"'). ''; } if ($fn =~ m|/portfolio/|) { my ($path, $new_fn) = ($fn =~ m|/(portfolio.*)/([^/]*)$|); $env{'form.'.$formname}=$file_content."\n"; $env{'form.'.$formname.'.filename'}=$new_fn; my $result =&Apache::lonnet::userfileupload($formname,'', $path); if ($result =~ /(error|notfound)/) { $r->print('

'. &mt('Could not write metadata').', '. &mt('FAIL').'

'); } else { $r->print('

'.&mt('Wrote Metadata'). ' '.&Apache::lonlocal::locallocaltime(time). '

'); } } else { if (! ($mfh=Apache::File->new('>'.$fn))) { $r->print('

'. &mt('Could not write metadata').', '. &mt('FAIL').'

'); } else { print $mfh $file_content; $r->print('

'.&mt('Wrote Metadata'). ' '.&Apache::lonlocal::locallocaltime(time). '

'); } } } $r->print($output.'
'); $r->print('

'. ''. ''); } $r->print('
'); return; } 1; __END__ 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.