Allow cache busting string in theme_image

Created on 31 July 2014, over 10 years ago
Updated 17 February 2023, over 1 year ago

Problem/Motivation

When working on a module that uses File Entity to handle media assets we've discovered that currently, there no way to bypass browser file cache in theme_image and theme_image_style. File Entity provides users with a way to replace their file with a new one, without changing the name of the file. Because filename remains the same, it's still cached in browser and will not show up until clearing page cache with CTRL+R.
This might be fine and we're used to it on the user facing site, but it might confuse authors who just replaced their image with a new one, and it's not showing the latest image in admin interface. It would be nice to have a way to bust browser cache that works with Drupal's theming functions, so we don't reinvent the wheel.

Proposed resolution

In order to bust browser cache we might add some query parameter to achieve a unique URL. This hard to do with theme_image code because of file_create_url.
Any image path passed to theme_image is passed throw file_create_url as seen below:

function theme_image($variables) {
  $attributes = $variables['attributes'];
  $attributes['src'] = file_create_url($variables['path']);
  ...

You could construct a URL like public://filename.jpg?hash=1234567 and pass it to theme_image to get a fresh image when you really need it, but your URL will be encoded inside file_create_url using drupal_encode_path($uri) which will encode your "?" and "=" and will render your URL incorrectly. To bypass this you could send an absolute URL to theme_image, but then you have to construct your absolute URL yourself everywhere you need it, and then you will have to fix theme_image_style which already constructs an absolute URL with the same file_create_url and lacks a cache bust token option.

I suggest having a way to indicate that a cache bust token should be appended to the passed 'path' parameter.
Here is a way to do that:

function theme_image($variables) {
  $attributes = $variables['attributes'];
  $attributes['src'] = file_create_url($variables['path']);

  // Provide a way to bust browser file cache.
  if (isset($variables['cache']) && !$variables['cache']) {
    $attributes['src'] = $attributes['src'] . (strpos($attributes['src'], '?') !== FALSE ? '&' : '?') . 'ihash=' . time();
  }

  foreach (array('width', 'height', 'alt', 'title') as $key) {

    if (isset($variables[$key])) {
      $attributes[$key] = $variables[$key];
    }
  }

  return '<img' . drupal_attributes($attributes) . ' />';
}

Then we can use it like this:

 $variables = array(
      'path' => 'path/to/img.jpg', 
      'alt' => 'Test alt',
      'title' => 'Test title',
      'width' => '50%',
      'height' => '50%',
      'attributes' => array('class' => 'some-img', 'id' => 'my-img'),
      // Bypass cache
      'cache' => FALSE,
      );
  $img = theme('image', $variables);

This should not affect any image rendering when 'cache' parameter is not set, and will allow to enable cache busting form both theme_image and theme_image_style as theme_image_style will call theme_image.

In order to be able to use it with image formatter we also need to modify image formatter, otherwise people will have to create their own image formatter to use that option.

Remaining tasks

Patch to follow

User interface changes

Not applicable

API changes

You can use 'cache' parameter set to FALSE to bust browser cache like this:

 $variables = array(
      'path' => 'path/to/img.jpg', 
      'alt' => 'Test alt',
      'title' => 'Test title',
      'width' => '50%',
      'height' => '50%',
      'attributes' => array('class' => 'some-img', 'id' => 'my-img'),
      // Bypass cache
      'cache' => FALSE,
      );
  $img = theme('image', $variables);
Feature request
Status

Needs work

Version

9.5

Component
Image system 

Last updated 3 days ago

Created by

🇺🇸United States asgorobets

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024