[LON-CAPA-cvs] cvs: loncom /homework essayresponse.pm inputtags.pm structuretags.pm /interface loncommon.pm

raeburn raeburn at source.lon-capa.org
Tue Jul 26 13:14:56 EDT 2011


raeburn		Tue Jul 26 17:14:56 2011 EDT

  Modified files:              
    /loncom/homework	essayresponse.pm inputtags.pm structuretags.pm 
    /loncom/interface	loncommon.pm 
  Log:
  - Bug 6459.
   - Overwriting previously submitted file in "turned_in" portfolio.
    - code used to generate path to subdirectory in portfolio moved
      from essayresponse.pm to loncommon.pm to facilitate re-use.
    - client side javascript used to detect if submitted file will
      overwrite previously submitted file. User prompted to confirm.
    - If resource includes more than one file upload, partid_responseid
      included as additional subdirectory in path where file is stored.
  - Work in progress. Still need to support multiple dropboxes in a .page.  
  
  
-------------- next part --------------
Index: loncom/homework/essayresponse.pm
diff -u loncom/homework/essayresponse.pm:1.114 loncom/homework/essayresponse.pm:1.115
--- loncom/homework/essayresponse.pm:1.114	Sat Jan 29 19:41:41 2011
+++ loncom/homework/essayresponse.pm	Tue Jul 26 17:14:51 2011
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # essay (ungraded) style responses
 #
-# $Id: essayresponse.pm,v 1.114 2011/01/29 19:41:41 raeburn Exp $
+# $Id: essayresponse.pm,v 1.115 2011/07/26 17:14:51 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -441,81 +441,58 @@
         }
     }
     if ($accepted_upload ne '') {
-        my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb);
-        my $turnindir;
-        my %userhash = &Apache::lonnet::userenvironment($udom,$uname,'turnindir');
-        $turnindir = $userhash{'turnindir'};
-        if ($turnindir eq '') {
-            $turnindir = &mt('turned in');
-            $turnindir =~ s/\W+/_/g;
-            my %newhash = (
-                            'turnindir' => $turnindir,
-                          );
-            &Apache::lonnet::put('environment',\%newhash,$udom,$uname);
-        }
-        my $prefix = 'portfolio';
-        my $path = '/'.$turnindir.'/';
-        my $restitle=&Apache::lonnet::gettitle($symb);
-        $restitle =~ s/\W+/_/g;
-        if ($restitle eq '') {
-            $restitle = ($resurl =~ m{/[^/]+$});
-            if ($restitle eq '') {
-                $restitle = time;
-            }
-        }
-        my @pathitems;
-        my $navmap = Apache::lonnavmaps::navmap->new();
-        if (defined($navmap)) {
-            my $mapres = $navmap->getResourceByUrl($map);
-            if (ref($mapres)) {
-                my $pcslist = $mapres->map_hierarchy();
-                if ($pcslist ne '') {
-                    foreach my $pc (split(/,/,$pcslist)) {
-                        my $res = $navmap->getByMapPc($pc);
-                        if (ref($res)) {
-                            my $title = $res->compTitle();
-                            $title =~ s/\W+/_/g;
-                            if ($title ne '') {
-                                push(@pathitems,$title);
-                            }
+        my ($path,$multiresp) = 
+            &Apache::loncommon::get_turnedin_filepath($symb,$uname,$udom,
+                                                      'submission');
+        if ($path eq '') {
+            $$award = 'INTERNAL_ERROR';
+        } else {
+            if ($multiresp) {
+                $path .= '/'.$jspart.'_'.$id;
+            }
+            my $prefix = 'portfolio';
+            my $formelement = 'HWFILE'.$jspart.'_'.$id;
+            my $fname = &Apache::lonnet::clean_filename($env{'form.'.$formelement.'.filename'});
+            my $url = '/uploaded/'.$udom.'/'.$uname.'/'.$prefix.$path.'/'.$fname;
+            my @stat = &Apache::lonnet::stat_file($url);
+            my $conflicts = 0;
+            if (@stat && $stat[0] ne 'no_such_dir') {
+                my $current_permissions = 
+                    &Apache::lonnet::get_portfile_permissions($udom,$uname);
+                if (ref($current_permissions) eq 'HASH') {
+                    if (ref($current_permissions->{$path.'/'.$fname}) eq 'ARRAY') {
+                        foreach my $record (@{$current_permissions->{$path.'/'.$fname}}) {
+                            if (ref($record) eq 'ARRAY') {
+                                next if (($record->[0] eq $symb) && 
+                                         ($record->[1] eq $crsid));
+                                $conflicts ++;
+                            } 
                         }
                     }
                 }
-                my $maptitle = $mapres->compTitle();
-                $maptitle =~ s/\W+/_/g;
-                if ($maptitle ne '') {
-                    push(@pathitems,$maptitle);
+                if ($conflicts) {
+                    $$award = 'FILENAME_INUSE';
                 }
-            } else {
-                $$award = 'INTERNAL_ERROR';
             }
-        } else {
-            $$award = 'INTERNAL_ERROR';
-        }
-        push(@pathitems,$restitle);
-        $path .= join('/', at pathitems);
-        my $formelement = 'HWFILE'.$jspart.'_'.$id;
-        my $fname = &Apache::lonnet::clean_filename($env{'form.'.$formelement.'.filename'});
-        my $url = '/uploaded/'.$udom.'/'.$uname.'/'.$prefix.$path.'/'.$fname;
-        my @stat = &Apache::lonnet::stat_file($url);
-        if (@stat && $stat[0] ne 'no_such_dir') {
-            $$award = 'FILENAME_INUSE';
-        } else {
-            my ($mode,%allfiles,%codebase);
-            my $result = &Apache::lonnet::userfileupload($formelement,'',
+            unless ($conflicts) { 
+                my ($mode,%allfiles,%codebase);
+                my $result = &Apache::lonnet::userfileupload($formelement,'',
                              $prefix.$path,$mode,\%allfiles,\%codebase);
-            if ($result =~ m{^/uploaded/}) {
-                $stored_upload = $path.'/'.$fname;
-                $Apache::lonhomework::results{"resource.$part.$id.portfiles"} = $stored_upload;
-                push(@tolock,$stored_upload);
-            } else {
-                $$award = 'INTERNAL_ERROR';
+                if ($result =~ m{^/uploaded/}) {
+                    $stored_upload = $path.'/'.$fname;
+                    unless (grep(/^\Q$stored_upload\E$/, at accepted_portfiles)) {
+                        $Apache::lonhomework::results{"resource.$part.$id.portfiles"} = $stored_upload;
+                        push(@tolock,$stored_upload);
+                    }
+                } else {
+                    $$award = 'INTERNAL_ERROR';
+                }
             }
         }
         delete($env{'form.HWFILE'.$jspart.'_'.$id});
     }
     if (@accepted_portfiles) {
-        if ($stored_upload) {
+        if ($Apache::lonhomework::results{"resource.$part.$id.portfiles"}) {
             $Apache::lonhomework::results{"resource.$part.$id.portfiles"} .= ',';
         }
         $Apache::lonhomework::results{"resource.$part.$id.portfiles"}.=join(',', at accepted_portfiles);
Index: loncom/homework/inputtags.pm
diff -u loncom/homework/inputtags.pm:1.292 loncom/homework/inputtags.pm:1.293
--- loncom/homework/inputtags.pm:1.292	Tue Jul 12 12:55:50 2011
+++ loncom/homework/inputtags.pm	Tue Jul 26 17:14:51 2011
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # input  definitons
 #
-# $Id: inputtags.pm,v 1.292 2011/07/12 12:55:50 christianto Exp $
+# $Id: inputtags.pm,v 1.293 2011/07/26 17:14:51 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -571,7 +571,7 @@
     if ($which eq 'uploadonly' || $which eq 'both') { 
 	$result.=&mt('Submit a file: (only one file per submission)').
 	    ' <br /><input type="file" size="50" name="HWFILE'.
-	    $jspart.'_'.$id.'" /><br />';
+	    $jspart.'_'.$id.'" id="HWFILE'.$jspart.'_'.$id.'" /><br />';
     }
     if ( $which eq 'both') {
 	$result.='<br />'.'<strong>'.&mt('OR:').'</strong><br />';
Index: loncom/homework/structuretags.pm
diff -u loncom/homework/structuretags.pm:1.492 loncom/homework/structuretags.pm:1.493
--- loncom/homework/structuretags.pm:1.492	Mon Jul 25 12:02:45 2011
+++ loncom/homework/structuretags.pm	Tue Jul 26 17:14:51 2011
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA 
 # definition of tags that give a structure to a document
 #
-# $Id: structuretags.pm,v 1.492 2011/07/25 12:02:45 christianto Exp $
+# $Id: structuretags.pm,v 1.493 2011/07/26 17:14:51 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -170,37 +170,154 @@
     return <<"ENDSCRIPT";
 <script type="text/javascript">
 // <![CDATA[
-function file_deletion_check(formname) {
+function file_deletion_check(formname,uploadid) {
     var elemnum = formname.elements.length;
     if (elemnum == 0) {
         return true;
     }
-    var str = new RegExp("^HWFILE.+_delete\$");
-    var delboxes = new Array();
+    var alluploads = new Array();
+    if ((uploadid != '') && (uploadid != undefined)) {
+        alluploads.push(uploadid);
+    } else {
+        var uploadstr = /^HWFILE.+\$/;
+        for (var i=0; i<formname.elements.length; i++) {
+            var id = formname.elements[i].id;
+            if (id != '') {
+                if (uploadstr.test(id)) {
+                    if (formname.elements[i].type == 'file') {
+                        alluploads.push(id);
+                    }
+                }
+            }
+        }
+    }
+    for (var i=0; i<alluploads.length; i++) {
+        var delstr = new RegExp('^'+alluploads[i]+'_\\\\d+_delete\$');
+        var delboxes = new Array();
+        for (var j=0; j<formname.elements.length; j++) {
+            var id = formname.elements[j].id;
+            if (id != '') {
+                if (delstr.test(id)) {
+                    if (formname.elements[j].type == 'checkbox') {
+                        if (formname.elements[j].checked) {
+                            delboxes.push(id);
+                        }
+                    }
+                }
+            }
+        }
+        if (delboxes.length > 0) {
+            if (!confirm("$delfilewarn")) {
+                for (var j=0; j<delboxes.length; j++) {
+                    formname.elements[delboxes[j]].checked = false;
+                }
+                return false;
+            }
+        }
+    }
+    return true;
+}
+// ]]>
+</script>
+ENDSCRIPT
+}
+
+sub file_overwritechk_js {
+    my $overwritewarn = &mt('File(s) you uploaded for your submission will overwrite existing file(s) submitted for this item').'\\n'.
+                      &mt('Continue submission and overwrite the file(s)?');
+    return <<"ENDSCRIPT";
+<script type="text/javascript">
+// <![CDATA[
+function file_overwrite_check(formname,path,multiresp) {
+    var elemnum = formname.elements.length;
+    if (elemnum == 0) {
+        return true;
+    }
+    var alluploads = new Array();
+    var uploaded = new Array();
+    var uploadstr = /^HWFILE.+\$/;
+    var fnametrim = /[^\\/\\\\]+\$/;
     for (var i=0; i<formname.elements.length; i++) {
         var id = formname.elements[i].id;
         if (id != '') {
-            if (str.test(id)) {
-                if (formname.elements[i].type == 'checkbox') {
-                    if (formname.elements[i].checked) {
-                        delboxes.push(id);
+            if (uploadstr.test(id)) {
+                if (formname.elements[i].type == 'file') {
+                    alluploads.push(id);
+                    if ((formname.elements[i].value != undefined) &&
+                        (formname.elements[i].value != '')) {
+                        uploaded.push(id);
                     }
                 }
             }
         }
     }
-    if (delboxes.length > 0) {
-        if (confirm("$delfilewarn")) {
-            return true;
-        } else {
-            for (var j=0; j<delboxes.length; j++) {
-                formname.elements[delboxes[j]].checked = false;
+    for (var i=0; i<alluploads.length; i++) {
+        var delstr = new RegExp("^"+alluploads[i]+"_\\\\d+_delete\$");
+        var delboxes = new Array();
+        for (var j=0; j<formname.elements.length; j++) {
+            var id = formname.elements[j].id;
+            if (id != '') {
+                if (delstr.test(id)) {
+                    if (formname.elements[j].type == 'checkbox') {
+                        delboxes.push(id);
+                    }
+                }
+            }
+        }
+        var overwrites = new Array();
+        if (delboxes.length > 0) {
+            if ((formname.elements[alluploads[i]].value != undefined) &&
+                (formname.elements[alluploads[i]].value != '')) {
+                var filepath = formname.elements[alluploads[i]].value;
+                var newfilename = fnametrim.exec(filepath);
+                if (newfilename != null) {
+                    var filename = String(newfilename);
+                    var nospaces = filename.replace(/\\s+/g,'_');
+                    var nospecials = nospaces.replace(/[^\\/\\w\\.\\-]/g,'');
+                    var cleanfilename = nospecials.replace(/\\.(\\d+\\.)/g,"_\$1");
+                    if (cleanfilename != '') {
+                        var fullpath = path+"/"+cleanfilename;
+                        if (multiresp == 1) {
+                            var partid = String(alluploads[i]);
+                            var subdir = partid.replace(/^HWFILE/,'');
+                            if (subdir != "" && subdir != undefined) {
+                                fullpath = path+"/"+subdir+"/"+cleanfilename;
+                            }
+                        }
+                        for (var k=0; k<delboxes.length; k++) {
+                            if (fullpath == formname.elements[delboxes[k]].value) {
+                                var id = formname.elements[delboxes[k]].id;
+                                if (id != '') {
+                                    if (!formname.elements[delboxes[k]].checked) {
+                                        overwrites.push(id);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (overwrites.length > 0) {
+                if (confirm("$overwritewarn")) {
+                    var delcheck = file_deletion_check(formname,alluploads[i]);
+                    if (delcheck == false) {
+                        return false;
+                    }
+                } else {
+                    for (var n=0; n<overwrites.length; n++) {
+                        formname.elements[overwrites[n]].value = "";
+                    }
+                    return false;
+                }
+            } else {
+                var delcheck = file_deletion_check(formname);
+                if (delcheck == false) {
+                    return false;
+                }
             }
-            return false;
         }
-    } else {
-        return true;
     }
+    return true;
 }
 // ]]>
 </script>
@@ -232,8 +349,43 @@
         $extra_head .= &Apache::lonhtmlcommon::htmlareaselectactive(\%textarea_args);
     }
     my $is_task = ($env{'request.uri'} =~ /\.task$/);
+    my $needs_upload;
     if ($is_task) {
         $extra_head .= &file_delchk_js();
+    } else {
+        if (&Apache::lonnet::EXT("resource.$Apache::inputtags::part.uploadedfiletypes") ne '') {
+            $needs_upload = 1;
+        } else {
+            unless ($env{'request.state'} eq 'construct') {
+                my ($symb)= &Apache::lonnet::whichuser();
+                my $navmap = Apache::lonnavmaps::navmap->new();
+                if (ref($navmap)) {
+                    my $res = $navmap->getBySymb($symb);
+                    if (ref($res)) {
+                        my $partlist = $res->parts();
+                        if (ref($partlist) eq 'ARRAY') {
+                            foreach my $part (@{$partlist}) {
+                                my @types = $res->responseType($part);
+                                my @ids = $res->responseIds($part);
+                                for (my $i=0; $i < scalar(@ids); $i++) {
+                                    if ($types[$i] eq 'essay') {
+                                        my $partid = $part.'_'.$ids[$i];
+                                        if (&Apache::lonnet::EXT("resource.$partid.uploadedfiletypes") ne '') {
+                                            $needs_upload = 1;
+                                            last;
+                                        }
+                                    }
+                                }
+                            }
+                        } 
+                    }
+                }
+            }
+        }
+    }
+    if ($needs_upload) {
+        $extra_head .= &file_overwritechk_js()."\n".
+                       &file_delchk_js();
     }
 
     my %body_args;
@@ -316,7 +468,6 @@
     if (!defined($found{'body'}) && $env{'request.state'} ne 'construct') {
 	$page_start .= &Apache::lonxml::message_location();
     }
-    
     my $form_tag_start;
     if (!defined($found{'form'})) {
 	$form_tag_start='<form name="lonhomework" enctype="multipart/form-data" method="post" action="';
@@ -327,8 +478,13 @@
 	if ($target eq 'edit') {
 	    $form_tag_start.=&Apache::edit::form_change_detection();
 	}
+        my ($symb,$courseid,$udom,$uname)=&Apache::lonnet::whichuser();
+        my ($path,$multiresp) = 
+            &Apache::loncommon::get_turnedin_filepath($symb,$uname,$udom);
         if ($is_task) {
             $form_tag_start .= ' onsubmit="return file_deletion_check(this);"';
+        } elsif ($needs_upload) {
+            $form_tag_start .= ' onsubmit="return file_overwrite_check(this,'."'$path','$multiresp'".');"';
         }
 	$form_tag_start.='>'."\n";
 
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1014 loncom/interface/loncommon.pm:1.1015
--- loncom/interface/loncommon.pm:1.1014	Mon Jul  4 09:24:58 2011
+++ loncom/interface/loncommon.pm	Tue Jul 26 17:14:56 2011
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.1014 2011/07/04 09:24:58 foxr Exp $
+# $Id: loncommon.pm,v 1.1015 2011/07/26 17:14:56 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -9106,6 +9106,113 @@
 
 =pod
 
+=item * &get_turnedin_filepath()
+
+Determines path in a user's portfolio file for storage of files uploaded
+to a specific essayresponse or dropbox item.
+
+Inputs: 3 required + 1 optional.
+$symb is symb for resource, $uname and $udom are for current user (required).
+$caller is optional (can be "submission", if routine is called when storing
+an upoaded file when "Submit Answer" button was pressed).
+
+Returns array containing $path and $multiresp. 
+$path is path in portfolio.  $multiresp is 1 if this resource contains more
+than one file upload item.  Callers of routine should append partid as a 
+subdirectory to $path in cases where $multiresp is 1.
+
+Called by: homework/essayresponse.pm and homework/structuretags.pm
+
+=cut
+
+sub get_turnedin_filepath {
+    my ($symb,$uname,$udom,$caller) = @_;
+    my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb);
+    my $turnindir;
+    my %userhash = &Apache::lonnet::userenvironment($udom,$uname,'turnindir');
+    $turnindir = $userhash{'turnindir'};
+    my ($path,$multiresp);
+    if ($turnindir eq '') {
+        if ($caller eq 'submission') {
+            $turnindir = &mt('turned in');
+            $turnindir =~ s/\W+/_/g;
+            my %newhash = (
+                            'turnindir' => $turnindir,
+                          );
+            &Apache::lonnet::put('environment',\%newhash,$udom,$uname);
+        }
+    }
+    if ($turnindir ne '') {
+        $path = '/'.$turnindir.'/';
+        my ($multipart,$turnin, at pathitems);
+        my $navmap = Apache::lonnavmaps::navmap->new();
+        if (defined($navmap)) {
+            my $mapres = $navmap->getResourceByUrl($map);
+            if (ref($mapres)) {
+                my $pcslist = $mapres->map_hierarchy();
+                if ($pcslist ne '') {
+                    foreach my $pc (split(/,/,$pcslist)) {
+                        my $res = $navmap->getByMapPc($pc);
+                        if (ref($res)) {
+                            my $title = $res->compTitle();
+                            $title =~ s/\W+/_/g;
+                            if ($title ne '') {
+                                push(@pathitems,$title);
+                            }
+                        }
+                    }
+                }
+                my $maptitle = $mapres->compTitle();
+                $maptitle =~ s/\W+/_/g;
+                if ($maptitle ne '') {
+                    push(@pathitems,$maptitle);
+                }
+                unless ($env{'request.state'} eq 'construct') {
+                    my $res = $navmap->getBySymb($symb);
+                    if (ref($res)) {
+                        my $partlist = $res->parts();
+                        my $totaluploads = 0;
+                        if (ref($partlist) eq 'ARRAY') {
+                            foreach my $part (@{$partlist}) {
+                                my @types = $res->responseType($part);
+                                my @ids = $res->responseIds($part);
+                                for (my $i=0; $i < scalar(@ids); $i++) {
+                                    if ($types[$i] eq 'essay') {
+                                        my $partid = $part.'_'.$ids[$i];
+                                        if (&Apache::lonnet::EXT("resource.$partid.uploadedfiletypes") ne '') {
+                                            $totaluploads ++;
+                                        }
+                                    }
+                                }
+                            }
+                            if ($totaluploads > 1) {
+                                $multiresp = 1;
+                            }
+                        }
+                    }
+                }
+            } else {
+                return;
+            }
+        } else {
+            return;
+        }
+        my $restitle=&Apache::lonnet::gettitle($symb);
+        $restitle =~ s/\W+/_/g;
+        if ($restitle eq '') {
+            $restitle = ($resurl =~ m{/[^/]+$});
+            if ($restitle eq '') {
+                $restitle = time;
+            }
+        }
+        push(@pathitems,$restitle);
+        $path .= join('/', at pathitems);
+    }
+    return ($path,$multiresp);
+}
+
+=pod
+
 =back
 
 =head1 CSV Upload/Handling functions


More information about the LON-CAPA-cvs mailing list