PageRenderTime 56ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/compressor.class.php

https://bitbucket.org/ardydedase/web-build-optimizer
PHP | 512 lines | 265 code | 102 blank | 145 comment | 14 complexity | fef9b9d5ff2f38df75998fe88dba1081 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1. <?php
  2. /**
  3. * Abstract Compressor class
  4. * this class is dependent on the AWS SDK
  5. *
  6. */
  7. abstract class Compressor
  8. {
  9. // CompressorType
  10. protected $_compressor_script;
  11. protected $_file_type;
  12. /**
  13. * This method will call the appropriate compress method
  14. *
  15. * @param type $input
  16. * @param type $output
  17. */
  18. public function perform_compression($input)
  19. {
  20. if(isset($input))
  21. {
  22. return $this->_compressor_script->compress($input);
  23. }
  24. else
  25. {
  26. echo "nothing to compress\n";
  27. }
  28. }
  29. /**
  30. * Generate hashed filename with with its "date modified" string
  31. *
  32. * @param type $input
  33. * @param type $file_type
  34. * @param type $prefix
  35. * @return type
  36. */
  37. public static function generate_filename($input, $file_type, $prefix = 'x-')
  38. {
  39. echo __METHOD__;
  40. echo PHP_EOL . 'input: ' . $input . PHP_EOL;
  41. $last_changed = date("F d Y H:i:s.", filemtime($input));
  42. // use the relative file path instead to easily test it.
  43. $relative_file_path = str_replace(Config::$resources_path, '', $input);
  44. return $prefix . md5($relative_file_path . $last_changed) . '.' . $file_type;
  45. }
  46. public static function sync_to_build()
  47. {
  48. $source_path = Config::$source_path;
  49. $build_path = Config::$build_path;
  50. echo PHP_EOL . 'Synching to the target build path.' . PHP_EOL;
  51. // sync the required build folders, exclude folders that are not needed
  52. // $cmd = "sh $source_path/build_rsync.sh $source_path/. $build_path";
  53. $cmd = sprintf('sh %s %s/. %s', Config::$build_rsync, $source_path, $build_path);
  54. echo $cmd . PHP_EOL;
  55. $shell_output = shell_exec($cmd);
  56. echo 'shell s' . PHP_EOL;
  57. var_dump($shell_output);
  58. }
  59. }
  60. /**
  61. * JSCompressor
  62. */
  63. class JSCompressor extends Compressor
  64. {
  65. public function __construct()
  66. {
  67. $this->_compressor_script = new ClosureCompiler();
  68. // set the file type
  69. $this->_file_type = JS_FILETYPE;
  70. }
  71. }
  72. /**
  73. * CSSCompressor
  74. */
  75. class CSSCompressor extends Compressor
  76. {
  77. public function __construct()
  78. {
  79. $this->_compressor_script = new YUICompressor();
  80. $this->_file_type = CSS_FILETYPE;
  81. }
  82. }
  83. /**
  84. * HTMLCompressor
  85. */
  86. class TemplateCompressor extends Compressor
  87. {
  88. public function __construct()
  89. {
  90. $this->_compressor_script = new HTMLCompressor();
  91. $this->_file_type = HTML_FILETYPE;
  92. }
  93. }
  94. /**
  95. * PNGCompressor
  96. *
  97. */
  98. class PNGCompressor extends Compressor
  99. {
  100. public function __construct()
  101. {
  102. $this->_compressor_script = new PNGOut();
  103. //$this->_file_type;
  104. }
  105. }
  106. /**
  107. * GZip Compressor
  108. *
  109. */
  110. class GZipCompressor extends Compressor
  111. {
  112. public function __construct()
  113. {
  114. $this->_compressor_script = new GZip();
  115. }
  116. }
  117. /**
  118. * CompressorScript interface makes sure that our compression classes are uniform
  119. * and easier to maintain
  120. *
  121. */
  122. interface CompressorScript
  123. {
  124. public function compress($input);
  125. public function prepare_input($input);
  126. public function prepare_output($input, $ext='');
  127. //public function generate_
  128. }
  129. class ClosureCompiler implements CompressorScript
  130. {
  131. /**
  132. * Compress using Google Closure Compiler.
  133. *
  134. * @param type $input
  135. * @param type $output
  136. */
  137. public function compress($input)
  138. {
  139. $output = $this->prepare_output($input);
  140. $input = $this->prepare_input($input);
  141. $compressor = Config::$closure_compiler;
  142. $output_full_path = Config::$compressed_resources_path . '/' . JS_FILETYPE . '/' . $output;
  143. if(file_exists($output_full_path))
  144. {
  145. echo PHP_EOL . "Skipping $output_full_path. This file was already compressed." . PHP_EOL;
  146. // do nothing if file already exists
  147. return $output;
  148. }
  149. $cmd = Config::$java . " -jar $compressor $input --js_output_file $output_full_path";
  150. $cmd = escapeshellcmd($cmd);
  151. echo 'executing: ' . $cmd . PHP_EOL;
  152. exec($cmd, $cmd_output);
  153. // TODO: checker to verify whether the compression was successful
  154. return $output;
  155. }
  156. /**
  157. * Use this to pre-format/prepare the input parameters for Google Closure Compiler.
  158. * Different compression methods require different input params
  159. *
  160. *
  161. * @param type $input
  162. * @return type
  163. */
  164. public function prepare_input($input)
  165. {
  166. echo __METHOD__ . PHP_EOL;
  167. var_dump($input);
  168. echo PHP_EOL;
  169. foreach ($input as $i)
  170. {
  171. $res[] = '--js ' . $i;
  172. }
  173. $js_input = implode(' ', $res);
  174. return $js_input;
  175. }
  176. public function prepare_output($input, $ext=JS_FILETYPE)
  177. {
  178. $combined_str = '';
  179. foreach ($input as $file)
  180. {
  181. $combined_str .= Compressor::generate_filename($file, JS_FILETYPE, 'm-');
  182. }
  183. return 'm-' . md5($combined_str) . '.js';
  184. }
  185. }
  186. class YUICompressor implements CompressorScript
  187. {
  188. /**
  189. * Compress using YUICompressor
  190. *
  191. * @param type $input
  192. * @param type $output
  193. */
  194. public function compress($input)
  195. {
  196. $output = $this->prepare_output($input);
  197. $input = $this->prepare_input($input);
  198. $compressor = Config::$yui_compressor;
  199. $output_full_path = Config::$compressed_resources_path . '/' . CSS_FILETYPE . '/' . $output;
  200. if(file_exists($output_full_path))
  201. {
  202. echo PHP_EOL . "Skipping $output_full_path. This file was already compressed." . PHP_EOL;
  203. // do nothing if file already exists
  204. return $output;
  205. }
  206. $cmd = Config::$java . " -jar $compressor $input --type css > $output_full_path";
  207. //$cmd = escapeshellcmd($cmd);
  208. echo 'executing: ' . $cmd . PHP_EOL;
  209. exec($cmd, $cmd_output);
  210. // TODO: checker to verify whether the compression was successful
  211. // when we're done, delete the temporary css file in /tmp folder
  212. if (unlink($input))
  213. {
  214. return $output;
  215. }
  216. }
  217. /**
  218. * Use this to pre-format/prepare the input parameters for Google Closure Compiler.
  219. * Different compression methods require different input params
  220. *
  221. *
  222. * @param type $input
  223. * @return type
  224. */
  225. public function prepare_input($input)
  226. {
  227. $combined_contents = '';
  228. foreach ($input as $file)
  229. {
  230. $combined_contents .= file_get_contents($file);
  231. }
  232. $temp_file = TMP . '/css-' . md5($combined_contents) . '.css';
  233. if (file_put_contents($temp_file, $combined_contents))
  234. {
  235. return $temp_file;
  236. }
  237. return false;
  238. }
  239. public function prepare_output($input, $ext=CSS_FILETYPE)
  240. {
  241. $combined_str = '';
  242. foreach ($input as $file)
  243. {
  244. $combined_str .= Compressor::generate_filename($file, CSS_FILETYPE, 'm-');
  245. }
  246. return 'm-' . md5($combined_str) . '.' . CSS_FILETYPE;
  247. }
  248. }
  249. class HTMLCompressor implements CompressorScript
  250. {
  251. /**
  252. * Compress using htmlcompressor
  253. * http://code.google.com/p/htmlcompressor/wiki/Documentation
  254. *
  255. * @param type $input
  256. * @return type $output
  257. */
  258. public function compress($input)
  259. {
  260. // do nothing if input file doesn't exist
  261. if (!file_exists($input))
  262. {
  263. return false;
  264. }
  265. $output = $this->prepare_output($input);
  266. $input = $this->prepare_input($input);
  267. $compressor = Config::$html_compressor;
  268. $cmd = Config::$java . " -jar $compressor -o $output --type html --compress-js --compress-css --remove-intertag-spaces $input";
  269. //$cmd = escapeshellcmd($cmd);
  270. echo 'executing: ' . $cmd . PHP_EOL;
  271. exec($cmd, $cmd_output);
  272. return $output;
  273. }
  274. /**
  275. * Use this to pre-format/prepare the input parameters for Google Closure Compiler.
  276. * Different compression methods require different input params
  277. *
  278. *
  279. * @param type $input
  280. * @return type
  281. */
  282. public function prepare_input($input)
  283. {
  284. return $input;
  285. }
  286. public function prepare_output($input, $ext='')
  287. {
  288. // do nothing here..
  289. return $input;
  290. }
  291. }
  292. class PNGOut implements CompressorScript
  293. {
  294. /**
  295. * Disable compression for now to save time.
  296. *
  297. * @param type $input
  298. * @return string
  299. */
  300. public function compress($input)
  301. {
  302. if (!file_exists($input))
  303. {
  304. return false;
  305. }
  306. // get extension
  307. $ext = pathinfo($input, PATHINFO_EXTENSION);
  308. $output = $this->prepare_output($input, $ext);
  309. $input = $this->prepare_input($input);
  310. $output_full_path = Config::$compressed_resources_path . '/' . IMG_FILE . '/' . $output;
  311. $compressed_image = IMG_FILE . '/' . $output;
  312. if (file_exists($output_full_path))
  313. {
  314. echo PHP_EOL . "Skipping $output_full_path. This file was not changed." . PHP_EOL;
  315. // do nothing if file already exists
  316. return $compressed_image;
  317. }
  318. // get the operating system and machine
  319. $os = php_uname('s');
  320. $machine = php_uname('m');
  321. // skip compression for now until we find a faster and better png compression tool
  322. /*
  323. // set the pngout script path based on its environment
  324. $pngout_subpath = ('Darwin' === $os) ? $os : "$os/$machine";
  325. $pngout = SCRIPTS_PATH . '/' . $pngout_subpath . '/' . Compressor::PNG_COMPRESSOR;
  326. echo PHP_EOL . 'Compressing: ' . $input . PHP_EOL;
  327. perform compression using pngout
  328. exec($pngout . ' ' . $input . ' ' . $output_full_path . ' -y');
  329. */
  330. // just copy the entire file to the output folder
  331. if (copy($input, $output_full_path))
  332. {
  333. return $compressed_image;
  334. }
  335. else
  336. {
  337. return false;
  338. }
  339. }
  340. /**
  341. * Use this to pre-format/prepare the input parameters for Google Closure Compiler.
  342. * Different compression methods require different input params
  343. *
  344. * @param type $input
  345. * @return type
  346. */
  347. public function prepare_input($input)
  348. {
  349. return $input;
  350. }
  351. public function prepare_output($input, $ext=PNG_FILETYPE)
  352. {
  353. return Compressor::generate_filename($input, $ext, 'm-');
  354. }
  355. }
  356. class GZip implements CompressorScript
  357. {
  358. /**
  359. * Disable compression for now to save time.
  360. *
  361. * @param type $input
  362. * @return string
  363. */
  364. public function compress($input)
  365. {
  366. // gzip compress each file with the .gz extension on each of them
  367. foreach ($input as $file_to_compress)
  368. {
  369. $cmd = GZIP . " -c $file_to_compress > $file_to_compress.gz";
  370. echo "running: $cmd\n";
  371. $shell_out = shell_exec($cmd);
  372. echo 'gzip result: ';
  373. var_dump($shell_out);
  374. }
  375. // remove the .gz extension and overwrite the existing files, after making sure
  376. // that the files were successfully gzipped
  377. foreach ($input as $compressed_file)
  378. {
  379. if (true === copy($compressed_file . ".gz", $compressed_file))
  380. {
  381. // delete the gz file if successfully copied
  382. if (unlink($compressed_file . ".gz"))
  383. {
  384. echo "successfully deleted $compressed_file.gz file";
  385. }
  386. }
  387. else
  388. {
  389. echo "something went wrong while copying the file and overwriting the original: $compressed_file";
  390. }
  391. }
  392. }
  393. /**
  394. * Different compression methods require different input params
  395. * Use this to pre-format/prepare the input parameters for Google Closure Compiler.
  396. *
  397. * @param type $input
  398. * @return type
  399. */
  400. public function prepare_input($input)
  401. {
  402. return $input;
  403. }
  404. public function prepare_output($input, $ext=PNG_FILETYPE)
  405. {
  406. return Compressor::generate_filename($input, $ext, 'm-');
  407. }
  408. }