PageRenderTime 1231ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/src/PieCrust/Baker/Processors/CompassProcessor.php

https://bitbucket.org/ndj/piecrust
PHP | 265 lines | 214 code | 38 blank | 13 comment | 26 complexity | 70406b584bfff27fc8bc11fd173b42c7 MD5 | raw file
  1. <?php
  2. namespace PieCrust\Baker\Processors;
  3. use PieCrust\IPieCrust;
  4. use PieCrust\PieCrustException;
  5. use PieCrust\Baker\IBaker;
  6. class CompassProcessor implements IProcessor
  7. {
  8. protected $pieCrust;
  9. protected $logger;
  10. protected $baker;
  11. protected $initialized;
  12. protected $needsRunning;
  13. protected $needsRunningInTheme;
  14. protected $binDir;
  15. protected $configPath;
  16. protected $options;
  17. public function __construct()
  18. {
  19. $this->initialized = false;
  20. }
  21. public function getName()
  22. {
  23. return 'compass';
  24. }
  25. public function initialize(IPieCrust $pieCrust, $logger = null)
  26. {
  27. $this->pieCrust = $pieCrust;
  28. if ($logger == null)
  29. $logger = \Log::singleton('null', '', '');
  30. $this->logger = $logger;
  31. }
  32. public function getPriority()
  33. {
  34. return IProcessor::PRIORITY_DEFAULT;
  35. }
  36. public function onBakeStart(IBaker $baker)
  37. {
  38. $this->baker = $baker;
  39. $this->needsRunning = false;
  40. $this->needsRunningInTheme = false;
  41. }
  42. public function supportsExtension($extension)
  43. {
  44. // Initialize ourselves... if Compass is not specifically enabled,
  45. // don't support anything.
  46. $this->ensureInitialized();
  47. if (!$this->usingCompass)
  48. return false;
  49. return ($extension == 'scss' or $extension == 'sass');
  50. }
  51. public function isBypassingStructuredProcessing()
  52. {
  53. return true;
  54. }
  55. public function isDelegatingDependencyCheck()
  56. {
  57. return false;
  58. }
  59. public function getDependencies($path)
  60. {
  61. throw new PieCrustException("Compass processor should bypass structured processing.");
  62. }
  63. public function getOutputFilenames($filename)
  64. {
  65. throw new PieCrustException("Compass processor should bypass structured processing.");
  66. }
  67. public function process($inputPath, $outputDir)
  68. {
  69. // Nothing... Compass processes all files in the project, so we
  70. // run it when the bake is finished.
  71. $themeDir = $this->pieCrust->getThemeDir();
  72. if ($themeDir && strncmp($inputPath, $themeDir, count($themeDir)))
  73. {
  74. if (!$this->needsRunningInTheme)
  75. $this->logger->debug("Scheduling Compass execution in theme directory after the bake.");
  76. $this->needsRunningInTheme = true;
  77. }
  78. else
  79. {
  80. if (!$this->needsRunning)
  81. $this->logger->debug("Scheduling Compass execution after the bake.");
  82. $this->needsRunning = true;
  83. }
  84. }
  85. public function onBakeEnd()
  86. {
  87. $this->runCompass();
  88. $this->baker = null;
  89. }
  90. protected function runCompass()
  91. {
  92. // If no SCSS or SASS files were encountered during the bake,
  93. // there's no need to run Compass.
  94. $this->ensureInitialized();
  95. if (!$this->usingCompass)
  96. return;
  97. $runCompassIn = array();
  98. if ($this->needsRunning)
  99. $runCompassIn[] = $this->pieCrust->getRootDir();
  100. if ($this->needsRunningInTheme)
  101. $runCompassIn[] = $this->pieCrust->getThemeDir();
  102. if (count($runCompassIn) == 0)
  103. return;
  104. // Run Compass!
  105. foreach ($runCompassIn as $i => $dir)
  106. {
  107. $exePath = 'compass';
  108. if ($this->binDir != null)
  109. $exePath = $this->binDir . $exePath;
  110. $cssDir = $this->baker->getBakeDir() . 'stylesheets';
  111. $cmd = "{$exePath} compile --css-dir=\"{$cssDir}\" {$this->options}";
  112. $this->logger->debug("Running Compass in '{$dir}'");
  113. $this->logger->debug('$> '.$cmd);
  114. $cwd = getcwd();
  115. chdir($dir);
  116. shell_exec($cmd);
  117. chdir($cwd);
  118. }
  119. }
  120. protected function ensureInitialized()
  121. {
  122. if ($this->initialized)
  123. return;
  124. $config = $this->pieCrust->getConfig();
  125. if ($config->getValue('compass/use_compass') !== true)
  126. {
  127. // This processor is deactivated unless `use_compass` is
  128. // specifically set to `true`.
  129. $this->initialized = true;
  130. $this->usingCompass = false;
  131. return;
  132. }
  133. $this->logger->debug("Will use Compass for processing SCSS/SASS files.");
  134. // Get the compass binary location, if any.
  135. $this->binDir = $config->getValue('compass/bin_dir');
  136. if ($this->binDir != null)
  137. $this->binDir = rtrim($this->binDir, '/\\') . DIRECTORY_SEPARATOR;
  138. // Get the compass configuration location, if any.
  139. $autoGenConfig = $config->getValue('compass/auto_config');
  140. $this->configPath = $config->getValue('compass/config_path');
  141. if ($this->configPath == null)
  142. $this->configPath = $this->pieCrust->getRootDir() . 'config.rb';
  143. if (!$autoGenConfig && !is_file($this->configPath))
  144. throw new PieCrustException(
  145. "No such Compass configuration file '{$this->configPath}'. ".
  146. "Either specify an existing one with `compass/config_path`, ".
  147. "or set `compass/auto_config` to `true` to let PieCrust create it for you."
  148. );
  149. if ($autoGenConfig)
  150. {
  151. // Figure out where to put the compass configuration file.
  152. if ($this->pieCrust->isCachingEnabled())
  153. $this->configPath = $this->pieCrust->getCacheDir() . 'compass-config.rb';
  154. else
  155. $this->configPath = tempnam(sys_get_temp_dir(), 'compass-config');
  156. // Build the configuration file if it doesn't exist.
  157. if (!is_file($this->configPath))
  158. $this->autoGenConfig($this->configPath);
  159. }
  160. // Build the compass command line options.
  161. $this->options = '--config "' . $this->configPath . '"';
  162. $frameworks = $config->getValue('compass/frameworks');
  163. if (!$frameworks)
  164. {
  165. $frameworks = array();
  166. }
  167. elseif (!is_array($frameworks))
  168. {
  169. $frameworks = array($frameworks);
  170. }
  171. foreach ($frameworks as $f)
  172. {
  173. $this->options .= " --load {$p}";
  174. }
  175. $miscOptions = $config->getValue('compass/options');
  176. if ($miscOptions)
  177. $this->options .= ' ' . $miscOptions;
  178. $this->usingCompass = true;
  179. $this->runInTheme = false;
  180. $this->runInRoot = false;
  181. $this->initialized = true;
  182. }
  183. protected function autoGenConfig($configPath)
  184. {
  185. $this->logger->debug("Generating Compass config file at: {$configPath}");
  186. $configContents = '';
  187. $config = $this->pieCrust->getConfig();
  188. // Root HTTP url.
  189. $rootUrl = $config->getValue('site/root');
  190. if ($rootUrl)
  191. $configContents .= 'http_path = "' . addcslashes($rootUrl, '\\') . '"' . PHP_EOL;
  192. // CSS style.
  193. $style = $config->getValue('compass/style');
  194. if (!$style)
  195. $style = 'nested';
  196. $configContents .= 'output_style = :' . $style . PHP_EOL;
  197. // Cache location.
  198. if ($this->pieCrust->isCachingEnabled())
  199. {
  200. $cacheDir = $this->pieCrust->getCacheDir() . 'sass_cache';
  201. $escapedCacheDir = addcslashes($cacheDir, '\\');
  202. $configContents .= 'sass_options = { :cache_location => "' . $escapedCacheDir . '" }' . PHP_EOL;
  203. }
  204. else
  205. {
  206. $configContents .= 'sass_options = { :cache => false }' . PHP_EOL;
  207. }
  208. // Custom directories.
  209. $dirNames = array('sass', 'images', 'generated_images', 'javascripts', 'fonts');
  210. foreach ($dirNames as $dirName)
  211. {
  212. $dir = $config->getValue("compass/{$dirName}_dir");
  213. if ($dir)
  214. {
  215. $escapedDir = addcslashes($dir, '\\');
  216. $configContents .= $dirName . '_dir = "' . $escapedDir . '"' . PHP_EOL;
  217. }
  218. }
  219. // Done!
  220. file_put_contents($configPath, $configContents);
  221. }
  222. }