From 874b8cbf002e9d8bf0ff39671e1501165016320a Mon Sep 17 00:00:00 2001 From: Michael Save Date: Mon, 9 Apr 2012 20:52:26 +1000 Subject: inc/contrib -> inc/lib --- inc/lib/minify/Minify/JS/ClosureCompiler.php | 133 +++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100755 inc/lib/minify/Minify/JS/ClosureCompiler.php (limited to 'inc/lib/minify/Minify/JS/ClosureCompiler.php') diff --git a/inc/lib/minify/Minify/JS/ClosureCompiler.php b/inc/lib/minify/Minify/JS/ClosureCompiler.php new file mode 100755 index 00000000..f4ed5bdb --- /dev/null +++ b/inc/lib/minify/Minify/JS/ClosureCompiler.php @@ -0,0 +1,133 @@ + + * + * @todo can use a stream wrapper to unit test this? + */ +class Minify_JS_ClosureCompiler { + const URL = 'http://closure-compiler.appspot.com/compile'; + + /** + * Minify Javascript code via HTTP request to the Closure Compiler API + * + * @param string $js input code + * @param array $options unused at this point + * @return string + */ + public static function minify($js, array $options = array()) + { + $obj = new self($options); + return $obj->min($js); + } + + /** + * + * @param array $options + * + * fallbackFunc : default array($this, 'fallback'); + */ + public function __construct(array $options = array()) + { + $this->_fallbackFunc = isset($options['fallbackMinifier']) + ? $options['fallbackMinifier'] + : array($this, '_fallback'); + } + + public function min($js) + { + $postBody = $this->_buildPostBody($js); + $bytes = (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) + ? mb_strlen($postBody, '8bit') + : strlen($postBody); + if ($bytes > 200000) { + throw new Minify_JS_ClosureCompiler_Exception( + 'POST content larger than 200000 bytes' + ); + } + $response = $this->_getResponse($postBody); + if (preg_match('/^Error\(\d\d?\):/', $response)) { + if (is_callable($this->_fallbackFunc)) { + $response = "/* Received errors from Closure Compiler API:\n$response" + . "\n(Using fallback minifier)\n*/\n"; + $response .= call_user_func($this->_fallbackFunc, $js); + } else { + throw new Minify_JS_ClosureCompiler_Exception($response); + } + } + if ($response === '') { + $errors = $this->_getResponse($this->_buildPostBody($js, true)); + throw new Minify_JS_ClosureCompiler_Exception($errors); + } + return $response; + } + + protected $_fallbackFunc = null; + + protected function _getResponse($postBody) + { + $allowUrlFopen = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen')); + if ($allowUrlFopen) { + $contents = file_get_contents(self::URL, false, stream_context_create(array( + 'http' => array( + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => $postBody, + 'max_redirects' => 0, + 'timeout' => 15, + ) + ))); + } elseif (defined('CURLOPT_POST')) { + $ch = curl_init(self::URL); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded')); + curl_setopt($ch, CURLOPT_POSTFIELDS, $postBody); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15); + $contents = curl_exec($ch); + curl_close($ch); + } else { + throw new Minify_JS_ClosureCompiler_Exception( + "Could not make HTTP request: allow_url_open is false and cURL not available" + ); + } + if (false === $contents) { + throw new Minify_JS_ClosureCompiler_Exception( + "No HTTP response from server" + ); + } + return trim($contents); + } + + protected function _buildPostBody($js, $returnErrors = false) + { + return http_build_query(array( + 'js_code' => $js, + 'output_info' => ($returnErrors ? 'errors' : 'compiled_code'), + 'output_format' => 'text', + 'compilation_level' => 'SIMPLE_OPTIMIZATIONS' + ), null, '&'); + } + + /** + * Default fallback function if CC API fails + * @param string $js + * @return string + */ + protected function _fallback($js) + { + require_once 'JSMin.php'; + return JSMin::minify($js); + } +} + +class Minify_JS_ClosureCompiler_Exception extends Exception {} -- cgit v1.3