Add a background image form to a Drupal 7 theme setting form

Profile picture for user Phil Frilling
By Phil Frilling, 27 November, 2012
Recently I needed to have a dynamically changing background image for a Drupal 7 theme I was working on. Allowing the user to change this background image directly from theme's settings page.

How to add a dynamic background image to a Drupal theme

  1. The first step is to add a file named 'theme-settings.php' to your theme.
  2. Next, we need to add our background image form. I came up with the code below based on the standard logo form that is on by default for all themes:
    
    /**
     * Implements hook_form_FORM_ID_alter().
     *
     * @param $form
     *   The form.
     * @param $form_state
     *   The form state.
     */
    function MYTHEME_form_system_theme_settings_alter(&$form, &$form_state) {
      
      $form['background_image'] = array(
        '#type' => 'fieldset',
        '#title' => t('Background image'),
      );
      
      $form['background_image']['default_background_image'] = array(
        '#type' => 'checkbox',
        '#title' => t('Use the default background image'),
        '#default_value' => theme_get_setting('default_background_image'),
      );
      
      $form['background_image']['settings'] = array(
        '#type' => 'container',
        '#states' => array(
          // Don't show any extra forms when none is selected.
          'invisible' => array(
            ':input[name="default_background_image"]' => array('checked' => TRUE),
          ),
        ),
      );
      
      $form['background_image']['settings']['background_image_upload'] = array(
        '#type' => 'file',
        '#title' => t('Upload a new background image'),
        '#maxlength' => 40,
        '#description' => t('Upload a new background image for this theme. 1920x1080.') . '' . theme('image', array('path' => image_style_url('thumbnail', theme_get_setting('background_image_path')))) . '',
      );
    
      $form['#validate'][] = 'MYTHEME_form_system_theme_settings_validate';
      $form['#submit'][] = 'MYTHEME_form_system_theme_settings_submit';
    
    }
    
  3. The next step is to handle the file upload with our custom validate and submit function (I borrowed the file handling from the noggin module).
    
    function MYTHEME_form_system_theme_settings_validate($form, &$form_state){
      // Handle file uploads.
      $validators = array('file_validate_is_image' => array());
      // Check for a new uploaded logo.
      $file = file_save_upload('background_image_upload', $validators);
      if (isset($file)) {
        // File upload was attempted.
        if ($file) {
          // Put the temporary file in form_values so we can save it on submit.
          $form_state['values']['background_image_upload'] = $file;
        }
        else {
          // File upload failed.
          form_set_error('background_image_upload', t('The background image could not be uploaded.'));
        }
      }
    }
    
    function MYTHEME_form_system_theme_settings_submit($form, &$form_state){
      $values = $form_state['values'];
      // If the user uploaded a new header image, save it to a permanent location
      if ($file = $values['background_image_upload']) {
        unset($values['background_image_upload']);
        $filename = file_unmanaged_copy($file->uri);
        $form_state['values']['background_image_path'] = $filename;
      }
    }
    
  4. The last step is to set your new background image as a variable in your tpl files. To do this, we implement theme_preprocess_page() in our template.php file:
    
    function MYTHEME_preprocess_page(&$vars) {
      
        if($bg = theme_get_setting('background_image_path')) {
         $vars['background_image'] = theme('image', array('path' => file_create_url($bg))); 
        } 
        else {
          $vars['background_image'] = theme('image', array('path' => base_path() . drupal_get_path('theme', 'MYTHEME') . '/images/default_background_image.jpg'));
        }
    }
    
Done!