6 hours

Managed file upload in Drupal theme settings

So you want to add a managed file field to your theme settings to allow for an additional logo, great! Using FAPI and a theme-settings.php file it will be a piece of cake.  Not so fast….

The sticking point here is that a managed file once uploaded has to have its status changed to 1 to make it persist.  If you don’t change that status then cron will come along and merrily remove it after 6 hours, leaving you with a broken image on your theme.

Add the field to the theme settings in the usual way

MYTHEME_form_system_theme_settings_alter(&$form, $form_state) {
  $form['secondary_logo'] = array(
    '#title' => t('Secondary logo'),
    '#description' => t('A description'),
    '#type' => 'managed_file',
    '#upload_location' => 'public://secondary-logo/',
    '#upload_validators' => array(
      'file_validate_extensions' => array('gif png jpg jpeg'),
    ),
    '#default_value' => theme_get_setting('secondary_logo'),
  );
}

This gets the field on the settings screen, but doesn’t allow you to persist by altering the status.  On any normal form you could use hook_form_submit(), but unfortunately this does not work with theme settings.

The fix is to add a custom submit handler to the form, but due to a bug in the theme settings system you need to specify your theme settings file as a dependency.  Add the following to the MYTHEME_form_system_theme_settings_alter function

$form['#submit'][] = 'MYTHEME_settings_form_submit';

// Get all themes.
$themes = list_themes();
// Get the current theme
$active_theme = $GLOBALS['theme_key']
$form_state['build_info']['files'][] = str_replace("/$active_theme.info", '', $themes[$active_theme]->filename) . '/theme-settings.php'

It is important to note that as you are now altering the $form_state variable you need to add an & to the parameter so that it is passed by reference.

Now you can create the submit handler to actually change the status of the file.

function MYTHEME_settings_form_submit(&$form, $form_state) {
$image_fid = $form_state['values']['secondary_logo'];
  $image = file_load($image_fid);
  if (is_object($image)) {
    // Check to make sure that the file is set to be permanent.
    if ($image->status == 0) {
      // Update the status.
      $image->status = FILE_STATUS_PERMANENT;
      // Save the update.
      file_save($image);
      // Add a reference to prevent warnings.
      file_usage_add($image, 'MYTHEME', 'theme', 1);
     }
  }
}

And there you have it, you should be able to keep hold of your file for longer than 6 hours.

Disclaimer

I was put on the right track to this solution and have used code from this stack overflow question.

3 thoughts on “Managed file upload in Drupal theme settings”

  1. Hello Thank you for this. Altough there are some errors here it pointed me in the irhgt direction.

    In MYTHEME_form_system_theme_settings_alter you dont have the reference sign in here (but nice that you mention this is important it is what was missing on my part)

    Next to $form['#submit'][] = ‘MYTHEME_settings_form_submit';

    There are a couple of “)” and “;” missing. Might be a bad copy paste.

    Anyway saved my day! this addresses btw a serious bug in Drupal core system https://drupal.org/node/1862892 : “When theme-settings.php has a managed_file field and a submit callback, ” Call to undefined function” error is thrown”

    I am posting a reply here maybe this helps someone in the future;)

    best regards,
    Joao

  2. Both of you are legends, thanks for this! So for others, your function should be:
    MYTHEME_form_system_theme_settings_alter(&$form, &$form_state)

    Cheers
    Shaun

Leave a Reply