Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Middleware for LESS CSS #70

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions Middleware/Less.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<?php
/**
* LESS CSS Middleware
*
* Use this middleware with your Slim Framework application
* to compile LESS CSS files to plain CSS on-the-fly.
*
* @author Gerard Sychay <[email protected]>
* @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
$res = $app->response();
$res['Content-Type'] = 'text/css';
$app->halt(200, $css->dump());
}
});

$this->next->call();
}
}
33 changes: 33 additions & 0 deletions Middleware/README.markdown
Original file line number Diff line number Diff line change
@@ -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. Default is `true`.
* `debug` - Send debug messages to Slim Logger. Default is `false`.

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
));

3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -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": {