I'm developing a theme that it requires to have a header image on the front page, so I have this.

casper.theme

function casper_form_system_theme_settings_alter(&$form, &$form_state) {

$form['theme_extra']['front_page_background_image'] = array(
    '#type' => 'managed_file',
    '#title' => 'Front Page Background Image',
    '#description' => 'Add background image for the front page',
    '#required' => FALSE,
    '#weight' => -4,
    '#upload_location' => file_default_scheme() . '://theme/backgrounds/',
    '#default_value' => theme_get_setting('front_page_background_image' , 'casper'),
    '#upload_validators' => array(
        'file_validate_extensions' => array('gif png jpg jpeg'),
    ),
 );
}

However, after it, while the file been missing and after some reading, I find out that is because managed_file does not save your image permanent.

There are similar questions:

How can I save my image permanently?

The way it was done in Drupal 7 was that you wrote a function for hook_form_submit where you would

// Get the File ID (fid).
$fid = $form_status['values']['managed_file_field'];

// Load the file.
$file = file_load($fid);

// Set the status to permanent.
$file->status = FILE_STATUS_PERMANENT;

// Finally save the file.
$file->save();

You can read more about this with a great Drupal 7 example here. I'm sure there's something similar on Drupal 8. You'll just need to register a submit handler for the form. Take a look at the docs for managed_file if you want to go that route. here for it.

I have created a method that does exactly this. I can confirm that it does indeed work.

public static function saveFile($fid, $moduleName, $fileType){

  if(isset($fid) && is_string($fid)){

    /**
     * @var $file File
     */
    $file = File::load($fid);

    // save the file
    /**
     * @var $file_usage DatabaseFileUsageBackend
     */
    $file_usage = \Drupal::service('file.usage');
    $file_usage->add($file, $moduleName, $fileType, 1); // or $themeName

    return true;
  }

  return false;
}
  • Hey Adrian, this seem like is specify to a module and I'm trying to use it with a theme. In order for me to give you the bounty you need to show using it snipped of code in the question. =) So how can I use that method with the snipped of code in my question ? – darol100 Jan 24 '16 at 21:32
  • 1
    I think you can still specify submit callbacks in the $form array that you have. Such as $form['#submit'][] = 'casper_form_submit', and then you could do something similar to the above. – mradcliffe Jan 26 '16 at 20:06

While I had thought that you could include a submit callback string, it looks like the theme file is not included when the form is submitted. This can be worked around dirty by making the submit callback a function in the form callback. Closures won't work because they cannot be serialized.

// @todo Please fix me, Drupal-Core Kenowbi!
$submit = function($form, \Drupal\Core\Form\FormStateInterface $form_state) {
  $values = $form_state->getValue('front_page_background_image', []);
  if ($values) {
    $fid = $values[0];
    $file = \Drupal\file\Entity\File::load($fid);
    $file_usage = \Drupal::service('file.usage');
    $file_usage->add($file, 'casper', 'theme', 1);
  }
};

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

Realistically this seems like a good case for a core fix or a contrib module that would provide a way for themes to call their own submit callbacks.

Drupal 7

I used many places file_managed to save my files. Please find the below code in my bartik theme, working fine:

bartik.info

settings[front_page_background_image] = headerimage.png 

template.php

function bartik_form_system_theme_settings_alter(&$form, &$form_state) {

$form['theme_extra']['front_page_background_image'] = array(
    '#type' => 'managed_file',
    '#title' => 'Front Page Background Image',
    '#description' => 'Add background image for the front page',
    '#required' => FALSE,
    '#weight' => -4,
    '#upload_location' => file_default_scheme() . '://theme/backgrounds/',
    '#default_value' => theme_get_setting('front_page_background_image' , 'bartik'),
    '#upload_validators' => array(
        'file_validate_extensions' => array('gif png jpg jpeg'),
    ),
 );

}

page.tpl.php

$file =  file_load(theme_get_setting('front_page_background_image')); 

$image = image_load($file->uri); 

$content = array(
        'file' => array(
            '#theme' => 'image_style', 
            '#style_name' => 'large',
            '#path' => $image->source, 
            '#width' => $image->info['width'], 
            '#height' => $image->info['height'],
        ),
        );
echo drupal_render($content); 
  • This question is for Drupal 8. And your answer if for Drupal 7. – darol100 Jan 29 '16 at 6:54

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.