Download & Extend

$source parameter in file_save_upload() not work as expected when field is in a fieldset with #tree set to TRUE

Project:Drupal core
Version:6.x-dev
Component:file system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:needs work

Issue Summary

With a form of the following type (assmuming enctype is set correctly):

$form['foo'] = array(
  '#type' => 'fieldset',
  '#title' => 'foo',
  '#tree' => TRUE,   
);
$form['foo']['bar'] = array(
  '#type' => 'file',
  '#title' => 'bar',
}

There is no way to use form_check_upload or file_save_upload as those functions only check $_FILES['edit']['name'][$source] but the form will generate $_FILES['edit']['name']['foo']['bar'].

Comments

#1

Title:file_check_upload and file_save_upload don't work when #tree is TRUE» When #tree is TRUE causes problems with file_check_upload() and file_save_upload()

Anyone else had this problem? Need confirmation, because it seems strange to the presence of this bug.

Thanks.

#2

I can confirm this, had to use flat fieldset for files.

#3

I also had this problem. I had to use markup tags in the form to display fields in a fieldset.

explained here http://drupal.org/node/83506

#4

Title:When #tree is TRUE causes problems with file_check_upload() and file_save_upload()» file_save_upload() incompatible with #tree = TRUE
Version:4.7.3» 6.3

This issue remains in Drupal 6 - is there a reason not to support file_save_upload() in forms with #tree=TRUE, other than no one has offered a patch yet?

Thanks.

#5

Status:active» closed (fixed)

Actually, never mind... Looking closer at how $_FILES is arranged I see that it does work, you just have to pass the fieldset name in $source.

Thanks.

#6

Title:file_save_upload() incompatible with #tree = TRUE» $source parameter in file_save_upload() when field is in a fieldset
Version:6.3» 6.4
Category:bug report» support request
Status:closed (fixed)» active

Can anyone confirm this is working for them? And if so, how they specified the $source parameter in file_save_upload(). I have a form with two upload fields as follows:

$form['photos']['photo01'] = array(
'#type' => 'file',
'#title' => t('Photo 1'),

);

$form['photo02'] = array(
'#type' => 'file',
'#title' => t('Photo 2'),

);

I put the second in just to make sure the form was okay.

$file = file_save_upload('photo01', $validators, $dest, FALSE) produces a $file object with just "0" but
$file = file_save_upload('photo02', $validators, $dest, FALSE) works fine.

Yet in system.admin.inc, which has an upload field for the site logo in a fieldset, $file = file_save_upload('logo_upload', array('file_validate_is_image' => array())) also works.

Is there something else I need to declare so the function knows the field name is inside a fieldset?

#7

Status:active» fixed

Like mikeryan said; if you use a file field inside a field setting you use the fieldset name in stead of the file field name.
So in your case that would mean $file = file_save_upload('photos', $validators, $dest, FALSE) would get you photo1.

You will run into problems if you try to use more than one file field inside a fieldset. In that case the last file field is returned.

- Arie

#8

Status:fixed» closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

#9

Title:$source parameter in file_save_upload() when field is in a fieldset» $source parameter in file_save_upload() not work as expected when field is in a fieldset with #tree set to TRUE
Version:6.4» 6.12
Category:support request» bug report
Status:closed (fixed)» active

I just got here while porting a module which uses a file field inside a fieldset with #tree set to true. Not sure if this issue should be closed.

- What happens if we have more than one file field inside a fieldset with #tree set to true? Probably it won't work, thus it's a bug, unless it's a known issue, which should be documented somewhere in the API, but at least leaving it open leaves some probability of looking into this issue.

#10

This is a Q&D on how we did it with system_settings_form on Drupal 6.12

In ours we did this with our fieldset:

//function yourform

    $form['exhibitor']      = array(
        '#type'             => 'fieldset',
        '#title'            => t('Exhibitor Settings'),
        '#collapsible'      => true,
        '#collapsed'        => false
    );


    $file = variable_get('event_registration_exhibitor_floor_plan','');
    $form['#attributes'] = array('enctype' => "multipart/form-data");
    $form['exhibitor']['event_registration_exhibitor_floor_plan']   = array(
        '#type'             => 'file',
        '#title'            => t('Floor Plan'),
        '#description'      => t('Upload the floorplan for the event this year. If you are changing the floorplan you will need <a href="taylor@liquidfire.com">LiquidFire</a> to make the floorplan clickable.'),
    );
   
    $form['exhibitor']['floorplan']['preview'] = array(
        '#value' => theme('image',$file->filepath)
    );

//rest of form
return system_settings_form($form);


//then in function yourform_validate

        $dest = variable_get('file_directory_path', '').'/floorplans';
   
        // set error is file was not uploaded
        if ( $file = file_save_upload( 'event_registration_exhibitor_floor_plan', array(), $dest, false ) ) {
            drupal_set_message('Success! Your floorplan has been uploaded.','status');
        } else {
            drupal_set_message('Sorry, your floorplan has not been uploaded. Please try again.','error');
            return;
        }
      
        // set files to form_state, to process when form is submitted
        $form_state['values']['event_registration_exhibitor_floor_plan'] = $file; 

#11

Version:6.12» 6.15
Status:active» needs review

Patch was made from Drupal 6.15, it adds support for #tree and file form elements inside tree. You can use it just like you set error in validation function for elements inside tree:

<?php
 
//Form definition:
 
$form = array(
   
'#attributes' => array(
     
'enctype' => 'multipart/form-data',
    ),

   
'fisrt' => array(
     
'#tree' => TRUE,
     
'second' => array(
       
'my-upload' => array(
         
'#type' => 'file',
         
'#title' => t('Upload inside tree'),
        ),
      ),
    )
  );
 
 
//Validation/submission:
 
$file = file_save_upload('first][second][my-upload');
?>

I don't think it can break additional modules, because before it files with #tree didn't work at all.

AttachmentSizeStatusTest resultOperations
drupal-6.15-tree-file-fix.patch4.49 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch drupal-6.15-tree-file-fix.patch.View details | Re-test

#12

Status:needs review» needs work

The last submitted patch, drupal-6.15-tree-file-fix.patch, failed testing.

#13

New patch, made from CVS checkout of DRUPAL-6

AttachmentSizeStatusTest resultOperations
drupal-6.15-tree-file-fix-cvs.patch4.97 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch drupal-6.15-tree-file-fix-cvs.patch.View details | Re-test

#14

Status:needs work» needs review

Sorry, didn't change status...

AttachmentSizeStatusTest resultOperations
drupal-6.15-tree-file-fix-cvs.patch4.97 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch drupal-6.15-tree-file-fix-cvs_0.patch.View details | Re-test

#15

Status:needs review» needs work

The last submitted patch, drupal-6.15-tree-file-fix-cvs.patch, failed testing.

#16

Version:6.15» 6.x-dev
Status:needs work» needs review

#17

#14: drupal-6.15-tree-file-fix-cvs.patch queued for re-testing.

#18

New patch, fixed bug with filename

AttachmentSizeStatusTest resultOperations
drupal-6.15-tree-file-fix-cvs-2.patch5.08 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch drupal-6.15-tree-file-fix-cvs-2_1.patch.View details | Re-test

#19

Subscribing

#20

Does anyone know what is wrong with testing? Patch has status "Test request sent" since 02/26/2010 !!!

#21

#22

I encountered the same problem.
I wrote a module for a client which defines a new custom content type (due to various reasons CCK is not suitable). This content type also includes a number of images which (for workflow reasons) are contained in a fieldset named 'images'. When adding multiple images (user may add additional images by clicking AHAH button 'add another image') Drupal only saves the last entered image in fieldset.

However, by just giving the form element a proper name, I was able to get around this behaviour:

<?php
function mymodule_form(&$node, $form_state) {
...
 
$form['images'] = array(
       
'#type' => 'fieldset',
       
'#title' =>  t('Images'),
       
'#weight' => 0
 
);
...
  for (
$delta = 0; $delta < $images_count; $delta++)
  {
   
$form['images']['images_wrapper']['image'][$delta] = _mymodule_images_form($delta, $images_list[$delta]);
  }
}

function
_mymodule_images_form($delta, $value = array(), $votes = 0) {
...
 
$form[$delta]['image_upload'] = array(
       
'#type' => 'file',
       
'#title' => t('Upload image'),
   
'#parents' => array('images', $delta, 'image_upload'),
       
'#description' => t('Select an image file (.jpg, .gif, .png)'),
   
'#name' => 'files[images]['.$delta.'][image_upload]'
 
);
...
}
?>

Upon saving an image I can recall these array paths:

<?php
 
if ($file = file_save_upload('images]['.$delta.'][image_uploads', $validators, file_directory_path() . '/uploads/images')) {
?>

While this works for me, I'm not sure if it is the "Drupal" way or could break anything else. But as I understand, Dmitriy.trt's patch tries to shift this into an automated service (the patch didn't work for me, though).

Regards,
Paul

Edit: Seems I got something messed up with the patches. When it stopped working I tried to investigate further and am now pretty sure what was going on.
When applying the patch, it didn't work for me which was probably the fault of my modules code. Anyhow after removing the patch I wrote my "workaround" above and it worked for me. However, my FTP programme failed on uploading the original file.inc so my code only works if I apply the patch to file.inc. I didn't patch form.inc but used my code instead.
Anyway, the support of file uploads within fieldsets should be provided by core.

#23

So, it has been almost four years since this bug was first reported. This is just disappointing.

#24

Status:needs review» needs work

The last submitted patch, drupal-6.15-tree-file-fix-cvs-2.patch, failed testing.

#25

Still counting... issue is not fixed. Any updates on the patch?

#26

same problem, give up...

#27

I'm attempting to use the fix from #22, but having trouble with it. For now, I am hardcoding the #name and #parents values to be similar to the ones shown above, once I get it working I'll change it to a dynamic name.
My form gets declared like this:

<?php
$form
['folders'][$projectfolder->name][$graphic->filepath.'_upload'] = array(
         
'#type' => 'file',
         
'#field_prefix' => 'Upload: ',
         
'#description' => 'Upload a new branded graphic to replace the stock graphic',
         
'#name' => 'files[images][delta][image_upload]', //TODO
         
'#parents' => array('images', 'delta', 'image_upload'), //TODO
);
?>

And I try to retrieve the file like this:

<?php
$file
= file_save_upload('images][delta][image_upload', array(), file_directory_path() . '/uploads/images');
?>

When I pick an image to upload and hit submit, the resulting [files] array looks like this:

<?php
[files] => Array
                (
                    [
images] => Array
                        (
                            [
delta] => Array
                                (
                                    [
image_upload] => icon.png
                               
)

                        )

                )
?>

I've tried lots of variations on this, but file_save_upload always seems to return 0. What am I doing wrong?

If more detail on the issue would be helpful, check my post over here: http://drupal.stackexchange.com/questions/6059/uploading-from-within-fie...

nobody click here