mirror of
https://github.com/mrclay/minify.git
synced 2025-08-20 21:02:30 +02:00
* Allow additional HTTP options to be passed to the Closure compiler service
* Allow option for overriding the maximum byte size POST limit
This commit is contained in:
@@ -14,11 +14,47 @@
|
|||||||
* @todo can use a stream wrapper to unit test this?
|
* @todo can use a stream wrapper to unit test this?
|
||||||
*/
|
*/
|
||||||
class Minify_JS_ClosureCompiler {
|
class Minify_JS_ClosureCompiler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the option for the maximum POST byte size
|
||||||
|
*/
|
||||||
|
const OPTION_MAX_BYTES = 'maxBytes';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int the default maximum POST byte size according to https://developers.google.com/closure/compiler/docs/api-ref
|
||||||
|
*/
|
||||||
|
const MAX_BYTES_DEFAULT = 200000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var $url URL to compiler server. defaults to google server
|
* @var $url URL to compiler server. defaults to google server
|
||||||
*/
|
*/
|
||||||
protected $url = 'http://closure-compiler.appspot.com/compile';
|
protected $url = 'http://closure-compiler.appspot.com/compile';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var $maxBytes The maximum JS size that can be sent to the compiler server in bytes
|
||||||
|
*/
|
||||||
|
protected $maxBytes = self::MAX_BYTES_DEFAULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var $additionalOptions array additional options to pass to the compiler service
|
||||||
|
*/
|
||||||
|
protected $additionalOptions = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var $DEFAULT_OPTIONS array the default options to pass to the compiler service
|
||||||
|
*/
|
||||||
|
private static $DEFAULT_OPTIONS = array(
|
||||||
|
'output_format' => 'text',
|
||||||
|
'compilation_level' => 'SIMPLE_OPTIMIZATIONS');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the option for additional params.
|
||||||
|
* Read more about additional params here: https://developers.google.com/closure/compiler/docs/api-ref
|
||||||
|
* This also allows you to override the output_format or the compilation_level.
|
||||||
|
* The parameters js_code and output_info can not be set in this way
|
||||||
|
*/
|
||||||
|
const OPTION_ADDITIONAL_HTTP_PARAMS = 'additionalParams';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minify Javascript code via HTTP request to the Closure Compiler API
|
* Minify Javascript code via HTTP request to the Closure Compiler API
|
||||||
*
|
*
|
||||||
@@ -36,8 +72,10 @@ class Minify_JS_ClosureCompiler {
|
|||||||
*
|
*
|
||||||
* @param array $options
|
* @param array $options
|
||||||
*
|
*
|
||||||
* fallbackFunc : default array($this, 'fallback');
|
* fallbackFunc : array default array($this, '_fallback');
|
||||||
* compilerUrl : URL to closure compiler server
|
* compilerUrl : string URL to closure compiler server
|
||||||
|
* maxBytes : int The maximum amount of bytes to be sent as js_code in the POST request. Defaults to 200000.
|
||||||
|
* additionalParams: array The additional parameters to pass to the compiler server. Can be anything named in https://developers.google.com/closure/compiler/docs/api-ref except for js_code and output_info
|
||||||
*/
|
*/
|
||||||
public function __construct(array $options = array())
|
public function __construct(array $options = array())
|
||||||
{
|
{
|
||||||
@@ -48,19 +86,28 @@ class Minify_JS_ClosureCompiler {
|
|||||||
if (isset($options['compilerUrl'])) {
|
if (isset($options['compilerUrl'])) {
|
||||||
$this->url = $options['compilerUrl'];
|
$this->url = $options['compilerUrl'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($options[self::OPTION_ADDITIONAL_HTTP_PARAMS]) && is_array($options[self::OPTION_ADDITIONAL_HTTP_PARAMS])) {
|
||||||
|
$this->additionalOptions = $options[self::OPTION_ADDITIONAL_HTTP_PARAMS];
|
||||||
|
}
|
||||||
|
if (isset($options[self::OPTION_MAX_BYTES])) {
|
||||||
|
$this->maxBytes = (int) $options[self::OPTION_MAX_BYTES];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function min($js)
|
public function min($js)
|
||||||
{
|
{
|
||||||
$postBody = $this->_buildPostBody($js);
|
$postBody = $this->_buildPostBody($js);
|
||||||
|
if ($this->maxBytes > 0) {
|
||||||
$bytes = (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2))
|
$bytes = (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2))
|
||||||
? mb_strlen($postBody, '8bit')
|
? mb_strlen($postBody, '8bit')
|
||||||
: strlen($postBody);
|
: strlen($postBody);
|
||||||
if ($bytes > 200000) {
|
if ($bytes > $this->maxBytes) {
|
||||||
throw new Minify_JS_ClosureCompiler_Exception(
|
throw new Minify_JS_ClosureCompiler_Exception(
|
||||||
'POST content larger than 200000 bytes'
|
'POST content larger than ' . $this->maxBytes . ' bytes'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$response = $this->_getResponse($postBody);
|
$response = $this->_getResponse($postBody);
|
||||||
if (preg_match('/^Error\(\d\d?\):/', $response)) {
|
if (preg_match('/^Error\(\d\d?\):/', $response)) {
|
||||||
if (is_callable($this->_fallbackFunc)) {
|
if (is_callable($this->_fallbackFunc)) {
|
||||||
@@ -118,12 +165,18 @@ class Minify_JS_ClosureCompiler {
|
|||||||
|
|
||||||
protected function _buildPostBody($js, $returnErrors = false)
|
protected function _buildPostBody($js, $returnErrors = false)
|
||||||
{
|
{
|
||||||
return http_build_query(array(
|
return http_build_query(
|
||||||
|
array_merge(
|
||||||
|
self::$DEFAULT_OPTIONS,
|
||||||
|
$this->additionalOptions,
|
||||||
|
array(
|
||||||
'js_code' => $js,
|
'js_code' => $js,
|
||||||
'output_info' => ($returnErrors ? 'errors' : 'compiled_code'),
|
'output_info' => ($returnErrors ? 'errors' : 'compiled_code')
|
||||||
'output_format' => 'text',
|
)
|
||||||
'compilation_level' => 'SIMPLE_OPTIMIZATIONS'
|
),
|
||||||
), null, '&');
|
null,
|
||||||
|
'&'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -42,6 +42,84 @@ function test_Minify_JS_ClosureCompiler()
|
|||||||
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
||||||
echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n";
|
echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test maximum byte size check (default)
|
||||||
|
$fn = "(function() {})();";
|
||||||
|
$src = str_repeat($fn, ceil(Minify_JS_ClosureCompiler::MAX_BYTES_DEFAULT / strlen($fn)));
|
||||||
|
$exc = null;
|
||||||
|
try {
|
||||||
|
$minOutput = Minify_JS_ClosureCompiler::minify($src);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$exc = $e;
|
||||||
|
}
|
||||||
|
$passed = assertTrue(
|
||||||
|
$exc instanceof Minify_JS_ClosureCompiler_Exception
|
||||||
|
, 'Minify_JS_ClosureCompiler : Throws Minify_JS_ClosureCompiler_Exception');
|
||||||
|
assertTrue(
|
||||||
|
$exc->getMessage() === 'POST content larger than ' . Minify_JS_ClosureCompiler::MAX_BYTES_DEFAULT . ' bytes'
|
||||||
|
, 'Minify_JS_ClosureCompiler : Message must tell how big maximum byte size is');
|
||||||
|
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
||||||
|
echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test maximum byte size check (no limit)
|
||||||
|
$src = "(function(){})();";
|
||||||
|
try {
|
||||||
|
$minOutput = Minify_JS_ClosureCompiler::minify($src, array(
|
||||||
|
Minify_JS_ClosureCompiler::OPTION_MAX_BYTES => 0
|
||||||
|
));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$exc = $e;
|
||||||
|
}
|
||||||
|
$passed = assertTrue(
|
||||||
|
$src === $minOutput
|
||||||
|
, 'Minify_JS_ClosureCompiler : With no limit set, it should compile properly');
|
||||||
|
|
||||||
|
// Test maximum byte size check (custom)
|
||||||
|
$src = "(function() {})();";
|
||||||
|
$allowedBytes = 5;
|
||||||
|
$exc = null;
|
||||||
|
try {
|
||||||
|
$minOutput = Minify_JS_ClosureCompiler::minify($src, array(
|
||||||
|
Minify_JS_ClosureCompiler::OPTION_MAX_BYTES => $allowedBytes
|
||||||
|
));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$exc = $e;
|
||||||
|
}
|
||||||
|
$passed = assertTrue(
|
||||||
|
$exc instanceof Minify_JS_ClosureCompiler_Exception
|
||||||
|
, 'Minify_JS_ClosureCompiler : Throws Minify_JS_ClosureCompiler_Exception');
|
||||||
|
assertTrue(
|
||||||
|
$exc->getMessage() === 'POST content larger than ' . $allowedBytes . ' bytes'
|
||||||
|
, 'Minify_JS_ClosureCompiler : Message must tell how big maximum byte size is');
|
||||||
|
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
||||||
|
echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test additional options passed to HTTP request
|
||||||
|
$ecmascript5 = "[1,].length;";
|
||||||
|
$exc = null;
|
||||||
|
try {
|
||||||
|
$minOutput = Minify_JS_ClosureCompiler::minify($ecmascript5);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$exc = $e;
|
||||||
|
}
|
||||||
|
$passed = assertTrue(
|
||||||
|
$exc instanceof Minify_JS_ClosureCompiler_Exception
|
||||||
|
, 'Minify_JS_ClosureCompiler : Throws Minify_JS_ClosureCompiler_Exception');
|
||||||
|
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
||||||
|
echo "\n---Message: " . var_export($exc->getMessage(), 1) . "\n\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$minExpected = '1;';
|
||||||
|
$minOutput = Minify_JS_ClosureCompiler::minify($ecmascript5, array(
|
||||||
|
Minify_JS_ClosureCompiler::OPTION_ADDITIONAL_HTTP_PARAMS => array(
|
||||||
|
'language' => 'ECMASCRIPT5'
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$passed = assertTrue(
|
||||||
|
$minOutput === $minExpected
|
||||||
|
, 'Minify_JS_ClosureCompiler : Language option should make it compile');
|
||||||
}
|
}
|
||||||
|
|
||||||
test_Minify_JS_ClosureCompiler();
|
test_Minify_JS_ClosureCompiler();
|
||||||
|
Reference in New Issue
Block a user