You are here

function imagecache_cache in ImageCache 5

Same name and namespace in other branches
  1. 5.2 imagecache.module \imagecache_cache()
  2. 6.2 imagecache.module \imagecache_cache()
1 string reference to 'imagecache_cache'
imagecache_menu in ./imagecache.module
Implementation of hook_menu().

File

./imagecache.module, line 106
Dynamic image resizer and image cacher.

Code

function imagecache_cache() {
  $args = func_get_args();
  $preset = array_shift($args);
  $preset_id = _imagecache_preset_load_by_name($preset);
  if (!$preset_id) {
    watchdog('imagecache', t('Preset(%p) not found', array(
      '%p' => $preset,
    )), WATCHDOG_ERROR);
    header('HTTP/1.0 404 Not Found');
    exit;
  }

  // Verify that the source exists, if not exit. Maybe display a missing image.
  $src = file_create_path(implode('/', $args));
  if (!is_file($src)) {
    watchdog('imagecache', t('Source(%s) not found.', array(
      '%s' => $src,
    )), WATCHDOG_ERROR);
    header('HTTP/1.0 404 Not Found');
    exit;
  }

  // Build the destination folder tree if it doesn't already exists,
  // and make sure it is writable.
  $dst = 'imagecache/' . $preset . '/' . $src;

  // Build the destination folder tree if it doesn't already exists.
  if (!file_check_directory(file_create_path($dst))) {
    $folders = explode("/", _imagecache_strip_file_directory(dirname($dst)));
    foreach ($folders as $folder) {
      $tpath[] = $folder;
      $checkpath = implode("/", $tpath);
      if (!file_check_directory(file_create_path($checkpath), FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
        watchdog('imagecache', t('Cannot create/fix dir(%d).', array(
          '%d' => $checkpath,
        )), WATCHDOG_ERROR);
        header("HTTP/1.0 500 Internal Server Error");
        exit;
      }
    }
  }

  // Prepend presetname to tmp file name to prevent namespace clashes when
  // multiple presets for the same image are called in rapid succession.
  $tmp = file_directory_temp() . '/tmp_imagecache_' . md5($src) . '_' . $preset . '_' . basename($src);
  register_shutdown_function('file_delete', $tmp);

  // Check if file exists to prevent multiple apache children from trying to generate.
  if (is_file($tmp)) {
    watchdog('imagecache', t('tmp file(%t) already exists.', array(
      '%t' => $tmp,
    )), WATCHDOG_NOTICE);

    // non-caching redirect to self, we hope the processing has finished by the time we come back.
    // 307 Temporary Redirect
    header("Location: " . $_SERVER['REQUEST_URI'], TRUE, 307);
    exit;
  }

  // copy source to a temporary file we will use to apply the imagecache actions to.
  if (!file_copy($src, $tmp)) {
    watchdog('imagecache', t('Could not copy src(%s) to tmp(%t).', array(
      '%s' => $src,
      '%t' => $tmp,
    )), WATCHDOG_ERROR);
    header("HTTP/1.0 500 Internal Server Error");
    exit;
  }
  $actions = _imagecache_actions_get_by_presetid($preset_id);
  foreach ($actions as $action) {
    $size = getimagesize($tmp);
    if (empty($action['data']['height'])) {
      $action['data']['height'] = round($size[1] * ($action['data']['width'] / $size[0]));
    }
    if (empty($action['data']['width'])) {
      $action['data']['width'] = $size[0] * ($action['data']['height'] / $size[1]);
    }
    $new_width = _imagecache_filter('width', $action['data']['width'], $size[0], $size[1]);
    $new_height = _imagecache_filter('height', $action['data']['height'], $size[0], $size[1]);
    foreach ($action['data'] as $key => $value) {
      $action['data'][$key] = _imagecache_filter($key, $value, $size[0], $size[1], $new_width, $new_height);
    }
    switch ($action['data']['function']) {
      case 'resize':
        if (!image_resize($tmp, $tmp, $action['data']['width'], $action['data']['height'])) {
          watchdog('imagecache', t('Imagecache resize action ID %id failed.', array(
            '%id' => $action['actionid'],
          )), WATCHDOG_ERROR);
        }
        break;
      case 'scale':
        if ($action['data']['fit'] == 'outside' && $action['data']['width'] && $action['data']['height']) {
          $ratio = $size[0] / $size[1];
          $new_ratio = $action['data']['width'] / $action['data']['height'];
          $action['data']['width'] = $ratio > $new_ratio ? 0 : $action['data']['width'];
          $action['data']['height'] = $ratio < $new_ratio ? 0 : $action['data']['height'];
        }

        // Set impossibly large values if the width and height aren't set.
        $action['data']['width'] = $action['data']['width'] ? $action['data']['width'] : 9999999;
        $action['data']['height'] = $action['data']['height'] ? $action['data']['height'] : 9999999;
        if (!image_scale($tmp, $tmp, $action['data']['width'], $action['data']['height'])) {
          watchdog('imagecache', t('Imagecache scale action ID %id failed.', array(
            '%id' => $action['actionid'],
          )), WATCHDOG_ERROR);
        }
        break;
      case 'crop':
        if (!image_crop($tmp, $tmp, $action['data']['xoffset'], $action['data']['yoffset'], $action['data']['width'], $action['data']['height'])) {
          watchdog('imagecache', t('Imagecache crop action ID %id failed.', array(
            '%id' => $action['actionid'],
          )), WATCHDOG_ERROR);
        }
        break;
    }
  }

  // move the temporary file to it's final destination.
  $final_path = file_create_path($dst);
  if (!file_move($tmp, $final_path)) {
    watchdog('imagecache', t('Could not move tmp(%t) to dst(%d).', array(
      '%d' => $dst,
      '%t' => $tmp,
    )), WATCHDOG_ERROR);
    header("HTTP/1.0 500 Internal Server Error");
    exit;
  }

  // Serve it up...
  $size = getimagesize($final_path);
  file_transfer($final_path, array(
    'Content-Type: ' . mime_header_encode($size['mime']),
    'Content-Length: ' . filesize($final_path),
  ));
  exit;
}