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.
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
This is exactly what I was missing out on. Persisting a field is not something I came up with myself. Thanks for sharing thoughts and code!
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
Thanks a lot for this.
It works perfectly, but after changing status file couldn’t be removed from folder and DB 🙁
When I try this, I get “Parse error: syntax error, unexpected ‘$form_state’ (T_VARIABLE)” for line 125 of my theme-settings.php file. Line 125 is:
$form_state[‘build_info’][‘files’][] = str_replace(“/$active_theme.info”, ”, $themes[$active_theme]->filename) . ‘/theme-settings.php’
Any thoughts?
Never mind. The code was just missing semicolons on that line and the line before it. I should have picked up on that from joaogarin’s comment.
Cheers, I have amended the code to prevent that from happening to anyone one else.
Hi, I’ve tried using your code, as it seems like it will solve the problem I’m running into.
I can’t get it to work. First, there is still a semicolon missing at the end of this line:
$form_state[‘build_info’][‘files’][] = str_replace(“/$active_theme.info”, ”, $themes[$active_theme]->filename) . ‘/theme-settings.php’
Even if I add the semicolon, the code fails with the same error (undefined function).
Is this working for anyone?
How can I get the path to the uploaded file into a twig variable?
For those of you looking into how to get the path of your image you can use the following:
$secondary_logo = file_create_url(file_load(theme_get_setting(‘secondary_logo’))->uri);