--- loncom/interface/lonmeta.pm 2007/01/16 07:26:45 1.199 +++ loncom/interface/lonmeta.pm 2008/11/17 14:06:14 1.214 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Metadata display handler # -# $Id: lonmeta.pm,v 1.199 2007/01/16 07:26:45 raeburn Exp $ +# $Id: lonmeta.pm,v 1.214 2008/11/17 14:06:14 schafran Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,6 +26,141 @@ # http://www.lon-capa.org/ +=head1 NAME + +Apache::lonmeta - display meta data + +=head1 SYNOPSIS + +Handler to display meta data + +This is part of the LearningOnline Network with CAPA project +described at http://www.lon-capa.org. + +=head1 HANDLER SUBROUTINE + +handler() + +=head1 OTHER SUBROUTINES + +=over + +=item * + +&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} + +=item * + +dynamicmeta() : Fetch and evaluate dynamic metadata + +=item * + +access_count() + +=item * + +alttag() : Try to make an alt tag if there is none + +=item * + +authordisplay() : Author display + +=item * + +evalgraph() : Pretty display + +=item * + +diffgraph() + +=item * + +fieldnames() + +=item * + +portfolio_linked_path() + +=item * + +get_port_path_and_group() + +=item * + +portfolio_display_uri() + +=item * + +pre_select_course() + +=item * + +select_course() + +=item * + +prettyprint() : Pretty printing of metadata field + +=item * + +direct() : Pretty input of metadata field + +=item * + +selectbox() + +=item * + +relatedfield() + +=item * + +prettyinput() + +=item * + +report_bombs() + +=item * + +present_uneditable_metadata() + +=item * + +present_editable_metadata() + +=item * + +store_metadata() + +=item * + +store_transferred_addedfields() + +=item * + +store_portfolio_metadata() + +=item * + +update_metadata_table() + +=back + +=cut + + package Apache::lonmeta; use strict; @@ -42,24 +177,6 @@ use Apache::lonmsg; use LONCAPA qw(:DEFAULT :match); -############################################################ -############################################################ -## -## &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/($match_domain)/($match_username)/}); @@ -265,7 +382,7 @@ sub fieldnames { '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', + 'stdno' => 'Statistics calculated for number of students', 'difficulty' => 'Degree of difficulty', 'disc' => 'Degree of discrimination', 'dependencies' => 'Resources used by this resource', @@ -383,7 +500,40 @@ sub select_course { $Apache::lonpublisher::metadatafields{'courserestricted'}; my $selected = ($current_restriction eq 'none' ? 'selected="selected"' : ''); - + if ($current_restriction =~ /^course\.($match_domain\_$match_courseid)$/) { + my $assoc_crs = $1; + my $added_metadata_fields = &Apache::lonparmset::get_added_meta_fieldnames($assoc_crs); + if (ref($added_metadata_fields) eq 'HASH') { + if (keys(%{$added_metadata_fields}) > 0) { + my $transfernotes; + foreach my $field_name (keys(%{$added_metadata_fields})) { + my $value = $Apache::lonpublisher::metadatafields{$field_name}; + if ($value) { + $transfernotes .= + &Apache::loncommon::start_data_table_row(). + ''. + $field_name.''.$value.''. + &Apache::loncommon::end_data_table_row(); + } + } + if ($transfernotes ne '') { + my %courseinfo = &Apache::lonnet::coursedescription($assoc_crs,{'one_time' => 1}); + my $assoc_crs_description = $courseinfo{'description'}; + $output .= &mt('This resource is currently associated with a course ([_1]) which includes added metadata fields specific to the course.',$assoc_crs_description).'
'."\n". + &mt('You can choose to transfer data from the added fields to the "Notes" field if you are planning to change the course association.').'

'. + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + 'Copy to notes?'."\n". + 'Field name'."\n". + 'Values'."\n". + &Apache::loncommon::end_data_table_header_row(). + $transfernotes. + &Apache::loncommon::end_data_table().'
'; + } + } + } + } $output .= ' - +$cancel +
ENDCLEAR my %brokenurls = &Apache::lonmsg::all_url_author_res_msg($author,$domain); @@ -990,17 +1147,17 @@ sub print_dynamic_metadata { # # New assessment statistics $r->print('

'. - &mt('Detailed Assessment Statistical Data'). + &mt('Recent Detailed Assessment Statistical Data'). '

'); my $table = ''. ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. ''.$/; foreach my $identifier (sort(keys(%{$dynmeta{'stats'}}))) { my $data = $dynmeta{'stats'}->{$identifier}; @@ -1038,7 +1195,7 @@ sub print_dynamic_metadata { $table .= '
CourseSection(s)Num StudentsMean TriesDegree of DifficultyDegree of DiscriminationTime of computation'.&mt('Course').''.&mt('Section(s)').''.&mt('Num Student').'s'.&mt('Mean Tries').''.&mt('Degree of Difficulty').''.&mt('Degree of Discrimination').''.&mt('Time of computation').'
'.$/; $r->print($table); } else { - $r->print('No new dynamic data found.'); + $r->print(&mt('No new dynamic data found.')); } } else { $r->print('

'. @@ -1176,17 +1333,20 @@ ENDBOMBS ENDDEL } else { - $r->print(''.$goback.''); + $r->print('

'.$goback.'

'); + if ($env{'form.clearmsg'}) { + my ($diruri) = ($disuri =~ m{(.*/)[^/]*}); + $r->print('

'. + &mt('Back To Directory').'

'); + } } $r->print('
'.$bombs); } else { - my $displayfile='Catalog Information for '.$disuri; + my $displayfile=&mt('Metadata for [_1]',$disuri); if ($disuri=~/\/default$/) { my $dir=$disuri; $dir=~s/default$//; - $displayfile= - &mt('Default Cataloging Information for Directory').' '. - $dir; + $displayfile=&mt('Default Metadata for Directory [_1]',$dir); } %Apache::lonpublisher::metadatafields=(); %Apache::lonpublisher::metadatakeys=(); @@ -1196,13 +1356,26 @@ ENDDEL } else { &Apache::lonpublisher::metaeval($result); } + if ($env{'form.new_courserestricted'}) { + my $new_assoc_course = $env{'form.new_courserestricted'}; + my $prev_courserestricted = $Apache::lonpublisher::metadatafields{'courserestricted'}; + if (($prev_courserestricted) && + ($prev_courserestricted ne $new_assoc_course)) { + my $transfers = []; + foreach my $key (keys(%env)) { + if ($key =~ /^form\.transfer_(.+)$/) { + push(@{$transfers},$1); + } + } + if (@{$transfers} > 0) { + &store_transferred_addedfields($fn,$uri,$transfers); + } + } + } $r->print(<$displayfile

ENDEDIT - $r->print(''); my %lt=&fieldnames($file_type); my $output; my @fields; @@ -1258,6 +1431,11 @@ ENDEDIT $Apache::lonpublisher::metadatafields{'owner'} = $env{'user.name'}.':'.$env{'user.domain'}; } + if (! $Apache::lonpublisher::metadatafields{'author'}) { + $Apache::lonpublisher::metadatafields{'author'} = + &Apache::loncommon::plainname($env{'user.name'}, + $env{'user.domain'}); + } if ($Apache::lonpublisher::metadatafields{'courserestricted'} ne 'none') { if ($file_type eq 'portfolio') { @@ -1273,7 +1451,7 @@ ENDEDIT ".description"}.'').'
'); } } else { - $r->print('This resource is not associated with a course.
'); + $r->print(''.&mt('This resource is not associated with a course.').'
'); } } if (@added_order) { @@ -1291,8 +1469,15 @@ ENDEDIT my $row_alt = 1; 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)); + my @values = &Apache::loncommon::get_env_multiple('form.new_'.$field_name); + my $newvalue = ''; + foreach my $item (@values) { + if ($item ne '') { + $newvalue .= $item.','; + } + } + $newvalue =~ s/,$//; + $Apache::lonpublisher::metadatafields{$field_name}=$newvalue; } if ($Apache::lonpublisher::metadatafields{'courserestricted'} ne 'none' && exists($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.'.$field_name.'.options'})) { @@ -1321,60 +1506,11 @@ ENDEDIT } $output .= &Apache::loncommon::end_data_table(); 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 my $field (sort(keys(%Apache::lonpublisher::metadatafields))) { - next if ($field =~ /\./); - my $unikey=$field; - $unikey=~/^([A-Za-z_]+)/; - my $tag=$1; - $tag=~tr/A-Z/a-z/; - $file_content.= "\n\<$tag"; - foreach my $key (split(/\,/, - $Apache::lonpublisher::metadatakeys{$unikey}) - ) { - my $value= - $Apache::lonpublisher::metadatafields{$unikey.'.'.$key}; - $value=~s/\"/\'\'/g; - $file_content.=' '.$key.'="'.$value.'"' ; - } - $file_content.= '>'. - &HTML::Entities::encode - ($Apache::lonpublisher::metadatafields{$unikey}, - '<>&"'). - ''; - } - if ($fn =~ m|^$Apache::lonnet::perlvar{'lonDocRoot'}/userfiles|) { - my ($path, $new_fn); - if ($fn =~ m|$match_name/groups/\w+/portfolio/|) { - ($path, $new_fn) = ($fn =~ m|/(groups/\w+/portfolio.*)/([^/]*)$|); - } else { - ($path, $new_fn) = ($fn =~ m|/(portfolio.*)/([^/]*)$|); - } - $r->print(&store_portfolio_metadata($formname,$file_content,$path, - $new_fn,$uri)); - } else { - if (! ($mfh=Apache::File->new('>'.$fn))) { - $r->print('

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

'); - } else { - print $mfh ($file_content); - close($mfh); - &update_metadata_table($uri); - $r->print('

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

'); - } - } + my ($outcome,$result) = &store_metadata($fn,$uri,'store'); + $r->print($result); } - $r->print($output.'
'); + $r->print($output.'
'); if ($file_type eq 'portfolio' || $file_type eq 'groups') { my ($port_path,$group) = &get_port_path_and_group($uri); @@ -1396,20 +1532,114 @@ ENDEDIT return; } +sub store_metadata { + my ($fn,$uri,$caller) = @_; + my $mfh; + my $formname='store'; + my ($file_content,$output,$outcome); + if (&Apache::loncommon::get_env_multiple('form.new_keywords')) { + $Apache::lonpublisher::metadatafields{'keywords'} = + join (',', &Apache::loncommon::get_env_multiple('form.new_keywords')); + } + foreach my $field (sort(keys(%Apache::lonpublisher::metadatafields))) { + next if ($field =~ /\./); + my $unikey=$field; + $unikey=~/^([A-Za-z_]+)/; + my $tag=$1; + $tag=~tr/A-Z/a-z/; + $file_content.= "\n\<$tag"; + foreach my $key (split(/\,/,$Apache::lonpublisher::metadatakeys{$unikey})) { + my $value = $Apache::lonpublisher::metadatafields{$unikey.'.'.$key}; + $value=~s/\"/\'\'/g; + $file_content.=' '.$key.'="'.$value.'"' ; + } + $file_content.= '>'. + &HTML::Entities::encode + ($Apache::lonpublisher::metadatafields{$unikey},'<>&"'). + ''; + } + if ($fn =~ m|^$Apache::lonnet::perlvar{'lonDocRoot'}/userfiles|) { + my ($path, $new_fn); + if ($fn =~ m|$match_name/groups/\w+/portfolio/|) { + ($path, $new_fn) = ($fn =~ m|/(groups/\w+/portfolio.*)/([^/]*)$|); + } else { + ($path, $new_fn) = ($fn =~ m|/(portfolio.*)/([^/]*)$|); + } + ($outcome,my $result) = + &store_portfolio_metadata($formname,$file_content, + $path,$new_fn,$uri,$caller); + $output .= $result; + } else { + if (! ($mfh=Apache::File->new('>'.$fn))) { + $output .= '

'; + if ($caller eq 'transfer') { + $output .= &mt('Could not transfer data in added fields to notes'); + } else { + $output .= &mt('Could not write metadata'); + } + $output .= ', '.&mt('FAIL').'

'; + $outcome = 'fail'; + } else { + print $mfh ($file_content); + close($mfh); + &update_metadata_table($uri); + $output .= '

'; + if ($caller eq 'transfer') { + $output .= &mt('Transferred data in added fields to notes'); + } else { + $output .= &mt('Wrote Metadata'); + } + $output .= ' '.&Apache::lonlocal::locallocaltime(time). + '

'; + $outcome = 'ok'; + } + } + return ($outcome,$output); +} + +sub store_transferred_addedfields { + my ($fn,$uri,$transfers) = @_; + foreach my $item (@{$transfers}) { + $Apache::lonpublisher::metadatafields{'notes'} .= + ' '.$item.' = '.$Apache::lonpublisher::metadatafields{$item}; + } + my ($outcome,$output) = &store_metadata($fn,$uri,'transfer'); + if ($outcome eq 'ok') { + foreach my $item (@{$transfers}) { + delete($Apache::lonpublisher::metadatafields{$item}); + } + } +} + sub store_portfolio_metadata { - my ($formname,$content,$path,$new_fn,$uri) = @_; + my ($formname,$content,$path,$new_fn,$uri,$caller) = @_; + my ($outcome,$output); $env{'form.'.$formname}=$content."\n"; $env{'form.'.$formname.'.filename'}=$new_fn; my $result =&Apache::lonnet::userfileupload($formname,'',$path); if ($result =~ /(error|notfound)/) { - return '

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

'; + $output = '

'; + if ($caller eq 'transfer') { + $output .= + &mt('Could not transfer data in added fields to notes'); + } else { + $output .= &mt('Could not write metadata'); + } + $output .= ', '.&mt('FAIL').'

'; + $outcome = 'fail'; } else { &update_metadata_table($uri); - return '

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

'; + $output = '

'; + if ($caller eq 'transfer') { + $output .= &mt('Transferred data in added fields to notes'); + } else { + $output .= &mt('Wrote Metadata'); + } + $output .= ' '.&Apache::lonlocal::locallocaltime(time). + '

'; + $outcome = 'ok'; } + return ($outcome,$output); } sub update_metadata_table { 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.