--- loncom/interface/lonmeta.pm 2005/11/11 21:25:50 1.125 +++ loncom/interface/lonmeta.pm 2010/06/06 02:40:30 1.240 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Metadata display handler # -# $Id: lonmeta.pm,v 1.125 2005/11/11 21:25:50 banghart Exp $ +# $Id: lonmeta.pm,v 1.240 2010/06/06 02:40:30 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -39,29 +39,12 @@ use Apache::lonpublisher; use Apache::lonlocal; use Apache::lonmysql; 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/(\w+)/(\w+)/:); + my ($authordom,$author)=($url=~m{^/res/($match_domain)/($match_username)/}); if (! defined($authordom)) { $authordom = shift(); } @@ -71,20 +54,7 @@ sub get_dynamic_metadata_from_sql { 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 $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]); @@ -106,13 +76,10 @@ sub get_dynamic_metadata_from_sql { 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]; + my %hash=&LONCAPA::lonmetadata::metadata_col_to_hash('metadata', + map { &unescape($_) } split(/\,/,$result)); + foreach my $key (keys(%hash)) { + $ReturnHash{$hash{'url'}}->{$key}=$hash{$key}; } } $finished = 1; @@ -126,7 +93,7 @@ sub get_dynamic_metadata_from_sql { sub dynamicmeta { my $url=&Apache::lonnet::declutter(shift); $url=~s/\.meta$//; - my ($adomain,$aauthor)=($url=~/^(\w+)\/(\w+)\//); + my ($adomain,$aauthor)=($url=~/^($match_domain)\/($match_username)\//); my $regexp=$url; $regexp=~s/(\W)/\\$1/g; $regexp='___'.$regexp.'___'; @@ -185,7 +152,7 @@ sub authordisplay { my ($aname,$adom)=@_; return &Apache::loncommon::aboutmewrapper (&Apache::loncommon::plainname($aname,$adom), - $aname,$adom,'preview').' ['.$aname.'@'.$adom.']'; + $aname,$adom,'preview').' ['.$aname.':'.$adom.']'; } # Pretty display @@ -197,7 +164,7 @@ sub evalgraph { my $val=int($value*10.+0.5)-10; my $output=''; if ($val>=20) { - $output.=''; + $output.=''; } else { $output.=''. ''; @@ -207,7 +174,7 @@ sub evalgraph { $output.=''. ''; } else { - $output.=''; + $output.=''; } $output.='
  '.(' ' x2).'      '.(' ' x2).' ('.sprintf("%5.2f",$value).')
'; return $output; @@ -243,18 +210,17 @@ sub fieldnames { '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') { + 'highestgradelevel' => 'Highest Grade Level'); + + if ( !defined($file_type) || ($file_type ne 'portfolio' && $file_type ne 'groups') ) { %fields = (%fields, 'domain' => 'Domain', - 'standards' => 'Standards', 'mime' => 'MIME Type', 'language' => 'Language', 'creationdate' => 'Creation Date', @@ -281,63 +247,192 @@ 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', + 'dependencies' => 'Resources used by this resource', ); } return &Apache::lonlocal::texthash(%fields); } +sub portfolio_linked_path { + my ($path,$group,$port_path) = @_; + + my $start = 'portfolio'; + if ($group) { + $start = "groups/$group/".$start; + } + my %anchor_fields = ( + 'selectfile' => $start, + 'currentpath' => '/' + ); + my $result = &Apache::portfolio::make_anchor($port_path,\%anchor_fields,$start); + my $fullpath = '/'; + my (undef,@tree) = split('/',$path); + my $filename = pop(@tree); + foreach my $dir (@tree) { + $fullpath .= $dir.'/'; + $result .= '/'; + my %anchor_fields = ( + 'selectfile' => $dir, + 'currentpath' => $fullpath + ); + $result .= &Apache::portfolio::make_anchor($port_path,\%anchor_fields,$dir); + } + $result .= "/$filename"; + return $result; +} + +sub get_port_path_and_group { + my ($uri)=@_; + + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + + 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('
'); + $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(''); + $r->print('
'); + + my ($port_path,$group) = &get_port_path_and_group($uri); + my $group_input; + if ($group) { + $group_input = ''; + } + $r->print('

'. + ''. + $group_input. + ''. + '
'); + + return; +} sub select_course { - my ($r)=@_; + my $output=$/; + my $current_restriction= + $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 .= ''); - my $meta_not_found = 1; - foreach my $key (keys (%courses)) { - if ($meta_not_found) { - undef($meta_not_found); - $r->print('

Portfolio Meta-Data


'); - $r->print('
'); - $r->print('Select your course
'); - $r->print('
'); - $r->print(''); - $r->print('
'); + foreach my $key (keys(%env)) { + if ($key !~ m/^course\.(.+)\.description$/) { next; } + my $cid = $1; + if ($env{$key} !~ /\S/) { next; } + $courses{$key} = $cid; + } + foreach my $key (sort { lc($env{$a}) cmp lc($env{$b}) } (keys(%courses))) { + my $cid = 'course.'.$courses{$key}; + my $selected = ($current_restriction eq $cid ? 'selected="selected"' + : ''); + if ($env{$key} !~ /\S/) { next; } + $output .= ''.$/; + $selected = ''; } - return 'ok'; + $output .= '
'; + return ($output); } # Pretty printing of metadata field sub prettyprint { - my ($type,$value,$target,$prefix,$form,$noformat)=@_; + my ($type,$value,$target,$prefix,$form)=@_; # $target,$prefix,$form are optional and for filecrumbs only if (! defined($value)) { return ' '; } # Title if ($type eq 'title') { - return ''.$value.''; + return $value; } # Dates if (($type eq 'creationdate') || @@ -368,7 +463,7 @@ sub prettyprint { ($type eq 'owner') || ($type eq 'modifyinguser') || ($type eq 'authorspace')) { - $value=~s/(\w+)(\:|\@)(\w+)/&authordisplay($1,$3)/gse; + $value=~s/($match_username)(\:|\@)($match_domain)/&authordisplay($1,$3)/gse; return $value; } # Gradelevel @@ -387,8 +482,8 @@ sub prettyprint { ($type eq 'comefrom_list') || ($type eq 'sequsage_list') || ($type eq 'dependencies')) { - return ''; } # Evaluations if (($type eq 'clear') || @@ -424,18 +519,26 @@ sub prettyprint { # List of courses if ($type=~/\_list/) { my @Courses = split(/\s*\,\s*/,$value); - my $Str; + my $Str=''; } # No pretty print found return $value; @@ -452,12 +555,13 @@ sub selectbox { $functionref=\&direct; } my $selout=''; } @@ -474,7 +578,7 @@ sub relatedfield { return $relatedsep.' '; } return $relatedsep.''; + ($relatedvalue?' checked="checked"':'').' />'; } sub prettyinput { @@ -483,56 +587,70 @@ sub prettyinput { if (! defined($size)) { $size = 80; } - if (defined($course_key)) { + my $output; + if (defined($course_key) + && exists($env{$course_key.'.metadata.'.$type.'.options'})) { my $stu_add; my $only_one; - my $values = $env{$course_key.'.metadata.'.$_.'.values'}; - if ($env{$course_key.'.metadata.'.$_.'.options'} =~ m/stuadd/) { + 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.'.$_.'.options'} =~ m/onlyone/) { + if ($env{$course_key.'.metadata.'.$type.'.options'} =~ m/onlyone/) { $only_one = 'true'; } - if ($type eq 'author') { - return - ''. - &relatedfield(1,$relatedsearchflag,$relatedsep,$fieldname, - $relatedvalue); - + # 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 { + if ($item ne '') { + $cur_values_stu .= $item.','; + } + } + } + $cur_values_stu =~ s/,$//; + my @key_order = sort(keys(%meta_options)); + unshift(@key_order,''); + $meta_options{''} = 'Not specified'; + $meta_options{'select_form_order'} = \@key_order; + } else { + $cur_values_stu = $value; } if ($type eq 'courserestricted') { - return (''); - } - if ($type eq 'authorspace') { - } - if ($type eq 'modifyinguser') { - } - if ($type eq 'subject') { + return (&select_course()); + # return (''); } - if ($type eq 'keywords') { - my %hash; - my $def; - my @cur_values; - foreach (split(/,/,$value)) { - $_ =~ s/^\s+//; - push(@cur_values,$_); - } - foreach (split(/,/,$values)) { - $_ =~ s/^\s+//; - $hash{$_} = $_; + if (($type eq 'keywords') || ($type eq 'subject') + || ($type eq 'author')||($type eq 'notes') + || ($type eq 'abstract')|| ($type eq 'title')|| ($type eq 'standards') + || (exists($env{$course_key.'.metadata.'.$type.'.added'}))) { + + 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 ($only_one) { - return(&Apache::loncommon::select_form($def,'new_keywords',%hash)); - } else { - return (&Apache::loncommon::multiple_select_form('new_keywords',\@cur_values,undef,\%hash)); + if ($stu_add) { + $output .= ''. + &relatedfield(1,$relatedsearchflag,$relatedsep,$fieldname, + $relatedvalue); } - } - if ($type eq 'notes') { - } - if ($type eq 'abstract') { - } - + return ($output); + } if (($type eq 'lowestgradelevel') || ($type eq 'highestgradelevel')) { return &Apache::loncommon::select_level_form($value,$fieldname). @@ -573,7 +691,7 @@ sub prettyinput { # Obsolete if ($type eq 'obsolete') { return ''. + ($value?' checked="checked"':'').' />'. &relatedfield(0,$relatedsearchflag,$relatedsep); } # Obsolete replacement file @@ -600,6 +718,11 @@ sub prettyinput { ",'rights')\">".&mt('Select').''. &relatedfield(0,$relatedsearchflag,$relatedsep); } + if ($type eq 'courserestricted') { + return (&select_course()); + #return (''); + } + # Dates if (($type eq 'creationdate') || ($type eq 'lastrevisiondate')) { @@ -619,45 +742,121 @@ sub prettyinput { $relatedvalue); } +# Create pageheader +sub pageheader { + my $output = ''; + # No CSTR? Include breadcrumbs + if ($env{'request.state'} ne 'construct') { + # loncommon::bodytag already includes breadcrumbs for CSTR + # by calling lonmenu::innerregister + $output = &Apache::lonhtmlcommon::breadcrumbs(); + } + # CSTR? Include CSTR header + if ($env{'request.state'} eq 'construct') { + $output .= &Apache::loncommon::head_subbox( + &Apache::loncommon::CSTR_pageheader()); + } + return $output; +} + # Main Handler sub handler { my $r=shift; - # + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['currentpath','changecourse']); 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'. - ''); + (&Apache::lonnet::declutter($uri)=~/^($match_domain)\/($match_username)\//); + + # Breadcrumbs + &Apache::lonhtmlcommon::clear_breadcrumbs(); + + if ($env{'request.state'} eq 'construct') { + &Apache::lonhtmlcommon::add_breadcrumb({ + 'text' => 'Construction Space', + 'href' => &Apache::loncommon::authorspace(), + }); + } + if ($uri=~m:/adm/bombs/(.*)$:) { - $r->print(&Apache::loncommon::bodytag('Error Messages')); + &Apache::lonhtmlcommon::add_breadcrumb({ + 'text' => 'Error Messages', + 'href' => '', + }); + $r->print(&Apache::loncommon::start_page('Error Messages')); + $r->print(&pageheader()); # 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)); - &present_editable_metadata($r,$uri,'portfolio'); - &select_course($r); - } elsif ($uri=~/^\/\~/) { + } elsif ($uri=~m|^/editupload/[^/]+/[^/]+/portfolio/|) { + &Apache::lonhtmlcommon::add_breadcrumb({ + 'text' => 'Edit Portfolio File Metadata', + 'href' => '', + }); + ($resdomain,$resuser)= + (&Apache::lonnet::declutter($uri)=~m|^($match_domain)/($match_name)/portfolio|); + $r->print(&Apache::loncommon::start_page('Edit Portfolio File Metadata', + undef, + {'domain' => $resdomain,})); + $r->print(&pageheader()); + if ($env{'form.store'}) { + &present_editable_metadata($r,$uri,'portfolio'); + } else { + my $fn=&Apache::lonnet::filelocation('',$uri); + %Apache::lonpublisher::metadatafields=(); + %Apache::lonpublisher::metadatakeys=(); + my $result=&Apache::lonnet::getfile($fn); + &Apache::lonpublisher::metaeval($result); + if ((!$Apache::lonpublisher::metadatafields{'courserestricted'}) || + ($env{'form.changecourse'} eq 'true')) { + &pre_select_course($r,$uri); + } else { + &present_editable_metadata($r,$uri,'portfolio'); + } + } + } elsif ($uri=~m|^/editupload/[^/]+/[^/]+/groups/|) { + &Apache::lonhtmlcommon::add_breadcrumb({ + 'text' => 'Edit Group Portfolio File Metadata', + 'href' => '', + }); + $r->print(&Apache::loncommon::start_page('Edit Group Portfolio File Metadata', + undef, + {'domain' => $resdomain,})); + $r->print(&pageheader()); + &present_editable_metadata($r,$uri,'groups'); + } elsif ($uri=~m|^/~|) { # Construction space - $r->print(&Apache::loncommon::bodytag - ('Edit Catalog Information','','','',$resdomain)); + &Apache::lonhtmlcommon::add_breadcrumb({ + 'text' => 'Edit Metadata', + 'href' => '', + }); + $r->print(&Apache::loncommon::start_page('Edit Metadata', + "\n".'', + {'domain' => $resdomain,})); + $r->print(&pageheader()); &present_editable_metadata($r,$uri); } else { - $r->print(&Apache::loncommon::bodytag - ('Catalog Information','','','',$resdomain)); + &Apache::lonhtmlcommon::add_breadcrumb({ + 'text' => 'Metadata', + 'href' => '', + }); + $r->print( + &Apache::loncommon::start_page( + 'Metadata', + undef, + {'domain' => $resdomain, + 'only_body' => 1,}) + .'

'.&mt('Metadata').'

' + ); &present_uneditable_metadata($r,$uri); } - $r->print(''); + $r->print(&Apache::loncommon::end_page()); return OK; } @@ -674,24 +873,28 @@ sub report_bombs { $uri =~ s:/adm/bombs/::; $uri = &Apache::lonnet::declutter($uri); $r->print('

'.&Apache::lonnet::clutter($uri).'

'); - my ($domain,$author)=($uri=~/^(\w+)\/(\w+)\//); + my ($domain,$author)=($uri=~/^($match_domain)\/($match_username)\//); 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(<print(< - +$cancel +
ENDCLEAR my %brokenurls = &Apache::lonmsg::all_url_author_res_msg($author,$domain); - foreach (sort(keys(%brokenurls))) { - if ($_=~/^\Q$uri\E/) { + foreach my $key (sort(keys(%brokenurls))) { + if ($key=~/^\Q$uri\E/) { $r->print - (''.$_.''. - &Apache::lonmsg::retrieve_author_res_msg($_). + (''.$key.''. + &Apache::lonmsg::retrieve_author_res_msg($key). '
'); } } @@ -711,38 +914,40 @@ ENDCLEAR 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,$_); + foreach my $key (split(/\,/,&Apache::lonnet::metadata($uri,'keys'))) { + $content{$key}=&Apache::lonnet::metadata($uri,$key); } # Render Output # displayed url my ($thisversion)=($uri=~/\.(\d+)\.(\w+)\.meta$/); $uri=~s/\.meta$//; - my $disuri=&Apache::lonnet::clutter($uri); + my $disuri=&Apache::lonnet::clutter_with_no_wrapper($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; + 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; + # crumbify displayed URL uri target prefix form + $disuri=&Apache::lonhtmlcommon::crumbs($disuri,undef, undef, undef); # obsolete my $obsolete=$content{'obsolete'}; my $obsoletewarning=''; if (($obsolete) && ($env{'user.adv'})) { - $obsoletewarning='

'. + $obsoletewarning='

'. &mt('This resource has been marked obsolete by the author(s)'). - '

'; + '

'; } # my %lt=&fieldnames(); @@ -751,44 +956,55 @@ sub present_uneditable_metadata { 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{$_}; + 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'); + } + my $rownum = 0; + foreach my $field (@fields) { + my $lastrow = ''; + $rownum ++; + $lastrow = 1 if ($rownum == @fields); + $table.=&Apache::lonhtmlcommon::row_title($lt{$field}) + .&prettyprint($field,$content{$field}) + .&Apache::lonhtmlcommon::row_closure($lastrow); + delete($content{$field}); } # - $r->print(<$title -

-$disuri
-$obsoletewarning -$versiondisplay -

- -$table -
-ENDHEAD - if ($env{'user.adv'}) { + $r->print("

$title

" + .'

' + .$disuri.'
' + .$obsoletewarning + .$versiondisplay + .'

' + .&Apache::lonhtmlcommon::start_pick_box() + .$table + .&Apache::lonhtmlcommon::end_pick_box() + ); + if (!$uploaded && $env{'user.adv'}) { &print_dynamic_metadata($r,$uri,\%content); } return; @@ -808,25 +1024,32 @@ sub print_dynamic_metadata { my %dynmeta=&dynamicmeta($uri); # # General Access and Usage Statistics + $r->print('

'.&mt('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(&Apache::lonhtmlcommon::start_pick_box()); + my @counts = ('count','sequsage','sequsage_list', + 'comefrom','comefrom_list','goto', + 'goto_list','course','course_list'); + my $rownum = 0; + foreach my $item (@counts) { + my $lastrow = ''; + $rownum ++; + $lastrow = 1 if ($rownum == @counts); + $r->print(&Apache::lonhtmlcommon::row_title($lt{$item}) + .&prettyprint($item,$dynmeta{$item}) + .&Apache::lonhtmlcommon::row_closure($lastrow) + ); } - $r->print('
'.$lt{$_}.''. - &prettyprint($_,$dynmeta{$_})."
'); + $r->print(&Apache::lonhtmlcommon::end_pick_box()); } else { - $r->print('

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

'); + $r->print('

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

' + ); } # # Assessment statistics @@ -839,70 +1062,80 @@ sub print_dynamic_metadata { $r->print('

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

'. - ''); - $r->print(''. - ''."\n"); - foreach ('avetries','difficulty','disc') { - $r->print(''. - ''."\n"); + &Apache::lonhtmlcommon::start_pick_box()); + $r->print(&Apache::lonhtmlcommon::row_title($lt{'stdno'}) + .&prettyprint('stdno',$dynmeta{'stdno'}) + .&Apache::lonhtmlcommon::row_closure() + ); + my @stats = ('avetries','difficulty','disc'); + my $rownum = 0; + foreach my $item (@stats) { + my $lastrow = ''; + $rownum ++; + $lastrow = 1 if ($rownum == @stats); + $r->print(&Apache::lonhtmlcommon::row_title($lt{$item}) + .&prettyprint($item,sprintf('%5.2f',$dynmeta{$item})) + .&Apache::lonhtmlcommon::row_closure($lastrow) + ); } - $r->print('
'.$lt{'stdno'}.''. - &prettyprint('stdno',$dynmeta{'stdno'}). - '
'.$lt{$_}.''. - &prettyprint($_,sprintf('%5.2f',$dynmeta{$_})). - '
'); + $r->print(&Apache::lonhtmlcommon::end_pick_box()); } + # + # New assessment statistics + $r->print('

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

' + ); if (exists($dynmeta{'stats'})) { - # - # New assessment statistics - $r->print('

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

'); - my $table = ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''. - ''.$/; + my $table=&Apache::loncommon::start_data_table() + .&Apache::loncommon::start_data_table_header_row() + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .&Apache::loncommon::end_data_table_header_row().$/; foreach my $identifier (sort(keys(%{$dynmeta{'stats'}}))) { my $data = $dynmeta{'stats'}->{$identifier}; my $course = $data->{'course'}; - my %courseinfo = &Apache::lonnet::coursedescription($course); + my %courseinfo = + &Apache::lonnet::coursedescription($course, + {'one_time' => 1}); if (! exists($courseinfo{'num'}) || $courseinfo{'num'} eq '') { &Apache::lonnet::logthis('lookup for '.$course.' failed'); next; } - $table .= ''; + $table .= &Apache::loncommon::start_data_table_row(); $table .= - ''; + ''; $table .= ''; $table .= ''; - foreach ('avetries','difficulty','disc') { + foreach my $item ('avetries','difficulty','disc') { $table .= ''; } $table .= - ''; - $table .= - ''.$/; + ''; + $table .= &Apache::loncommon::end_data_table_row().$/; } - $table .= '
CourseSection(s)Num StudentsMean TriesDegree of DifficultyDegree of DiscriminationTime of computation
'.&mt('Course').''.&mt('Section(s)').''.&mt('Num Students').''.&mt('Mean Tries').''.&mt('Degree of Difficulty').''.&mt('Degree of Discrimination').''.&mt('Time of computation').'
'.$courseinfo{'description'}.''.$courseinfo{'description'}.''.$data->{'sections'}.''.$data->{'stdno'}.''; - if (exists($data->{$_})) { - $table .= sprintf('%.2f',$data->{$_}).' '; + if (exists($data->{$item})) { + $table .= sprintf('%.2f',$data->{$item}).' '; } else { $table .= ''; } $table .= ''. + ''. &Apache::lonlocal::locallocaltime($data->{'timestamp'}). - '
'.$/; + $table .= &Apache::loncommon::end_data_table().$/; $r->print($table); } else { - $r->print('No new dynamic data found.'); + $r->print('

' + .&mt('No new dynamic data found.') + .'

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

'. @@ -911,73 +1144,105 @@ sub print_dynamic_metadata { } # - # + # Evaluation Data + $r->print('

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

'); 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(&Apache::lonhtmlcommon::start_pick_box()); + my @criteria = ('clear','depth','helpful','correct','technical'); + my $rownum = 0; + foreach my $item (@criteria) { + my $lastrow = ''; + $rownum ++; + $lastrow = 1 if ($rownum == @criteria); + $r->print(&Apache::lonhtmlcommon::row_title($lt{$item}) + .&prettyprint($item,$dynmeta{$item}) + .&Apache::lonhtmlcommon::row_closure($lastrow) + ); } - $r->print('
'.$lt{$_}.''. - &prettyprint($_,$dynmeta{$_})."
'); + $r->print(&Apache::lonhtmlcommon::end_pick_box()); } else { - $r->print('

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

'); + $r->print('

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

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

'.&mt('Evaluation Comments').'

' + .'
(' + .&mt('visible to author and co-authors only') + .')
' + ); if (exists($dynmeta{'comments'})) { - $r->print('

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

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

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

'); + $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.').'

'); - } + $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$/) { + ''); + $r->print(&Apache::lonhtmlcommon::start_pick_box()); + my @names; + foreach my $key (sort(keys(%content))) { + if ($key!~/\.display$/) { + push(@names,$key); + } + } + if (@names > 0) { + my $rownum = 0; + foreach my $name (@names) { + my $lastrow = ''; + $rownum ++; + $lastrow = 1 if ($rownum == @names); + my $display=&Apache::lonnet::metadata($uri, $name.'.display'); if (! $display) { $display=$name; }; my $otherinfo=''; - foreach ('name','part','type','default') { + foreach my $item ('name','part','type','default') { if (defined(&Apache::lonnet::metadata($uri, - $name.'.'.$_))) { - $otherinfo.=' '.$_.'='. + $name.'.'.$item))) { + $otherinfo.=' '.$item.'='. &Apache::lonnet::metadata($uri, - $name.'.'.$_).'; '; + $name.'.'.$item).'; '; } } - $r->print('\n"); + $r->print(&Apache::lonhtmlcommon::row_closure($lastrow)); } } - $r->print("
'.$display.''.$content{$name}); + $r->print(&Apache::lonhtmlcommon::row_title($display) + .$content{$name} + ); if ($otherinfo) { $r->print(' ('.$otherinfo.')'); } - $r->print("
"); + $r->print(&Apache::lonhtmlcommon::end_pick_box()); return; } @@ -991,16 +1256,20 @@ sub print_dynamic_metadata { ##################################################### ##################################################### sub present_editable_metadata { - my ($r,$uri, $file_type) = @_; + my ($r,$uri,$file_type) = @_; # Construction Space Call # Header my $disuri=$uri; my $fn=&Apache::lonnet::filelocation('',$uri); - $disuri=~s/^\/\~/\/priv\//; + $disuri=~s{^/\~}{/priv/}; $disuri=~s/\.meta$//; - $disuri=~s|^/editupload||; + 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{^/\~}{/res/$env{'request.role.domain'}/}; $target=~s/\.meta$//; my $bombs=&Apache::lonmsg::retrieve_author_res_msg($target); if ($bombs) { @@ -1028,7 +1297,7 @@ sub present_editable_metadata { my $goback=&mt('Back to Source File'); $r->print(<$disuri -
+ ENDBOMBS if ($showdel) { $r->print(< 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=(); my $result=&Apache::lonnet::getfile($fn); if ($result == -1){ - $r->print('Creating new '.$disuri); + $r->print(&mt('Creating new file [_1]'),$meta_uri); } 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 - +

$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','courserestricted'); + my $added_metadata_fields; + my @added_order; + if ($file_type eq 'groups') { + $Apache::lonpublisher::metadatafields{'courserestricted'}= + 'course.'.$env{'request.course.id'}; + } + if ((! $Apache::lonpublisher::metadatafields{'courserestricted'}) && + (! $env{'form.new_courserestricted'}) && (! $file_type eq 'groups')) { + $Apache::lonpublisher::metadatafields{'courserestricted'}= + 'none'; + } elsif ($env{'form.new_courserestricted'}) { + $Apache::lonpublisher::metadatafields{'courserestricted'}= + $env{'form.new_courserestricted'}; + } + if ($file_type eq 'portfolio' || $file_type eq 'groups') { + if(exists ($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.fieldlist'})) { + # retrieve fieldnames (in order) from the course restricted list + @fields = (split(/,/,$env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.fieldlist'})); + } else { + # no saved field list, use default list + @fields = ('author','title','subject','keywords','abstract', + 'notes','lowestgradelevel', + 'highestgradelevel','standards'); + if ($Apache::lonpublisher::metadatafields{'courserestricted'} =~ /^course\.($match_domain\_$match_courseid)$/) { + my $assoc_crs = $1; + $added_metadata_fields = &Apache::lonparmset::get_added_meta_fieldnames($assoc_crs); + if ($env{'course.'.$assoc_crs.'.metadata.addedorder'}) { + @added_order = split(/,/,$env{'course.'.$assoc_crs.'.metadata.addedorder'}); + } + $env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.fieldlist'} = join(",",@fields); + } + } } else { @fields = ('author','title','subject','keywords','abstract','notes', - 'copyright','customdistributionfile','language', - 'standards', - 'lowestgradelevel','highestgradelevel','sourceavail','sourcerights', - 'obsolete','obsoletereplacement'); - } - my $metacourse; - if ($env{'form.metacourse'} ) { - $Apache::lonpublisher::metadatafields{'courserestricted'} = $env{'form.metacourse'}; - $metacourse = $env{'form.metacourse'}; - } else { - if (! $Apache::lonpublisher::metadatafields{'courserestricted'}) { - $Apache::lonpublisher::metadatafields{'courserestricted'}= - 'none'; - $metacourse = 'none'; - } else { - $metacourse = $Apache::lonpublisher::metadatafields{'courserestricted'}; - } + 'copyright','customdistributionfile','language', + 'standards', + 'lowestgradelevel','highestgradelevel','sourceavail','sourcerights', + 'obsolete','obsoletereplacement'); } if (! $Apache::lonpublisher::metadatafields{'copyright'}) { $Apache::lonpublisher::metadatafields{'copyright'}= - 'default'; - } - if ($metacourse ne 'none') { - $r->print('Document metadata restricted by : '.$env{$metacourse.".description"}."
"); + 'default'; } - - foreach (@fields) { - if (defined($env{'form.new_'.$_})) { - $Apache::lonpublisher::metadatafields{$_}= - join(',',&Apache::loncommon::get_env_multiple('form.new_'.$_)); - } - if ($metacourse ne 'none') { - # handle restrictions here - if (($env{$metacourse.'.metadata.'.$_.'.options'} =~ m/active/)|| - ($_ eq 'courserestricted')) { - $output.=('

'.$lt{$_}.': '. - &prettyinput($_, - $Apache::lonpublisher::metadatafields{$_}, - 'new_'.$_,'defaultmeta',undef,undef,undef,undef,$metacourse).'

'); + if (($file_type eq 'portfolio') || ($file_type eq 'groups')) { + if (! $Apache::lonpublisher::metadatafields{'mime'}) { + ($Apache::lonpublisher::metadatafields{'mime'}) = + ( $target=~/\.(\w+)$/ ); + } + if (! $Apache::lonpublisher::metadatafields{'owner'}) { + $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') { + $r->print(&mt('Associated with course [_1]', + ''. + $env{$Apache::lonpublisher::metadatafields{'courserestricted'}. + ".description"}. + '').'
'); + } else { + $r->print(&mt('Associated with course [_1]', + ''. + $env{$Apache::lonpublisher::metadatafields{'courserestricted'}. + ".description"}.'').'
'); } - } else { - $output.=('

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

'); + } else { + $r->print(''.&mt('This resource is not associated with a course.').'
'); + } + } + if (@added_order) { + foreach my $field_name (@added_order) { + push(@fields,$field_name); + $lt{$field_name} = $$added_metadata_fields{$field_name}; + } + } else { + foreach my $field_name (keys(%$added_metadata_fields)) { + push(@fields,$field_name); + $lt{$field_name} = $$added_metadata_fields{$field_name}; } } - if ($env{'form.store'}) { - my $mfh; - my $formname='store'; - my $file_content; - foreach my $meta_field (keys %env) { - if (&Apache::loncommon::get_env_multiple('form.new_keywords')) { - $Apache::lonpublisher::metadatafields{'keywords'} = - join (',', &Apache::loncommon::get_env_multiple('form.new_keywords')); + $output .= &Apache::lonhtmlcommon::start_pick_box(); + my $last = $#fields + 1; + my $rowcount = 0; + foreach my $field_name (@fields) { + $rowcount++; + if (defined($env{'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; } - 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 =~ /\/portfolio\//) { - $fn =~ /\/portfolio\/(.*)$/; - my $new_fn = '/'.$1; - $env{'form.'.$formname}=$file_content; - $env{'form.'.$formname.'.filename'}=$new_fn; - &Apache::lonnet::userfileupload('uploaddoc','', - 'portfolio'.$env{'form.currentpath'}); - if (&Apache::lonnet::userfileupload($formname,'','portfolio') eq 'error: no uploaded file') { - $r->print('

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

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

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

'); - } + if ($Apache::lonpublisher::metadatafields{'courserestricted'} ne 'none' + && exists($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.'.$field_name.'.options'})) { + # handle restrictions here + if ((($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.'.$field_name.'.options'} =~ m/active/) || + ($field_name eq 'courserestricted'))&& + (!($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/))){ + + $output .= &Apache::lonhtmlcommon::row_title($lt{$field_name}) + .&prettyinput($field_name, + $Apache::lonpublisher::metadatafields{$field_name}, + 'new_'.$field_name,'defaultmeta', + undef,undef,undef,undef, + $Apache::lonpublisher::metadatafields{'courserestricted'}); + $output .= &Apache::lonhtmlcommon::row_closure($rowcount == $last?1:0); + } } 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). - '

'); - } + + $output .= &Apache::lonhtmlcommon::row_title($lt{$field_name}) + .&prettyinput($field_name, + $Apache::lonpublisher::metadatafields{$field_name}, + 'new_'.$field_name,'defaultmeta') + .&Apache::lonhtmlcommon::row_closure($rowcount == $last?1:0); + } } - $r->print($output.'
'); + $output .= &Apache::lonhtmlcommon::end_pick_box(); + if ($env{'form.store'}) { + my ($outcome,$result) = &store_metadata($fn,$uri,'store'); + $r->print($result); + } + my $savebutton = '

'; + $r->print($savebutton.$output.$savebutton); + + if ($file_type eq 'portfolio' || $file_type eq 'groups') { + my ($port_path,$group) = &get_port_path_and_group($uri); + if ($group ne '') { + $r->print(''); + } + $r->print(''); + $r->print('

'); + if ($group ne '') { + $r->print(''); + } + $r->print(''. + ''); + } } + $r->print('
'); + 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); + my $confirmtext; + if ($caller eq 'transfer') { + $confirmtext = &mt('Transferred data in added fields to notes'); + } else { + $confirmtext = &mt('Wrote Metadata'); + } + $output .= &Apache::loncommon::confirmwrapper( + &Apache::lonhtmlcommon::confirm_success( + $confirmtext.' '.&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,$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)/) { + $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); + $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 { + my ($uri) = @_; + my ($type,$udom,$uname,$file_name,$group) = + &Apache::lonnet::parse_portfolio_url($uri); + $file_name =~ s/\.meta$//; + my $current_permissions = + &Apache::lonnet::get_portfile_permissions($udom,$uname); + my %access_controls = + &Apache::lonnet::get_access_controls($current_permissions,$group, + $file_name); + my $access_hash = $access_controls{$file_name}; + my $available = 0; + if (ref($access_hash) eq 'HASH') { + foreach my $key (keys(%{$access_hash})) { + my ($num,$scope,$end,$start) = + ($key =~ /^([^:]+):([a-z]+)_(\d*)_?(\d*)$/); + if ($scope eq 'public' || $scope eq 'guest') { + $available = 1; + last; + } + } + } + if ($available) { + my $result = + &Apache::lonnet::update_portfolio_table($uname,$udom, + $file_name,'portfolio_metadata',$group,'update'); + } +} + + 1; __END__ - + +=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 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 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.