From 6b3626a6b2e9791e950be533706d385a13babedb Mon Sep 17 00:00:00 2001 From: gerard sychay Date: Fri, 3 May 2013 17:26:27 -0400 Subject: [PATCH 1/4] Middleware for LESS CSS --- Middleware/Less.php | 174 +++++++++++++++++++++++++++++++++++++ Middleware/README.markdown | 33 +++++++ composer.json | 3 + 3 files changed, 210 insertions(+) create mode 100644 Middleware/Less.php diff --git a/Middleware/Less.php b/Middleware/Less.php new file mode 100644 index 0000000..f9b8e2a --- /dev/null +++ b/Middleware/Less.php @@ -0,0 +1,174 @@ + + * @version 1.0 + * + * USAGE + * + * $app = new \Slim\Slim(); + * $app->add(new \Slim\Extras\Middleware\Less(array( + * 'src' => '/path/to/public' + * )); + * + * MIT LICENSE + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +namespace Slim\Extras\Middleware; + +use \Slim\Middleware; +use \Assetic\Filter\LessphpFilter; +use \Assetic\Filter\CssMinFilter; +use \Assetic\Filter\CssImportFilter; +use \Assetic\Asset\FileAsset; +use \Assetic\Asset\AssetCache; +use \Assetic\Cache\FilesystemCache; + +class Less extends Middleware +{ + /** + * @var array + */ + public $options; + + /** + * Constructor + * + * @param array $options Configuration options for LESS compilation + */ + public function __construct($options = null) + { + // Default options + $this->options = array( + 'src' => null, + 'cache' => true, + 'cache.dir' => null, + 'minify' => true, + 'debug' => false + ); + + if ($options) + { + $this->options = array_merge($this->options, (array) $options); + } + + if ($this->options['src'] === null) + { + throw new \InvalidArgumentException("'src' directory is required."); + } + + if ($this->options['cache.dir'] === null) + { + $this->options['cache.dir'] = $this->options['src']; + } + } + + /** + * Debug + * + * This method will send messages to the Slim Logger at a DEBUG level. + */ + public function debug($arg) + { + if ($this->options['debug'] === true) + { + $this->app->getLog()->debug($arg); + } + } + + /** + * Call + * + * This method will check the HTTP request to see if it is a CSS file. If + * so, it will attempt to find a corresponding LESS file. If one is found, + * it will compile the file to CSS and serve it, optionally saving the CSS + * to a filesystem cache. The request will end at this point. + * + * If the request is not for a CSS file, or if the corresponding LESS file + * is not found, this middleware will pass the request on. + */ + public function call() + { + $app = $this->app; + + // PHP 5.3 closures do not have access to $this, so we must proxy it in. + // However, the proxy only has access to public fields. + $self = $this; + + $app->hook('slim.before', function() use ($app, $self) { + $path = $app->request()->getPathInfo(); + + // Run filter only for requests for CSS files + if (preg_match('/\.css$/', $path)) + { + $path = preg_replace('/\.css$/', '.less', $path); + + // Get absolute physical path on filesystem for LESS file + $abs = $self->options['src'] . '/' . $path; + + $self->debug("Looking for LESS file: $abs"); + + $abs = realpath($abs); + + if ($abs === false) + { + // If LESS file is not found, just return + $self->debug("LESS file not found: $abs"); + return; + } + + $self->debug("LESS file found: $abs"); + + // Prepare Assetic + $lessFilter = new LessphpFilter(); + $importFilter = new CssImportFilter(); + $css = new FileAsset($abs, array($lessFilter, $importFilter)); + + if ($self->options['minify'] === true) + { + // Minify, if desired + $self->debug("Minifying LESS file: $abs"); + $css->ensureFilter(new CssMinFilter()); + } + + if ($self->options['cache'] === true) + { + // Cache results, if desired + $self->debug("Caching LESS file: {$self->options['cache.dir']}"); + $cache = new FilesystemCache($self->options['cache.dir']); + $css = new AssetCache($css, $cache); + } + + // Render results and exit + header('Content-Type: text/css'); + echo $css->dump(); + ob_end_flush(); + exit; + } + }); + + $this->next->call(); + } +} diff --git a/Middleware/README.markdown b/Middleware/README.markdown index c6d76da..4aa19ec 100644 --- a/Middleware/README.markdown +++ b/Middleware/README.markdown @@ -73,3 +73,36 @@ Here is some sample code for using PDO provider and securing some routes using r ); $app->add(new StrongAuth($config)); + +## LESS + +This middleware will intercept requests for CSS files and attempt to find a +corresponding [LESS CSS](http://lesscss.org) file. If one is found, it will +compile the file to CSS and serve it, optionally saving the CSS to a filesystem +cache. Inspired by [less.js-middleware](https://github.com/emberfeather/less.js-middleware). + +### How to use + +* `src` - Directory to look for LESS files. Example: if `src` is set to + `/path/to/public`, and a request for `http://mysite.com/css/style.css` is + received, then it will look for a LESS file in + `/path/to/public/css/style.less`. __REQUIRED__. +* `cache` - Cache CSS file to filesystem. Default is `true`. +* `cache.dir` - Directory for the cached CSS file. Default is `src`. +* `minify` - Minify the CSS output. +* `debug` - Send debug messages to Slim Logger. + +Example: + + use \Slim\Slim; + use \Slim\Extras\Middleware\Less; + + $app = new Slim(); + $app->add(new Less(array( + 'src' => '/path/to/public', + 'cache' => true, + 'cache.dir' => '/path/to/cache', + 'minify' => true, + 'debug' => false + )); + diff --git a/composer.json b/composer.json index 5901dc7..f6d22bc 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,9 @@ ], "require": { "slim/slim": ">=2.0.0", + "kriswallsmith/assetic": "1.0.*", + "leafo/lessphp": "0.3.*", + "natxet/CssMin": "dev-master#9801e2a0de7ae252ca4f2b85542d75a82047a8b4", "php": ">=5.3.0" }, "autoload": { From ccd0e31bd010f7a306df505552011613ae0881aa Mon Sep 17 00:00:00 2001 From: gerard sychay Date: Fri, 3 May 2013 18:43:12 -0400 Subject: [PATCH 2/4] Fix README. Add defaults to LESS example. --- Middleware/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Middleware/README.markdown b/Middleware/README.markdown index 4aa19ec..bef0821 100644 --- a/Middleware/README.markdown +++ b/Middleware/README.markdown @@ -89,8 +89,8 @@ cache. Inspired by [less.js-middleware](https://github.com/emberfeather/less.js- `/path/to/public/css/style.less`. __REQUIRED__. * `cache` - Cache CSS file to filesystem. Default is `true`. * `cache.dir` - Directory for the cached CSS file. Default is `src`. -* `minify` - Minify the CSS output. -* `debug` - Send debug messages to Slim Logger. +* `minify` - Minify the CSS output. Default is `true`. +* `debug` - Send debug messages to Slim Logger. Default is `false`. Example: From b4ba8d99358e6daa8cab96d1e223ddbaed129706 Mon Sep 17 00:00:00 2001 From: gerard sychay Date: Sat, 4 May 2013 11:26:37 -0400 Subject: [PATCH 3/4] Halt app the "Slim" way --- Middleware/Less.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Middleware/Less.php b/Middleware/Less.php index f9b8e2a..5bbd26c 100644 --- a/Middleware/Less.php +++ b/Middleware/Less.php @@ -162,10 +162,9 @@ public function call() } // Render results and exit - header('Content-Type: text/css'); - echo $css->dump(); - ob_end_flush(); - exit; + $res = $app->response(); + $res['Content-Type'] = 'text/css'; + $app->halt(200, echo $css->dump()); } }); From 122195426f4fc6ee7069aa913b1a444fad6514af Mon Sep 17 00:00:00 2001 From: gerard sychay Date: Tue, 7 May 2013 20:06:14 -0400 Subject: [PATCH 4/4] Remove stray 'echo' --- Middleware/Less.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Middleware/Less.php b/Middleware/Less.php index 5bbd26c..2fb6168 100644 --- a/Middleware/Less.php +++ b/Middleware/Less.php @@ -164,7 +164,7 @@ public function call() // Render results and exit $res = $app->response(); $res['Content-Type'] = 'text/css'; - $app->halt(200, echo $css->dump()); + $app->halt(200, $css->dump()); } });