1<?php 2 3/* 4 * This file is part of the Assetic package, an OpenSky project. 5 * 6 * (c) 2010-2014 OpenSky Project Inc 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Assetic\Filter; 13 14use Assetic\Asset\AssetInterface; 15use Assetic\Factory\AssetFactory; 16use Assetic\Util\CssUtils; 17use Leafo\ScssPhp\Compiler; 18 19/** 20 * Loads SCSS files using the PHP implementation of scss, scssphp. 21 * 22 * Scss files are mostly compatible, but there are slight differences. 23 * 24 * @link http://leafo.net/scssphp/ 25 * 26 * @author Bart van den Burg <bart@samson-it.nl> 27 */ 28class ScssphpFilter implements DependencyExtractorInterface 29{ 30 private $compass = false; 31 private $importPaths = array(); 32 private $customFunctions = array(); 33 private $formatter; 34 private $variables = array(); 35 36 public function enableCompass($enable = true) 37 { 38 $this->compass = (Boolean) $enable; 39 } 40 41 public function isCompassEnabled() 42 { 43 return $this->compass; 44 } 45 46 public function setFormatter($formatter) 47 { 48 $legacyFormatters = array( 49 'scss_formatter' => 'Leafo\ScssPhp\Formatter\Expanded', 50 'scss_formatter_nested' => 'Leafo\ScssPhp\Formatter\Nested', 51 'scss_formatter_compressed' => 'Leafo\ScssPhp\Formatter\Compressed', 52 'scss_formatter_crunched' => 'Leafo\ScssPhp\Formatter\Crunched', 53 ); 54 55 if (isset($legacyFormatters[$formatter])) { 56 @trigger_error(sprintf('The scssphp formatter `%s` is deprecated. Use `%s` instead.', $formatter, $legacyFormatters[$formatter]), E_USER_DEPRECATED); 57 58 $formatter = $legacyFormatters[$formatter]; 59 } 60 61 $this->formatter = $formatter; 62 } 63 64 public function setVariables(array $variables) 65 { 66 $this->variables = $variables; 67 } 68 69 public function addVariable($variable) 70 { 71 $this->variables[] = $variable; 72 } 73 74 public function setImportPaths(array $paths) 75 { 76 $this->importPaths = $paths; 77 } 78 79 public function addImportPath($path) 80 { 81 $this->importPaths[] = $path; 82 } 83 84 public function registerFunction($name, $callable) 85 { 86 $this->customFunctions[$name] = $callable; 87 } 88 89 public function filterLoad(AssetInterface $asset) 90 { 91 $sc = new Compiler(); 92 93 if ($this->compass) { 94 new \scss_compass($sc); 95 } 96 97 if ($dir = $asset->getSourceDirectory()) { 98 $sc->addImportPath($dir); 99 } 100 101 foreach ($this->importPaths as $path) { 102 $sc->addImportPath($path); 103 } 104 105 foreach ($this->customFunctions as $name => $callable) { 106 $sc->registerFunction($name, $callable); 107 } 108 109 if ($this->formatter) { 110 $sc->setFormatter($this->formatter); 111 } 112 113 if (!empty($this->variables)) { 114 $sc->setVariables($this->variables); 115 } 116 117 $asset->setContent($sc->compile($asset->getContent())); 118 } 119 120 public function filterDump(AssetInterface $asset) 121 { 122 } 123 124 public function getChildren(AssetFactory $factory, $content, $loadPath = null) 125 { 126 $sc = new Compiler(); 127 if ($loadPath !== null) { 128 $sc->addImportPath($loadPath); 129 } 130 131 foreach ($this->importPaths as $path) { 132 $sc->addImportPath($path); 133 } 134 135 $children = array(); 136 foreach (CssUtils::extractImports($content) as $match) { 137 $file = $sc->findImport($match); 138 if ($file) { 139 $children[] = $child = $factory->createAsset($file, array(), array('root' => $loadPath)); 140 $child->load(); 141 $children = array_merge($children, $this->getChildren($factory, $child->getContent(), $loadPath)); 142 } 143 } 144 145 return $children; 146 } 147} 148