diff --git a/composer.json b/composer.json index 99349e8..a2ab3d5 100644 --- a/composer.json +++ b/composer.json @@ -1,36 +1,36 @@ { - "name": "anahkiasen/illuminage", - "description": "Wrapper for the Imagine library to hook into the Laravel framework", - "license": "MIT", - "keywords": [ - "laravel", - "imagine", - "thumb", - "images" - ], - "authors": [ - { - "name": "Maxime Fabre", - "email": "ehtnam6@gmail.com" - } - ], - "require": { - "php": ">=5.3.0", - "anahkiasen/html-object": "dev-master", - "illuminate/cache": "~4", - "illuminate/container": "~4", - "illuminate/config": "~4", - "illuminate/routing": "~4", - "illuminate/support": "~4", - "imagine/Imagine": "dev-develop" - }, - "require-dev": { - "mockery/mockery": "dev-master" - }, - "autoload": { - "psr-0": { - "Illuminage": "src/" - } - }, - "minimum-stability": "dev" + "name" : "anahkiasen/illuminage", + "description" : "Wrapper for the Imagine library to hook into the Laravel framework", + "license" : "MIT", + "keywords" : [ + "laravel", + "imagine", + "thumb", + "images" + ], + "authors" : [ + { + "name" : "Maxime Fabre", + "email": "ehtnam6@gmail.com" + } + ], + "require" : { + "php" : ">=5.3.0", + "anahkiasen/html-object": "~1.4.0", + "illuminate/cache" : "~4.1", + "illuminate/container" : "~4.1", + "illuminate/config" : "~4.1", + "illuminate/routing" : "~4.1", + "illuminate/support" : "~4.1", + "imagine/imagine" : "~0.5.0" + }, + "require-dev" : { + "mockery/mockery": "dev-master" + }, + "autoload" : { + "psr-0": { + "Illuminage": "src/" + } + }, + "minimum-stability": "dev" } diff --git a/src/Illuminage/Cache.php b/src/Illuminage/Cache.php index e7103ac..2ae4073 100644 --- a/src/Illuminage/Cache.php +++ b/src/Illuminage/Cache.php @@ -1,6 +1,7 @@ illuminage->getCacheFolder().$this->getHashOf($image); - } + public function getCachePathOf(Image $image) + { + $hash = $this->getHashOf($image); + $cacheFolder = $this->illuminage->getCacheFolder(); + $hashedFolder = $cacheFolder . $this->getHashedPath($hash); - /** + if ( $hashedFolder and ! File::isDirectory($hashedFolder) ) @File::makeDirectory($hashedFolder,511,true); + + + + return $hashedFolder . $hash; + } + + /** + * get hashed path with subfolders in case random_folder = true + * + * @param $hash + * @return string + */ + public function getHashedPathOf(Image $image){ + + $hash = $this->getHashOf($image); + + return $this->getHashedPath($hash) . $hash; + } + + /** + * get hashed folder with subfolders in case random_folder = true + * + * @param $hash + * @return string + */ + public function getHashedPath($hash){ + + if ($this->illuminage->getOption('random_folder')) { + return substr($hash, 0, 2) . '/' . substr($hash, 2, 2). '/'; + } + + return ''; + } + + /** * Check if an image is in cache * * @param Image $image diff --git a/src/Illuminage/Illuminage.php b/src/Illuminage/Illuminage.php index 58994ab..c93e623 100644 --- a/src/Illuminage/Illuminage.php +++ b/src/Illuminage/Illuminage.php @@ -8,195 +8,227 @@ use Illuminate\Http\Request; use Illuminate\Routing\UrlGenerator; use Symfony\Component\Routing\RouteCollection; +use HtmlObject\Image as HtmlImage; /** * Handles image creation and caching * * @property request $request */ -class Illuminage -{ - - /** - * The IoC Container - * - * @var Container - */ - protected $app; - - /** - * The UrlGenerator instance - * - * @var UrlGenerator - */ - protected $url; - - /** - * The Imagine instance - * - * @var Imagine - */ - protected $imagine; - - /** - * The Cache instance - * - * @var Cache - */ - protected $cache; - - /** - * The Config instance - * - * @var Config - */ - protected $config; - - /** - * Set up Illuminage - * - * @param Container $container A base Container to bind onto - */ - public function __construct($container = null) - { - $this->app = $this->createContainer($container); - - // Bind instances - $this->config = $this->app['config']; - $this->cache = $this->app['illuminage.cache']; - $this->imagine = $this->app['imagine']; - } - - /** - * Get an instance from the Container - * - * @param string $key - * - * @return object - */ - public function __get($key) - { - return $this->app->make($key); - } - - /** - * Create Illuminage's IoC Container - * - * @param Container $container A base Container to bind onto - * - * @return Container - */ - protected function createContainer($container = null) - { - $app = $container ?: new Container; - $me = $this; - - // System classes ---------------------------------------------- / - - $app->bindIf('Filesystem', 'Illuminate\Filesystem\Filesystem'); - - $app->bindIf('request', function() { - return Request::createFromGlobals(); - }); - - // Core classes ------------------------------------------------ / - - $app->bindIf('config', function($app) { - $fileloader = new FileLoader($app['Filesystem'], __DIR__.'/../../'); - - return new Repository($fileloader, 'src/config'); - }); - - $app->bindIf('cache', function($app) { - return new FileStore($app['Filesystem'], __DIR__.'/../../public'); - }); - - $app->bindIf('url', function($app) { - $routeCollection = new RouteCollection; - - return new UrlGenerator($routeCollection, $app['request']); - }); - - // Illuminage classes ------------------------------------------ / - - $app->bindIf('imagine', function($app) use ($me) { - $engine = $me->getOption('image_engine'); - $imagine = "\Imagine\\$engine\Imagine"; - - return new $imagine; - }); - - $app->bindIf('illuminage.processor', function($app) { - return new ImageProcessor($app['imagine']); - }); - - $app->bindIf('illuminage.cache', function() use ($me) { - return new Cache($me); - }); - - return $app; - } - - /** - * Get an option from the config - * - * @param string $option - * @param string $fallback - * - * @return array|string|null - */ - public function getOption($option, $fallback = null) - { - $root = class_exists('App') ? 'illuminage::' : 'config.'; - - return $this->config->get($root.$option, $fallback); - } - - //////////////////////////////////////////////////////////////////// - ///////////////////////////// CONSTRUCTORS ///////////////////////// - //////////////////////////////////////////////////////////////////// - - /** - * Create a new Image - * - * @param string $image Path to the image - * - * @return Image - */ - public function image($image) - { - return new Image($this, $image); - } - - /** - * Create a resized image - * - * @param string $image - * @param integer $width - * @param integer $height - * - * @return Image - */ - public function thumb($image, $width, $height) - { - $image = new Image($this, $image); - $image->thumbnail($width, $height); - - return $image; - } - - /** - * Create a thumb image - * - * @param string $image - * @param integer $size - * - * @return Image - */ - public function square($image, $size) - { - return $this->thumb($image, $size, $size); - } +class Illuminage { + + /** + * The IoC Container + * + * @var Container + */ + protected $app; + + /** + * The UrlGenerator instance + * + * @var UrlGenerator + */ + protected $url; + + /** + * The Imagine instance + * + * @var Imagine + */ + protected $imagine; + + /** + * The Cache instance + * + * @var Cache + */ + protected $cache; + + /** + * The Config instance + * + * @var Config + */ + protected $config; + + /** + * Set up Illuminage + * + * @param Container $container A base Container to bind onto + */ + public function __construct($container = null) { + + $this->app = $this->createContainer($container); + + // Bind instances + $this->config = $this->app['config']; + $this->cache = $this->app['illuminage.cache']; + $this->imagine = $this->app['imagine']; + } + + /** + * Get an instance from the Container + * + * @param string $key + * + * @return object + */ + public function __get($key) { + + return $this->app->make($key); + } + + /** + * Create Illuminage's IoC Container + * + * @param Container $container A base Container to bind onto + * + * @return Container + */ + protected function createContainer($container = null) { + + $app = $container ? : new Container; + $me = $this; + + // System classes ---------------------------------------------- / + + $app->bindIf('Filesystem', 'Illuminate\Filesystem\Filesystem'); + + $app->bindIf( + 'request', function () { + + return Request::createFromGlobals(); + } + ); + + // Core classes ------------------------------------------------ / + + $app->bindIf( + 'config', function ($app) { + + $fileloader = new FileLoader($app['Filesystem'], __DIR__ . '/../../'); + + return new Repository($fileloader, 'src/config'); + } + ); + + $app->bindIf( + 'cache', function ($app) { + + return new FileStore($app['Filesystem'], __DIR__ . '/../../public'); + } + ); + + $app->bindIf( + 'url', function ($app) { + + $routeCollection = new RouteCollection; + + return new UrlGenerator($routeCollection, $app['request']); + } + ); + + // Illuminage classes ------------------------------------------ / + + $app->bindIf( + 'imagine', function ($app) use ($me) { + + $engine = $me->getOption('image_engine'); + $imagine = "\Imagine\\$engine\Imagine"; + + return new $imagine; + } + ); + + $app->bindIf( + 'illuminage.processor', function ($app) { + + return new ImageProcessor($app['imagine']); + } + ); + + $app->bindIf( + 'illuminage.cache', function () use ($me) { + + return new Cache($me); + } + ); + + return $app; + } + + /** + * Get an option from the config + * + * @param string $option + * @param string $fallback + * + * @return array|string|null + */ + public function getOption($option, $fallback = null) { + + $root = class_exists('App') ? 'illuminage::' : 'config.'; + + return $this->config->get($root . $option, $fallback); + } + + //////////////////////////////////////////////////////////////////// + ///////////////////////////// CONSTRUCTORS ///////////////////////// + //////////////////////////////////////////////////////////////////// + + /** + * Create a new Image + * + * @param string $image Path to the image + * + * @return Image + */ + public function image($image) { + + try { + $image = new Image($this, $image); + + if (!is_null($image->getImage())) return $image; + + } catch (\RuntimeException $e) {} + + return false; + } + + /** + * Create a resized image + * + * @param string $image + * @param integer $width + * @param integer $height + * + * @return Image + */ + public function thumb($image, $width, $height) { + + $image = $this->image($image); + + if (!$image) + return new HtmlImage('', 'broken image'); + + $image->thumbnail($width, $height); + + return $image; + } + + /** + * Create a thumb image + * + * @param string $image + * @param integer $size + * + * @return Image + */ + public function square($image, $size) { + + return $this->thumb($image, $size, $size); + } /** * Create a proportional resize that fits provided dimensions @@ -206,78 +238,126 @@ public function square($image, $size) * * @return Image */ - public function fit($image, $width, $height, $upscale = false) - { - $image = new Image($this, $image); + public function fit($image, $width, $height, $upscale = false) { + + $image = $this->image($image); + + if (!$image) + return new HtmlImage('', 'broken image'); + $image->proportional($width, $height, $upscale); return $image; + } - //////////////////////////////////////////////////////////////////// - /////////////////////////// IMAGE PROCESSING /////////////////////// - //////////////////////////////////////////////////////////////////// - - /** - * Process an Image - * - * @param Image $image - * - * @return string - */ - public function process(Image $image) - { - $endpoint = $this->cache->getCachePathOf($image); - - // If the image hasn't yet been processed, do it - // and then cache it - if (!$this->cache->isCached($image)) { - $quality = $image->getQuality() ?: $this->getOption('quality'); - $processedImage = $this->app['illuminage.processor']->process($image); - $processedImage->save($endpoint, array('quality' => (int) $quality)); + /** + * Create a proportional to width resize + * + * @param string $image + * @param integer $width + * + * @return Image + */ + public function width($image, $width) { + + $image = $this->image($image); + + if (!$image) + return new HtmlImage('', 'broken image'); + + $image->proportionalWidth($width); + + return $image; + + } + + /** + * Create a proportional to height resize + * + * @param string $image + * @param integer $height + * + * @return Image + */ + public function height($image, $height) { + + $image = $this->image($image); + + if (!$image) + return new HtmlImage('', 'broken image'); + + $image->proportionalHeight($height); + + return $image; + } - return $endpoint; - } - - //////////////////////////////////////////////////////////////////// - ////////////////////////////// HELPERS ///////////////////////////// - //////////////////////////////////////////////////////////////////// - - /** - * Get the URL to an image - * - * @param Image $image - * - * @return string - */ - public function getUrlTo(Image $image) - { - return $this->app['url']->asset( - $this->getOption('cache_folder'). - $this->cache->getHashOf($image)); - } - - /** - * Get the path to the public folder - * - * @return string - */ - public function getPublicFolder() - { - return $this->app['path.public'] - ? $this->app['path.public'].'/' - : './'; - } - - /** - * Get the cache folder - * - * @return string - */ - public function getCacheFolder() - { - return $this->getPublicFolder().$this->getOption('cache_folder'); - } + //////////////////////////////////////////////////////////////////// + /////////////////////////// IMAGE PROCESSING /////////////////////// + //////////////////////////////////////////////////////////////////// + + /** + * Process an Image + * + * @param Image $image + * + * @return string + */ + public function process(Image $image) { + + $endpoint = $this->cache->getCachePathOf($image); + + // If the image hasn't yet been processed, do it + // and then cache it + if (!$this->cache->isCached($image)) { + $quality = $image->getQuality() ? : $this->getOption('quality'); + $processedImage = $this->app['illuminage.processor']->process($image); + $processedImage->save($endpoint, array('quality' => (int)$quality)); + } + + return $endpoint; + } + + //////////////////////////////////////////////////////////////////// + ////////////////////////////// HELPERS ///////////////////////////// + //////////////////////////////////////////////////////////////////// + + /** + * Get the URL to an image + * + * @param Image $image + * + * @return string + */ + public function getUrlTo(Image $image) { + + return $this->app['url']->asset( + $this->getOption('cache_folder') . + $this->cache->getHashedPathOf($image) + ); + } + + /** + * Get the path to the public folder + * + * @return string + */ + public function getPublicFolder() { + + return $this->app['path.public'] + ? $this->app['path.public'] . '/' + : './'; + } + + /** + * Get the cache folder + * + * @return string + */ + public function getCacheFolder() { + + return $this->getPublicFolder() . $this->getOption('cache_folder'); + } } diff --git a/src/Illuminage/Image.php b/src/Illuminage/Image.php index 2f6f1a5..e634735 100644 --- a/src/Illuminage/Image.php +++ b/src/Illuminage/Image.php @@ -272,6 +272,39 @@ public function proportional($width, $height, $upscale = false) return $this; } + /** + * Resize an Image, proportional to width + * + * @param integer $width + */ + public function proportionalWidth($width) + { + $ratio = $width / $this->getOriginalSize()->getWidth(); + + $resize = $this->getOriginalSize()->scale($ratio); + $salts['resize'] = array($resize); + + $this->salts['resize'] = array($resize); + + return $this; + } + + /** + * Resize an Image, proportional to height + * + * @param integer $height + */ + public function proportionalHeight($height) + { + $ratio = $height / $this->getOriginalSize()->getHeight(); + + $resize = $this->getOriginalSize()->scale($ratio); + $salts['resize'] = array($resize); + + $this->salts['resize'] = array($resize); + + return $this; + } /** * Inverts the colors diff --git a/src/config/config.php b/src/config/config.php index 622120c..98e070d 100644 --- a/src/config/config.php +++ b/src/config/config.php @@ -6,6 +6,9 @@ // The cache folder inside `public` 'cache_folder' => 'packages/anahkiasen/illuminage/', + // The cache folder inside `public` + 'random_folder' => false, + // The default image quality 'quality' => 75,