1

I have a flexslider and I make its images customizable through the theme settings. I added a caption property for the the slide to meet multiple languages websites as follows in theme-settings.php:

// setting property to determine the rendered images fields 
$form['best_responsive_settings']['imagesCount'] = array(
      '#markup' => t('Enter the total number of images in the slideshow'),
      '#type' => 'select',
      '#options' => associate_array_vals(explode(',',  theme_get_setting('imagesCountOptions'))),
      '#selected' => theme_get_setting('imagesCount'),
      '#default_value' => theme_get_setting('imagesCount'),

  );

  $lang_list = language_list();
// rendering upload image form with caption textfield for every language supported by the website

  for ($i = 0; $i < theme_get_setting('imagesCount'); $i++){
      $form['best_responsive_settings']['slideshowImages'.$i] = array(
        '#type' => 'managed_file',
        '#title' => t('Image').' #'.($i+1),
         '#required' => false,
        '#upload_location' => file_default_scheme() . '://slides',
    '#default_value' => theme_get_setting('slideshowImages'.$i,'best_responsive'), 
    '#upload_validators' => array(
      'file_validate_extensions' => array('gif png jpg jpeg'),
      'file_validate_image_resolution' => array('960x400','430x400')        ),

      );
      foreach ($lang_list as $lang){
      $form['best_responsive_settings']['slideshowCaption'.$lang->language.$i] = array(
    '#type' => 'textfield',
    '#title' => t('Caption').' #'.($i+1).' -- '.$lang->name,  
    '#required' => false,
    '#default_value' => theme_get_setting('slideshowCaption'.$lang->language.$i, 'best_responsive'),
  );
      }
  } 

In page.tpl.php I use the following to render the images:

<?php if (theme_get_setting('slideshow_display','best_responsive')): ?> 

    <div id="home-slider">
      <div class="flexslider-container">
        <div id="single-post-slider" class="flexslider">
          <ul class="slides">
            <?php for ($i = 0; $i < theme_get_setting('imagesCount'); $i++): ?>
              <?php  if (theme_get_setting('slideshowImages'.$i) != ''): ?>
 //the following line causes a problem after some time
            <li class="slide"><img src="<?php echo file_create_url(file_load(theme_get_setting('slideshowImages'.$i))->uri);?>" alt="Slide"/><?php if (theme_get_setting('slideshowCaption'.$language->language.$i)): ?><span class="flex-caption"><?php echo theme_get_setting('slideshowCaption'.$language->language.$i) ;?></span><?php endif;?></li>

              <?php endif; ?>
            <?php endfor; ?>
          </ul><!-- /slides -->
        </div><!-- /flexslider -->
      </div>
    </div>
    <?php endif; ?>
    <?php endif; ?>

Everything, initially, works fine, the images are uploaded to the theme settings and images are rendered well in the slideshow. However, after some time! I noticed that the images are disappeared from the template settings page and only the caption if supplied is remained. In addition I got the following notice:

Notice: Trying to get property of non-object in include() (line 159 of C:\xampp-2\htdocs\4test\drupal-7.28\sites\all\themes\best_responsive\templates\page.tpl.php).

Where the line 159 is the line regarded in the comment of the second code snippet above. This notice is repeated twice. What is the problem here? What is making this code initially works then after sometime it fails? What is making the uploaded files disappeared from the settings. In addition, the destination in-which images should be uploaded /sites/default/files/slides becomes empty. i.e the uploaded images files are deleted!

4

My solution is to ensure to make permanent the image when drupal load page theme settings. You don't need to create a custom submit handler because after the new settings are saved the settings page is reloaded, and the fix executed.

Plus, you cannot use "active theme" because sometimes the current active theme is the admin theme, and not the default or maybe the user is changing the settings theme in a theme that it's not set as default.

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

  $default_file_dir = 'public://template/logos';
  $folder = file_prepare_directory($default_file_dir, FILE_CREATE_DIRECTORY);
  $settings_theme = $form_state['build_info']['args'][0];

  if ($folder) {
    $my_logo = theme_get_setting('my_logo');
    // BUG: Force file to be permanent.
    if (!empty($my_logo)) {
      _fix_permanent_image('my_logo', $settings_theme);
    }
    $form['my_logo'] = array(
      '#type'               => 'managed_file',
      '#title'              => l('My logo'),
      '#default_value'      => $my_logo,
      '#progress_message'   => t('Please wait...'),
      '#progress_indicator' => 'bar',
      '#upload_location'    => $default_file_dir,
      '#upload_validators'  => array(
        'file_validate_extensions' => array('gif png jpg jpeg'),
        'file_validate_image_resolution' => array('375x50', '30x50'),
      ),
    );
  }

}

function _fix_permanent_image($image, $theme) {
  $fid = theme_get_setting($image, $theme);
  if ($fid > 0) {
    $file = file_load($fid);
    if (is_object($file) && $file->status == 0) {
      $file->status = FILE_STATUS_PERMANENT;
      file_save($file);
      file_usage_add($file, $theme, 'theme', 1);
      drupal_set_message($image . ' saved permanently.', 'status');
    }
  }
}
1

By default, Drupal marks files as "temporary", meaning that they will be deleted after 6 hours.

You will need to change the file status to permanent in order to keep the files. This doesn't seem to be clearly stated in the documentation.

See these question for some example code and explanations: Managed file: the file used in the field may not be referenced

You will need to do the following in a submit validation (or similar):

// Change status to permanent.
$file->status = FILE_STATUS_PERMANENT;
// Save the file.
file_save($file);
// Record that the module (e.g. user module) is using the file.
file_usage_add($file, 'user', 'user', $user->uid);
1

For a detailed guide on where to implement the custom code to set your files as permanent, you might want to check this: http://ghosty.co.uk/2014/03/managed-file-upload-in-drupal-theme-settings/

Basically, it adds a custom form submit handler for the theme settings form; which is not straightforward in Drupal and a bit hackish.

$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'

And then inside your submit handler you can do something like this to set the files as permanent.

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);
     }
  }
}

Good luck.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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