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