New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ClosureCompiler
filter.
#170
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
<?php | ||
|
||
App::uses('AssetFilter', 'AssetCompress.Lib'); | ||
|
||
/** | ||
* Google Closure Compiler API Filter | ||
* | ||
* Allows you to filter Javascript files through the Google Closure compiler API. The script | ||
* needs to have web access to run. | ||
* | ||
* @package AssetCompress.Lib.Filter | ||
*/ | ||
class ClosureCompiler extends AssetFilter { | ||
|
||
/** | ||
* Defaults. | ||
* | ||
* @var array | ||
*/ | ||
protected $_defaults = array('compilation_level' => 'WHITESPACE_ONLY'); | ||
|
||
/** | ||
* Settings. | ||
* | ||
* NOTE: statistics and warnings are only used when in debug mode. | ||
* | ||
* - level (string) Defaults to WHITESPACE_ONLY. Values: SIMPLE_OPTIMIZATIONS, ADVANCED_OPTIMIZATIONS. | ||
* - statistics (boolean) Defaults to FALSE. | ||
* - warnings (mixed) Defaults to FALSE. Values: TRUE or QUIET, DEFAULT, VERBOSE. | ||
* | ||
* @var array | ||
*/ | ||
protected $_settings = array( | ||
'level' => null, | ||
'statistics' => false, | ||
'warnings' => false | ||
); | ||
|
||
/** | ||
* Optional API parameters. | ||
* | ||
* - The `output_file_name` hasn't been included because AssetCompress is used for saving the minified javascript. | ||
* - The `warning_level` is automatically handled in `self::$_settings`. | ||
* | ||
* @var array | ||
* @see https://developers.google.com/closure/compiler/docs/api-ref | ||
*/ | ||
private $__params = array( | ||
'js_externs', | ||
'externs_url', | ||
'exclude_default_externs', | ||
'formatting', | ||
'use_closure_library', | ||
'language' | ||
); | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function output($filename, $content) { | ||
$defaults = array('compilation_level' => $this->_settings['level']); | ||
|
||
$errors = $this->_query($content, array('output_info' => 'errors')); | ||
if (!empty($errors)) { | ||
throw new Exception(sprintf("%s:\n%s\n", 'Errors', $errors)); | ||
} | ||
|
||
$output = $this->_query($content, array('output_info' => 'compiled_code')); | ||
|
||
if (!Configure::read('debug')) { | ||
return $output; | ||
} | ||
|
||
foreach ($this->_settings as $setting => $value) { | ||
if (!in_array($setting, array('warnings', 'statistics')) || true != $value) { | ||
continue; | ||
} | ||
|
||
$args = array('output_info' => $setting); | ||
if ('warnings' == $setting && in_array($value, array('QUIET', 'DEFAULT', 'VERBOSE'))) { | ||
$args['warning_level'] = $value; | ||
} | ||
|
||
$$setting = $this->_query($content, $args); | ||
printf("%s:\n%s\n", ucfirst($setting), $$setting); | ||
} | ||
|
||
return $output; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it helpful to have the warnings dumped? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe so, depending on the compression level, different warnings are thrown. |
||
} | ||
|
||
/** | ||
* Query the Closure compiler API. | ||
* | ||
* @param string $content Javascript to compile. | ||
* @param array $args API parameters. | ||
* @throws Exception If curl extension is missing. | ||
* @throws Exception If curl triggers an error. | ||
* @return string | ||
*/ | ||
protected function _query($content, $args = array()) { | ||
if (!extension_loaded('curl')) { | ||
throw new Exception('Missing the `curl` extension.'); | ||
} | ||
|
||
$args = array_merge($this->_defaults, $args); | ||
if (!empty($this->_settings['level'])) { | ||
$args['compilation_level'] = $this->_settings['level']; | ||
} | ||
|
||
foreach ($this->_settings as $key => $val) { | ||
if (in_array($key, $this->__params)) { | ||
$args[$key] = $val; | ||
} | ||
} | ||
|
||
$ch = curl_init(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably should throw an exception when the environment is lacking curl. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using HttpSocket would be better as some environments may lack curl support. |
||
curl_setopt_array($ch, array( | ||
CURLOPT_URL => 'http://closure-compiler.appspot.com/compile', | ||
CURLOPT_POST => 1, | ||
CURLOPT_POSTFIELDS => 'js_code=' . urlencode($content) . '&' . http_build_query($args), | ||
CURLOPT_RETURNTRANSFER => 1, | ||
CURLOPT_HEADER => 0, | ||
CURLOPT_FOLLOWLOCATION => 0 | ||
)); | ||
|
||
$output = curl_exec($ch); | ||
|
||
if (false === $output) { | ||
throw new Exception('Curl error: ' . curl_error($ch)); | ||
} | ||
|
||
curl_close($ch); | ||
return $output; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this printing here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the shell command's output. Should I remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not overly familiar with the closure webservice, what purpose does printing this out serve?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Closure can return an output:
In here it's used to output 'warnings' and/or 'statistics'.