1<?php 2 3/* 4 * This file is part of the Assetic package, an OpenSky project. 5 * 6 * (c) 2010-2014 OpenSky Project Inc 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Assetic\Filter\GoogleClosure; 13 14use Assetic\Asset\AssetInterface; 15 16/** 17 * Filter for the Google Closure Compiler API. 18 * 19 * @link https://developers.google.com/closure/compiler/ 20 * @author Kris Wallsmith <kris.wallsmith@gmail.com> 21 */ 22class CompilerApiFilter extends BaseCompilerFilter 23{ 24 private $proxy; 25 private $proxyFullUri; 26 27 public function setProxy($proxy) 28 { 29 $this->proxy = $proxy; 30 } 31 32 public function setProxyFullUri($proxyFullUri) 33 { 34 $this->proxyFullUri = $proxyFullUri; 35 } 36 37 public function filterDump(AssetInterface $asset) 38 { 39 $query = array( 40 'js_code' => $asset->getContent(), 41 'output_format' => 'json', 42 'output_info' => 'compiled_code', 43 ); 44 45 if (null !== $this->compilationLevel) { 46 $query['compilation_level'] = $this->compilationLevel; 47 } 48 49 if (null !== $this->jsExterns) { 50 $query['js_externs'] = $this->jsExterns; 51 } 52 53 if (null !== $this->externsUrl) { 54 $query['externs_url'] = $this->externsUrl; 55 } 56 57 if (null !== $this->excludeDefaultExterns) { 58 $query['exclude_default_externs'] = $this->excludeDefaultExterns ? 'true' : 'false'; 59 } 60 61 if (null !== $this->formatting) { 62 $query['formatting'] = $this->formatting; 63 } 64 65 if (null !== $this->useClosureLibrary) { 66 $query['use_closure_library'] = $this->useClosureLibrary ? 'true' : 'false'; 67 } 68 69 if (null !== $this->warningLevel) { 70 $query['warning_level'] = $this->warningLevel; 71 } 72 73 if (null !== $this->language) { 74 $query['language'] = $this->language; 75 } 76 77 if (preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'))) { 78 $contextOptions = array('http' => array( 79 'method' => 'POST', 80 'header' => 'Content-Type: application/x-www-form-urlencoded', 81 'content' => http_build_query($query), 82 )); 83 if (null !== $this->timeout) { 84 $contextOptions['http']['timeout'] = $this->timeout; 85 } 86 if ($this->proxy) { 87 $contextOptions['http']['proxy'] = $this->proxy; 88 $contextOptions['http']['request_fulluri'] = (Boolean) $this->proxyFullUri; 89 } 90 $context = stream_context_create($contextOptions); 91 92 $response = file_get_contents('http://closure-compiler.appspot.com/compile', false, $context); 93 $data = json_decode($response); 94 } elseif (defined('CURLOPT_POST') && !in_array('curl_init', explode(',', ini_get('disable_functions')))) { 95 $ch = curl_init('http://closure-compiler.appspot.com/compile'); 96 curl_setopt($ch, CURLOPT_POST, true); 97 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded')); 98 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 99 curl_setopt($ch, CURLOPT_POSTFIELDS, $query); 100 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15); 101 if (null !== $this->timeout) { 102 curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); 103 } 104 if ($this->proxy) { 105 curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, true); 106 curl_setopt($ch, CURLOPT_PROXY, $this->proxy); 107 } 108 $response = curl_exec($ch); 109 curl_close($ch); 110 111 $data = json_decode($response); 112 } else { 113 throw new \RuntimeException("There is no known way to contact closure compiler available"); 114 } 115 116 if (isset($data->serverErrors) && 0 < count($data->serverErrors)) { 117 // @codeCoverageIgnoreStart 118 throw new \RuntimeException(sprintf('The Google Closure Compiler API threw some server errors: '.print_r($data->serverErrors, true))); 119 // @codeCoverageIgnoreEnd 120 } 121 122 if (isset($data->errors) && 0 < count($data->errors)) { 123 // @codeCoverageIgnoreStart 124 throw new \RuntimeException(sprintf('The Google Closure Compiler API threw some errors: '.print_r($data->errors, true))); 125 // @codeCoverageIgnoreEnd 126 } 127 128 $asset->setContent($data->compiledCode); 129 } 130} 131