PageRenderTime 25ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/public/js/tiny_mce/plugins/imagemanager/classes/Utils/JSCompressor.php

https://bitbucket.org/cidious/raise.org
PHP | 288 lines | 163 code | 65 blank | 60 comment | 46 complexity | e62af56c930ca40ee7e7d16483a5d485 MD5 | raw file
  1. <?php
  2. /**
  3. * Moxiecode JS Compressor.
  4. *
  5. * @version 1.0
  6. * @author Moxiecode
  7. * @site http://www.moxieforge.com/
  8. * @copyright Copyright � 2004-2008, Moxiecode Systems AB, All rights reserved.
  9. * @licence LGPL
  10. * @ignore
  11. */
  12. /**
  13. * This class is used to compress JS files by minifying and gzipping them to reduce the overall download time for the JS of a site or system.
  14. *
  15. * @package Moxiecode_Utils
  16. */
  17. class Moxiecode_JSCompressor {
  18. /**#@+ @access private */
  19. var $_items, $_settings, $_lastUpdate;
  20. /**#@-*/
  21. /**
  22. * Constructs a new JS compressor instance.
  23. *
  24. * @param Array $settings Name/value array with settings for the compressor instance.
  25. */
  26. function Moxiecode_JSCompressor($settings = array()) {
  27. $this->_items = array();
  28. $default = array(
  29. 'expires_offset' => '10d',
  30. 'disk_cache' => true,
  31. 'cache_dir' => '_cache',
  32. 'gzip_compress' => true,
  33. 'remove_whitespace' => true,
  34. 'charset' => 'UTF-8',
  35. 'patch_ie' => true,
  36. 'remove_firebug' => false,
  37. 'name' => ''
  38. );
  39. $this->_settings = array_merge($default, $settings);
  40. $this->_lastUpdate = 0;
  41. }
  42. /**
  43. * Add raw contents as part of the concatenation/compression. This method should only be used if
  44. * you really need to.
  45. *
  46. * @param String $content Content to add as part of the concatenation process.
  47. */
  48. function addContent($content) {
  49. $this->_items[] = array('content', $content);
  50. }
  51. /**
  52. * Adds a file to the concatenation/compression process.
  53. *
  54. * @param String $path Path to the file to include in the compressed package/output.
  55. * @param bool $whitespace Set this state to false to skip whitespace removal for the specified file.
  56. */
  57. function addFile($path, $whitespace = true) {
  58. $this->_items[] = array('file', $path, $whitespace);
  59. $mtime = @filemtime($path);
  60. if ($mtime > $this->_lastUpdate)
  61. $this->_lastUpdate = $mtime;
  62. }
  63. /**
  64. * Compress and output all files that got added to the process by addFile.
  65. */
  66. function compress() {
  67. $key = "";
  68. foreach ($this->_items as $item)
  69. $key .= $item[1];
  70. // Setup some variables
  71. $cacheFile = $this->_settings['cache_dir'] . "/";
  72. if ($this->_settings['name'])
  73. $cacheFile .= preg_replace('/[^a-z0-9_]/i', '', $this->_settings['name']);
  74. else
  75. $cacheFile .= md5($key);
  76. $supportsGzip = false;
  77. $content = "";
  78. $encodings = array();
  79. // Check if it supports gzip
  80. if (isset($_SERVER['HTTP_ACCEPT_ENCODING']))
  81. $encodings = explode(',', strtolower(preg_replace("/\s+/", "", $_SERVER['HTTP_ACCEPT_ENCODING'])));
  82. if ($this->_settings['gzip_compress'] && (in_array('gzip', $encodings) || in_array('x-gzip', $encodings) || isset($_SERVER['---------------'])) && function_exists('gzencode') && !ini_get('zlib.output_compression')) {
  83. $enc = in_array('x-gzip', $encodings) ? "x-gzip" : "gzip";
  84. $supportsGzip = true;
  85. $cacheFile .= ".gz";
  86. } else
  87. $cacheFile .= ".js";
  88. // Set headers
  89. header("Content-type: text/javascript;charset=" . $this->_settings['charset']);
  90. header("Vary: Accept-Encoding"); // Handle proxies
  91. header("Expires: " . gmdate("D, d M Y H:i:s", time() + $this->_parseTime($this->_settings['expires_offset'])) . " GMT");
  92. header("Cache-Control: public, max-age=" . $this->_parseTime($this->_settings['expires_offset']));
  93. // Output explorer workaround or compressed file
  94. if (!isset($_GET["gz"]) && $supportsGzip && $this->_settings['patch_ie'] && strpos($_SERVER["HTTP_USER_AGENT"], "MSIE") !== false) {
  95. // Build request URL
  96. $url = $_SERVER["PHP_SELF"];
  97. if (isset($_SERVER["QUERY_STRING"]) && $_SERVER["QUERY_STRING"])
  98. $url .= "?" . $_SERVER["QUERY_STRING"] . "&gz=1";
  99. else
  100. $url .= "?gz=1";
  101. // This script will ensure that the gzipped script gets loaded on IE versions with the Gzip request chunk bug
  102. echo 'var gz;try {gz = new XMLHttpRequest();} catch(gz) { try {gz = new ActiveXObject("Microsoft.XMLHTTP");}';
  103. echo 'catch (gz) {gz = new ActiveXObject("Msxml2.XMLHTTP");}}';
  104. echo 'gz.open("GET", "' . $url . '", false);gz.send(null);eval(gz.responseText);';
  105. die();
  106. }
  107. // Use cached file
  108. if ($this->_settings['disk_cache'] && file_exists($cacheFile) && @filemtime($cacheFile) == $this->_lastUpdate) {
  109. if ($supportsGzip)
  110. header("Content-Encoding: " . $enc);
  111. echo $this->_getFileContents($cacheFile);
  112. return;
  113. }
  114. // Load content
  115. foreach ($this->_items as $item) {
  116. if ($item[0] == 'file')
  117. $chunk = $this->_getFileContents($item[1]);
  118. else
  119. $chunk = $item[1];
  120. // Remove UTF-8 BOM
  121. if (substr($chunk, 0, 3) == pack("CCC", 0xef, 0xbb, 0xbf))
  122. $chunk = substr($chunk, 3);
  123. if ($this->_settings['remove_whitespace'] && $item[2])
  124. $chunk = $this->_removeWhiteSpace($chunk);
  125. if (!$item[2])
  126. $chunk = "\n" . $chunk . ";\n";
  127. $content .= $chunk;
  128. }
  129. // Remove firebug calls
  130. if ($this->_settings['remove_firebug'])
  131. $content = preg_replace('/console\\.[^;]+;/', '', $content);
  132. // GZip content
  133. if ($supportsGzip) {
  134. header("Content-Encoding: " . $enc);
  135. $content = gzencode($content, 9, FORCE_GZIP);
  136. }
  137. // Write cache file
  138. if ($this->_settings['disk_cache']) {
  139. if (!is_dir($this->_settings['cache_dir']))
  140. @mkdir($this->_settings['cache_dir']);
  141. $this->_putFileContents($cacheFile, $content);
  142. if (@file_exists($cacheFile))
  143. @touch($cacheFile, $this->_lastUpdate);
  144. }
  145. // Output content to client
  146. echo $content;
  147. }
  148. /**#@+ @access private */
  149. function _removeWhiteSpace($content) {
  150. $this->_strings = array();
  151. $this->_count = 0;
  152. // Replace strings and regexps
  153. $content = preg_replace_callback('/\\\\(\"|\'|\\/)/', array(&$this, '_encode'), $content); // Replace all \/, \", \' with tokens
  154. $content = preg_replace_callback('/(\'[^\'\\n\\r]*\')|("[^"\\n\\r]*")|(\\s+(\\/[^\\/\\n\\r\\*][^\\/\\n\\r]*\\/g?i?))|([^\\w\\x24\\/\'"*)\\?:]\\/[^\\/\\n\\r\\*][^\\/\\n\\r]*\\/g?i?)/', array(&$this, '_strToItems'), $content);
  155. // Remove comments
  156. $content = preg_replace('/(\\/\\/[^\\n\\r]*[\\n\\r])|(\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\/)/', '', $content);
  157. // Remove whitespace
  158. $content = preg_replace('/[\r\n]+/', ' ', $content);
  159. $content = preg_replace('/\s*([=&|!+\\-\\/?:;,\\^\\(\\)\\{\\}<>%]+)\s*/', '$1', $content);
  160. $content = preg_replace('/(;)\s+/', '$1', $content);
  161. $content = preg_replace('/\s+/', ' ', $content);
  162. // Restore strings and regexps
  163. $content = preg_replace_callback('/�@([^�]+)�/', array(&$this, '_itemsToStr'), $content);
  164. $content = preg_replace_callback('/�#([^�]+)�/', array(&$this, '_decode'), $content); // Restore all \/, \", \'
  165. return $content;
  166. }
  167. function _putFileContents($path, $content) {
  168. if (!is_writable($path))
  169. return;
  170. if (function_exists("file_put_contents"))
  171. return @file_put_contents($path, $content);
  172. $fp = @fopen($path, "wb");
  173. if ($fp) {
  174. fwrite($fp, $content);
  175. fclose($fp);
  176. }
  177. }
  178. function _getFileContents($path) {
  179. $path = realpath($path);
  180. if (!$path || !@is_file($path))
  181. return "";
  182. if (function_exists("file_get_contents"))
  183. return @file_get_contents($path);
  184. $content = "";
  185. $fp = @fopen($path, "r");
  186. if (!$fp)
  187. return "";
  188. while (!feof($fp))
  189. $content .= fread($fp, 1024);
  190. fclose($fp);
  191. return $content;
  192. }
  193. function _strToItems($matches) {
  194. $this->_strings[] = $matches[0];
  195. return '�@' . ($this->_count++) . '�';
  196. }
  197. function _itemsToStr($matches) {
  198. return $this->_strings[intval($matches[1])];
  199. }
  200. function _encode($matches) {
  201. $this->_strings[] = $matches[0];
  202. return '�#' . ($this->_count++) . '�';
  203. }
  204. function _decode($matches) {
  205. return $this->_strings[intval($matches[1])];
  206. }
  207. function _parseTime($time) {
  208. $multipel = 1;
  209. // Hours
  210. if (strpos($time, "h") != false)
  211. $multipel = 60 * 60;
  212. // Days
  213. if (strpos($time, "d") != false)
  214. $multipel = 24 * 60 * 60;
  215. // Months
  216. if (strpos($time, "m") != false)
  217. $multipel = 24 * 60 * 60 * 30;
  218. // Trim string
  219. return intval($time) * $multipel;
  220. }
  221. /**#@-*/
  222. }
  223. ?>