--- loncom/interface/lonmeta.pm 2004/04/13 15:41:19 1.65 +++ loncom/interface/lonmeta.pm 2006/10/23 20:53:46 1.184 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Metadata display handler # -# $Id: lonmeta.pm,v 1.65 2004/04/13 15:41:19 matthew Exp $ +# $Id: lonmeta.pm,v 1.184 2006/10/23 20:53:46 banghart Exp $ # # Copyright Michigan State University Board of Trustees # @@ -17,7 +17,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # @@ -31,18 +31,82 @@ package Apache::lonmeta; use strict; use LONCAPA::lonmetadata(); use Apache::Constants qw(:common); -use Apache::lonnet(); +use Apache::lonnet; use Apache::loncommon(); -use Apache::lonhtmlcommon(); +use Apache::lonhtmlcommon(); use Apache::lonmsg; use Apache::lonpublisher; use Apache::lonlocal; use Apache::lonmysql; use Apache::lonmsg; +use lib '/home/httpd/lib/perl/'; +use LONCAPA; -# MySQL table columns -my @columns; +############################################################ +############################################################ +## +## &get_dynamic_metadata_from_sql($url) +## +## Queries sql database for dynamic metdata +## Returns a hash of hashes, with keys of urls which match $url +## Returned fields are given below. +## +## Examples: +## +## %DynamicMetadata = &Apache::lonmeta::get_dynmaic_metadata_from_sql +## ('/res/msu/korte/'); +## +## $DynamicMetadata{'/res/msu/korte/example.problem'}->{$field} +## +############################################################ +############################################################ +sub get_dynamic_metadata_from_sql { + my ($url) = shift(); + my ($authordom,$author)=($url=~m:^/res/(\w+)/(\w+)/:); + if (! defined($authordom)) { + $authordom = shift(); + } + if (! defined($author)) { + $author = shift(); + } + if (! defined($authordom) || ! defined($author)) { + return (); + } + my $query = 'SELECT * FROM metadata WHERE url LIKE "'.$url.'%"'; + my $server = &Apache::lonnet::homeserver($author,$authordom); + my $reply = &Apache::lonnet::metadata_query($query,undef,undef, + ,[$server]); + return () if (! defined($reply) || ref($reply) ne 'HASH'); + my $filename = $reply->{$server}; + if (! defined($filename) || $filename =~ /^error/) { + return (); + } + my $max_time = time + 10; # wait 10 seconds for results at most + my %ReturnHash; + # + # Look for results + my $finished = 0; + while (! $finished && time < $max_time) { + my $datafile=$Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/'.$filename; + if (! -e "$datafile.end") { next; } + my $fh; + if (!($fh=Apache::File->new($datafile))) { next; } + while (my $result = <$fh>) { + chomp($result); + next if (! $result); + my %hash=&LONCAPA::lonmetadata::metadata_col_to_hash('metadata', + map { &unescape($_) } split(/\,/,$result)); + foreach my $key (keys(%hash)) { + $ReturnHash{$hash{'url'}}->{$key}=$hash{$key}; + } + } + $finished = 1; + } + # + return %ReturnHash; +} + # Fetch and evaluate dynamic metadata sub dynamicmeta { @@ -60,6 +124,15 @@ sub dynamicmeta { # # 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; } @@ -98,7 +171,7 @@ sub authordisplay { my ($aname,$adom)=@_; return &Apache::loncommon::aboutmewrapper (&Apache::loncommon::plainname($aname,$adom), - $aname,$adom,'preview').' <tt>['.$aname.'@'.$adom.']</tt>'; + $aname,$adom,'preview').' <tt>['.$aname.':'.$adom.']</tt>'; } # Pretty display @@ -108,21 +181,21 @@ sub evalgraph { return ''; } my $val=int($value*10.+0.5)-10; - my $output='<table border=0 cellpadding=0 cellspacing=0><tr>'; + my $output='<table border="0" cellpadding="0" cellspacing="0"><tr>'; if ($val>=20) { - $output.='<td width=20 bgcolor="#555555">  </td>'; + $output.='<td width="20" bgcolor="#555555">  </td>'; } else { - $output.='<td width='.($val).' bgcolor="#555555"> </td>'. - '<td width='.(20-$val).' bgcolor="#FF3333"> </td>'; + $output.='<td width="'.($val).'" bgcolor="#555555"> </td>'. + '<td width="'.(20-$val).'" bgcolor="#FF3333"> </td>'; } $output.='<td bgcolor="#FFFF33"> </td>'; if ($val>20) { - $output.='<td width='.($val-20).' bgcolor="#33FF33"> </td>'. - '<td width='.(40-$val).' bgcolor="#555555"> </td>'; + $output.='<td width="'.($val-20).'" bgcolor="#33FF33"> </td>'. + '<td width="'.(40-$val).'" bgcolor="#555555"> </td>'; } else { - $output.='<td width=20 bgcolor="#555555">  </td>'; + $output.='<td width="20" bgcolor="#555555">  </td>'; } - $output.='<td> ('.$value.') </td></tr></table>'; + $output.='<td> ('.sprintf("%5.2f",$value).') </td></tr></table>'; return $output; } @@ -134,43 +207,39 @@ sub diffgraph { my $val=int(40.0*$value+0.5); my @colors=('#FF9933','#EEAA33','#DDBB33','#CCCC33', '#BBDD33','#CCCC33','#DDBB33','#EEAA33'); - my $output='<table border=0 cellpadding=0 cellspacing=0><tr>'; + my $output='<table border="0" cellpadding="0" cellspacing="0"><tr>'; for (my $i=0;$i<8;$i++) { if ($val>$i*5) { - $output.='<td width=5 bgcolor="'.$colors[$i].'"> </td>'; + $output.='<td width="5" bgcolor="'.$colors[$i].'"> </td>'; } else { - $output.='<td width=5 bgcolor="#555555"> </td>'; + $output.='<td width="5" bgcolor="#555555"> </td>'; } } - $output.='<td> ('.$value.') </td></tr></table>'; + $output.='<td> ('.sprintf("%3.2f",$value).') </td></tr></table>'; return $output; } -# Turn MySQL row into hash -sub metadata_col_to_hash { - my @cols=@_; - my %hash=(); - for (my $i=0; $i<=$#columns; $i++) { - $hash{$columns[$i]}=$cols[$i]; - } - return %hash; -} # The field names sub fieldnames { - return &Apache::lonlocal::texthash - ( - 'title' => 'Title', + 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', - 'standards' => 'Standards', + 'highestgradelevel' => 'Highest Grade Level'); + + if (! defined($file_type) || $file_type ne 'portfolio') { + %fields = + (%fields, + 'domain' => 'Domain', 'mime' => 'MIME Type', 'language' => 'Language', 'creationdate' => 'Creation Date', @@ -178,6 +247,8 @@ sub fieldnames { '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)', @@ -196,14 +267,152 @@ sub fieldnames { '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' + '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,$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('<hr /><form method="post" action="" >'); + $r->print('<p>'.&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\'','<tt>'.$res_uri.'</tt>').'</p>'); + $output = &select_course(); + $r->print($output.'<br /><input type="submit" name="store" value="'. + &mt('Associate Resource With Selected Course').'" />'); + $r->print('<input type="hidden" name="currentpath" value="'.$env{'form.currentpath'}.'" />'); + $r->print('<input type="hidden" name="associate" value="true" />'); + $r->print('</form>'); + + my ($port_path,$group) = &get_port_path_and_group($uri); + my $group_input; + if ($group) { + $group_input = '<input type="hidden" name="group" value="'.$group.'" />'; + } + $r->print('<br /><br /><form method="post" action="'.$port_path.'">'. + '<input type="hidden" name="currentpath" value="'.$path.'" />'. + $group_input. + '<input type="submit" name="cancel" value="'.&mt('Cancel').'" />'. + '</form>'); + + return; +} +sub select_course { + my $output=$/; + my $current_restriction= + $Apache::lonpublisher::metadatafields{'courserestricted'}; + my $selected = ($current_restriction eq 'none' ? 'selected="selected"' + : ''); + + $output .= '<select name="new_courserestricted" >'; + $output .= '<option value="none" '.$selected.'>'. + &mt('None').'</option>'.$/; + my %courses; + 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 .= '<option value="'.$cid.'" '.$selected.'>'; + $output .= $env{$key}; + $output .= '</option>'.$/; + $selected = ''; + } + $output .= '</select><br />'; + return ($output); +} # Pretty printing of metadata field sub prettyprint { - my ($type,$value)=@_; + my ($type,$value,$target,$prefix,$form,$noformat)=@_; +# $target,$prefix,$form are optional and for filecrumbs only if (! defined($value)) { return ' '; } @@ -226,6 +435,10 @@ sub prettyprint { 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 '<img src="'.&Apache::loncommon::icon($value).'" /> '. @@ -245,7 +458,7 @@ sub prettyprint { return &Apache::loncommon::gradeleveldescription($value); } # Only for advance users below - if (! $ENV{'user.adv'}) { + if (! $env{'user.adv'}) { return '<i>- '.&mt('not displayed').' -</i>'; } # File @@ -253,12 +466,29 @@ sub prettyprint { ($type eq 'obsoletereplacement') || ($type eq 'goto_list') || ($type eq 'comefrom_list') || - ($type eq 'sequsage_list')) { - return join('<br />',map { - my $url=&Apache::lonnet::clutter($_); - '<b>'.&Apache::lonnet::gettitle($url).'</b>'. - &Apache::lonhtmlcommon::crumbs($url,'preview','',undef,'+0'); - } split(/\s*\,\s*/,$value)); + ($type eq 'sequsage_list') || + ($type eq 'dependencies')) { + return '<font size="-1"><ul>'.join("\n",map { + my $url = &Apache::lonnet::clutter_with_no_wrapper($_); + my $title = &Apache::lonnet::gettitle($url); + if ($title eq '') { + $title = 'Untitled'; + if ($url =~ /\.sequence$/) { + $title .= ' Sequence'; + } elsif ($url =~ /\.page$/) { + $title .= ' Page'; + } elsif ($url =~ /\.problem$/) { + $title .= ' Problem'; + } elsif ($url =~ /\.html$/) { + $title .= ' HTML document'; + } elsif ($url =~ m:/syllabus$:) { + $title .= ' Syllabus'; + } + } + $_ = '<li>'.$title.' '. + &Apache::lonhtmlcommon::crumbs($url,$target,$prefix,$form,'-1',$noformat). + '</li>' + } split(/\s*\,\s*/,$value)).'</ul></font>'; } # Evaluations if (($type eq 'clear') || @@ -269,17 +499,32 @@ sub prettyprint { return &evalgraph($value); } # Difficulty - if ($type eq 'difficulty') { + if ($type eq 'difficulty' || $type eq 'disc') { return &diffgraph($value); } # List of courses if ($type=~/\_list/) { - return join('<br />',map { - my %courseinfo=&Apache::lonnet::coursedescription($_); - '<a href="/public/'. - $courseinfo{'domain'}.'/'.$courseinfo{'num'}.'/syllabus" target="preview">'. - $courseinfo{'description'}.'</a>'; - } split(/\s*\,\s*/,$value)); + my @Courses = split(/\s*\,\s*/,$value); + my $Str='<font size="-1"><ul>'; + my %descriptions; + foreach my $course (@Courses) { + my %courseinfo = + &Apache::lonnet::coursedescription($course, + {'one_time' => 1}); + if (! exists($courseinfo{'num'}) || $courseinfo{'num'} eq '') { + next; + } + $descriptions{join('\0',@courseinfo{'domain','description'})} .= + '<li><a href="/public/'.$courseinfo{'domain'}.'/'. + $courseinfo{'num'}.'/syllabus" target="preview">'. + $courseinfo{'description'}.' ('.$courseinfo{'domain'}. + ')</a></li>'; + } + foreach my $course (sort {lc($a) cmp lc($b)} (keys(%descriptions))) { + $Str .= $descriptions{$course}; + } + + return $Str.'</ul></font>'; } # No pretty print found return $value; @@ -323,7 +568,74 @@ sub relatedfield { sub prettyinput { my ($type,$value,$fieldname,$formname, - $relatedsearchflag,$relatedsep,$relatedvalue)=@_; + $relatedsearchflag,$relatedsep,$relatedvalue,$size,$course_key)=@_; + if (! defined($size)) { + $size = 80; + } + my $output; + if (defined($course_key) + && exists($env{$course_key.'.metadata.'.$type.'.options'})) { + 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 ('<input type="hidden" name="new_courserestricted" value="'.$course_key.'" />'); + } + my $course = $env{'request.course.id'}; + 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.'.$env{'request.course.id'}.'.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 ($stu_add) { + $output .= '<input type="text" name="'.$fieldname.'" size="'.$size.'" '. + 'value="'.$cur_values_stu.'" />'. + &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, @@ -340,6 +652,14 @@ sub prettyinput { (&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')) { @@ -368,6 +688,19 @@ sub prettyinput { ",'rights')\">".&mt('Select').'</a>'. &relatedfield(0,$relatedsearchflag,$relatedsep); } + # Source Customdistribution file + if ($type eq 'sourcerights') { + return '<input type="text" name="'.$fieldname. + '" size="60" value="'.$value.'" /><a href="javascript:openbrowser'. + "('".$formname."','".$fieldname."'". + ",'rights')\">".&mt('Select').'</a>'. + &relatedfield(0,$relatedsearchflag,$relatedsep); + } + if ($type eq 'courserestricted') { + return (&select_course()); + #return ('<input type="hidden" name="new_courserestricted" value="'.$course_key.'" />'); + } + # Dates if (($type eq 'creationdate') || ($type eq 'lastrevisiondate')) { @@ -379,9 +712,9 @@ sub prettyinput { $value=~s/^\s+//gs; $value=~s/\s+$//gs; $value=~s/\s+/ /gs; - $value=~s/\"/\&quod\;/gs; + $value=~s/\"/\"\;/gs; return - '<input type="text" name="'.$fieldname.'" size="80" '. + '<input type="text" name="'.$fieldname.'" size="'.$size.'" '. 'value="'.$value.'" />'. &relatedfield(1,$relatedsearchflag,$relatedsep,$fieldname, $relatedvalue); @@ -390,329 +723,658 @@ sub prettyinput { # Main Handler sub handler { my $r=shift; - # - my $loaderror=&Apache::lonnet::overloaderror($r); - if ($loaderror) { return $loaderror; } - # + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['currentpath']); my $uri=$r->uri; # - # Looking for all bombs? - if ($uri=~/\/adm\/bombs\/(.*)$/) { - # Set document type - $uri=&Apache::lonnet::declutter($1); - &Apache::loncommon::content_type($r,'text/html'); - $r->send_http_header; - # - return OK if $r->header_only; - $r->print(&Apache::loncommon::bodytag('Error Messages')); - $r->print('<h1>'.&Apache::lonnet::clutter($uri).'</h1>'); - my ($domain,$author)=($uri=~/^(\w+)\/(\w+)\//); - if (&Apache::loncacc::constructaccess('/~'.$author.'/',$domain)) { - my %brokenurls=&Apache::lonmsg::all_url_author_res_msg($author, - $domain); - foreach (sort keys %brokenurls) { - if ($_=~/^\Q$uri\E/) { - $r->print(&Apache::lonhtmlcommon::crumbs - (&Apache::lonnet::clutter($_)). - &Apache::lonmsg::retrieve_author_res_msg($_). - '<hr />'); - } - } + # 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+)\//); + if ($uri=~m:/adm/bombs/(.*)$:) { + $r->print(&Apache::loncommon::start_page('Error Messages')); + # Looking for all bombs? + &report_bombs($r,$uri); + } elsif ($uri=~m|^/editupload/[^/]+/[^/]+/portfolio/|) { + ($resdomain,$resuser)= + (&Apache::lonnet::declutter($uri)=~m|^(\w+)/(\w+)/portfolio|); + $r->print(&Apache::loncommon::start_page('Edit Portfolio File Catalog Information', + undef, + {'domain' => $resdomain,})); + if ($env{'form.store'}) { + &present_editable_metadata($r,$uri,'portfolio'); } else { - $r->print(&mt('Not authorized')); + &pre_select_course($r,$uri); } - $r->print('</body></html>'); - } elsif ($uri!~/^\/\~/) { - # This is not in construction space - my ($resdomain,$resuser)= - (&Apache::lonnet::declutter($uri)=~/^(\w+)\/(\w+)\//); - $loaderror=&Apache::lonnet::overloaderror - ($r, - &Apache::lonnet::homeserver($resuser,$resdomain)); - if ($loaderror) { return $loaderror; } - # - my %content=(); - # Set document type - &Apache::loncommon::content_type($r,'text/html'); - $r->send_http_header; - return OK if $r->header_only; - # 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; + } elsif ($uri=~m|^/editupload/[^/]+/[^/]+/groups/|) { + $r->print(&Apache::loncommon::start_page('Edit Group Portfolio File Catalog Information', + undef, + {'domain' => $resdomain,})); + &present_editable_metadata($r,$uri,'groups'); + } elsif ($uri=~m|^/~|) { + # Construction space + $r->print(&Apache::loncommon::start_page('Edit Catalog nformation', + undef, + {'domain' => $resdomain,})); + &present_editable_metadata($r,$uri); + } else { + $r->print(&Apache::loncommon::start_page('Catalog Information', + undef, + {'domain' => $resdomain,})); + &present_uneditable_metadata($r,$uri); + } + $r->print(&Apache::loncommon::end_page()); + return OK; +} + +##################################################### +##################################################### +### ### +### Report Bombs ### +### ### +##################################################### +##################################################### +sub report_bombs { + my ($r,$uri) = @_; + # Set document type + $uri =~ s:/adm/bombs/::; + $uri = &Apache::lonnet::declutter($uri); + $r->print('<h1>'.&Apache::lonnet::clutter($uri).'</h1>'); + 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); +<form method="post"> +<input type="submit" name="clearbombs" value="$clear" /> +</form> +ENDCLEAR + my %brokenurls = + &Apache::lonmsg::all_url_author_res_msg($author,$domain); + foreach (sort(keys(%brokenurls))) { + if ($_=~/^\Q$uri\E/) { + $r->print + ('<a href="'.&Apache::lonnet::clutter($_).'">'.$_.'</a>'. + &Apache::lonmsg::retrieve_author_res_msg($_). + '<hr />'); + } } - # crumbify displayed URL - $disuri=&Apache::lonhtmlcommon::crumbs($disuri); - # obsolete - my $obsolete=$content{'obsolete'}; - my $obsoletewarning=''; - if (($obsolete) && ($ENV{'user.adv'})) { - $obsoletewarning='<p><font color="red">'. - &mt('This resource has been marked obsolete by the author(s)'). - '</font></p>'; - } - # - my %lt=&fieldnames(); - my $table=''; - my $bodytag=&Apache::loncommon::bodytag - ('Catalog Information','','','',$resdomain); - foreach ('title', - 'author', - 'subject', - 'keywords', - 'notes', - 'abstract', - 'lowestgradelevel', - 'highestgradelevel', - 'standards', - 'mime', - 'language', - 'creationdate', - 'lastrevisiondate', - 'owner', - 'copyright', - 'customdistributionfile', - 'obsolete', - 'obsoletereplacement') { - $table.='<tr><td bgcolor="#AAAAAA">'.$lt{$_}. - '</td><td bgcolor="#CCCCCC">'. - &prettyprint($_,$content{$_}).'</td></tr>'; - delete $content{$_}; - } - # - $r->print(<<ENDHEAD); -<html><head><title>Catalog Information</title></head> -$bodytag -<h2>$content{'title'}</h2> -<h3><tt>$disuri</tt></h3> + } else { + $r->print(&mt('Not authorized')); + } + return; +} + +##################################################### +##################################################### +### ### +### Uneditable Metadata Display ### +### ### +##################################################### +##################################################### +sub present_uneditable_metadata { + my ($r,$uri) = @_; + # + my $uploaded = ($uri =~ m|/uploaded/|); + my %content=(); + # Read file + foreach (split(/\,/,&Apache::lonnet::metadata($uri,'keys'))) { + $content{$_}=&Apache::lonnet::metadata($uri,$_); + } + # Render Output + # displayed url + my ($thisversion)=($uri=~/\.(\d+)\.(\w+)\.meta$/); + $uri=~s/\.meta$//; + my $disuri=&Apache::lonnet::clutter_with_no_wrapper($uri); + # version + my $versiondisplay=''; + if (!$uploaded) { + my $currentversion=&Apache::lonnet::getversion($disuri); + if ($thisversion) { + $versiondisplay=&mt('Version').': '.$thisversion. + ' ('.&mt('most recent version').': '. + ($currentversion>0 ? + $currentversion : + &mt('information not available')).')'; + } else { + $versiondisplay='Version: '.$currentversion; + } + } + # crumbify displayed URL uri target prefix form size + $disuri=&Apache::lonhtmlcommon::crumbs($disuri,undef, undef, undef,'+1'); + $disuri =~ s:<br />::g; + # obsolete + my $obsolete=$content{'obsolete'}; + my $obsoletewarning=''; + if (($obsolete) && ($env{'user.adv'})) { + $obsoletewarning='<p><font color="red">'. + &mt('This resource has been marked obsolete by the author(s)'). + '</font></p>'; + } + # + my %lt=&fieldnames(); + my $table=''; + my $title = $content{'title'}; + if (! defined($title)) { + $title = 'Untitled Resource'; + } + my @fields; + if ($uploaded) { + @fields = ('title','author','subject','keywords','notes','abstract', + 'lowestgradelevel','highestgradelevel','standards','mime', + 'owner'); + } else { + @fields = ('title', + 'author', + 'subject', + 'keywords', + 'notes', + 'abstract', + 'lowestgradelevel', + 'highestgradelevel', + 'standards', + 'mime', + 'language', + 'creationdate', + 'lastrevisiondate', + 'owner', + 'copyright', + 'customdistributionfile', + 'sourceavail', + 'sourcerights', + 'obsolete', + 'obsoletereplacement'); + } + foreach my $field (@fields) { + $table.='<tr><td bgcolor="#AAAAAA">'.$lt{$field}. + '</td><td bgcolor="#CCCCCC">'. + &prettyprint($field,$content{$field}).'</td></tr>'; + delete($content{$field}); + } + # + $r->print(<<ENDHEAD); +<h2>$title</h2> +<p> +$disuri<br /> $obsoletewarning -$versiondisplay<br /> -<table cellspacing=2 border=0> +$versiondisplay +</p> +<table cellspacing="2" border="0"> $table </table> ENDHEAD - if ($ENV{'user.adv'}) { - # Dynamic Metadata - $r->print( - '<h3>'.&mt('Dynamic Metadata').' ('. - &mt('updated periodically').')</h3>'.&mt('Processing'). - ' ...<br />'); - $r->rflush(); - my %items=&fieldnames(); - my %dynmeta=&dynamicmeta($uri); - # General Access and Usage Statistics - $r->print('<h4>'.&mt('Access and Usage Statistics').'</h4>'. - '<table cellspacing=2 border=0>'); - foreach ('count', - 'sequsage','sequsage_list', - 'comefrom','comefrom_list', - 'goto','goto_list', - 'course','course_list') { + if (!$uploaded && $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('<h3>'.&mt($description).'</h3>'. + &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('<h4>'.&mt('Access and Usage Statistics').'</h4>'. + '<table cellspacing="2" border="0">'); + foreach ('count', + 'sequsage','sequsage_list', + 'comefrom','comefrom_list', + 'goto','goto_list', + 'course','course_list') { + $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. + '<td bgcolor="#CCCCCC">'. + &prettyprint($_,$dynmeta{$_})."</td></tr>\n"); + } + $r->print('</table>'); + } else { + $r->print('<h4>'.&mt('No Access or Usages Statistics are available for this resource.').'</h4>'); + } + # + # 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('<h4>'. + &mt('Overall Assessment Statistical Data'). + '</h4>'. + '<table cellspacing="2" border="0">'); + $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{'stdno'}.'</td>'. + '<td bgcolor="#CCCCCC">'. + &prettyprint('stdno',$dynmeta{'stdno'}). + '</td>'."</tr>\n"); + foreach ('avetries','difficulty','disc') { $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. '<td bgcolor="#CCCCCC">'. - &prettyprint($_,$dynmeta{$_})."</td></tr>\n"); + &prettyprint($_,sprintf('%5.2f',$dynmeta{$_})). + '</td>'."</tr>\n"); } - $r->print('</table>'); - if ($uri=~/\.(problem|exam|quiz|assess|survey|form)\.meta$/) { - # This is an assessment, print assessment data - $r->print( - '<h4>'.&mt('Assessment Statistical Data').'</h4>'. - '<table cellspacing=2 border=0>'); - foreach ('stdno','avetries','difficulty') { - $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. - '<td bgcolor="#CCCCCC">'. - &prettyprint($_,$dynmeta{$_})."</td></tr>\n"); + $r->print('</table>'); + } + if (exists($dynmeta{'stats'})) { + # + # New assessment statistics + $r->print('<h4>'. + &mt('Detailed Assessment Statistical Data'). + '</h4>'); + my $table = '<table cellspacing="2" border="0">'. + '<tr>'. + '<th>Course</th>'. + '<th>Section(s)</th>'. + '<th>Num Students</th>'. + '<th>Mean Tries</th>'. + '<th>Degree of Difficulty</th>'. + '<th>Degree of Discrimination</th>'. + '<th>Time of computation</th>'. + '</tr>'.$/; + foreach my $identifier (sort(keys(%{$dynmeta{'stats'}}))) { + my $data = $dynmeta{'stats'}->{$identifier}; + my $course = $data->{'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; } - $r->print('</table>'); - } - $r->print('<h4>'.&mt('Evaluation Data').'</h4>'. - '<table cellspacing=2 border=0>'); - foreach ('clear','depth','helpful','correct','technical') { - $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. - '<td bgcolor="#CCCCCC">'. - &prettyprint($_,$dynmeta{$_})."</td></tr>\n"); - } - $r->print('</table>'); - $uri=~/^\/res\/(\w+)\/(\w+)\//; - if ((($ENV{'user.domain'} eq $1) && ($ENV{'user.name'} eq $2)) - || ($ENV{'user.role.ca./'.$1.'/'.$2})) { - $r->print('<h4>'.&mt('Evaluation Comments').' ('. - &mt('visible to author and co-authors only'). - ')</h4>'. - '<blockquote>'.$dynmeta{'comments'}.'</blockquote>'); - $r->print('<a name="bombs" /><h4>'.&mt('Error Messages').' ('. - &mt('visible to author and co-authors only').')'. - '</h4>'. - &Apache::lonmsg::retrieve_author_res_msg($uri)); - } - # All other stuff - $r->print('<h3>'. - &mt('Additional Metadata (non-standard, parameters, exports)'). - '</h3>'); - 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('<b>'.$display.':</b> '.$content{$name}); - if ($otherinfo) { - $r->print(' ('.$otherinfo.')'); + $table .= '<tr>'; + $table .= + '<td><nobr>'.$courseinfo{'description'}.'</nobr></td>'; + $table .= + '<td align="right">'.$data->{'sections'}.'</td>'; + $table .= + '<td align="right">'.$data->{'stdno'}.'</td>'; + foreach ('avetries','difficulty','disc') { + $table .= '<td align="right">'; + if (exists($data->{$_})) { + $table .= sprintf('%.2f',$data->{$_}).' '; + } else { + $table .= ''; } - $r->print("<br />\n"); + $table .= '</td>'; } + $table .= + '<td><nobr>'. + &Apache::lonlocal::locallocaltime($data->{'timestamp'}). + '</nobr></td>'; + $table .= + '</tr>'.$/; } + $table .= '</table>'.$/; + $r->print($table); + } else { + $r->print('No new dynamic data found.'); } - # End Resource Space Call } else { - # Construction Space Call - # Set document type - &Apache::loncommon::content_type($r,'text/html'); - $r->send_http_header; - # - return OK if $r->header_only; - # Header - my $disuri=$uri; - my $fn=&Apache::lonnet::filelocation('',$uri); - $disuri=~s/^\/\~/\/priv\//; - $disuri=~s/\.meta$//; - my $target=$uri; - $target=~s/^\/\~/\/res\/$ENV{'request.role.domain'}\//; - $target=~s/\.meta$//; - my $bombs=&Apache::lonmsg::retrieve_author_res_msg($target); - if ($bombs) { - if ($ENV{'form.delmsg'}) { - if (&Apache::lonmsg::del_url_author_res_msg($target) eq 'ok') { - $bombs=&mt('Messages deleted.'); - } else { - $bombs=&mt('Error deleting messages'); + $r->print('<h4>'. + &mt('No Assessment Statistical Data is available for this resource'). + '</h4>'); + } + + # + # + if (exists($dynmeta{'clear'}) || + exists($dynmeta{'depth'}) || + exists($dynmeta{'helpful'}) || + exists($dynmeta{'correct'}) || + exists($dynmeta{'technical'})){ + $r->print('<h4>'.&mt('Evaluation Data').'</h4>'. + '<table cellspacing="2" border="0">'); + foreach ('clear','depth','helpful','correct','technical') { + $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. + '<td bgcolor="#CCCCCC">'. + &prettyprint($_,$dynmeta{$_})."</td></tr>\n"); + } + $r->print('</table>'); + } else { + $r->print('<h4>'.&mt('No Evaluation Data is available for this resource.').'</h4>'); + } + $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('<h4>'.&mt('Evaluation Comments').' ('. + &mt('visible to author and co-authors only'). + ')</h4>'. + '<blockquote>'.$dynmeta{'comments'}.'</blockquote>'); + } else { + $r->print('<h4>'.&mt('There are no Evaluation Comments on this resource.').'</h4>'); + } + my $bombs = &Apache::lonmsg::retrieve_author_res_msg($uri); + if (defined($bombs) && $bombs ne '') { + $r->print('<a name="bombs" /><h4>'.&mt('Error Messages').' ('. + &mt('visible to author and co-authors only').')'. + '</h4>'.$bombs); + } else { + $r->print('<h4>'.&mt('There are currently no Error Messages for this resource.').'</h4>'); + } + } + # + # All other stuff + $r->print('<h3>'. + &mt('Additional Metadata (non-standard, parameters, exports)'). + '</h3><table border="0" cellspacing="1">'); + 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.'.'.$_).'; '; } } - my $bodytag=&Apache::loncommon::bodytag('Error Messages'); - my $del=&mt('Delete Messages'); - $r->print(<<ENDBOMBS); -<html><head><title>Edit Catalog Information</title></head> -$bodytag + $r->print('<tr><td bgcolor="#bbccbb"><font size="-1" color="#556655">'.$display.'</font></td><td bgcolor="#ccddcc"><font size="-1" color="#556655">'.$content{$name}); + if ($otherinfo) { + $r->print(' ('.$otherinfo.')'); + } + $r->print("</font></td></tr>\n"); + } + } + $r->print("</table>"); + 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(<<ENDBOMBS); <h1>$disuri</h1> -<form method="post" name="defaultmeta"> -<input type="submit" name="delmsg" value="$del" /> -<br />$bombs -</form> -</body> -</html> +<form method="post" action="" name="defaultmeta"> ENDBOMBS + if ($showdel) { + $r->print(<<ENDDEL); +<input type="submit" name="delmsg" value="$del" /> +<input type="submit" name="clearmsg" value="$clear" /> +ENDDEL } else { - my $displayfile='Catalog Information for '.$disuri; - if ($disuri=~/\/default$/) { - my $dir=$disuri; - $dir=~s/default$//; - $displayfile= - &mt('Default Cataloging Information for Directory').' '. - $dir; - } - my $bodytag= - &Apache::loncommon::bodytag('Edit Catalog Information'); - %Apache::lonpublisher::metadatafields=(); - %Apache::lonpublisher::metadatakeys=(); - &Apache::lonpublisher::metaeval(&Apache::lonnet::getfile($fn)); - $r->print(<<ENDEDIT); -<html><head><title>Edit Catalog Information</title></head> -$bodytag + $r->print('<a href="'.$disuri.'" />'.$goback.'</a>'); + } + $r->print('<br />'.$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(<<ENDEDIT); <h1>$displayfile</h1> -<form method="post" name="defaultmeta"> +<form method="post" action="" name="defaultmeta"> ENDEDIT - $r->print('<script language="JavaScript">'. - &Apache::loncommon::browser_and_searcher_javascript. - '</script>'); - my %lt=&fieldnames(); - foreach ('author','title','subject','keywords','abstract','notes', - 'copyright','customdistributionfile','language', - 'standards', - 'lowestgradelevel','highestgradelevel', - 'obsolete','obsoletereplacement') { - if (defined($ENV{'form.new_'.$_})) { - $Apache::lonpublisher::metadatafields{$_}= - $ENV{'form.new_'.$_}; - } - if (! $Apache::lonpublisher::metadatafields{'copyright'}) { - $Apache::lonpublisher::metadatafields{'copyright'}= - 'default'; - } - $r->print('<p>'.$lt{$_}.': '. - &prettyinput - ($_,$Apache::lonpublisher::metadatafields{$_}, - 'new_'.$_,'defaultmeta').'</p>'); - } - if ($ENV{'form.store'}) { - my $mfh; - if (! ($mfh=Apache::File->new('>'.$fn))) { - $r->print('<p><font color=red>'. - &mt('Could not write metadata').', '. - &mt('FAIL').'</font>'); - } else { - foreach (sort keys %Apache::lonpublisher::metadatafields) { - if ($_!~/\./) { - my $unikey=$_; - $unikey=~/^([A-Za-z]+)/; - my $tag=$1; - $tag=~tr/A-Z/a-z/; - print $mfh "\n\<$tag"; - foreach (split(/\,/, - $Apache::lonpublisher::metadatakeys{$unikey}) - ) { - my $value= - $Apache::lonpublisher::metadatafields{$unikey.'.'.$_}; - $value=~s/\"/\'\'/g; - print $mfh ' '.$_.'="'.$value.'"'; - } - print $mfh '>'. - &HTML::Entities::encode($Apache::lonpublisher::metadatafields{$unikey},'<>&"'). - '</'.$tag.'>'; - } - } - $r->print('<p>'.&mt('Wrote Metadata')); - } + $r->print('<script type="JavaScript">'. + &Apache::loncommon::browser_and_searcher_javascript(). + '</script>'); + my %lt=&fieldnames($file_type); + my $output; + my @fields; + my $added_metadata_fields; + my @added_order; + 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'); + $added_metadata_fields = &Apache::lonparmset::get_added_meta_fieldnames(); + if ($env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'}) { + @added_order = split /,/,$env{'course.'.$env{'request.course.id'}.'.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'); + } + 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 (! $Apache::lonpublisher::metadatafields{'copyright'}) { + $Apache::lonpublisher::metadatafields{'copyright'}= + 'default'; + } + 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{'courserestricted'} ne 'none') { + $r->print(&mt('Associated with course [_1]','<strong>'.$env{$Apache::lonpublisher::metadatafields{'courserestricted'}.".description"}. + '</strong>').'<br />'); + } else { + $r->print("This resource is not associated with a course.<br />"); + } + } + 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}; } - $r->print('<br /><input type="submit" name="store" value="'. - &mt('Store Catalog Information').'"></form>'. - '</body></html>'); } + 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' + && 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.=("\n".'<p>'.$lt{$field_name}.': '. + &prettyinput($field_name, + $Apache::lonpublisher::metadatafields{$field_name}, + 'new_'.$field_name,'defaultmeta', + undef,undef,undef,undef, + $Apache::lonpublisher::metadatafields{'courserestricted'}).'</p>'."\n"); + } + } else { + + $output.=('<p>'.$lt{$field_name}.': '. + &prettyinput($field_name, + $Apache::lonpublisher::metadatafields{$field_name}, + 'new_'.$field_name,'defaultmeta').'</p>'); + + } + } + 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}, + '<>&"'). + '</'.$tag.'>'; + } + if ($fn =~ m|^$Apache::lonnet::perlvar{'lonDocRoot'}/userfiles|) { + my ($path, $new_fn); + if ($fn =~ m|\w+/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)); + } else { + if (! ($mfh=Apache::File->new('>'.$fn))) { + $r->print('<p><font color="red">'. + &mt('Could not write metadata').', '. + &mt('FAIL').'</font></p>'); + } else { + print $mfh $file_content; + $r->print('<p><font color="blue">'.&mt('Wrote Metadata'). + ' '.&Apache::lonlocal::locallocaltime(time). + '</font></p>'); + } + } + } + $r->print($output.'<br /><input type="submit" name="store" value="'. + &mt('Store Catalog Information').'" />'); + + if ($file_type eq 'portfolio') { + my ($port_path,$group) = &get_port_path_and_group($uri); + if ($group) { + $r->print('<input type="hidden" name="group" value="'.$group.'" />'); + } + $r->print('<input type="hidden" name="currentpath" value="'.$env{'form.currentpath'}.'" />'); + $r->print('</form><br /><br /><form method="post" action="'.$port_path.'">'); + if ($group) { + $r->print('<input type="hidden" name="group" value="'.$group.'" />'); + } + $r->print('<input type="hidden" name="currentpath" value="'.$path.'" />'. + '<input type="submit" name="cancel" value="'.&mt('Discard Edits and Return to Portfolio').'" />'); + } } - return OK; + + $r->print('</form>'); + + return; } -# BEGIN Block -BEGIN { - # Get columns of MySQL metadata table - @columns=&Apache::lonmysql::col_order('metadata'); +sub store_portfolio_metadata { + my ($formname,$content,$path,$new_fn) = @_; + $env{'form.'.$formname}=$content."\n"; + $env{'form.'.$formname.'.filename'}=$new_fn; + my $result =&Apache::lonnet::userfileupload($formname,'',$path); + if ($result =~ /(error|notfound)/) { + return '<p><font color="red">'. + &mt('Could not write metadata').', '. + &mt('FAIL').'</font></p>'; + } else { + return '<p><font color="blue">'.&mt('Wrote Metadata'). + ' '.&Apache::lonlocal::locallocaltime(time).'</font></p>'; + } } 1; __END__ +