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 1 commit
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,133 @@ | ||
<?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. | ||
* - print (string) How to output the errors, statistics and/or warnings. | ||
* - statistics (boolean) Defaults to FALSE. | ||
* - warnings (mixed) Defaults to FALSE. Values: TRUE or QUIET, DEFAULT, VERBOSE. | ||
* | ||
* @var array | ||
*/ | ||
protected $_settings = array( | ||
'level' => null, | ||
'print' => "%s:\n%s\n", | ||
'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)) { | ||
printf($this->_settings['print'], 'Errors', $errors); | ||
exit; | ||
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. It is probably better to throw an exception instead of calling exit here. 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. |
||
} | ||
|
||
$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($this->_settings['print'], ucfirst($setting), $$setting); | ||
} | ||
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. Why is this printing here? 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. For the shell command's output. Should I remove it? 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'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 commentThe 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'. |
||
|
||
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 triggers an error. | ||
* @return string | ||
*/ | ||
protected function _query($content, $args = array()) { | ||
$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.
Does this need to be configurable?
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.
No.