Last updated February 16, 2013. Created by JohnAlbin on September 23, 2007.
Edited by chrisjlee, iva2k, drupalshrek, Spleshka. Log in to edit this page.

Drupal 6
In the Drupal administration section, each theme has its own settings page at admin/build/themes/settings/themeName. And this page has a form with standard settings like “Logo image settings” and “Shortcut icon settings.”

Drupal 7
Drupal 7 uses admin/appearance/settings/themeName.

In Drupal 6 and beyond, theme authors can now customize this page by adding additional settings to the form. In Drupal 5, theme authors and theme users will have to install the Theme Settings API module (5.x-2.1 or later) before being able to use the method described below.

Adding form widgets for your custom theme settings (Drupal 6 only)

First, create a theme-settings.php file in your theme directory and add a themeName_settings() or themeEngineName_settings() function. The themeEngineName_settings() form is discouraged since it can lead to fatal errors when two functions with the same name are defined in your Drupal installation. The function should use the Forms API to create the additional form widgets.

For example: to add settings to the Garland theme, a garland_settings() or phptemplate_settings() function would be placed in the theme’s theme-settings.php file.

Directly modifying Garland or Minnelli is strongly discouraged, since they are used for the install and upgrade process.

If a user has previously saved the theme settings form, the saved values will be passed to this function in the $saved_settings parameter. The widgets to add to the form should be returned as a Forms API array.

The comments in the following example explain the details:

<?php
// An example themes/garland/theme-settings.php file.
/**
* Implementation of THEMEHOOK_settings() function.
*
* @param $saved_settings
*   array An array of saved settings for this theme.
* @return
*   array A form array.
*/
function garland_settings($saved_settings) {
 
/*
   * The default values for the theme variables. Make sure $defaults exactly
   * matches the $defaults in the template.php file.
   */
 
$defaults = array(
   
'garland_happy' => 1,
   
'garland_shoes' => 0,
  );
 
// Merge the saved variables and their default values
 
$settings = array_merge($defaults, $saved_settings);
 
// Create the form widgets using Forms API
 
$form['garland_happy'] = array(
   
'#type' => 'checkbox',
   
'#title' => t('Get happy'),
   
'#default_value' => $settings['garland_happy'],
  );
 
$form['garland_shoes'] = array(
   
'#type' => 'checkbox',
   
'#title' => t('Use ruby red slippers'),
   
'#default_value' => $settings['garland_shoes'],
  );
 
// Return the additional form widgets
 
return $form;
}
?>

Note that theme authors can create complex, dynamic forms using advanced Forms API (auto-completion, collapsible fieldsets) and the JavaScript library, jQuery.

Getting the settings’ values in your theme files

In order to retrieve the settings in the theme’s template.php or .tpl.php files, simply use theme_get_setting('varname'). See the Drupal API for details: http://api.drupal.org/api/6/function/theme_get_setting

For example:

<?php
$happy
= theme_get_setting('garland_happy');
?>

Initializing the default values

Since we can’t guarantee that a user will ever go to the admin/build/themes/settings/themeName page, we have to ensure that the default values for our custom settings get initialized.

The theme settings variables aren’t set until we submit the admin/build/themes/settings/themeName form for the first time, so in our template.php file we need to check whether the variables are set or not. If they aren’t set, we need to set them to the default values. We accomplish that by retrieving one of the variables and seeing if it is null. If it is null, we save the defaults using variable_set() and then force the refresh of the settings in Drupal’s internals using theme_get_setting('', TRUE).

Add the following code near the top of your template.php file:

<?php
/*
* Initialize theme settings
*/
if (is_null(theme_get_setting('garland_happy'))) {  // <-- change this line
 
global $theme_key;
 
/*
   * The default values for the theme variables. Make sure $defaults exactly
   * matches the $defaults in the theme-settings.php file.
   */
 
$defaults = array(             // <-- change this array
   
'garland_happy' => 1,
   
'garland_shoes' => 0,
  );
 
// Get default theme settings.
 
$settings = theme_get_settings($theme_key);
 
// Don't save the toggle_node_info_ variables.
 
if (module_exists('node')) {
   
// NOTE: node_get_types() is renamed to node_type_get_types() in Drupal 7
   
foreach (node_type_get_types() as $type => $name) {
      unset(
$settings['toggle_node_info_' . $type]);
    }
  }
 
// Save default theme settings.
 
variable_set(
   
str_replace('/', '_', 'theme_'. $theme_key .'_settings'),
   
array_merge($defaults, $settings)
  );
 
// Force refresh of Drupal internals.
 
theme_get_setting('', TRUE);
}
?>

Note that the variable name “garland_happy” in the first line of the above code would be replaced with a variable name from your custom theme settings and the $defaults array would need to be copied from your theme-settings.php file.

Adding additional settings to a new version of your theme

After you have released a 1.0 version of your theme, you will eventually want to add some additional custom settings to the 2.0 version. The process is mostly straight-forward. But pay close attention to the initialization code in the third step:

  1. In your theme-settings.php file, add the new settings to the $defaults and $form variables.
  2. In your template.php file, add the settings to the $defaults variable in the Initialize theme settings code.
  3. In your template.php file, update the initialization code to check for the existence of one of your new settings. For example, if you added several settings, including a garland_slippers setting, you would change the first line of the Initialize theme settings code to read:
    if (is_null(theme_get_setting('garland_slippers'))) {

This will ensure that the defaults for your newly-added custom settings get added to the saved values of the old custom settings.

Drupal 7

In Drupal 7, themes can more flexibly modify the entire theme settings form. In a theme’s theme-settings.php, themes should now use a THEMENAME_form_system_theme_settings_alter(&$form, $form_state) function. This gives the same power to themes that modules have if they use hook_form_system_theme_settings_alter(). See the “Forms API Quickstart Guide” and “Forms API Reference” on http://api.drupal.org/api/7, as well as the hook_form_FORM_ID_alter() docs to learn the full flexibility of Forms API. Note that themes can no longer use the phptemplate_ prefix to the function; you’ll need to use the actual name of your theme as the prefix.

Here’s an example if you had a “foo” theme and wanted to add a textfield whose default value was “blue bikeshed”:

<?php
function foo_form_system_theme_settings_alter(&$form, $form_state) {
 
$form['foo_example'] = array(
   
'#type'          => 'textfield',
   
'#title'         => t('Widget'),
   
'#default_value' => theme_get_setting('foo_example'),
   
'#description'   => t("Place this text in the widget spot on your site."),
  );
}
?>

In order to set the default value for any form element you add, you’ll need to add a simple line to your .info file: settings[SETTING_NAME] = DEFAULT_VALUE. For our foo theme, you’d need to edit the foo.info file and add this line:

settings[foo_example] = blue bikeshed

In any of your theme’s PHP files, you can retrieve the value the user set by calling:

<?php
$foo_example
= theme_get_setting('foo_example');
?>

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

The text says:

The themeEngineName_settings() form is preferred since it allows others to more easily create derivative themes based on your theme.

Is this really correct? What about sub-themes. If they want to implement their own settings and follow this advice, they will produce a function name conflict. I think the sentence should read

Use themeEngineName_settings() for base themes and themeName_settings() for derived themes.

In Drupal 5 you may have wanted to access theme-specific variables in _phptemplate_variables(). That has been deprecated, and the Drupal 6 way of passing or modifying theme $variables (variables available to your templates) is through theme preprocess functions.

.. just cross-referencing here, because this is the page I thought this information would be on :-)

.dan.

I'm working with theme-settings.php and am seeking for a way to validate these settings.

I tried using something like phptemplate_settings_validate() but this does not work for me.

I also tried to use $form['#validate'], but this doesn't seem to work either.

Do anybody know how to perform validation on theme specific settings?

It would be nice to have the same validation process we have with the standard Forms API when building modules, wouldn't it?

Yep, #element_validate is the answer. I needed to validate a numeric value for this custom theme setting. In Drupal 7 this code is in theme-settings.php.

<?php
function THEMENAME_form_system_theme_settings_alter(&$form, $form_state) { 
 
$form['carousel_images'] = array(
   
'#type' => 'textfield',
   
'#title' => t('Carousel Images'),
   
'#default_value' => theme_get_setting('carousel_images'),
   
'#description' => t("Enter the number of images uploaded."),
   
'#element_validate' => array('_carousel_images_setting'),
  );
  function
_carousel_images_setting($element, &$form_state) {
      if (!
is_numeric($element['#value'])) {
       
form_error($element, t('Please enter a number.'));
      }
  }
}
?>

Maybe it's a stupid question but how can i upload a file
in the theme settings ???

i'v already tried :

http://drupal.org/node/85922
http://drupal.org/node/111782
http://api.drupal.org/api/file/developer/topics/forms_api.html
etc...

The problem seems that i can't validate my form because there is another handler on all the theme settings forms... (i'm maybe wrong...)

My reason to do that : i want a second logo (on the left of the page) that the webmaster would change with a upload... EXACTLY like the regular logo...

Is there a better solution ???

Thanks a lot (if i'm not in a good place to put that i'm sorry, but i've found nothing in the forum)

Angel

Angel

This worked fo me. An additional logo (Appeared in the footer everywhere)
Not sure why I had to put the submit handler into the #validate pass :-/
It was copied from the existing theme settings funcs.
'campaign_' is the theme name.

<?php
/**
* Implementation of THEMEHOOK_settings() function.
*
* @param $saved_settings
*   array An array of saved settings for this theme.
* @return
*   array A form array.
*/
function campaign_settings($saved_settings) {
 
$settings = theme_get_settings('campaign');
 
$form['sublogo'] = array(
   
'#type' => 'fieldset',
   
'#title' => t('Secondary logo'),
   
'#description' => t("May be displayed in the footer or under a column.")
  );
 
$form['sublogo']['use_sublogo'] = array(
   
'#type' => 'checkbox',
   
'#title' => t('Use a sublogo.'),
   
'#default_value' => $settings['use_sublogo'],
  );
 
$form['sublogo']['sublogo_path'] = array(
   
'#type' => 'textfield',
   
'#title' => t('Path to sublogo'),
   
'#default_value' => $settings['sublogo_path'],
  );
 
$form['sublogo']['sublogo_upload'] = array(
   
'#type' => 'file',
   
'#title' => t('Upload sublogo image'),
  );
 
$form['#submit'][] = 'campaign_settings_submit';
 
$form['sublogo']['sublogo_upload']['#element_validate'][] = 'campaign_settings_submit';
  return
$form;
}
/**
* Capture theme settings submissions and update uploaded image
*/
function campaign_settings_submit($form, &$form_state) {
 
// Check for a new uploaded file, and use that if available.
 
if ($file = file_save_upload('sublogo_upload')) {
   
$parts = pathinfo($file->filename);
   
$filename = (! empty($key)) ? str_replace('/', '_', $key) .'_sublogo.'. $parts['extension'] : 'sublogo.'. $parts['extension'];
   
// The image was saved using file_save_upload() and was added to the
    // files table as a temporary file. We'll make a copy and let the garbage
    // collector delete the original upload.
   
if (file_copy($file, $filename)) {
     
$_POST['use_sublogo'] = $form_state['values']['use_sublogo'] = TRUE;
     
$_POST['sublogo_path'] = $form_state['values']['sublogo_path'] = $file->filepath;
    }
  }
}
?>

Thanks a lot...
It worked very well....

Angel

Angel

@dman, this works great for the upload, but i can't seem to access this image in my page.tpl.php file...i have tried <?php print $sublogo;?> as well as adding <?php $vars['sublogo'] = theme_get_setting('sublogo->sublogo_path');?> in the img src area and nothing seems to work...how can i access this file path?

<?php
print theme('image', theme_get_setting('sublogo_path'));
?>

or
<img src="<?php print url(theme_get_setting('sublogo_path')); ?>" />

... If you looked at your HTML source or your 404 log you'd see the problem pretty quick.

.. the above code is without even rolling it through the $vars, although using hook_preprocess_page() to set the var is probably best practice.

First, a huge thanks for posting this dan - the book chapter is a bit obscure by itself, and I needed to do a theme settings upload too.

I am not sure of what I'm about to write here and don't mean any kind of criticism, so: you more educated themers out there, please respond to set things straight. ;)

I was able to put the upload check/copy code directly into my theme_settings function instead of writing a separate submit function.

I'm not sure what is best practice, but if you look atsystem_theme_settings() and system_theme_settings_submit(), similar form element creation and upload/copy code occurs in system_theme_settings(), not the submit function. Because system_theme_settings() includes a line of code to require_once() code from your own theme-settings.php file, you can essentially write your own theme_settings() function from your theme-settings.php file as though it were just adding to system_theme_settings (not replacing it).

But if you put your upload/copy code into a separate submit function and call it instead of system_theme_settings_submit(), aren't you bypassing it and thereby disabling all the other stuff that would be done by system_theme_settings_submit (such as the variable sets)?

Again - really not sure of this, but I've got my uploads working with file_save_upload, and file_copy sitting in my theme_settings() function (no separate submit function).

<?php
function opus_settings($saved_settings){
$opus_defaults = array(
   
'default_background' => 1,
   
'background_path' => 'sites/default/themes/opus/images/backgrounds/pencildisplay.jpg',
);
$settings = array_merge($opus_defaults,$saved_settings);
// Check for a new uploaded background and use that instead.
 
if ($file = file_save_upload('background_upload', array('file_validate_is_image' => array()),FILE_EXISTS_REPLACE)) {
   
$parts = pathinfo($file->filepath);
   
$filename = 'backgrounds/';
   
$filename .= ($key) ? str_replace('/', '_', $key) .'_bg_'. $parts['basename'] : $parts['basename'];
   
// The image was saved using file_save_upload() and was added to the
    // files table as a temporary file. We'll make a copy and let the garbage
    // collector delete the original upload.
   
if (file_copy($file, $filename, FILE_EXISTS_REPLACE)) {
     
$_POST['default_background'] = 0;
     
$_POST['background_path'] = $file->filepath;
     
drupal_set_message($message = t('Your new background image has been saved at: ').$file->filepath, $type = 'status', $repeat = TRUE);
    }
  }
$form['default_background'] = array(
     
'#type' => 'checkbox',
     
'#title' => t('Use the default background image'),
     
'#default_value' => $settings['default_background'],
     
'#tree' => FALSE,
     
'#description' => t('Check here if you want the theme to use the background supplied with it.')
    );
$form['background_path'] = array(
 
'#type' => 'textfield',
 
'#title' => t('Background image path'),
 
'#default_value' => $settings['background_path'],
  );
$form['background_upload'] = array(
 
'#type' => 'file',
 
'#title' => t('Upload new background image'),
  );
  return
$form;
}
?>

Then, in template.php using template_preprocess_page() I defined my background path variable that I can use in page.tpl.php. This was necessary because the regular theme settings rely on a "toggle" setting to determine the default path for uploads (logo, favicon). I don't want this - my theme always has a background - so I needed a way for the theme to respond to the check mark in "Use the default background image" that didn't involve rewriting $settings['background_path'].

<?php
 
/* get background settings */
$opus_default_background_path = 'sites/default/themes/opus/images/backgrounds/pencildisplay.jpg';
if(
theme_get_setting('default_background')==1){
 
$opusbackground= base_path() . $opus_default_background_path;
} else {
 
$opusbackground= base_path() . theme_get_setting('background_path');
}
$vars['opusbackground'] = $opusbackground;
?>

<?php
  $form
['#submit'][] = 'campaign_settings_submit';
?>

Is an array of submit actions. It doesn't replace or remove any other functionality, it does this as well.
Form API is nice like that.

Processing the form submission in the same function as building the form can work, and is the way I've seen many many old one-file PHP scripts structured. In some ways it's more concise if you are coding more stream-of-consciousness than architectured. But that was last century.

In Drupal we have Form API that allows us to separate the structure from the process, and allow other Drupal features to interact with it if needed. We can automate form submissions with drupal_execute and other magic. Having those two phases separate - building the form & submitting the form - is pretty sensible.

You can do it the old way if you want. It's just not the Drupal way.

I do see what you mean about system_theme_settings(). That's odd for it to be there. Not sure whether there is a reason or if it's left over from pre-FAPI days. It's manipulating $_POST directly too. That can't be right..

Dan,

Thanks for the response - I'm sorry it has taken so long to see it here.

In any case, I appreciate you taking the time to explain - would really love to get my head around doing things the Drupal Way. I don't have a foundation in programming (making me a bit of a liability sometimes), so the information about the context and overall approach really helps.

Cheers!
Chris

From a bit of a poke around in the code it seems that the theme specific form elements are dumped into a fieldset and so if you do:

<?php
  $form
['#submit'][] = 'campaign_settings_submit';
?>

then ultimately you get:

<?php
  $form
['theme_specific']['#submit'][] = 'campaign_settings_submit';
?>

Which naturally has no effect.

Please, please, please... is there any way that this can be done in Drupal 7? Or any hint how to do in D7?
Thanks.

I have some question about this.
1. What is $theme_key return in doc it said active theme. If it just a theme why need to replace it in variable get

global $theme_key;
  // Save default theme settings.
  variable_set(
    str_replace('/', '_', 'theme_'. $theme_key .'_settings'),
    array_merge($defaults, $settings)
  );

2. What is these lines of codes doing ?
  // Don't save the toggle_node_info_ variables.
  if (module_exists('node')) {
    foreach (node_get_types() as $type => $name) {
      unset($settings['toggle_node_info_' . $type]);
    }
  }

3. What is this do?
  // Force refresh of Drupal internals.
  theme_get_setting('', TRUE);
}

Thank you,
Sarun

Okay, I think my answers might be about right, but maybe PSTM can step in clear up what I get wrong:

#2 is to prevent the initialization process from tampering with the content type features (e.g., whether pages, stories, blogs, etc. add authors,dates,etc.) Since this whole routine only gets called when a visit happens to the theme for the first time after being installed (whether for the whole site, or just one user --that's what the if... checks for at the beginning, to see if this theme has been properly initialized) and since there is no way to set the defaults for content types that might have been or will be created, you don't want the $defaults in the array merge to be contaminated with a bunch of null variables from the $settings variable. In other words, it is just preparing for the array_merge a few lines below.

#3 forces the $settings cache to be cleared so that the next call for the theme settings will have to go to the database variables set in #1 with the now merged $default values included in #3.

#1 actually sets the settings as variables in the database (in table: variables), but as $theme_key is not just the file name, but also the path to the theme, the illegal variable characters '/' are replaced with '_' so that the variable name in the database holding all the settings will be something like: "theme_path_to_my_theme_MYTHEME_settings"

Assuming you want your defaults to override the Drupal defaults, isn't the variable_set() function wrong?

The example uses this -

  // Save default theme settings.
  variable_set(
    str_replace('/', '_', 'theme_'. $theme_key .'_settings'),
    array_merge($defaults, $settings)
  );

According to PHP's manual for array_merge(),

If the input arrays have the same string keys, then the later value for that key will overwrite the previous one.

Therefore, you need your $defaults array to appear second, and double-checking that $settings is an actual array. I did this instead -

  // Get default theme settings.
  if (!is_array($settings = theme_get_settings($theme_key))) $settings = array();
  // Save default theme settings.
  variable_set(
    str_replace('/', '_', 'theme_'. $theme_key .'_settings'),
    array_merge($settings, $defaults)
  );

Erik

Erik Webb
Technical Team Lead, Acquia

The original is correct. Yours would overwrite the saved settings with the defaults, making it impossible for people to change the settings.

Since we can’t guarantee that a user will ever go to the admin/build/themes/settings/themeName page, we have to ensure that the default values for our custom settings get initialized.

[snip]

Add the following code near the top of your template.php file

I'm making my first theme as a subtheme of Zen. Looking at Zen's own template.php (zen/zen/template.php) there's no initialisation, just lots of uses of theme_get_setting. So I'm wondering if maybe it's no longer necessary to initialise vars before use... or maybe the initialisation's hiding somewhere else...

A.

It just depends on whether your code can handle null values if the variable isn't initialized.

For example, I use if($siteID = theme_get_setting('wsuidentity_site_id')) {...} in one of my themes. If it's set then it does something, if not, it just goes happily along its way.

You should initialize your default values, but there's more than one way to skin a cat.

The Zen theme defines its default theme settings in its zen.info file, e.g.

settings[zen_block_editing]        = 1

You'll then see that Zen uses the following code to get the values:

<?php
  $themes
= list_themes();
 
// Get the default values from the .info file.
 
$defaults = !empty($themes[$theme]->info['settings']) ? $themes[$theme]->info['settings'] : array();
?>

It then merges those defaults with saved settings to get the current set of appropriate values.

Otherwise, you can do what is explained in this post; you can explicitly set your default values in your theme settings form.

reading the settings file is proper IMO, because keeping two arrays of defaults in two places in code is not right.

What file is the code it merges the defaults in?

Is it possible to do this in Drupal 7: http://drupal.org/node/177868#comment-1445178
I need to upload form in my Drupal 7 theme, and need some help with that. That solution is good for D6 but how to do that in D7?

Thanks.

Finally found how to do it.

All this code is in theme-settings.php
I've added my new upload field in a fieldset that is itself in the logo fieldset, hence why all the fields are starting by ['logo']['settings']. They won't show unless you check off the "use default icon" checkbox.

<?php
function themename_form_system_theme_settings_alter(&$form, &$form_state)  {
 
$form['logo']['settings']['sublogo'] = array(
   
'#type' => 'fieldset',
   
'#title' => t('Logo secondaire'),
   
'#description' => t("Apparait dans le bas de page")
  );
   
$logo_path = theme_get_setting('sublogo_path');
   
// If $logo_path is a public:// URI, display the path relative to the files
    // directory; stream wrappers are not end-user friendly.
   
if (file_uri_scheme($logo_path) == 'public') {
     
$logo_path = file_uri_target($logo_path);
    }
 
$form['logo']['settings']['sublogo']['sublogo_path'] = array(
   
'#type' => 'textfield',
   
'#title' => t('Chemin vers le logo secondaire'),
   
'#default_value' =>  $logo_path,
  );
 
$form['logo']['settings']['sublogo']['sublogo_upload'] = array(
   
'#type' => 'file',
   
'#title' => t('Envoyer un logo secondaire'),
  );
 
// We are editing the $form in place, so we don't need to return anything.
 
$form['#submit'][]   = 'themename_settings_submit';
}
?>

Then the function that will manage the file transfer. (In theme-settings.php)
I know atm i don't have any verification of the image format.

<?php
function sogetirh_settings_submit($form, &$form_state) {
 
$settings = array();
 
// Check for a new uploaded file, and use that if available.
 
if ($file = file_save_upload('sublogo_upload')) {
   
$parts = pathinfo($file->filename);
   
$destination = 'public://' . $parts['basename'];
   
$file->status = FILE_STATUS_PERMANENT;
     if (
file_copy($file, $destination, FILE_EXISTS_REPLACE)) {
       
$_POST['sublogo_path'] = $form_state['values']['sublogo_path'] = $destination;
     }
  }
}
?>

Your image should end up in the /sites/yoursite/files/ folder.

And finally the code to access it from the template.tpl.php files:

<img src="<?php print file_create_url(theme_get_setting('sublogo_path')); ?>" />

theme_get_setting('sublogo_path') get the path of the sublogo.
print file_create_url() transform that path (public://sublogo.png") into a correct url:
http://yoursite:8082/sites/yoursite/files/sublogo.png

I'm sure there are "cleaner" ways to do it though.

Thanks for the post WilliamB; this helped me out as a designer working with D7.

I'm wondering if there is a way to choose an image from a theme settings interface. This could let user's browse the images they have already uploaded. I'm going to see if I can have the settings page generate a thumbnail of the current sublogo/image.

Here is an improved version, avoiding to leave old uploads in the filesystem.

<?php
// @file: theme-settings.php
function THEMENAME_form_system_theme_settings_alter(&$form, &$form_state) {
 
// Container fieldset
 
$form['slideshow'] = array(
   
'#type' => 'fieldset',
   
'#title' => t('Slideshow'),
  );
 
// Default path for image
 
$bg_path = theme_get_setting('bg_path');
  if (
file_uri_scheme($bg_path) == 'public') {
   
$bg_path = file_uri_target($bg_path);
  }
 
// Helpful text showing the file name, disabled to avoid the user thinking it can be used for any purpose.
 
$form['slideshow']['bg_path'] = array(
   
'#type' => 'textfield',
   
'#title' => 'Path to background image',
   
'#default_value' => $bg_path,
   
'#disabled' => TRUE,
  );
 
// Upload field
 
$form['slideshow']['bg_upload'] = array(
   
'#type' => 'file',
   
'#title' => 'Upload background image',
   
'#description' => 'Upload a new image for the background.',
  );
 
// Attach custom submit handler to the form
 
$form['#submit'][] = 'THEMENAME_settings_submit';
}
function
THEMENAME_settings_submit($form, &$form_state) {
 
$settings = array();
 
// Get the previous value
 
$previous = 'public://' . $form['slideshow']['bg_path']['#default_value'];
 
$file = file_save_upload('bg_upload');
  if (
$file) {
   
$parts = pathinfo($file->filename);
   
$destination = 'public://' . $parts['basename'];
   
$file->status = FILE_STATUS_PERMANENT;
    if(
file_copy($file, $destination, FILE_EXISTS_REPLACE)) {
     
$_POST['bg_path'] = $form_state['values']['bg_path'] = $destination;
     
// If new file has a different name than the old one, delete the old
     
if ($destination != $previous) {
       
drupal_unlink($previous);
      }
    }
  } else {
   
// Avoid error when the form is submitted without specifying a new image
   
$_POST['bg_path'] = $form_state['values']['bg_path'] = $previous;
  }
}
?>

The usage in the theme is as indicated:

<img src="<?php print file_create_url(theme_get_setting('bg_path')); ?>" />

thank you! you may want to include a check if the old destination exists before unlinking...

Is there any way to display it in the drop-down list for the guests so that they can choose the color scheme (one of the predefined sets) and change the colors of the displayed page?

Note that node_get_types() is renamed to node_type_get_types() in Drupal 7

When a theme gets uninstalled or upgraded would the user be at risk of loosing their settings? How does this work?

Is it possible to add multilingual variables like we see for default theme settings (logo etc..)?

Thanks


IT Sys Admin / Developer
DNN & Drupal Fan/User

Troubleshooting tip: Try re-enabling the theme from admin/appearance/list.

I ran into an issue where the theme settings would not appear in the menu and even display permission denied when directly accessing it. The issue was that the default theme was being used when viewing the site was not actually enabled. The Drupal theme settings had my theme as default but not enabled. I am unaware with how to reproduce such a state. I activated the theme and the settings now appear.

I am finding that when you hit 'Reset to defaults' on the theme config form, $defaults is not added to $saved_settings unless I then hit 'Save configuration'. Anyone run into this?

I've been trying to get around this for weeks. Storing a value like:

settings[setting_name] = '6-1'

Then parsing it out in theme-settings and attempting to save it as a default using either:

(int) substr(theme_get_setting('setting_name'), 0, 2),

or a

list($var1, $var2) = explode("-",theme_get_setting('setting_name')),

but neither method seems to allow the theme-settings form to save a new value after submission. Any suggestions?

Have had a Drupal Answers post on this for a while too http://drupal.stackexchange.com/q/38787/2256

If you look into theme_get_setting(), it is responsible to fetch data from .info and also database. Did you actually create "setting_name" as perhaps hidden input that will store the values into database?

love, light n laughter