/** * Compiles the less source file $path to the CSS file $compiled unless it is up to date * according to the high quality dependency checking provided by lessphp */ public static function compileLessIfNeeded($path, $compiled, $options = array()) { // In production just return if the final compiled file exists. // This is good enough in production because we symfony cc on deployment. // Unserializing the cache file is way faster than recompiling less code // but it's nowhere near instant as jeremy pointed out if (!sfConfig::get('app_a_less_check_dependencies', true)) { if (file_exists($compiled)) { return; } } // Leverage the considerable caching abilities of lessphp directly. // it's smart enough to pay attention to whether imported files // were cached or not, and we're not that smart if (!isset(aAssets::$lessc)) { // We do it like factories.yml does it, defaulting to the built in lessc. // this is a nice injection point because it's common to subclass lessc // The regular lessc class constructor doesn't take useful constructor parameters // as far as we're concerned, it doesn't even use its second argument '$opts'. // But you can write subclasses that take a useful options array as their // first argument $factory = sfConfig::get('app_a_lessc', array('class' => 'lessc', 'param' => null)); $class = $factory['class']; $param = $factory['param']; aAssets::$lessc = new $class($param); // set a new import directory in app.yml if you want to change our imported files, like a-helpers.less } // importDir must be reset for each file since they may be in different folders $importDir = sfConfig::get('app_a_less_import_directory', dirname($path) . '/'); aAssets::$lessc->importDir = $importDir; // The cache key should be the compiled css filename, not the original less filename, because // if we choose to compile the same less file to two different places we'll be misled by the // cache into thinking both destination files already exist. An awesomer solution might be to // keep the compiled css in the cache, but that would slow us down in the more common case where // there is only one destination CSS file per source less file $info = aAssets::getCached($compiled); if (is_null($info)) { $info = $path; } $lastUpdated = is_array($info) ? $info['updated'] : 0; $info = aAssets::cexecute($info, false); // Our replacement for cexecute() calls parse() on the contents of a file, so // the cache info structure is missing the name of the original requested file. // Add that back in so the dependency checking works for the file itself if (!isset($info['files'][$path])) { $info['files'][$path] = filemtime($path); } if ($info['updated'] !== $lastUpdated) { // Copy it to our asset cache folder since it has changed file_put_contents($compiled, $info['compiled']); } unset($info['compiled']); aAssets::setCached($compiled, $info); }