![]() ![]() | ![]() |
Allow changing metadata course association.
1: # The LearningOnline Network with CAPA 2: # Metadata display handler 3: # 4: # $Id: lonmeta.pm,v 1.188 2006/11/20 19:39:22 banghart Exp $ 5: # 6: # Copyright Michigan State University Board of Trustees 7: # 8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA). 9: # 10: # LON-CAPA is free software; you can redistribute it and/or modify 11: # it under the terms of the GNU General Public License as published by 12: # the Free Software Foundation; either version 2 of the License, or 13: # (at your option) any later version. 14: # 15: # LON-CAPA is distributed in the hope that it will be useful, 16: # but WITHOUT ANY WARRANTY; without even the implied warranty of 17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18: # GNU General Public License for more details. 19: # 20: # You should have received a copy of the GNU General Public License 21: # along with LON-CAPA; if not, write to the Free Software 22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23: # 24: # /home/httpd/html/adm/gpl.txt 25: # 26: # http://www.lon-capa.org/ 27: 28: 29: package Apache::lonmeta; 30: 31: use strict; 32: use LONCAPA::lonmetadata(); 33: use Apache::Constants qw(:common); 34: use Apache::lonnet; 35: use Apache::loncommon(); 36: use Apache::lonhtmlcommon(); 37: use Apache::lonmsg; 38: use Apache::lonpublisher; 39: use Apache::lonlocal; 40: use Apache::lonmysql; 41: use Apache::lonmsg; 42: use lib '/home/httpd/lib/perl/'; 43: use LONCAPA; 44: 45: 46: ############################################################ 47: ############################################################ 48: ## 49: ## &get_dynamic_metadata_from_sql($url) 50: ## 51: ## Queries sql database for dynamic metdata 52: ## Returns a hash of hashes, with keys of urls which match $url 53: ## Returned fields are given below. 54: ## 55: ## Examples: 56: ## 57: ## %DynamicMetadata = &Apache::lonmeta::get_dynmaic_metadata_from_sql 58: ## ('/res/msu/korte/'); 59: ## 60: ## $DynamicMetadata{'/res/msu/korte/example.problem'}->{$field} 61: ## 62: ############################################################ 63: ############################################################ 64: sub get_dynamic_metadata_from_sql { 65: my ($url) = shift(); 66: my ($authordom,$author)=($url=~m:^/res/(\w+)/(\w+)/:); 67: if (! defined($authordom)) { 68: $authordom = shift(); 69: } 70: if (! defined($author)) { 71: $author = shift(); 72: } 73: if (! defined($authordom) || ! defined($author)) { 74: return (); 75: } 76: my $query = 'SELECT * FROM metadata WHERE url LIKE "'.$url.'%"'; 77: my $server = &Apache::lonnet::homeserver($author,$authordom); 78: my $reply = &Apache::lonnet::metadata_query($query,undef,undef, 79: ,[$server]); 80: return () if (! defined($reply) || ref($reply) ne 'HASH'); 81: my $filename = $reply->{$server}; 82: if (! defined($filename) || $filename =~ /^error/) { 83: return (); 84: } 85: my $max_time = time + 10; # wait 10 seconds for results at most 86: my %ReturnHash; 87: # 88: # Look for results 89: my $finished = 0; 90: while (! $finished && time < $max_time) { 91: my $datafile=$Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/'.$filename; 92: if (! -e "$datafile.end") { next; } 93: my $fh; 94: if (!($fh=Apache::File->new($datafile))) { next; } 95: while (my $result = <$fh>) { 96: chomp($result); 97: next if (! $result); 98: my %hash=&LONCAPA::lonmetadata::metadata_col_to_hash('metadata', 99: map { &unescape($_) } split(/\,/,$result)); 100: foreach my $key (keys(%hash)) { 101: $ReturnHash{$hash{'url'}}->{$key}=$hash{$key}; 102: } 103: } 104: $finished = 1; 105: } 106: # 107: return %ReturnHash; 108: } 109: 110: 111: # Fetch and evaluate dynamic metadata 112: sub dynamicmeta { 113: my $url=&Apache::lonnet::declutter(shift); 114: $url=~s/\.meta$//; 115: my ($adomain,$aauthor)=($url=~/^(\w+)\/(\w+)\//); 116: my $regexp=$url; 117: $regexp=~s/(\W)/\\$1/g; 118: $regexp='___'.$regexp.'___'; 119: my %evaldata=&Apache::lonnet::dump('nohist_resevaldata',$adomain, 120: $aauthor,$regexp); 121: my %DynamicData = &LONCAPA::lonmetadata::process_reseval_data(\%evaldata); 122: my %Data = &LONCAPA::lonmetadata::process_dynamic_metadata($url, 123: \%DynamicData); 124: # 125: # Deal with 'count' separately 126: $Data{'count'} = &access_count($url,$aauthor,$adomain); 127: # 128: # Debugging code I will probably need later 129: if (0) { 130: &Apache::lonnet::logthis('Dynamic Metadata'); 131: while(my($k,$v)=each(%Data)){ 132: &Apache::lonnet::logthis(' "'.$k.'"=>"'.$v.'"'); 133: } 134: &Apache::lonnet::logthis('-------------------'); 135: } 136: return %Data; 137: } 138: 139: sub access_count { 140: my ($src,$author,$adomain) = @_; 141: my %countdata=&Apache::lonnet::dump('nohist_accesscount',$adomain, 142: $author,$src); 143: if (! exists($countdata{$src})) { 144: return &mt('Not Available'); 145: } else { 146: return $countdata{$src}; 147: } 148: } 149: 150: # Try to make an alt tag if there is none 151: sub alttag { 152: my ($base,$src)=@_; 153: my $fullpath=&Apache::lonnet::hreflocation($base,$src); 154: my $alttag=&Apache::lonnet::metadata($fullpath,'title').' '. 155: &Apache::lonnet::metadata($fullpath,'subject').' '. 156: &Apache::lonnet::metadata($fullpath,'abstract'); 157: $alttag=~s/\s+/ /gs; 158: $alttag=~s/\"//gs; 159: $alttag=~s/\'//gs; 160: $alttag=~s/\s+$//gs; 161: $alttag=~s/^\s+//gs; 162: if ($alttag) { 163: return $alttag; 164: } else { 165: return &mt('No information available'); 166: } 167: } 168: 169: # Author display 170: sub authordisplay { 171: my ($aname,$adom)=@_; 172: return &Apache::loncommon::aboutmewrapper 173: (&Apache::loncommon::plainname($aname,$adom), 174: $aname,$adom,'preview').' <tt>['.$aname.':'.$adom.']</tt>'; 175: } 176: 177: # Pretty display 178: sub evalgraph { 179: my $value=shift; 180: if (! $value) { 181: return ''; 182: } 183: my $val=int($value*10.+0.5)-10; 184: my $output='<table border="0" cellpadding="0" cellspacing="0"><tr>'; 185: if ($val>=20) { 186: $output.='<td width="20" bgcolor="#555555">  </td>'; 187: } else { 188: $output.='<td width="'.($val).'" bgcolor="#555555"> </td>'. 189: '<td width="'.(20-$val).'" bgcolor="#FF3333"> </td>'; 190: } 191: $output.='<td bgcolor="#FFFF33"> </td>'; 192: if ($val>20) { 193: $output.='<td width="'.($val-20).'" bgcolor="#33FF33"> </td>'. 194: '<td width="'.(40-$val).'" bgcolor="#555555"> </td>'; 195: } else { 196: $output.='<td width="20" bgcolor="#555555">  </td>'; 197: } 198: $output.='<td> ('.sprintf("%5.2f",$value).') </td></tr></table>'; 199: return $output; 200: } 201: 202: sub diffgraph { 203: my $value=shift; 204: if (! $value) { 205: return ''; 206: } 207: my $val=int(40.0*$value+0.5); 208: my @colors=('#FF9933','#EEAA33','#DDBB33','#CCCC33', 209: '#BBDD33','#CCCC33','#DDBB33','#EEAA33'); 210: my $output='<table border="0" cellpadding="0" cellspacing="0"><tr>'; 211: for (my $i=0;$i<8;$i++) { 212: if ($val>$i*5) { 213: $output.='<td width="5" bgcolor="'.$colors[$i].'"> </td>'; 214: } else { 215: $output.='<td width="5" bgcolor="#555555"> </td>'; 216: } 217: } 218: $output.='<td> ('.sprintf("%3.2f",$value).') </td></tr></table>'; 219: return $output; 220: } 221: 222: 223: # The field names 224: sub fieldnames { 225: my $file_type=shift; 226: my %fields = 227: ('title' => 'Title', 228: 'author' =>'Author(s)', 229: 'authorspace' => 'Author Space', 230: 'modifyinguser' => 'Last Modifying User', 231: 'subject' => 'Subject', 232: 'standards' => 'Standards', 233: 'keywords' => 'Keyword(s)', 234: 'notes' => 'Notes', 235: 'abstract' => 'Abstract', 236: 'lowestgradelevel' => 'Lowest Grade Level', 237: 'highestgradelevel' => 'Highest Grade Level'); 238: 239: if (! defined($file_type) || $file_type ne 'portfolio') { 240: %fields = 241: (%fields, 242: 'domain' => 'Domain', 243: 'mime' => 'MIME Type', 244: 'language' => 'Language', 245: 'creationdate' => 'Creation Date', 246: 'lastrevisiondate' => 'Last Revision Date', 247: 'owner' => 'Publisher/Owner', 248: 'copyright' => 'Copyright/Distribution', 249: 'customdistributionfile' => 'Custom Distribution File', 250: 'sourceavail' => 'Source Available', 251: 'sourcerights' => 'Source Custom Distribution File', 252: 'obsolete' => 'Obsolete', 253: 'obsoletereplacement' => 'Suggested Replacement for Obsolete File', 254: 'count' => 'Network-wide number of accesses (hits)', 255: 'course' => 'Network-wide number of courses using resource', 256: 'course_list' => 'Network-wide courses using resource', 257: 'sequsage' => 'Number of resources using or importing resource', 258: 'sequsage_list' => 'Resources using or importing resource', 259: 'goto' => 'Number of resources that follow this resource in maps', 260: 'goto_list' => 'Resources that follow this resource in maps', 261: 'comefrom' => 'Number of resources that lead up to this resource in maps', 262: 'comefrom_list' => 'Resources that lead up to this resource in maps', 263: 'clear' => 'Material presented in clear way', 264: 'depth' => 'Material covered with sufficient depth', 265: 'helpful' => 'Material is helpful', 266: 'correct' => 'Material appears to be correct', 267: 'technical' => 'Resource is technically correct', 268: 'avetries' => 'Average number of tries till solved', 269: 'stdno' => 'Total number of students who have worked on this problem', 270: 'difficulty' => 'Degree of difficulty', 271: 'disc' => 'Degree of discrimination', 272: 'dependencies' => 'Resources used by this resource', 273: ); 274: } 275: return &Apache::lonlocal::texthash(%fields); 276: } 277: 278: sub portfolio_linked_path { 279: my ($path,$group,$port_path) = @_; 280: 281: my $start = 'portfolio'; 282: if ($group) { 283: $start = "groups/$group/".$start; 284: } 285: my %anchor_fields = ( 286: 'selectfile' => $start, 287: 'currentpath' => '/' 288: ); 289: my $result = &Apache::portfolio::make_anchor($port_path,\%anchor_fields,$start); 290: my $fullpath = '/'; 291: my (undef,@tree) = split('/',$path); 292: my $filename = pop(@tree); 293: foreach my $dir (@tree) { 294: $fullpath .= $dir.'/'; 295: $result .= '/'; 296: my %anchor_fields = ( 297: 'selectfile' => $dir, 298: 'currentpath' => $fullpath 299: ); 300: $result .= &Apache::portfolio::make_anchor($port_path,\%anchor_fields,$dir); 301: } 302: $result .= "/$filename"; 303: return $result; 304: } 305: 306: sub get_port_path_and_group { 307: my ($uri)=@_; 308: 309: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; 310: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; 311: 312: my ($port_path,$group); 313: if ($uri =~ m{^/editupload/\Q$cdom\E/\Q$cnum\E/groups/}) { 314: $group = (split('/',$uri))[5]; 315: $port_path = '/adm/coursegrp_portfolio'; 316: } else { 317: $port_path = '/adm/portfolio'; 318: } 319: if ($env{'form.group'} ne $group) { 320: $env{'form.group'} = $group; 321: } 322: return ($port_path,$group); 323: } 324: 325: sub portfolio_display_uri { 326: my ($uri,$as_links)=@_; 327: 328: my ($port_path,$group) = &get_port_path_and_group($uri); 329: 330: $uri =~ s|.*/(portfolio/.*)$|$1|; 331: my ($res_uri,$meta_uri) = ($uri,$uri); 332: if ($uri =~ /\.meta$/) { 333: $res_uri =~ s/\.meta//; 334: } else { 335: $meta_uri .= '.meta'; 336: } 337: 338: my ($path) = ($res_uri =~ m|^portfolio(.*/)[^/]*$|); 339: if ($as_links) { 340: $res_uri = &portfolio_linked_path($res_uri,$group,$port_path); 341: $meta_uri = &portfolio_linked_path($meta_uri,$group,$port_path); 342: } 343: return ($res_uri,$meta_uri,$path); 344: } 345: 346: sub pre_select_course { 347: my ($r,$uri) = @_; 348: my $output; 349: my $fn=&Apache::lonnet::filelocation('',$uri); 350: my ($res_uri,$meta_uri,$path) = &portfolio_display_uri($uri); 351: %Apache::lonpublisher::metadatafields=(); 352: %Apache::lonpublisher::metadatakeys=(); 353: my $result=&Apache::lonnet::getfile($fn); 354: if ($result == -1){ 355: $r->print(&mt('Creating new file [_1]'),$meta_uri); 356: } else { 357: &Apache::lonpublisher::metaeval($result); 358: } 359: $r->print('<hr /><form method="post" action="" >'); 360: $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>'); 361: $output = &select_course(); 362: $r->print($output.'<br /><input type="submit" name="store" value="'. 363: &mt('Associate Resource With Selected Course').'" />'); 364: $r->print('<input type="hidden" name="currentpath" value="'.$env{'form.currentpath'}.'" />'); 365: $r->print('<input type="hidden" name="associate" value="true" />'); 366: $r->print('</form>'); 367: 368: my ($port_path,$group) = &get_port_path_and_group($uri); 369: my $group_input; 370: if ($group) { 371: $group_input = '<input type="hidden" name="group" value="'.$group.'" />'; 372: } 373: $r->print('<br /><br /><form method="post" action="'.$port_path.'">'. 374: '<input type="hidden" name="currentpath" value="'.$path.'" />'. 375: $group_input. 376: '<input type="submit" name="cancel" value="'.&mt('Cancel').'" />'. 377: '</form>'); 378: 379: return; 380: } 381: sub select_course { 382: my $output=$/; 383: my $current_restriction= 384: $Apache::lonpublisher::metadatafields{'courserestricted'}; 385: my $selected = ($current_restriction eq 'none' ? 'selected="selected"' 386: : ''); 387: 388: $output .= '<select name="new_courserestricted" >'; 389: $output .= '<option value="none" '.$selected.'>'. 390: &mt('None').'</option>'.$/; 391: my %courses; 392: foreach my $key (keys(%env)) { 393: if ($key !~ m/^course\.(.+)\.description$/) { next; } 394: my $cid = $1; 395: if ($env{$key} !~ /\S/) { next; } 396: $courses{$key} = $cid; 397: } 398: foreach my $key (sort { lc($env{$a}) cmp lc($env{$b}) } (keys(%courses))) { 399: my $cid = 'course.'.$courses{$key}; 400: my $selected = ($current_restriction eq $cid ? 'selected="selected"' 401: : ''); 402: if ($env{$key} !~ /\S/) { next; } 403: $output .= '<option value="'.$cid.'" '.$selected.'>'; 404: $output .= $env{$key}; 405: $output .= '</option>'.$/; 406: $selected = ''; 407: } 408: $output .= '</select><br />'; 409: return ($output); 410: } 411: # Pretty printing of metadata field 412: 413: sub prettyprint { 414: my ($type,$value,$target,$prefix,$form,$noformat)=@_; 415: # $target,$prefix,$form are optional and for filecrumbs only 416: if (! defined($value)) { 417: return ' '; 418: } 419: # Title 420: if ($type eq 'title') { 421: return '<font size="+1" face="arial">'.$value.'</font>'; 422: } 423: # Dates 424: if (($type eq 'creationdate') || 425: ($type eq 'lastrevisiondate')) { 426: return ($value?&Apache::lonlocal::locallocaltime( 427: &Apache::lonmysql::unsqltime($value)): 428: &mt('not available')); 429: } 430: # Language 431: if ($type eq 'language') { 432: return &Apache::loncommon::languagedescription($value); 433: } 434: # Copyright 435: if ($type eq 'copyright') { 436: return &Apache::loncommon::copyrightdescription($value); 437: } 438: # Copyright 439: if ($type eq 'sourceavail') { 440: return &Apache::loncommon::source_copyrightdescription($value); 441: } 442: # MIME 443: if ($type eq 'mime') { 444: return '<img src="'.&Apache::loncommon::icon($value).'" /> '. 445: &Apache::loncommon::filedescription($value); 446: } 447: # Person 448: if (($type eq 'author') || 449: ($type eq 'owner') || 450: ($type eq 'modifyinguser') || 451: ($type eq 'authorspace')) { 452: $value=~s/(\w+)(\:|\@)(\w+)/&authordisplay($1,$3)/gse; 453: return $value; 454: } 455: # Gradelevel 456: if (($type eq 'lowestgradelevel') || 457: ($type eq 'highestgradelevel')) { 458: return &Apache::loncommon::gradeleveldescription($value); 459: } 460: # Only for advance users below 461: if (! $env{'user.adv'}) { 462: return '<i>- '.&mt('not displayed').' -</i>'; 463: } 464: # File 465: if (($type eq 'customdistributionfile') || 466: ($type eq 'obsoletereplacement') || 467: ($type eq 'goto_list') || 468: ($type eq 'comefrom_list') || 469: ($type eq 'sequsage_list') || 470: ($type eq 'dependencies')) { 471: return '<font size="-1"><ul>'.join("\n",map { 472: my $url = &Apache::lonnet::clutter_with_no_wrapper($_); 473: my $title = &Apache::lonnet::gettitle($url); 474: if ($title eq '') { 475: $title = 'Untitled'; 476: if ($url =~ /\.sequence$/) { 477: $title .= ' Sequence'; 478: } elsif ($url =~ /\.page$/) { 479: $title .= ' Page'; 480: } elsif ($url =~ /\.problem$/) { 481: $title .= ' Problem'; 482: } elsif ($url =~ /\.html$/) { 483: $title .= ' HTML document'; 484: } elsif ($url =~ m:/syllabus$:) { 485: $title .= ' Syllabus'; 486: } 487: } 488: $_ = '<li>'.$title.' '. 489: &Apache::lonhtmlcommon::crumbs($url,$target,$prefix,$form,'-1',$noformat). 490: '</li>' 491: } split(/\s*\,\s*/,$value)).'</ul></font>'; 492: } 493: # Evaluations 494: if (($type eq 'clear') || 495: ($type eq 'depth') || 496: ($type eq 'helpful') || 497: ($type eq 'correct') || 498: ($type eq 'technical')) { 499: return &evalgraph($value); 500: } 501: # Difficulty 502: if ($type eq 'difficulty' || $type eq 'disc') { 503: return &diffgraph($value); 504: } 505: # List of courses 506: if ($type=~/\_list/) { 507: my @Courses = split(/\s*\,\s*/,$value); 508: my $Str='<font size="-1"><ul>'; 509: my %descriptions; 510: foreach my $course (@Courses) { 511: my %courseinfo = 512: &Apache::lonnet::coursedescription($course, 513: {'one_time' => 1}); 514: if (! exists($courseinfo{'num'}) || $courseinfo{'num'} eq '') { 515: next; 516: } 517: $descriptions{join('\0',@courseinfo{'domain','description'})} .= 518: '<li><a href="/public/'.$courseinfo{'domain'}.'/'. 519: $courseinfo{'num'}.'/syllabus" target="preview">'. 520: $courseinfo{'description'}.' ('.$courseinfo{'domain'}. 521: ')</a></li>'; 522: } 523: foreach my $course (sort {lc($a) cmp lc($b)} (keys(%descriptions))) { 524: $Str .= $descriptions{$course}; 525: } 526: 527: return $Str.'</ul></font>'; 528: } 529: # No pretty print found 530: return $value; 531: } 532: 533: # Pretty input of metadata field 534: sub direct { 535: return shift; 536: } 537: 538: sub selectbox { 539: my ($name,$value,$functionref,@idlist)=@_; 540: if (! defined($functionref)) { 541: $functionref=\&direct; 542: } 543: my $selout='<select name="'.$name.'">'; 544: foreach (@idlist) { 545: $selout.='<option value=\''.$_.'\''; 546: if ($_ eq $value) { 547: $selout.=' selected>'.&{$functionref}($_).'</option>'; 548: } 549: else {$selout.='>'.&{$functionref}($_).'</option>';} 550: } 551: return $selout.'</select>'; 552: } 553: 554: sub relatedfield { 555: my ($show,$relatedsearchflag,$relatedsep,$fieldname,$relatedvalue)=@_; 556: if (! $relatedsearchflag) { 557: return ''; 558: } 559: if (! defined($relatedsep)) { 560: $relatedsep=' '; 561: } 562: if (! $show) { 563: return $relatedsep.' '; 564: } 565: return $relatedsep.'<input type="checkbox" name="'.$fieldname.'_related"'. 566: ($relatedvalue?' checked="1"':'').' />'; 567: } 568: 569: sub prettyinput { 570: my ($type,$value,$fieldname,$formname, 571: $relatedsearchflag,$relatedsep,$relatedvalue,$size,$course_key)=@_; 572: if (! defined($size)) { 573: $size = 80; 574: } 575: my $output; 576: if (defined($course_key) 577: && exists($env{$course_key.'.metadata.'.$type.'.options'})) { 578: my $stu_add; 579: my $only_one; 580: my %meta_options; 581: my @cur_values_inst; 582: my $cur_values_stu; 583: my $values = $env{$course_key.'.metadata.'.$type.'.values'}; 584: if ($env{$course_key.'.metadata.'.$type.'.options'} =~ m/stuadd/) { 585: $stu_add = 'true'; 586: } 587: if ($env{$course_key.'.metadata.'.$type.'.options'} =~ m/onlyone/) { 588: $only_one = 'true'; 589: } 590: # need to take instructor values out of list where instructor and student 591: # values may be mixed. 592: if ($values) { 593: foreach my $item (split(/,/,$values)) { 594: $item =~ s/^\s+//; 595: $meta_options{$item} = $item; 596: } 597: foreach my $item (split(/,/,$value)) { 598: $item =~ s/^\s+//; 599: if ($meta_options{$item}) { 600: push(@cur_values_inst,$item); 601: } else { 602: $cur_values_stu .= $item.','; 603: } 604: } 605: } else { 606: $cur_values_stu = $value; 607: } 608: if ($type eq 'courserestricted') { 609: return (&select_course()); 610: # return ('<input type="hidden" name="new_courserestricted" value="'.$course_key.'" />'); 611: } 612: my $course = $env{'request.course.id'}; 613: if (($type eq 'keywords') || ($type eq 'subject') 614: || ($type eq 'author')||($type eq 'notes') 615: || ($type eq 'abstract')|| ($type eq 'title')|| ($type eq 'standards') 616: || (exists($env{'course.'.$env{'request.course.id'}.'.metadata.'.$type.'.added'}))) { 617: if ($values) { 618: if ($only_one) { 619: $output .= (&Apache::loncommon::select_form($cur_values_inst[0],'new_'.$type,%meta_options)); 620: } else { 621: $output .= (&Apache::loncommon::multiple_select_form('new_'.$type,\@cur_values_inst,undef,\%meta_options)); 622: } 623: } 624: if ($stu_add) { 625: $output .= '<input type="text" name="'.$fieldname.'" size="'.$size.'" '. 626: 'value="'.$cur_values_stu.'" />'. 627: &relatedfield(1,$relatedsearchflag,$relatedsep,$fieldname, 628: $relatedvalue); 629: } 630: return ($output); 631: } 632: if (($type eq 'lowestgradelevel') || 633: ($type eq 'highestgradelevel')) { 634: return &Apache::loncommon::select_level_form($value,$fieldname). 635: &relatedfield(0,$relatedsearchflag,$relatedsep); 636: } 637: return(); 638: } 639: # Language 640: if ($type eq 'language') { 641: return &selectbox($fieldname, 642: $value, 643: \&Apache::loncommon::languagedescription, 644: (&Apache::loncommon::languageids)). 645: &relatedfield(0,$relatedsearchflag,$relatedsep); 646: } 647: # Copyright 648: if ($type eq 'copyright') { 649: return &selectbox($fieldname, 650: $value, 651: \&Apache::loncommon::copyrightdescription, 652: (&Apache::loncommon::copyrightids)). 653: &relatedfield(0,$relatedsearchflag,$relatedsep); 654: } 655: # Source Copyright 656: if ($type eq 'sourceavail') { 657: return &selectbox($fieldname, 658: $value, 659: \&Apache::loncommon::source_copyrightdescription, 660: (&Apache::loncommon::source_copyrightids)). 661: &relatedfield(0,$relatedsearchflag,$relatedsep); 662: } 663: # Gradelevels 664: if (($type eq 'lowestgradelevel') || 665: ($type eq 'highestgradelevel')) { 666: return &Apache::loncommon::select_level_form($value,$fieldname). 667: &relatedfield(0,$relatedsearchflag,$relatedsep); 668: } 669: # Obsolete 670: if ($type eq 'obsolete') { 671: return '<input type="checkbox" name="'.$fieldname.'"'. 672: ($value?' checked="1"':'').' />'. 673: &relatedfield(0,$relatedsearchflag,$relatedsep); 674: } 675: # Obsolete replacement file 676: if ($type eq 'obsoletereplacement') { 677: return '<input type="text" name="'.$fieldname. 678: '" size="60" value="'.$value.'" /><a href="javascript:openbrowser'. 679: "('".$formname."','".$fieldname."'". 680: ",'')\">".&mt('Select').'</a>'. 681: &relatedfield(0,$relatedsearchflag,$relatedsep); 682: } 683: # Customdistribution file 684: if ($type eq 'customdistributionfile') { 685: return '<input type="text" name="'.$fieldname. 686: '" size="60" value="'.$value.'" /><a href="javascript:openbrowser'. 687: "('".$formname."','".$fieldname."'". 688: ",'rights')\">".&mt('Select').'</a>'. 689: &relatedfield(0,$relatedsearchflag,$relatedsep); 690: } 691: # Source Customdistribution file 692: if ($type eq 'sourcerights') { 693: return '<input type="text" name="'.$fieldname. 694: '" size="60" value="'.$value.'" /><a href="javascript:openbrowser'. 695: "('".$formname."','".$fieldname."'". 696: ",'rights')\">".&mt('Select').'</a>'. 697: &relatedfield(0,$relatedsearchflag,$relatedsep); 698: } 699: if ($type eq 'courserestricted') { 700: return (&select_course()); 701: #return ('<input type="hidden" name="new_courserestricted" value="'.$course_key.'" />'); 702: } 703: 704: # Dates 705: if (($type eq 'creationdate') || 706: ($type eq 'lastrevisiondate')) { 707: return 708: &Apache::lonhtmlcommon::date_setter($formname,$fieldname,$value). 709: &relatedfield(0,$relatedsearchflag,$relatedsep); 710: } 711: # No pretty input found 712: $value=~s/^\s+//gs; 713: $value=~s/\s+$//gs; 714: $value=~s/\s+/ /gs; 715: $value=~s/\"/\"\;/gs; 716: return 717: '<input type="text" name="'.$fieldname.'" size="'.$size.'" '. 718: 'value="'.$value.'" />'. 719: &relatedfield(1,$relatedsearchflag,$relatedsep,$fieldname, 720: $relatedvalue); 721: } 722: 723: # Main Handler 724: sub handler { 725: my $r=shift; 726: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, 727: ['currentpath','changecourse']); 728: my $uri=$r->uri; 729: # 730: # Set document type 731: &Apache::loncommon::content_type($r,'text/html'); 732: $r->send_http_header; 733: return OK if $r->header_only; 734: my ($resdomain,$resuser)= 735: (&Apache::lonnet::declutter($uri)=~/^(\w+)\/(\w+)\//); 736: if ($uri=~m:/adm/bombs/(.*)$:) { 737: $r->print(&Apache::loncommon::start_page('Error Messages')); 738: # Looking for all bombs? 739: &report_bombs($r,$uri); 740: } elsif ($uri=~m|^/editupload/[^/]+/[^/]+/portfolio/|) { 741: ($resdomain,$resuser)= 742: (&Apache::lonnet::declutter($uri)=~m|^(\w+)/(\w+)/portfolio|); 743: $r->print(&Apache::loncommon::start_page('Edit Portfolio File Catalog Information', 744: undef, 745: {'domain' => $resdomain,})); 746: if ($env{'form.store'}) { 747: &present_editable_metadata($r,$uri,'portfolio'); 748: } else { 749: my $fn=&Apache::lonnet::filelocation('',$uri); 750: %Apache::lonpublisher::metadatafields=(); 751: %Apache::lonpublisher::metadatakeys=(); 752: my $result=&Apache::lonnet::getfile($fn); 753: &Apache::lonpublisher::metaeval($result); 754: &Apache::lonnet::logthis("restricted is: ".$Apache::lonpublisher::metadatafields{'courserestricted'}); 755: if ((!$Apache::lonpublisher::metadatafields{'courserestricted'}) || 756: ($env{'form.changecourse'} eq 'true')) { 757: &pre_select_course($r,$uri); 758: } else { 759: &present_editable_metadata($r,$uri,'portfolio'); 760: } 761: } 762: } elsif ($uri=~m|^/editupload/[^/]+/[^/]+/groups/|) { 763: $r->print(&Apache::loncommon::start_page('Edit Group Portfolio File Catalog Information', 764: undef, 765: {'domain' => $resdomain,})); 766: &present_editable_metadata($r,$uri,'groups'); 767: } elsif ($uri=~m|^/~|) { 768: # Construction space 769: $r->print(&Apache::loncommon::start_page('Edit Catalog nformation', 770: undef, 771: {'domain' => $resdomain,})); 772: &present_editable_metadata($r,$uri); 773: } else { 774: $r->print(&Apache::loncommon::start_page('Catalog Information', 775: undef, 776: {'domain' => $resdomain,})); 777: &present_uneditable_metadata($r,$uri); 778: } 779: $r->print(&Apache::loncommon::end_page()); 780: return OK; 781: } 782: 783: ##################################################### 784: ##################################################### 785: ### ### 786: ### Report Bombs ### 787: ### ### 788: ##################################################### 789: ##################################################### 790: sub report_bombs { 791: my ($r,$uri) = @_; 792: # Set document type 793: $uri =~ s:/adm/bombs/::; 794: $uri = &Apache::lonnet::declutter($uri); 795: $r->print('<h1>'.&Apache::lonnet::clutter($uri).'</h1>'); 796: my ($domain,$author)=($uri=~/^(\w+)\/(\w+)\//); 797: if (&Apache::loncacc::constructaccess('/~'.$author.'/',$domain)) { 798: if ($env{'form.clearbombs'}) { 799: &Apache::lonmsg::clear_author_res_msg($uri); 800: } 801: my $clear=&mt('Clear all Messages in Subdirectory'); 802: $r->print(<<ENDCLEAR); 803: <form method="post"> 804: <input type="submit" name="clearbombs" value="$clear" /> 805: </form> 806: ENDCLEAR 807: my %brokenurls = 808: &Apache::lonmsg::all_url_author_res_msg($author,$domain); 809: foreach (sort(keys(%brokenurls))) { 810: if ($_=~/^\Q$uri\E/) { 811: $r->print 812: ('<a href="'.&Apache::lonnet::clutter($_).'">'.$_.'</a>'. 813: &Apache::lonmsg::retrieve_author_res_msg($_). 814: '<hr />'); 815: } 816: } 817: } else { 818: $r->print(&mt('Not authorized')); 819: } 820: return; 821: } 822: 823: ##################################################### 824: ##################################################### 825: ### ### 826: ### Uneditable Metadata Display ### 827: ### ### 828: ##################################################### 829: ##################################################### 830: sub present_uneditable_metadata { 831: my ($r,$uri) = @_; 832: # 833: my $uploaded = ($uri =~ m|/uploaded/|); 834: my %content=(); 835: # Read file 836: foreach (split(/\,/,&Apache::lonnet::metadata($uri,'keys'))) { 837: $content{$_}=&Apache::lonnet::metadata($uri,$_); 838: } 839: # Render Output 840: # displayed url 841: my ($thisversion)=($uri=~/\.(\d+)\.(\w+)\.meta$/); 842: $uri=~s/\.meta$//; 843: my $disuri=&Apache::lonnet::clutter_with_no_wrapper($uri); 844: # version 845: my $versiondisplay=''; 846: if (!$uploaded) { 847: my $currentversion=&Apache::lonnet::getversion($disuri); 848: if ($thisversion) { 849: $versiondisplay=&mt('Version').': '.$thisversion. 850: ' ('.&mt('most recent version').': '. 851: ($currentversion>0 ? 852: $currentversion : 853: &mt('information not available')).')'; 854: } else { 855: $versiondisplay='Version: '.$currentversion; 856: } 857: } 858: # crumbify displayed URL uri target prefix form size 859: $disuri=&Apache::lonhtmlcommon::crumbs($disuri,undef, undef, undef,'+1'); 860: $disuri =~ s:<br />::g; 861: # obsolete 862: my $obsolete=$content{'obsolete'}; 863: my $obsoletewarning=''; 864: if (($obsolete) && ($env{'user.adv'})) { 865: $obsoletewarning='<p><font color="red">'. 866: &mt('This resource has been marked obsolete by the author(s)'). 867: '</font></p>'; 868: } 869: # 870: my %lt=&fieldnames(); 871: my $table=''; 872: my $title = $content{'title'}; 873: if (! defined($title)) { 874: $title = 'Untitled Resource'; 875: } 876: my @fields; 877: if ($uploaded) { 878: @fields = ('title','author','subject','keywords','notes','abstract', 879: 'lowestgradelevel','highestgradelevel','standards','mime', 880: 'owner'); 881: } else { 882: @fields = ('title', 883: 'author', 884: 'subject', 885: 'keywords', 886: 'notes', 887: 'abstract', 888: 'lowestgradelevel', 889: 'highestgradelevel', 890: 'standards', 891: 'mime', 892: 'language', 893: 'creationdate', 894: 'lastrevisiondate', 895: 'owner', 896: 'copyright', 897: 'customdistributionfile', 898: 'sourceavail', 899: 'sourcerights', 900: 'obsolete', 901: 'obsoletereplacement'); 902: } 903: foreach my $field (@fields) { 904: $table.='<tr><td bgcolor="#AAAAAA">'.$lt{$field}. 905: '</td><td bgcolor="#CCCCCC">'. 906: &prettyprint($field,$content{$field}).'</td></tr>'; 907: delete($content{$field}); 908: } 909: # 910: $r->print(<<ENDHEAD); 911: <h2>$title</h2> 912: <p> 913: $disuri<br /> 914: $obsoletewarning 915: $versiondisplay 916: </p> 917: <table cellspacing="2" border="0"> 918: $table 919: </table> 920: ENDHEAD 921: if (!$uploaded && $env{'user.adv'}) { 922: &print_dynamic_metadata($r,$uri,\%content); 923: } 924: return; 925: } 926: 927: sub print_dynamic_metadata { 928: my ($r,$uri,$content) = @_; 929: # 930: my %content = %$content; 931: my %lt=&fieldnames(); 932: # 933: my $description = 'Dynamic Metadata (updated periodically)'; 934: $r->print('<h3>'.&mt($description).'</h3>'. 935: &mt('Processing')); 936: $r->rflush(); 937: my %items=&fieldnames(); 938: my %dynmeta=&dynamicmeta($uri); 939: # 940: # General Access and Usage Statistics 941: if (exists($dynmeta{'count'}) || 942: exists($dynmeta{'sequsage'}) || 943: exists($dynmeta{'comefrom'}) || 944: exists($dynmeta{'goto'}) || 945: exists($dynmeta{'course'})) { 946: $r->print('<h4>'.&mt('Access and Usage Statistics').'</h4>'. 947: '<table cellspacing="2" border="0">'); 948: foreach ('count', 949: 'sequsage','sequsage_list', 950: 'comefrom','comefrom_list', 951: 'goto','goto_list', 952: 'course','course_list') { 953: $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. 954: '<td bgcolor="#CCCCCC">'. 955: &prettyprint($_,$dynmeta{$_})."</td></tr>\n"); 956: } 957: $r->print('</table>'); 958: } else { 959: $r->print('<h4>'.&mt('No Access or Usages Statistics are available for this resource.').'</h4>'); 960: } 961: # 962: # Assessment statistics 963: if ($uri=~/\.(problem|exam|quiz|assess|survey|form)$/) { 964: if (exists($dynmeta{'stdno'}) || 965: exists($dynmeta{'avetries'}) || 966: exists($dynmeta{'difficulty'}) || 967: exists($dynmeta{'disc'})) { 968: # This is an assessment, print assessment data 969: $r->print('<h4>'. 970: &mt('Overall Assessment Statistical Data'). 971: '</h4>'. 972: '<table cellspacing="2" border="0">'); 973: $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{'stdno'}.'</td>'. 974: '<td bgcolor="#CCCCCC">'. 975: &prettyprint('stdno',$dynmeta{'stdno'}). 976: '</td>'."</tr>\n"); 977: foreach ('avetries','difficulty','disc') { 978: $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. 979: '<td bgcolor="#CCCCCC">'. 980: &prettyprint($_,sprintf('%5.2f',$dynmeta{$_})). 981: '</td>'."</tr>\n"); 982: } 983: $r->print('</table>'); 984: } 985: if (exists($dynmeta{'stats'})) { 986: # 987: # New assessment statistics 988: $r->print('<h4>'. 989: &mt('Detailed Assessment Statistical Data'). 990: '</h4>'); 991: my $table = '<table cellspacing="2" border="0">'. 992: '<tr>'. 993: '<th>Course</th>'. 994: '<th>Section(s)</th>'. 995: '<th>Num Students</th>'. 996: '<th>Mean Tries</th>'. 997: '<th>Degree of Difficulty</th>'. 998: '<th>Degree of Discrimination</th>'. 999: '<th>Time of computation</th>'. 1000: '</tr>'.$/; 1001: foreach my $identifier (sort(keys(%{$dynmeta{'stats'}}))) { 1002: my $data = $dynmeta{'stats'}->{$identifier}; 1003: my $course = $data->{'course'}; 1004: my %courseinfo = 1005: &Apache::lonnet::coursedescription($course, 1006: {'one_time' => 1}); 1007: if (! exists($courseinfo{'num'}) || $courseinfo{'num'} eq '') { 1008: &Apache::lonnet::logthis('lookup for '.$course.' failed'); 1009: next; 1010: } 1011: $table .= '<tr>'; 1012: $table .= 1013: '<td><nobr>'.$courseinfo{'description'}.'</nobr></td>'; 1014: $table .= 1015: '<td align="right">'.$data->{'sections'}.'</td>'; 1016: $table .= 1017: '<td align="right">'.$data->{'stdno'}.'</td>'; 1018: foreach ('avetries','difficulty','disc') { 1019: $table .= '<td align="right">'; 1020: if (exists($data->{$_})) { 1021: $table .= sprintf('%.2f',$data->{$_}).' '; 1022: } else { 1023: $table .= ''; 1024: } 1025: $table .= '</td>'; 1026: } 1027: $table .= 1028: '<td><nobr>'. 1029: &Apache::lonlocal::locallocaltime($data->{'timestamp'}). 1030: '</nobr></td>'; 1031: $table .= 1032: '</tr>'.$/; 1033: } 1034: $table .= '</table>'.$/; 1035: $r->print($table); 1036: } else { 1037: $r->print('No new dynamic data found.'); 1038: } 1039: } else { 1040: $r->print('<h4>'. 1041: &mt('No Assessment Statistical Data is available for this resource'). 1042: '</h4>'); 1043: } 1044: 1045: # 1046: # 1047: if (exists($dynmeta{'clear'}) || 1048: exists($dynmeta{'depth'}) || 1049: exists($dynmeta{'helpful'}) || 1050: exists($dynmeta{'correct'}) || 1051: exists($dynmeta{'technical'})){ 1052: $r->print('<h4>'.&mt('Evaluation Data').'</h4>'. 1053: '<table cellspacing="2" border="0">'); 1054: foreach ('clear','depth','helpful','correct','technical') { 1055: $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. 1056: '<td bgcolor="#CCCCCC">'. 1057: &prettyprint($_,$dynmeta{$_})."</td></tr>\n"); 1058: } 1059: $r->print('</table>'); 1060: } else { 1061: $r->print('<h4>'.&mt('No Evaluation Data is available for this resource.').'</h4>'); 1062: } 1063: $uri=~/^\/res\/(\w+)\/(\w+)\//; 1064: if ((($env{'user.domain'} eq $1) && ($env{'user.name'} eq $2)) 1065: || ($env{'user.role.ca./'.$1.'/'.$2})) { 1066: if (exists($dynmeta{'comments'})) { 1067: $r->print('<h4>'.&mt('Evaluation Comments').' ('. 1068: &mt('visible to author and co-authors only'). 1069: ')</h4>'. 1070: '<blockquote>'.$dynmeta{'comments'}.'</blockquote>'); 1071: } else { 1072: $r->print('<h4>'.&mt('There are no Evaluation Comments on this resource.').'</h4>'); 1073: } 1074: my $bombs = &Apache::lonmsg::retrieve_author_res_msg($uri); 1075: if (defined($bombs) && $bombs ne '') { 1076: $r->print('<a name="bombs" /><h4>'.&mt('Error Messages').' ('. 1077: &mt('visible to author and co-authors only').')'. 1078: '</h4>'.$bombs); 1079: } else { 1080: $r->print('<h4>'.&mt('There are currently no Error Messages for this resource.').'</h4>'); 1081: } 1082: } 1083: # 1084: # All other stuff 1085: $r->print('<h3>'. 1086: &mt('Additional Metadata (non-standard, parameters, exports)'). 1087: '</h3><table border="0" cellspacing="1">'); 1088: foreach (sort(keys(%content))) { 1089: my $name=$_; 1090: if ($name!~/\.display$/) { 1091: my $display=&Apache::lonnet::metadata($uri, 1092: $name.'.display'); 1093: if (! $display) { 1094: $display=$name; 1095: }; 1096: my $otherinfo=''; 1097: foreach ('name','part','type','default') { 1098: if (defined(&Apache::lonnet::metadata($uri, 1099: $name.'.'.$_))) { 1100: $otherinfo.=' '.$_.'='. 1101: &Apache::lonnet::metadata($uri, 1102: $name.'.'.$_).'; '; 1103: } 1104: } 1105: $r->print('<tr><td bgcolor="#bbccbb"><font size="-1" color="#556655">'.$display.'</font></td><td bgcolor="#ccddcc"><font size="-1" color="#556655">'.$content{$name}); 1106: if ($otherinfo) { 1107: $r->print(' ('.$otherinfo.')'); 1108: } 1109: $r->print("</font></td></tr>\n"); 1110: } 1111: } 1112: $r->print("</table>"); 1113: return; 1114: } 1115: 1116: 1117: 1118: ##################################################### 1119: ##################################################### 1120: ### ### 1121: ### Editable metadata display ### 1122: ### ### 1123: ##################################################### 1124: ##################################################### 1125: sub present_editable_metadata { 1126: my ($r,$uri,$file_type) = @_; 1127: # Construction Space Call 1128: # Header 1129: my $disuri=$uri; 1130: my $fn=&Apache::lonnet::filelocation('',$uri); 1131: $disuri=~s{^/\~}{/priv/}; 1132: $disuri=~s/\.meta$//; 1133: my $meta_uri = $disuri; 1134: my $path; 1135: if ($disuri =~ m|/portfolio/|) { 1136: ($disuri, $meta_uri, $path) = &portfolio_display_uri($disuri,1); 1137: } 1138: my $target=$uri; 1139: $target=~s{^/\~}{/res/$env{'request.role.domain'}/}; 1140: $target=~s/\.meta$//; 1141: my $bombs=&Apache::lonmsg::retrieve_author_res_msg($target); 1142: if ($bombs) { 1143: my $showdel=1; 1144: if ($env{'form.delmsg'}) { 1145: if (&Apache::lonmsg::del_url_author_res_msg($target) eq 'ok') { 1146: $bombs=&mt('Messages deleted.'); 1147: $showdel=0; 1148: } else { 1149: $bombs=&mt('Error deleting messages'); 1150: } 1151: } 1152: if ($env{'form.clearmsg'}) { 1153: my $cleardir=$target; 1154: $cleardir=~s/\/[^\/]+$/\//; 1155: if (&Apache::lonmsg::clear_author_res_msg($cleardir) eq 'ok') { 1156: $bombs=&mt('Messages cleared.'); 1157: $showdel=0; 1158: } else { 1159: $bombs=&mt('Error clearing messages'); 1160: } 1161: } 1162: my $del=&mt('Delete Messages for this Resource'); 1163: my $clear=&mt('Clear all Messages in Subdirectory'); 1164: my $goback=&mt('Back to Source File'); 1165: $r->print(<<ENDBOMBS); 1166: <h1>$disuri</h1> 1167: <form method="post" action="" name="defaultmeta"> 1168: ENDBOMBS 1169: if ($showdel) { 1170: $r->print(<<ENDDEL); 1171: <input type="submit" name="delmsg" value="$del" /> 1172: <input type="submit" name="clearmsg" value="$clear" /> 1173: ENDDEL 1174: } else { 1175: $r->print('<a href="'.$disuri.'" />'.$goback.'</a>'); 1176: } 1177: $r->print('<br />'.$bombs); 1178: } else { 1179: my $displayfile='Catalog Information for '.$disuri; 1180: if ($disuri=~/\/default$/) { 1181: my $dir=$disuri; 1182: $dir=~s/default$//; 1183: $displayfile= 1184: &mt('Default Cataloging Information for Directory').' '. 1185: $dir; 1186: } 1187: %Apache::lonpublisher::metadatafields=(); 1188: %Apache::lonpublisher::metadatakeys=(); 1189: my $result=&Apache::lonnet::getfile($fn); 1190: if ($result == -1){ 1191: $r->print(&mt('Creating new file [_1]'),$meta_uri); 1192: } else { 1193: &Apache::lonpublisher::metaeval($result); 1194: } 1195: $r->print(<<ENDEDIT); 1196: <h1>$displayfile</h1> 1197: <form method="post" action="" name="defaultmeta"> 1198: ENDEDIT 1199: $r->print('<script type="JavaScript">'. 1200: &Apache::loncommon::browser_and_searcher_javascript(). 1201: '</script>'); 1202: my %lt=&fieldnames($file_type); 1203: my $output; 1204: my @fields; 1205: my $added_metadata_fields; 1206: my @added_order; 1207: if ($file_type eq 'portfolio' || $file_type eq 'groups') { 1208: if(exists ($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.fieldlist'})) { 1209: # retrieve fieldnames (in order) from the course restricted list 1210: @fields = (split(/,/,$env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.fieldlist'})); 1211: } else { 1212: # no saved field list, use default list 1213: @fields = ('author','title','subject','keywords','abstract', 1214: 'notes','lowestgradelevel', 1215: 'highestgradelevel','standards'); 1216: $added_metadata_fields = &Apache::lonparmset::get_added_meta_fieldnames(); 1217: if ($env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'}) { 1218: @added_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'}); 1219: } 1220: $env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.fieldlist'} = join(",",@fields); 1221: } 1222: } else { 1223: @fields = ('author','title','subject','keywords','abstract','notes', 1224: 'copyright','customdistributionfile','language', 1225: 'standards', 1226: 'lowestgradelevel','highestgradelevel','sourceavail','sourcerights', 1227: 'obsolete','obsoletereplacement'); 1228: } 1229: if ($file_type eq 'groups') { 1230: $Apache::lonpublisher::metadatafields{'courserestricted'}= 1231: 'course.'.$env{'request.course.id'}; 1232: } 1233: if ((! $Apache::lonpublisher::metadatafields{'courserestricted'}) && 1234: (! $env{'form.new_courserestricted'}) && (! $file_type eq 'groups')) { 1235: $Apache::lonpublisher::metadatafields{'courserestricted'}= 1236: 'none'; 1237: } elsif ($env{'form.new_courserestricted'}) { 1238: $Apache::lonpublisher::metadatafields{'courserestricted'}= 1239: $env{'form.new_courserestricted'}; 1240: } 1241: if (! $Apache::lonpublisher::metadatafields{'copyright'}) { 1242: $Apache::lonpublisher::metadatafields{'copyright'}= 1243: 'default'; 1244: } 1245: if (($file_type eq 'portfolio') || ($file_type eq 'groups')) { 1246: if (! $Apache::lonpublisher::metadatafields{'mime'}) { 1247: ($Apache::lonpublisher::metadatafields{'mime'}) = 1248: ( $target=~/\.(\w+)$/ ); 1249: } 1250: if (! $Apache::lonpublisher::metadatafields{'owner'}) { 1251: $Apache::lonpublisher::metadatafields{'owner'} = 1252: $env{'user.name'}.':'.$env{'user.domain'}; 1253: } 1254: 1255: if ($Apache::lonpublisher::metadatafields{'courserestricted'} ne 'none') { 1256: $r->print(&mt('Associated with course [_1]', 1257: '<strong><a href="'.$uri.'?changecourse=true">'. 1258: $env{$Apache::lonpublisher::metadatafields{'courserestricted'}. 1259: ".description"}. 1260: '</a></strong>').'<br />'); 1261: } else { 1262: $r->print('<a href="'.$uri.'?changecourse=true">This resource is not associated with a course.</a><br />'); 1263: } 1264: } 1265: if (@added_order) { 1266: foreach my $field_name (@added_order) { 1267: push(@fields,$field_name); 1268: $lt{$field_name} = $$added_metadata_fields{$field_name}; 1269: } 1270: } else { 1271: foreach my $field_name (keys(%$added_metadata_fields)) { 1272: push(@fields,$field_name); 1273: $lt{$field_name} = $$added_metadata_fields{$field_name}; 1274: } 1275: } 1276: $output.='<table>'; 1277: my $row_alt = 1; 1278: foreach my $field_name (@fields) { 1279: # $row_alt = ($row_alt) ? 0 : 1; 1280: my $row_class = ($row_alt) ? ' class="LC_metadata_light" ' : ' class="LC_metadata_dark" '; 1281: if (defined($env{'form.new_'.$field_name})) { 1282: $Apache::lonpublisher::metadatafields{$field_name}= 1283: join(',',&Apache::loncommon::get_env_multiple('form.new_'.$field_name)); 1284: } 1285: if ($Apache::lonpublisher::metadatafields{'courserestricted'} ne 'none' 1286: && exists($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.'.$field_name.'.options'})) { 1287: # handle restrictions here 1288: if ((($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.'.$field_name.'.options'} =~ m/active/) || 1289: ($field_name eq 'courserestricted'))&& 1290: (!($env{$Apache::lonpublisher::metadatafields{'courserestricted'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/))){ 1291: 1292: $output.=("\n".'<tr '.$row_class.'><td><span class="LC_metadata">'.$lt{$field_name}.':</span></td><td> '. 1293: &prettyinput($field_name, 1294: $Apache::lonpublisher::metadatafields{$field_name}, 1295: 'new_'.$field_name,'defaultmeta', 1296: undef,undef,undef,undef, 1297: $Apache::lonpublisher::metadatafields{'courserestricted'}).'</td></tr>'."\n"); 1298: } 1299: } else { 1300: 1301: $output.=('<tr'.$row_class.'><td><span class="LC_metadata">'.$lt{$field_name}.':</span></td><td> '. 1302: &prettyinput($field_name, 1303: $Apache::lonpublisher::metadatafields{$field_name}, 1304: 'new_'.$field_name,'defaultmeta').'</td></tr>'); 1305: 1306: } 1307: } 1308: $output.='</table>'; 1309: if ($env{'form.store'}) { 1310: my $mfh; 1311: my $formname='store'; 1312: my $file_content; 1313: if (&Apache::loncommon::get_env_multiple('form.new_keywords')) { 1314: $Apache::lonpublisher::metadatafields{'keywords'} = 1315: join (',', &Apache::loncommon::get_env_multiple('form.new_keywords')); 1316: } 1317: foreach my $field (sort(keys(%Apache::lonpublisher::metadatafields))) { 1318: next if ($field =~ /\./); 1319: my $unikey=$field; 1320: $unikey=~/^([A-Za-z_]+)/; 1321: my $tag=$1; 1322: $tag=~tr/A-Z/a-z/; 1323: $file_content.= "\n\<$tag"; 1324: foreach my $key (split(/\,/, 1325: $Apache::lonpublisher::metadatakeys{$unikey}) 1326: ) { 1327: my $value= 1328: $Apache::lonpublisher::metadatafields{$unikey.'.'.$key}; 1329: $value=~s/\"/\'\'/g; 1330: $file_content.=' '.$key.'="'.$value.'"' ; 1331: } 1332: $file_content.= '>'. 1333: &HTML::Entities::encode 1334: ($Apache::lonpublisher::metadatafields{$unikey}, 1335: '<>&"'). 1336: '</'.$tag.'>'; 1337: } 1338: if ($fn =~ m|^$Apache::lonnet::perlvar{'lonDocRoot'}/userfiles|) { 1339: my ($path, $new_fn); 1340: if ($fn =~ m|\w+/groups/\w+/portfolio/|) { 1341: ($path, $new_fn) = ($fn =~ m|/(groups/\w+/portfolio.*)/([^/]*)$|); 1342: } else { 1343: ($path, $new_fn) = ($fn =~ m|/(portfolio.*)/([^/]*)$|); 1344: } 1345: $r->print(&store_portfolio_metadata($formname,$file_content,$path, 1346: $new_fn)); 1347: } else { 1348: if (! ($mfh=Apache::File->new('>'.$fn))) { 1349: $r->print('<p><font color="red">'. 1350: &mt('Could not write metadata').', '. 1351: &mt('FAIL').'</font></p>'); 1352: } else { 1353: print $mfh ($file_content); 1354: $r->print('<p><font color="blue">'.&mt('Wrote Metadata'). 1355: ' '.&Apache::lonlocal::locallocaltime(time). 1356: '</font></p>'); 1357: } 1358: } 1359: } 1360: $r->print($output.'<br /><input type="submit" name="store" value="'. 1361: &mt('Store Catalog Information').'" />'); 1362: 1363: if ($file_type eq 'portfolio') { 1364: my ($port_path,$group) = &get_port_path_and_group($uri); 1365: if ($group) { 1366: $r->print('<input type="hidden" name="group" value="'.$group.'" />'); 1367: } 1368: $r->print('<input type="hidden" name="currentpath" value="'.$env{'form.currentpath'}.'" />'); 1369: $r->print('</form><br /><br /><form method="post" action="'.$port_path.'">'); 1370: if ($group) { 1371: $r->print('<input type="hidden" name="group" value="'.$group.'" />'); 1372: } 1373: $r->print('<input type="hidden" name="currentpath" value="'.$path.'" />'. 1374: '<input type="submit" name="cancel" value="'.&mt('Discard Edits and Return to Portfolio').'" />'); 1375: } 1376: } 1377: 1378: $r->print('</form>'); 1379: 1380: return; 1381: } 1382: 1383: sub store_portfolio_metadata { 1384: my ($formname,$content,$path,$new_fn) = @_; 1385: $env{'form.'.$formname}=$content."\n"; 1386: $env{'form.'.$formname.'.filename'}=$new_fn; 1387: my $result =&Apache::lonnet::userfileupload($formname,'',$path); 1388: if ($result =~ /(error|notfound)/) { 1389: return '<p><font color="red">'. 1390: &mt('Could not write metadata').', '. 1391: &mt('FAIL').'</font></p>'; 1392: } else { 1393: return '<p><font color="blue">'.&mt('Wrote Metadata'). 1394: ' '.&Apache::lonlocal::locallocaltime(time).'</font></p>'; 1395: } 1396: } 1397: 1398: 1; 1399: __END__ 1400: