Skip to content

Instantly share code, notes, and snippets.

@christeredvartsen
Created April 11, 2012 15:17
Show Gist options
  • Save christeredvartsen/2359973 to your computer and use it in GitHub Desktop.
Save christeredvartsen/2359973 to your computer and use it in GitHub Desktop.
Transformation temp. storage
<?php
namespace Imbo\EventListener;
use Imbo\Exception\RuntimeException,
Imbo\EventManager\EventInterface;
/**
* Image transformation storage
*
* Event listener that stores (transformed) images to disk. By using this listener Imbo will only
* have to generate each transformation once.
*/
class ImageTransformationStorage extends Listener implements ListenerInterface {
/**
* Root path where the temp. images can be stored
*
* @var string
*/
private $path;
/**
* Class constructor
*
* @param string $path Path to store the temp. images
* @throws Imbo\Exception\RuntimeException
*/
public function __construct($path) {
$this->path = rtrim($path, '/');
// Try to create the path if it does not exist
if ((!is_dir($path) && !@mkdir($path, 0775, true)) || !is_writable($path)) {
throw new RuntimeException('Invalid path: ' . $path, 500);
}
}
/**
* @see Imbo\EventListener\ListenerInterface::getEvents
*/
public function getEvents() {
return array(
'image.get.pre',
'image.get.post',
);
}
/**
* @see Imbo\EventListener\ListenerInterface::invoke
* @throws Imbo\Exception\RuntimeException
*/
public function invoke(EventInterface $event) {
$eventName = $event->getName();
$request = $event->getRequest();
$hash = md5($request->getUrl());
$fullPath = $this->getFullPath($hash);
if ($eventName === 'image.get.pre') {
if (is_file($fullPath)) {
$response = unserialize(file_get_contents($fullPath));
$ifNoneMatch = $request->getHeaders()->get('if-none-match');
$ifModifiedSince = $request->getHeaders()->get('if-modified-since');
$etag = $response->getHeaders()->get('etag');
$lastModified = $response->getHeaders()->get('last-modified');
if (
$ifNoneMatch && $ifModifiedSince &&
$lastModified === $ifModifiedSince &&
$etag === $ifNoneMatch
) {
$response->setNotModified();
}
$response->send();
exit;
}
} else if ($eventName === 'image.get.post') {
$response = $event->getResponse();
if ($response->getStatusCode() === 304) {
// We don't want to put a 304 response in the cache
return;
}
$dir = dirname($fullPath);
if (!is_dir($dir) && !mkdir($dir, 0775, true)) {
throw new RuntimeException('Could not create directory: ' . $dir, 500);
}
file_put_contents($fullPath, serialize($response));
}
}
/**
* Get the full path based on the hash
*
* @param string $hash An MD5 hash (image identifier)
* @return string Returns a full path
*/
private function getFullPath($hash) {
return sprintf('%s/%s/%s/%s/%s', $this->path, $hash[0], $hash[1], $hash[2], $hash);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment