4 * This file provides the part of lessphp API (https://github.com/leafo/lessphp)
5 * to be a drop-in replacement for following products:
6 * - Drupal 7, by the less module v3.0+ (https://drupal.org/project/less)
8 * https://github.com/oyejorge/less.php
10 require_once 'HTML/Less/Version.php';
14 static public $VERSION = HTML_Less_Version::less_version;
15 public $importDir = '';
16 protected $allParsedFiles = array();
17 protected $libFunctions = array();
18 var $registeredVars = array();
19 private $formatterName;
20 private $options = array();
22 public function __construct($lessc = null, $sourceName = null)
27 public function setImportDir($dirs)
29 $this->importDir = (array) $dirs;
32 public function addImportDir($dir)
34 $this->importDir = (array) $this->importDir;
35 $this->importDir[] = $dir;
38 public function setFormatter($name)
40 $this->formatterName = $name;
43 public function setPreserveComments($preserve)
48 public function registerFunction($name, $func)
50 $this->libFunctions[$name] = $func;
53 public function unregisterFunction($name)
55 unset($this->libFunctions[$name]);
58 public function setVariables($variables)
60 foreach ($variables as $name => $value) {
61 $this->setVariable($name, $value);
65 public function setVariable($name, $value)
67 $this->registeredVars[$name] = $value;
70 public function unsetVariable($name)
72 unset($this->registeredVars[$name]);
75 public function setOptions($options)
77 foreach ($options as $name => $value) {
78 $this->setOption($name, $value);
82 public function setOption($name, $value)
84 $this->options[$name] = $value;
87 public function parse($buffer, $presets = array())
89 $this->setVariables($presets);
91 require_once 'HTML/Less/Parser.php';
93 $parser = new HTML_Less_Parser($this->getOptions());
94 $parser->setImportDirs($this->getImportDirs());
95 foreach ($this->libFunctions as $name => $func) {
96 $parser->registerFunction($name, $func);
98 $parser->parse($buffer);
99 if (count($this->registeredVars)) {
100 $parser->ModifyVars($this->registeredVars);
102 return $parser->getCss();
105 protected function getOptions()
107 $options = array('relativeUrls' => false);
108 switch ($this->formatterName) {
110 $options['compress'] = true;
113 if (is_array($this->options)) {
114 $options = array_merge($options, $this->options);
119 protected function getImportDirs()
121 $dirs_ = (array) $this->importDir;
123 foreach ($dirs_ as $dir) {
129 public function compile($string, $name = null)
131 $oldImport = $this->importDir;
132 $this->importDir = (array) $this->importDir;
134 $this->allParsedFiles = array();
136 require_once 'HTML/Less/Parser.php';
138 $parser = new HTML_Less_Parser($this->getOptions());
139 $parser->SetImportDirs($this->getImportDirs());
140 if (count($this->registeredVars)) {
141 $parser->ModifyVars($this->registeredVars);
143 foreach ($this->libFunctions as $name => $func) {
144 $parser->registerFunction($name, $func);
146 $parser->parse($string);
147 $out = $parser->getCss();
149 $parsed = HTML_Less_Parser::AllParsedFiles();
150 foreach ($parsed as $file) {
151 $this->addParsedFile($file);
154 $this->importDir = $oldImport;
159 public function compileFile($fname, $outFname = null)
161 if (!is_readable($fname)) {
162 throw new Exception('load error: failed to find ' . $fname);
165 require_once 'HTML/Less/Parser.php';
167 $pi = pathinfo($fname);
169 $oldImport = $this->importDir;
171 $this->importDir = (array) $this->importDir;
172 $this->importDir[] = HTML_Less_Parser::AbsPath($pi['dirname']) . '/';
174 $this->allParsedFiles = array();
175 $this->addParsedFile($fname);
177 $parser = new HTML_Less_Parser($this->getOptions());
178 $parser->SetImportDirs($this->getImportDirs());
179 if (count($this->registeredVars)) {
180 $parser->ModifyVars($this->registeredVars);
182 foreach ($this->libFunctions as $name => $func) {
183 $parser->registerFunction($name, $func);
185 $parser->parseFile($fname);
187 //print_R($parser->getVariables());
189 $out = $parser->getCss();
191 $parsed = HTML_Less_Parser::AllParsedFiles();
192 foreach ($parsed as $file) {
193 $this->addParsedFile($file);
196 $this->importDir = $oldImport;
198 if ($outFname !== null) {
199 return file_put_contents($outFname, $out);
205 public function checkedCompile($in, $out)
207 if (!is_file($out) || filemtime($in) > filemtime($out)) {
208 $this->compileFile($in, $out);
215 * Execute lessphp on a .less file or a lessphp cache structure
217 * The lessphp cache structure contains information about a specific
218 * less file having been parsed. It can be used as a hint for future
219 * calls to determine whether or not a rebuild is required.
221 * The cache structure contains two important keys that may be used
224 * compiled: The final compiled CSS
225 * updated: The time (in seconds) the CSS was last compiled
227 * The cache structure is a plain-ol' PHP associative array and can
228 * be serialized and unserialized without a hitch.
230 * @param mixed $in Input
231 * @param bool $force Force rebuild?
232 * @return array lessphp cache structure
234 public function cachedCompile($in, $force = false)
239 if (is_string($in)) {
241 } elseif (is_array($in) and isset($in['root'])) {
242 if ($force or ! isset($in['files'])) {
243 // If we are forcing a recompile or if for some reason the
244 // structure does not contain any file information we should
245 // specify the root to trigger a rebuild.
247 } elseif (isset($in['files']) and is_array($in['files'])) {
248 foreach ($in['files'] as $fname => $ftime) {
249 if (!file_exists($fname) or filemtime($fname) > $ftime) {
250 // One of the files we knew about previously has changed
251 // so we should look at our incoming root again.
258 // TODO: Throw an exception? We got neither a string nor something
259 // that looks like a compatible lessphp cache structure.
263 if ($root !== null) {
264 // If we have a root value which means we should rebuild.
266 $out['root'] = $root;
267 $out['compiled'] = $this->compileFile($root);
268 $out['files'] = $this->allParsedFiles();
269 $out['updated'] = time();
272 // No changes, pass back the structure
273 // we were given initially.
278 public function ccompile($in, $out, $less = null)
280 if ($less === null) {
283 return $less->checkedCompile($in, $out);
286 public static function cexecute($in, $force = false, $less = null)
288 if ($less === null) {
291 return $less->cachedCompile($in, $force);
294 public function allParsedFiles()
296 return $this->allParsedFiles;
299 protected function addParsedFile($file)
301 require_once 'HTML/Less/Parser.php';
302 $this->allParsedFiles[HTML_Less_Parser::AbsPath($file)] = filemtime($file);