<?php
namespace Assetic\Filter;
use Assetic\Exception\FilterException;
use Assetic\Asset\AssetInterface;
use Assetic\Filter\FilterInterface;
use Symfony\Component\Process\ProcessBuilder;
class CompassFilter implements FilterInterface {
private $compassPath;
private $rubyPath;
private $scss;
private $unixNewlines;
private $debugInfo;
private $cacheLocation;
private $noCache;
private $force;
private $style;
private $quiet;
private $boring;
private $noLineComments;
private $imagesDir;
private $javascriptsDir;
private $plugins = array();
private $loadPaths = array();
private $httpPath;
private $httpImagesPath;
private $generatedImagesPath;
private $httpJavascriptsPath;
private $homeEnv = true;
public function __construct($compassPath = '/usr/bin/compass', $rubyPath = null) {
$this->compassPath = $compassPath;
$this->rubyPath = $rubyPath;
$this->cacheLocation = sys_get_temp_dir();
if ('cli' !== php_sapi_name()) {
$this->boring = true;
}
}
public function setScss($scss) {
$this->scss = $scss;
}
public function setUnixNewlines($unixNewlines) {
$this->unixNewlines = $unixNewlines;
}
public function setDebugInfo($debugInfo) {
$this->debugInfo = $debugInfo;
}
public function setCacheLocation($cacheLocation) {
$this->cacheLocation = $cacheLocation;
}
public function setNoCache($noCache) {
$this->noCache = $noCache;
}
public function setForce($force) {
$this->force = $force;
}
public function setStyle($style) {
$this->style = $style;
}
public function setQuiet($quiet) {
$this->quiet = $quiet;
}
public function setBoring($boring) {
$this->boring = $boring;
}
public function setNoLineComments($noLineComments) {
$this->noLineComments = $noLineComments;
}
public function setImagesDir($imagesDir) {
$this->imagesDir = $imagesDir;
}
public function setJavascriptsDir($javascriptsDir) {
$this->javascriptsDir = $javascriptsDir;
}
public function setPlugins(array $plugins) {
$this->plugins = $plugins;
}
public function addPlugin($plugin) {
$this->plugins[] = $plugin;
}
public function setLoadPaths(array $loadPaths) {
$this->loadPaths = $loadPaths;
}
public function addLoadPath($loadPath) {
$this->loadPaths[] = $loadPath;
}
public function setHttpPath($httpPath) {
$this->httpPath = $httpPath;
}
public function setHttpImagesPath($httpImagesPath) {
$this->httpImagesPath = $httpImagesPath;
}
public function setGeneratedImagesPath($generatedImagesPath) {
$this->generatedImagesPath = $generatedImagesPath;
}
public function setHttpJavascriptsPath($httpJavascriptsPath) {
$this->httpJavascriptsPath = $httpJavascriptsPath;
}
public function setHomeEnv($homeEnv) {
$this->homeEnv = $homeEnv;
}
public function filterLoad(AssetInterface $asset) {
$root = $asset
->getSourceRoot();
$path = $asset
->getSourcePath();
$loadPaths = $this->loadPaths;
if ($root && $path) {
$loadPaths[] = dirname($root . '/' . $path);
}
$tempDir = realpath(sys_get_temp_dir());
$compassProcessArgs = array(
$this->compassPath,
'compile',
$tempDir,
);
if (null !== $this->rubyPath) {
$compassProcessArgs = array_merge(explode(' ', $this->rubyPath), $compassProcessArgs);
}
$pb = new ProcessBuilder($compassProcessArgs);
$pb
->inheritEnvironmentVariables();
if ($this->force) {
$pb
->add('--force');
}
if ($this->style) {
$pb
->add('--output-style')
->add($this->style);
}
if ($this->quiet) {
$pb
->add('--quiet');
}
if ($this->boring) {
$pb
->add('--boring');
}
if ($this->noLineComments) {
$pb
->add('--no-line-comments');
}
if ($this->imagesDir) {
$pb
->add('--images-dir')
->add($this->imagesDir);
}
if ($this->javascriptsDir) {
$pb
->add('--javascripts-dir')
->add($this->javascriptsDir);
}
$optionsConfig = array();
if (!empty($loadPaths)) {
$optionsConfig['additional_import_paths'] = $loadPaths;
}
if ($this->unixNewlines) {
$optionsConfig['sass_options']['unix_newlines'] = true;
}
if ($this->debugInfo) {
$optionsConfig['sass_options']['debug_info'] = true;
}
if ($this->cacheLocation) {
$optionsConfig['sass_options']['cache_location'] = $this->cacheLocation;
}
if ($this->noCache) {
$optionsConfig['sass_options']['no_cache'] = true;
}
if ($this->httpPath) {
$optionsConfig['http_path'] = $this->httpPath;
}
if ($this->httpImagesPath) {
$optionsConfig['http_images_path'] = $this->httpImagesPath;
}
if ($this->generatedImagesPath) {
$optionsConfig['generated_images_path'] = $this->generatedImagesPath;
}
if ($this->httpJavascriptsPath) {
$optionsConfig['http_javascripts_path'] = $this->httpJavascriptsPath;
}
if (count($optionsConfig)) {
$config = array();
foreach ($this->plugins as $plugin) {
$config[] = sprintf("require '%s'", addcslashes($plugin, '\\'));
}
foreach ($optionsConfig as $name => $value) {
if (!is_array($value)) {
$config[] = sprintf('%s = "%s"', $name, addcslashes($value, '\\'));
}
elseif (!empty($value)) {
$config[] = sprintf('%s = %s', $name, $this
->formatArrayToRuby($value));
}
}
$configFile = tempnam($tempDir, 'assetic_compass');
file_put_contents($configFile, implode("\n", $config) . "\n");
$pb
->add('--config')
->add($configFile);
}
$pb
->add('--sass-dir')
->add('')
->add('--css-dir')
->add('');
if (null !== $this->scss) {
$type = $this->scss ? 'scss' : 'sass';
}
elseif ($path) {
$type = pathinfo($path, PATHINFO_EXTENSION);
}
else {
$type = 'scss';
}
$tempName = tempnam($tempDir, 'assetic_compass');
unlink($tempName);
$input = $tempName . '.' . $type;
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
$input = str_replace('\\', '/', $input);
}
$pb
->add($input);
file_put_contents($input, $asset
->getContent());
$output = $tempName . '.css';
if ($this->homeEnv) {
$pb
->setEnv('HOME', sys_get_temp_dir());
}
$proc = $pb
->getProcess();
$code = $proc
->run();
if (0 < $code) {
unlink($input);
if (isset($configFile)) {
unlink($configFile);
}
throw FilterException::fromProcess($proc)
->setInput($asset
->getContent());
}
$asset
->setContent(file_get_contents($output));
unlink($input);
unlink($output);
if (isset($configFile)) {
unlink($configFile);
}
}
public function filterDump(AssetInterface $asset) {
}
private function formatArrayToRuby($array) {
$output = array();
if (count(array_filter(array_keys($array), "is_numeric")) != count($array)) {
foreach ($array as $name => $value) {
$output[] = sprintf(' :%s => "%s"', $name, addcslashes($value, '\\'));
}
$output = "{\n" . implode(",\n", $output) . "\n}";
}
else {
foreach ($array as $name => $value) {
$output[] = sprintf(' "%s"', addcslashes($value, '\\'));
}
$output = "[\n" . implode(",\n", $output) . "\n]";
}
return $output;
}
}