I'm trying to build a theme that will require unmanaged files, ie images, and handle the choosing of those in the theme settings. 

I am therefore doing this in the theme settings file:

$form['images']['common']['header'] = array(

'#name' => 'header_image',

'#type' => 'file',

'#title' => t('Header image'),

'#title_display' => 'invisible',

'#size' => 22,

'#prefix' => '<h4 class="settings-header">Header Image:</h4>',

'#description' => t('Upload a file, allowed extensions: jpg, jpeg, png, gif. Choose the highest resolution Landscape image.'),

'#weight' => -9,

);

 

But when I submit the image, the form_state value for the image field is empty. I've checked the temp storage, and the file is not being uploaded there. Other images uploaded, eg in creation of nodes, work fine.

Most helpful answers

Hi onyx. The file FAPI type is a "primitive" type that doesn't get processed and therefore is not included in $form_state['values']. It's used by other types to move the file to the correct location, etc, etc (all the processing).

You CAN actually get the file in your submit handlers. For example, these are the form builder and submit handler:

// Form builder.
function testing_stuff_test_file($form, &$form_state) {
  $form['a_file'] = array(
    '#title' => 'A file',
    '#type' => 'file',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit'
  );
  return $form;
}
// Submit handler
function testing_stuff_test_file_submit($form, &$form_state) {
  dpm($form_state['values']); // <--- This will NOT contain the file information
  dpm($_FILES); // <--- This superglobal variable will contain an array with the file information
}

The superglobal variable $_FILES is an array that contains the following:

array (
  'files' => 
  array (
    'name' => 
    array (
      'a_file' => 'tenutoweb-registrations_6.csv',
    ),
    'full_path' => 
    array (
      'a_file' => 'TenutoWeb-registrations (6).csv',
    ),
    'type' => 
    array (
      'a_file' => 'text/csv',
    ),
    'tmp_name' => 
    array (
      'a_file' => '/Applications/MAMP/tmp/php/phpZq4TsJ',
    ),
    'error' => 
    array (
      'a_file' => 0,
    ),
    'size' => 
    array (
      'a_file' => 62360,
    ),
    'orig_name' => 
    array (
      'a_file' => 'TenutoWeb-registrations (6).csv',
    ),
  ),
)

The most important bit here is: /Applications/MAMP/tmp/php/phpZq4TsJ THAT is a temporary file that is stored in the tmp folder of your site. Within the submit handler, you can do whatever you want with it, such as copy it to a different location and rename it.

Be aware that the temporary file gets deleted as soon as the page request is completed!

Comments

Refactoring the code to use a Managed file works. But this is not optimal. Why can't a theme settings form use unmanaged files on submit? The problem with being managed is that they are not as easily transferable between installations, as there needs to be a database entry, whereas unmanaged is merely copy folder and go.

Hi onyx. The file FAPI type is a "primitive" type that doesn't get processed and therefore is not included in $form_state['values']. It's used by other types to move the file to the correct location, etc, etc (all the processing).

You CAN actually get the file in your submit handlers. For example, these are the form builder and submit handler:

// Form builder.
function testing_stuff_test_file($form, &$form_state) {
  $form['a_file'] = array(
    '#title' => 'A file',
    '#type' => 'file',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit'
  );
  return $form;
}
// Submit handler
function testing_stuff_test_file_submit($form, &$form_state) {
  dpm($form_state['values']); // <--- This will NOT contain the file information
  dpm($_FILES); // <--- This superglobal variable will contain an array with the file information
}

The superglobal variable $_FILES is an array that contains the following:

array (
  'files' => 
  array (
    'name' => 
    array (
      'a_file' => 'tenutoweb-registrations_6.csv',
    ),
    'full_path' => 
    array (
      'a_file' => 'TenutoWeb-registrations (6).csv',
    ),
    'type' => 
    array (
      'a_file' => 'text/csv',
    ),
    'tmp_name' => 
    array (
      'a_file' => '/Applications/MAMP/tmp/php/phpZq4TsJ',
    ),
    'error' => 
    array (
      'a_file' => 0,
    ),
    'size' => 
    array (
      'a_file' => 62360,
    ),
    'orig_name' => 
    array (
      'a_file' => 'TenutoWeb-registrations (6).csv',
    ),
  ),
)

The most important bit here is: /Applications/MAMP/tmp/php/phpZq4TsJ THAT is a temporary file that is stored in the tmp folder of your site. Within the submit handler, you can do whatever you want with it, such as copy it to a different location and rename it.

Be aware that the temporary file gets deleted as soon as the page request is completed!

Thanks mate, have been looking at that before you posted. However I am still stumped; my $_FILES global is not correctly formed, as yours appears to be, and file_save_upload requires; my dpm($_FILES) at form submit:

Note the complete absence of the two top array keys required?  

( files, name ), from core/includes/file.inc file_save_upload Now of course I could fudge it in my code to put those back, but why are they gone... ??

It's beginning to look like the issue is that the theme-settings.php file is a poor cousin to a module in that the full FAPI is not available; validate and error handling also being at a loss ( I tried to add a validate to check the in-between phase ), so maybe that is why $_FILES is also being half-written. Plan D: move my code and logic into a module that purports to be for the themeing layer, so that the administrator can change images and CSS in the front end with ease.