--- loncom/interface/portfolio.pm 2004/06/28 16:07:47 1.8 +++ loncom/interface/portfolio.pm 2010/11/11 23:58:05 1.230 @@ -1,3 +1,8 @@ +# The LearningOnline Network +# portfolio browser +# +# $Id: portfolio.pm,v 1.230 2010/11/11 23:58:05 raeburn Exp $ +# # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). @@ -18,12 +23,9 @@ # # /home/httpd/html/adm/gpl.txt # - - # http://www.lon-capa.org/ # - package Apache::portfolio; use strict; use Apache::Constants qw(:common :http); @@ -32,227 +34,2661 @@ use Apache::lonnet; use Apache::lontexconvert; use Apache::lonfeedback; use Apache::lonlocal; +use Apache::lonnet; +use Apache::longroup; +use Apache::lonhtmlcommon; +use HTML::Entities; +use LONCAPA qw(:DEFAULT :match); -# receives a file name assumed to reside in username/userfiles/portfolio/ -# returns a form consisting of a single submit button labeled with the filename -sub makeAnchor { - my ($fileName, $currentPath) = @_; - my $anchor = ''.$fileName.''; -# my $button = ' -#
-# '; +sub group_args { + my $output; + if (defined($env{'form.group'})) { + $output .= '&group='.$env{'form.group'}; + if (defined($env{'form.ref'})) { + $output .= '&ref='.$env{'form.ref'}; + } + } + return $output; +} + +sub group_form_data { + my $output; + if (defined($env{'form.group'})) { + $output = ''; + if (exists($env{'form.ref'})) { + $output .= ''; + } + } + return $output; +} + +# receives a file name and path stub from username/userfiles/portfolio/ +# returns an anchor tag consisting encoding filename and currentpath +sub make_anchor { + my ($url, $anchor_fields, $inner_text) = @_; + if ($$anchor_fields{'continue'} ne 'true') {$$anchor_fields{'continue'} = 'false'}; + my $anchor = ''.$inner_text.''; return $anchor; } -# returns html with'.&mt('[quant,_1,file] in list not selectable as file size is 0 bytes.',$zerobyte).'
'); + } + $r->print(' + + + +
+
+
+
+ '. + &Apache::loncommon::help_open_topic('Portfolio DeleteFile').' +
+ + + ' + ); + } + } +} + +sub open_form { + my ($r,$url)=@_; + my @files=&Apache::loncommon::get_env_multiple('form.selectfile'); + $r->print(''); + $r->print(''); +} + +sub display_file { + my ($path,$filename)=@_; + my $display_file_text; + my $file_start=''; + my $file_end=''; + if (!defined($path)) { $path=$env{'form.currentpath'}; } + if (!defined($filename)) { + $filename=$env{'form.selectfile'}; + $display_file_text = $file_start.$path.$filename.$file_end; + } elsif (ref($filename) eq "ARRAY") { + foreach my $file (@$filename) { + $display_file_text .= $file_start.$path.$file.$file_end.''.&mt('Delete [_1]?',&display_file(undef,\@files)).'
'); + &close_form($r,$url); + } else { + $r->print("No file was checked to delete.'.&mt('Delete [_1]?',&display_file()).'
'); + &close_form($r,$url); +} + +sub delete_dir_confirmed { + my ($r,$url,$group)=@_; + my $directory_name = $env{'form.currentpath'}; + $directory_name =~ s|/$||; # remove any trailing slash + my ($uname,$udom) = &get_name_dom($group); + my $namespace = &get_namespace(); + my $port_path = &get_port_path(); + my $result=&Apache::lonnet::removeuserfile($uname,$udom,$port_path. + $directory_name); + + if ($result ne 'ok') { + $r->print('' + .&mt('An error occurred (dir) ([_1]) while trying to delete [_2].' + ,$result,$directory_name) + .''.&mt('Rename [_1] to [_2]?', &display_file() + , '').'
'); + &close_form($r,$url); + } +} + +sub rename_confirmed { + my ($r,$url,$group)=@_; + my $filenewname=&Apache::lonnet::clean_filename($env{'form.filenewname'}); + my ($uname,$udom) = &get_name_dom($group); + my $port_path = &get_port_path(); + if ($filenewname eq '') { + $r->print(''. + &mt("Error: no valid filename was provided to rename to."). + ''.&mt('Roles').' | '. + &mt('Access').' | '. + &mt('Sections').' | '); + $r->print(''.&mt('Groups').' | '); + $r->print('
---|---|---|---|
'); + if ($item eq 'role') { + my $role_output; + foreach my $role (@{$content->{'roles'}{$id}{$item}}) { + if ($role eq 'all') { + $role_output .= $role.','; + } elsif ($role =~ /^cr/) { + $role_output .= (split('/',$role))[3].','; + } else { + $role_output .= &Apache::lonnet::plaintext($role,$crstype).','; + } + } + $role_output =~ s/,$//; + $r->print($role_output); + } else { + $r->print(join(',',@{$content->{'roles'}{$id}{$item}})); + } + $r->print(' | '); + } + $r->print('
'); - #grab stuff that was sent - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['selectfile','currentpath', - 'currentfile']); - $r->print (''); + $r->print(&Apache::loncommon::end_page()); return OK; }
CP= '.$ENV{'form.currentpath'}.'
'); - # currentPath and currentFile need to be set for the rest of things to happen - # sometimes, currentFile will be passed by a form field, selectedfile - # if there is no 'form.selectedfile' then the current directory is - # considered as selected - if ($ENV{'form.currentpath'}) { - $currentPath = $ENV{'form.currentpath'}; - } else { - $currentPath = '/'; - } - if ($ENV{'form.selectfile'}) { - $r->print('
found selectfile'.$ENV{'form.selectfile'} .'
'); - # have to check if the selected file is a subdirectory - if ($ENV{'form.selectfile'} =~ /-\(Dir\)/) { - # $currentPath =~ /\-\(Dir\)/; - $currentPath = $`.'/'; - $r->print('
'.$currentPath.'
'); - } - $currentFile = $ENV{'form.selectfile'}; +sub sort_users { + my ($users) = @_; + my @curr_users = map { + $_->{'uname'}.':'.$_->{'udom'} + } (@{$users}); + my $curr_user_list = join(",\n",sort(@curr_users)); + return $curr_user_list; +} + +sub access_setting_table { + my ($r,$url,$filename,$access_controls,$action) = @_; + my ($public,$publictext); + $publictext ='Off'; + my ($guest,$guesttext); + $guesttext = 'Off'; + my @courses = (); + my @domains = (); + my @users = (); + my $now = time; + my $then = $now + (60*60*24*180); # six months approx. + my ($num,$scope,$publicnum,$guestnum); + my (%acl_count,%end,%start,%conditionals); + foreach my $key (sort(keys(%{$access_controls}))) { + ($num,$scope,$end{$key},$start{$key}) = &unpack_acc_key($key); + if ($scope eq 'public') { + $public = $key; + $publicnum = $num; + $publictext = &acl_status($start{$key},$end{$key},$now); + } elsif ($scope eq 'guest') { + $guest=$key; + $guestnum = $num; + $guesttext = &acl_status($start{$key},$end{$key},$now); + } else { + $conditionals{$scope}{$key} = $$access_controls{$key}; + if ($scope eq 'course') { + push(@courses,$key); + } elsif ($scope eq 'domains') { + push(@domains,$key); + } elsif ($scope eq 'users') { + push(@users,$key); + } + } + $acl_count{$scope} ++; + } + $r->print(''); +} + +sub standard_settings { + my ($r,$now,$then,$url,$filename,$acl_count,$start,$end,$public,$publicnum, + $publictext,$guest,$guestnum,$guesttext,$access_controls,%conditionals)=@_; + $r->print('
'); + if ($action eq 'chgaccess') { + &standard_settings($r,$now,$then,$url,$filename,\%acl_count,\%start, + \%end,$public,$publicnum,$publictext,$guest,$guestnum, + $guesttext,$access_controls,%conditionals); + } else { + &condition_setting($r,$access_controls,$now,$then,\%acl_count, + \@domains,\@users,\@courses); + } + $r->print(' '.&mt('Public access: [_1]',&mt($publictext)).'
'); + $r->print(&Apache::loncommon::start_data_table()); + $r->print(&Apache::loncommon::start_data_table_header_row()); + $r->print(''.&mt('Action').' '.&mt('Dates available').' '); + $r->print(&Apache::loncommon::end_data_table_header_row()); + $r->print(&Apache::loncommon::start_data_table_row()); + if ($public) { + $r->print(''.&actionbox('old',$publicnum,'public').' '. + &dateboxes($publicnum,$start->{$public},$end->{$public}).' '); + } else { + $r->print(''.&actionbox('new','0','public').' '. + &dateboxes('0',$now,$then).' '); + } + $r->print(&Apache::loncommon::end_data_table_row()); + $r->print(&Apache::loncommon::end_data_table()); + $r->print(''); + $r->print(' '.&mt('Passphrase-protected access: [_1]',&mt($guesttext)).'
'); + $r->print(&Apache::loncommon::start_data_table()); + $r->print(&Apache::loncommon::start_data_table_header_row()); + $r->print(''.&mt('Action').' '.&mt('Dates available'). + ' '. &mt('Passphrase').' '); + $r->print(&Apache::loncommon::end_data_table_header_row()); + $r->print(&Apache::loncommon::start_data_table_row()); + my $passwd; + if ($guest) { + $passwd = $$access_controls{$guest}{'password'}; + $r->print(''.&actionbox('old',$guestnum,'guest').' '. + &dateboxes($guestnum,$start->{$guest},$end->{$guest}).' '); + } else { + $r->print(''.&actionbox('new','1','guest').' '. + &dateboxes('1',$now,$then).' '); + } + $r->print(''); + $r->print(&Apache::loncommon::end_data_table_row()); + $r->print(&Apache::loncommon::end_data_table()); + $r->print(' '. + ' '); + my $numconditionals = 0; + my $conditionstext; + my %cond_status; + foreach my $scope ('domains','users','course') { + $numconditionals += $acl_count->{$scope}; + if ($acl_count->{$scope} > 0) { + if ($conditionstext ne 'Active') { + foreach my $key (keys(%{$conditionals{$scope}})) { + $conditionstext = &acl_status($start->{$key},$end->{$key},$now); + if ($conditionstext eq 'Active') { + last; + } + } + } + } + } + if ($conditionstext eq '') { + $conditionstext = 'Off'; + } + my %anchor_fields = ( + 'access' => $env{'form.selectfile'}, + 'action' => 'chgconditions', + 'currentpath' => $env{'form.currentpath'}, + ); + $r->print(' '.&mt('Conditional access: [_1]',&mt($conditionstext)).'
'); + if ($numconditionals > 0) { + my $count = 1; + my $chg = 'none'; + $r->print(&mt('You have previously set [_1] conditional access controls.',$numconditionals).' '.&make_anchor($url,\%anchor_fields,&mt('Change Conditions')).'
'); + $r->print(&Apache::loncommon::start_data_table()); + $r->print(&Apache::loncommon::start_data_table_header_row()); + $r->print(''.&mt('Access control').' '.&mt('Dates available'). + ' '.&mt('Additional information').' '); + $r->print(&Apache::loncommon::end_data_table_header_row()); + &build_access_summary($r,$count,$chg,%conditionals); + $r->print(&Apache::loncommon::end_data_table()); + } else { + $r->print(&make_anchor($url,\%anchor_fields,&mt('Add conditional access')).' '.&mt('based on domain, username, or course/community affiliation.')); + } +} + +sub condition_setting { + my ($r,$access_controls,$now,$then,$acl_count,$domains,$users,$courses) = @_; + $r->print(''); + &access_element($r,'domains',$acl_count,$domains,$access_controls,$now,$then); + $r->print(' '); + &access_element($r,'users',$acl_count,$users,$access_controls,$now,$then); + $r->print(' '); + if ($acl_count->{course} > 0) { + $r->print(' '); +} + +sub acl_status { + my ($start,$end,$now) = @_; + if ($start > $now) { + return 'Inactive'; + } + if ($end && $end<$now) { + return 'Inactive'; + } + return 'Active'; +} + +sub access_element { + my ($r,$type,$acl_count,$items,$access_controls,$now,$then) = @_; + my %typetext = &Apache::lonlocal::texthash( + domains => 'Domain', + users => 'User', + course => 'Course/Community' + ); + $r->print(''); + } else { + $r->print(' '); + } + &access_element($r,'course',$acl_count,$courses,$access_controls,$now,$then); + $r->print(' '); + $r->print(''.&mt('[_1]-based conditional access: ',$typetext{$type})); + if ($$acl_count{$type}) { + $r->print($$acl_count{$type}.' '); + if ($$acl_count{$type} > 1) { + $r->print(&mt('conditions')); + } else { + $r->print(&mt('condition')); + } + } else { + $r->print(&mt('Off')); + } + $r->print('
'); + &display_access_row($r,'old',$type,$items,$access_controls,$now,$then); + return; +} + +sub display_access_row { + my ($r,$status,$type,$items,$access_controls,$now,$then) = @_; + my $showtype; + if ($type eq 'course') { + $showtype = &mt('Courses/Communities'); + } elsif ($type eq 'domains') { + $showtype = &mt('Domains'); + } elsif ($type eq 'users') { + $showtype = &mt('Users'); + } + if (@{$items} > 0) { + my @all_doms; + my $colspan = 3; + $r->print(&Apache::loncommon::start_data_table()); + $r->print(&Apache::loncommon::start_data_table_header_row()); + $r->print(''.&mt('Action?').' '.$showtype.' '. + &mt('Dates available').' '); + if ($type eq 'course' && $status eq 'old') { + + $r->print(''.&mt('Allowed course/community affiliations'). + ' '); + $colspan ++; + } elsif ($type eq 'domains') { + @all_doms = sort(&Apache::lonnet::all_domains()); + } + $r->print(&Apache::loncommon::end_data_table_header_row()); + foreach my $key (@{$items}) { + $r->print(&Apache::loncommon::start_data_table_row()); + if ($type eq 'course') { + &course_row($r,$status,$type,$key,$access_controls,$now,$then); + } elsif ($type eq 'domains') { + &domains_row($r,$status,$key,\@all_doms,$access_controls,$now, + $then); + } elsif ($type eq 'users') { + &users_row($r,$status,$key,$access_controls,$now,$then); + } + $r->print(&Apache::loncommon::end_data_table_row()); + } + if ($status eq 'old') { + $r->print(&Apache::loncommon::start_data_table_row()); + $r->print(''.&additional_item($type). + ' '); + $r->print(&Apache::loncommon::end_data_table_row()); + } + $r->print(&Apache::loncommon::end_data_table()); + } else { + $r->print(&mt('No [_1]-based conditions defined.',$showtype).'
'. + &additional_item($type)); + } + return; +} + +sub course_js { + return qq| + +|; +} + +sub course_row { + my ($r,$status,$type,$item,$access_controls,$now,$then) = @_; + my $content; + my $defdom = $env{'user.domain'}; + if ($status eq 'old') { + $content = $$access_controls{$item}; + $defdom = $content->{'domain'}; + } + my $js = &Apache::loncommon::coursebrowser_javascript($defdom) + .&course_js(); + my $showtype = &mt('Course/Community'); + my $crstype = 'Course'; + my ($num,$scope,$end,$start) = &set_identifiers($status,$item,$now,$then, + $type); + $r->print(''.$js.&actionbox($status,$num,$scope).' '); + if ($status eq 'old') { + my $cid = $content->{'domain'}.'_'.$content->{'number'}; + my %course_description = &Apache::lonnet::coursedescription($cid); + if ($course_description{'type'} ne '') { + $crstype = $course_description{'type'}; + } + $r->print(''.$course_description{'description'}.' '); + } elsif ($status eq 'new') { + $r->print(''.&Apache::loncommon::selectcourse_link('portform','crsnum_'.$num,'crsdom_'.$num,'description_'.$num,$num.'_1',undef,$showtype).' '); + } + $r->print(''.&dateboxes($num,$start,$end)); + my $newrole_id = 1; + if ($status eq 'old') { + $r->print(' '); + my $max_id = 0; + if (keys(%{$content->{'roles'}}) > 0) { + $r->print(' '); + return; +} + +sub add_course_role { + my ($num,$max_id) = @_; + my $output; + $output .=''. + ''. + ''. + ''; + return $output; +} + +sub domains_row { + my ($r,$status,$item,$all_doms,$access_controls,$now,$then) = @_; + my ($num,$scope,$end,$start) = &set_identifiers($status,$item,$now,$then, + 'domains'); + my $dom_select = ''; + $r->print(''); + } + $r->print('
'); + foreach my $role_id (sort(keys(%{$content->{'roles'}}))) { + if ($role_id > $max_id) { + $max_id = $role_id; + } + $max_id ++; + my $role_selects = &role_selectors($num,$role_id,$crstype,$content,'display'); + $r->print(' '.&mt('Action').' '. + ''.&mt('Roles').' '. + ''.&mt('Access').' '. + ''.&mt('Sections').' '. + ''.&mt('Groups').' '); + } + $r->print(' '.$role_selects.'
'.&mt('Add a roles-based condition'). + ' {'domain'}','$content->{'number'}', + '$showtype'".')" value="" />'); + $newrole_id = $max_id; + } else { + $r->print(''); + } + $r->print(&add_course_role($num,$newrole_id)); + $r->print(''.&actionbox($status,$num,$scope).' '.$dom_select. + ' '.&dateboxes($num,$start,$end).' '); +} + +sub users_row { + my ($r,$status,$item,$access_controls,$now,$then) = @_; + my ($num,$scope,$end,$start) = &set_identifiers($status,$item,$now,$then, + 'users'); + my $curr_user_list; + if ($status eq 'old') { + my $content = $$access_controls{$item}; + $curr_user_list = &sort_users($content->{'users'}); + } + $r->print(''.&actionbox($status,$num,$scope).' '.&mt("Format for users' username:domain information:").'
sparty:msu,illini:uiuc ... etc.'.&dateboxes($num,$start,$end).' '); +} + +sub additional_item { + my ($type) = @_; + my $showtype; + if ($type eq 'course') { + $showtype = &mt('course/community'); + } elsif ($type eq 'domains') { + $showtype = &mt('domains'); + } elsif ($type eq 'users') { + $showtype = &mt('users'); + } + my $output = &mt('Add new [_1] condition(s)?',$showtype).' '.&mt('Number to add: ').''; + return $output; +} + +sub actionbox { + my ($status,$num,$scope) = @_; + my $output = '
'. + ''; + return $output; +} + +sub dateboxes { + my ($num,$start,$end) = @_; + my $noend; + if ($end == 0) { + $noend = 'checked="checked"'; + } + my $startdate = &Apache::lonhtmlcommon::date_setter('portform', + 'startdate_'.$num,$start,undef,undef,undef,1,undef, + undef,undef,1); + my $enddate = &Apache::lonhtmlcommon::date_setter('portform', + 'enddate_'.$num,$end,undef,undef,undef,1,undef, + undef,undef,1). ' '; + + my $output = &mt('Start: ').$startdate.'
'.&mt('End: ').$enddate; + return $output; +} + +sub unpack_acc_key { + my ($acc_key) = @_; + my ($num,$scope,$end,$start) = ($acc_key =~ /^([^:]+):([a-z]+)_(\d*)_?(\d*)$/); + return ($num,$scope,$end,$start); +} + +sub set_identifiers { + my ($status,$item,$now,$then,$scope) = @_; + if ($status eq 'old') { + return(&unpack_acc_key($item)); + } else { + return($item,$scope,$then,$now); + } +} + +sub role_selectors { + my ($num,$role_id,$type,$content,$caller) = @_; + my ($output,$cdom,$cnum,$longid); + if ($caller eq 'display') { + $longid = '_'.$num.'_'.$role_id; + $cdom = $$content{'domain'}; + $cnum = $$content{'number'}; + } elsif ($caller eq 'rolepicker') { + $cdom = $env{'form.cdom'}; + $cnum = $env{'form.cnum'}; + } + my $crstype = 'Course'; + if ($cnum =~ /^$match_community$/) { + $crstype = 'Community' + } + my ($sections,$groups,$allroles,$rolehash,$accesshash) = + &Apache::loncommon::get_secgrprole_info($cdom,$cnum,1,$crstype); + if (!@{$sections}) { + @{$sections} = ('none'); + } else { + unshift(@{$sections},('all','none')); + } + if (!@{$groups}) { + @{$groups} = ('none'); + } else { + unshift(@{$groups},('all','none')); + } + my @allacesses = sort(keys(%{$accesshash})); + my (%sectionhash,%grouphash); + foreach my $sec (@{$sections}) { + $sectionhash{$sec} = $sec; + } + foreach my $grp (@{$groups}) { + $grouphash{$grp} = $grp; + } + my %lookup = ( + 'role' => $rolehash, + 'access' => $accesshash, + 'section' => \%sectionhash, + 'group' => \%grouphash, + ); + my @allaccesses = sort(keys(%{$accesshash})); + my %allitems = ( + 'role' => $allroles, + 'access' => \@allaccesses, + 'section' => $sections, + 'group' => $groups, + ); + foreach my $item ('role','access','section','group') { + $output .= ''; + } + $output .= ' '; + return $output; +} + +sub role_options_window { + my ($r) = @_; + my $type = $env{'form.type'}; + my $rolenum = $env{'form.setroles'}; + my ($num,$role_id) = ($rolenum =~ /^([\d_]+)_(\d+)$/); + my $role_elements; + foreach my $item ('role','access','section','group') { + $role_elements .= "'".$item.'_'.$rolenum."',"; + } + $role_elements =~ s/,$//; + my $role_selects = &role_selectors($num,$role_id,$type,undef, + 'rolepicker'); + $r->print(<<"END_SCRIPT"); + +END_SCRIPT + $r->print( + '' + .&mt('Select roles, '.lc($type).' status, section(s) and group(s) for users' + .' who will be able to access the portfolio file.') + .'
' + ); + $r->print( + ' +END +} + +sub lock_info { + my ($r,$url,$group) = @_; + my ($uname,$udom) = &get_name_dom($group); + my $current_permissions = &Apache::lonnet::get_portfile_permissions($udom, + $uname); + my $file_name = $env{'form.lockinfo'}; + $file_name = &prepend_group($file_name); + if (defined($file_name) && defined($$current_permissions{$file_name})) { + foreach my $array_item (@{$$current_permissions{$file_name}}) { + next if (ref($array_item) ne 'ARRAY'); + + my $filetext; + if (defined($group)) { + $filetext = ''.$env{'form.lockinfo'}. + ' (group: '.$group.')'; + } else { + $filetext = ''.$file_name.''; + } + + my $title =''.&Apache::lonnet::gettitle($$array_item[0]). + '
'; + if ($$array_item[-1] eq 'graded') { + $r->print(&mt('[_1] was submitted in response to problem: [_2]', + $filetext,$title)); + } elsif ($$array_item[-1] eq 'handback') { + $r->print(&mt('[_1] was handed back in response to problem: [_2]', + $filetext,$title)); + } else { + # submission style lock + $r->print(&mt('[_1] was submitted in response to problem: [_2]', + $filetext,$title)); + } + my %course_description = + &Apache::lonnet::coursedescription($$array_item[1]); + if ( $course_description{'description'} ne '') { + $r->print(&mt('In the course:').' '.$course_description{'description'}.'
'); + } + } + } + $r->print(&done(&mt('Back'),$url)); + return 'ok'; +} + +sub createdir { + my ($r,$url,$group)=@_; + my $newdir=&Apache::lonnet::clean_filename($env{'form.newdir'}); + if ($newdir eq '') { + $r->print(''. + &mt("Error: no directory name was provided."). + '
'); + $r->print(&done(undef,$url)); + return; + } + my $portfolio_root = &get_portfolio_root(); + my @dir_list=&get_dir_list($portfolio_root,undef,$group); + my $found_file = 0; + foreach my $line (@dir_list) { + my ($filename)=split(/\&/,$line,2); + if ($filename eq $newdir){ + $found_file = 1; + } + } + if ($found_file){ + $r->print('' + .&mt('Unable to create a directory named [_1].',''.$newdir.'') + .' '.&mt('A file or directory by that name already exists.').'
'); + } else { + my ($uname,$udom) = &get_name_dom($group); + my $port_path = &get_port_path(); + my $result=&Apache::lonnet::mkdiruserfile($uname,$udom, + $port_path.$env{'form.currentpath'}.$newdir); + if ($result ne 'ok') { + $r->print('' + .&mt('An error occurred ([_1]) while trying to create a new directory [_2].' + ,$result,&display_file()) + .'
'); + } + } + if ($newdir ne $env{'form.newdir'}) { + $r->print(&mt('The new directory name was changed from [_1] to [_2].' + ,''.$env{'form.newdir'}.'',''.$newdir.'')); + } + $r->print(&done(undef,$url)); +} + +sub get_portfolio_root { + my ($udom,$uname,$group) = @_; + if (!(defined($udom)) || !(defined($uname))) { + ($uname,$udom) = &get_name_dom($group); + } + my $path = '/userfiles/portfolio'; + if (!defined($group)) { + if (defined($env{'form.group'})) { + $group = $env{'form.group'}; + } + } + if (defined($group)) { + $path = '/userfiles/groups/'.$group.'/portfolio'; + } + return $path; +} + +sub get_group_quota { + my ($group) = @_; + my $group_quota; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum,$group); + if (%curr_groups) { + my %group_info = &Apache::longroup::get_group_settings( + $curr_groups{$group}); + $group_quota = $group_info{'quota'}; #expressed in Mb + if ($group_quota) { + $group_quota = 1000 * $group_quota; #expressed in k + } + } + return $group_quota; +} + +sub get_dir_list { + my ($portfolio_root,$path,$group) = @_; + $path ||= $env{'form.currentpath'}; + my ($uname,$udom) = &get_name_dom($group); + my $getpropath = 1; + return &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname,$getpropath); +} + +sub get_name_dom { + my ($group) = @_; + my ($uname,$udom); + if (defined($group)) { + $udom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + $uname = $env{'course.'.$env{'request.course.id'}.'.num'}; + } else { + $udom = $env{'user.domain'}; + $uname = $env{'user.name'}; + } + return ($uname,$udom); +} + +sub prepend_group { + my ($filename) = @_; + if (defined($env{'form.group'})) { + $filename = $env{'form.group'}.$filename; + } + return $filename; +} + +sub get_namespace { + my $namespace = 'portfolio'; + if (defined($env{'form.group'})) { + my ($uname,$udom) = &get_name_dom($env{'form.group'}); + $namespace .= '_'.$udom.'_'.$uname.'_'.$env{'form.group'}; + } + return $namespace; +} + +sub get_port_path { + my $port_path; + if (defined($env{'form.group'})) { + $port_path = "groups/$env{'form.group'}/portfolio"; + } else { + $port_path = 'portfolio'; + } + return $port_path; +} + +sub missing_priv { + my ($r,$url,$priv) = @_; + my $longtext = { + upload => 'upload files', + delete => 'delete files', + rename => 'rename files', + setacl => 'set access controls for files', + }; + my $escpath = &HTML::Entities::encode($env{'form.currentpath'},'&<>"'); + my $rtnlink = 'print(&mt('in this portfolio.')); + } + $rtnlink .= '">'.&mt('Return to directory').''; + $r->print('
'.$rtnlink); + return; +} + +sub coursegrp_portfolio_header { + my ($cdom,$cnum,$grp_desc)=@_; + my $gpterm = &Apache::loncommon::group_term(); + my $ucgpterm = $gpterm; + $ucgpterm =~ s/^(\w)/uc($1)/e; + if ($env{'form.ref'}) { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>"/adm/coursegroups", + text=>"Groups", + title=>"Course Groups"}); + } + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>"/adm/$cdom/$cnum/$env{'form.group'}/smppg?ref=$env{'form.ref'}", + text=>"$ucgpterm: $grp_desc", + title=>"Go to group's home page"}, + {href=>"/adm/coursegrp_portfolio?".&group_args(), + text=>"Group Portfolio", + title=>"Display group portfolio"}); + my $output = &Apache::lonhtmlcommon::breadcrumbs( + &mt('[_1] portfolio files - [_2]',$gpterm,$grp_desc)); + return $output; +} + +sub get_quota { + my ($group) = @_; + my $disk_quota; + if (defined($group)) { + my $grp_quota = &get_group_quota($group); # quota expressed in k + if ($grp_quota ne '') { + $disk_quota = $grp_quota; + } else { + $disk_quota = 0; + } + } else { + $disk_quota = &Apache::loncommon::get_user_quota($env{'user.name'}, + $env{'user.domain'}); #expressed in Mb + $disk_quota = 1000 * $disk_quota; # convert from Mb to kb + } + return $disk_quota; +} + +sub suppress_embed_prompt { + my $suppress_prompt = 0; + if (($env{'request.role'} =~ /^st/) && ($env{'request.course.id'} ne '')) { + if ($env{'course.'.$env{'request.course.id'}.'.suppress_embed_prompt'} eq 'yes') { + $suppress_prompt = 1; + } + } + return $suppress_prompt; +} + + +sub handler { + # this handles file management + my $r = shift; + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['selectfile','currentpath','meta','lockinfo','currentfile','action', + 'fieldname','mode','rename','continue','group','access','setnum', + 'cnum','cdom','type','setroles','showversions','ref']); + my ($uname,$udom,$portfolio_root,$url,$caller,$title,$group,$grp_desc); + if ($r->uri =~ m|^(/adm/)([^/]+)|) { + $url = $1.$2; + $caller = $2; + } + my ($can_modify,$can_delete,$can_upload,$can_setacl); + if ($caller eq 'coursegrp_portfolio') { + # Needs to be in a course + if (! ($env{'request.course.fn'})) { + # Not in a course + $env{'user.error.msg'}= + "/adm/coursegrp_portfolio:rgf:0:0:Cannot view group portfolio"; + return HTTP_NOT_ACCEPTABLE; + } + my $earlyout = 0; + my $view_permission = + &Apache::lonnet::allowed('vcg',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')); + $env{'form.group'} =~ s/\W//g; + $group = $env{'form.group'}; + if ($group ne '') { + ($uname,$udom) = &get_name_dom($group); + my %curr_groups = &Apache::longroup::coursegroups($udom,$uname, + $group); + if (%curr_groups) { + my %grp_content = &Apache::longroup::get_group_settings( + $curr_groups{$group}); + $grp_desc = &unescape($grp_content{'description'}); + if (($view_permission) || (&Apache::lonnet::allowed('rgf', + $env{'request.course.id'}.'/'.$group))) { + $portfolio_root = &get_portfolio_root(); + } else { + $r->print(&mt('You do not have the privileges required to access the shared files space for this group.')); + $earlyout = 1; + } + } else { + $r->print(&mt('Not a valid group for this course')); + $earlyout = 1; + } + $title = &mt('Group portfolio for [_1]', $group); + } else { + $r->print(&mt('Invalid group')); + $earlyout = 1; + } + if ($earlyout) { return OK; } + if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) { + $can_modify = 1; + $can_delete = 1; + $can_upload = 1; + $can_setacl = 1; + } else { + if (&Apache::lonnet::allowed('agf',$env{'request.course.id'}.'/'.$group)) { + $can_setacl = 1; + } + if (&Apache::lonnet::allowed('ugf',$env{'request.course.id'}.'/'.$group)) { + $can_upload = 1; + } + if (&Apache::lonnet::allowed('mgf',$env{'request.course.id'}.'/'.$group)) { + $can_modify = 1; + } + if (&Apache::lonnet::allowed('dgf',$env{'request.course.id'}.'/'.$group)) { + $can_delete = 1; + } + } + } else { + ($uname,$udom) = &get_name_dom(); + $portfolio_root = &get_portfolio_root(); + $title = &mt('My Space'); + $can_modify = 1; + $can_delete = 1; + $can_upload = 1; + $can_setacl = 1; + } + + my $port_path = &get_port_path(); + &Apache::loncommon::no_cache($r); + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + # Give the LON-CAPA page header + my $brcrum = [{href=>"/adm/portfolio",text=>"Portfolio Manager"}]; + + if ($env{"form.mode"} eq 'selectfile'){ + $r->print(&Apache::loncommon::start_page($title,undef, + {'only_body' => 1})); + } elsif ($env{'form.action'} eq 'rolepicker') { + $r->print(&Apache::loncommon::start_page('New role-based condition',undef, + {'no_nav_bar' => 1, })); + } elsif ($caller eq 'coursegrp_portfolio') { + $r->print(&Apache::loncommon::start_page($title)); + } else { + $r->print(&Apache::loncommon::start_page($title,undef, + {'bread_crumbs' => $brcrum})); + if (!&Apache::lonnet::usertools_access($uname,$udom,'portfolio')) { + $r->print(''.&mt('No user portfolio available') .'
'. + &mt('This is a result of one of the following:').''. + '
'); + $r->print(&Apache::loncommon::end_page()); + return OK; + } + } + $r->rflush(); + my ($blocked,$blocktext) = + &Apache::loncommon::blocking_status('port',$uname,$udom); + if ($blocked) { + $r->print($blocktext); + $r->print(&Apache::loncommon::end_page()); + return OK; + } + if (($env{'form.storeupl'}) & (!$env{'form.uploaddoc.filename'})){ + $r->print(''); + $r->print(&mt('No file was selected to upload.').' '); + $r->print(&mt('To upload a file, click Browse... and select a file, then click Upload.')); + $r->print(''); + } + if ($env{'form.meta'}) { + &open_form($r,$url); + $r->print(&mt('Edit the meta data').'- '.&mt('The administrator of this domain has disabled portfolio functionality for this specific user.').'
'. + '- '.&mt('The domain has been configured to disable, by default, portfolio functionality for all users in the domain.').'
'. + '
'); + &close_form($r,$url); + } + if ($env{'form.uploaddoc.filename'}) { + if ($can_upload) { + &upload($r,$url,$group); + } else { + &missing_priv($r,$url,'upload'); + } + } elsif ($env{'form.action'} eq 'process_overwrite') { + if ($can_upload) { + &overwrite($r,$url,$group); + } else { + &missing_priv($r,$url,'existingfile'); + } + } elsif ($env{'form.action'} eq 'upload_embedded') { + if ($can_upload) { + my $disk_quota = &get_quota($group); + my $getpropath = 1; + my $current_disk_usage = + &Apache::lonnet::diskusage($udom,$uname,$portfolio_root,$getpropath); + $r->print( + &Apache::loncommon::upload_embedded('portfolio',$port_path,$uname,$udom, + $group,$portfolio_root,$group,$disk_quota,$current_disk_usage)); + $r->print(&done(undef,$url)); + } else { + &missing_priv($r,$url,'upload'); + } + } elsif ($env{'form.action'} eq 'delete' && $env{'form.confirmed'}) { + if ($can_delete) { + &delete_confirmed($r,$url,$group); + } else { + &missing_priv($r,$url,'delete'); + } + } elsif ($env{'form.action'} eq 'delete') { + if ($can_delete) { + &delete($r,$url,$group); + } else { + &missing_priv($r,$url,'delete'); + } + } elsif ($env{'form.action'} eq 'deletedir' && $env{'form.confirmed'}) { + if ($can_delete) { + &delete_dir_confirmed($r,$url,$group); + } else { + &missing_priv($r,$url,'delete'); + } + } elsif ($env{'form.action'} eq 'deletedir') { + if ($can_delete) { + &delete_dir($r,$url); + } else { + &missing_priv($r,$url,'delete'); + } + } elsif ($env{'form.action'} eq 'rename' && $env{'form.confirmed'}) { + if ($can_modify) { + &rename_confirmed($r,$url,$group); + } else { + &missing_priv($r,$url,'rename'); + } + } elsif ($env{'form.rename'}) { + $env{'form.selectfile'} = $env{'form.rename'}; + $env{'form.action'} = 'rename'; + if ($can_modify) { + &rename($r,$url,$group); + } else { + &missing_priv($r,$url,'rename'); + } + } elsif ($env{'form.access'}) { + $env{'form.selectfile'} = $env{'form.access'}; + if (!defined($env{'form.action'})) { + $env{'form.action'} = 'chgaccess'; + } + &display_access($r,$url,$group,$can_setacl,$port_path,$env{'form.action'}); + } elsif (($env{'form.action'} eq 'chgaccess') || + ($env{'form.action'} eq 'chgconditions')) { + if ($can_setacl) { + &update_access($r,$url,$group,$port_path); + } else { + &missing_priv($r,$url,'setacl'); + } + } elsif ($env{'form.action'} eq 'rolepicker') { + if ($can_setacl) { + &role_options_window($r); + } else { + &missing_priv($r,$url,'setacl'); + } + } elsif ($env{'form.createdir'}) { + if ($can_upload) { + &createdir($r,$url,$group); + } else { + &missing_priv($r,$url,'upload'); + } + } elsif ($env{'form.lockinfo'}) { + &lock_info($r,$url,$group); + } else { + if ($env{'form.action'} eq 'cancel_overwrite') { + if ($can_upload) { + my $formname = 'existingfile'; + my $fname = &Apache::lonnet::clean_filename($env{'form.filename'}); + $env{'form.'.$formname.'.filename'} = $fname; + &Apache::lonnet::userfileupload($formname,'canceloverwrite', + $port_path.$env{'form.currentpath'}); + } + } + my $current_path='/'; + if ($env{'form.currentpath'}) { + $current_path = $env{'form.currentpath'}; } + if ($caller eq 'coursegrp_portfolio') { + &Apache::lonhtmlcommon::clear_breadcrumbs(); + $r->print(&coursegrp_portfolio_header($udom,$uname,$grp_desc)); + } + my @dir_list=&get_dir_list($portfolio_root,$current_path,$group); + if ($dir_list[0] eq 'no_such_dir'){ + # two main reasons for this: + # 1) never been here, so directory structure not created + # 2) back-button navigation after deleting a directory + if ($current_path eq '/'){ + &Apache::lonnet::mkdiruserfile($uname,$udom, + &get_port_path()); + } else { + # some directory that snuck in get rid of the directory + # from the recent pulldown, just in case + &Apache::lonhtmlcommon::remove_recent('portfolio', + [$current_path]); + $current_path = '/'; # force it back to the root + } + # now grab the directory list again, for the first time + @dir_list=&get_dir_list($portfolio_root,$current_path,$group); + } + # need to know if directory is empty so it can be removed if desired + my $is_empty=(@dir_list == 2); + &display_common($r,$url,$current_path,$is_empty,\@dir_list, + $can_upload,$group); + &display_directory($r,$url,$current_path,$is_empty,\@dir_list,$group, + $can_upload,$can_modify,$can_delete,$can_setacl); } - ############################## - # - # Display begins here - # - ############################## - $r->print('
start '); - $r->print($udir); - $r->print(''); - $r->print('
'); - $r->print(&displayDirectory($currentPath, $currentFile, $isDir, @dirList)); - $r->print(' >'); - $r->print(&displayActions($currentPath, $currentFile, $isDir, $isFile)); - $r->print(' >
end display
'); - $r->print('