|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* @package s9e\TextFormatter |
|
5
|
|
|
* @copyright Copyright (c) 2010-2018 The s9e Authors |
|
6
|
|
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License |
|
7
|
|
|
*/ |
|
8
|
|
|
namespace s9e\TextFormatter\Configurator\JavaScript\Minifiers; |
|
9
|
|
|
|
|
10
|
|
|
use RuntimeException; |
|
11
|
|
|
use s9e\TextFormatter\Configurator\JavaScript\Minifier; |
|
12
|
|
|
|
|
13
|
|
|
class ClosureCompilerApplication extends Minifier |
|
14
|
|
|
{ |
|
15
|
|
|
/** |
|
16
|
|
|
* @var string Path to the Closure Compiler application |
|
17
|
|
|
* @deprecated 1.3.0 Set a command instead |
|
18
|
|
|
*/ |
|
19
|
|
|
public $closureCompilerBin; |
|
20
|
|
|
|
|
21
|
|
|
/** |
|
22
|
|
|
* @var string Command used to invoke the Closure Compiler application |
|
23
|
|
|
*/ |
|
24
|
|
|
public $command; |
|
25
|
|
|
|
|
26
|
|
|
/** |
|
27
|
|
|
* @var string Closure Compiler's compilation level |
|
28
|
|
|
*/ |
|
29
|
|
|
public $compilationLevel = 'ADVANCED_OPTIMIZATIONS'; |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* @var bool Whether to exclude Closure Compiler's default externs |
|
33
|
|
|
*/ |
|
34
|
|
|
public $excludeDefaultExterns = true; |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* @var string Path to java interpreter |
|
38
|
|
|
* @deprecated 1.3.0 Set a command instead |
|
39
|
|
|
*/ |
|
40
|
|
|
public $javaBin = 'java'; |
|
41
|
|
|
|
|
42
|
|
|
/** |
|
43
|
|
|
* @var string Extra options to be passed to the Closure Compiler application |
|
44
|
|
|
*/ |
|
45
|
|
|
public $options = '--use_types_for_optimization'; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* Constructor |
|
49
|
|
|
* |
|
50
|
|
|
* @param string $filepathOrCommand Path to the Closure Compiler .jar or command to execute |
|
51
|
|
|
*/ |
|
52
|
10 |
|
public function __construct($filepathOrCommand = null) |
|
53
|
|
|
{ |
|
54
|
10 |
|
if (isset($filepathOrCommand)) |
|
55
|
|
|
{ |
|
56
|
8 |
|
if (file_exists($filepathOrCommand) && substr($filepathOrCommand, -4) === '.jar') |
|
57
|
|
|
{ |
|
58
|
8 |
|
$this->closureCompilerBin = $filepathOrCommand; |
|
|
|
|
|
|
59
|
|
|
} |
|
60
|
|
|
else |
|
61
|
|
|
{ |
|
62
|
|
|
$this->command = $filepathOrCommand; |
|
63
|
|
|
} |
|
64
|
|
|
} |
|
65
|
10 |
|
} |
|
66
|
|
|
|
|
67
|
|
|
/** |
|
68
|
|
|
* {@inheritdoc} |
|
69
|
|
|
*/ |
|
70
|
6 |
|
public function getCacheDifferentiator() |
|
71
|
|
|
{ |
|
72
|
|
|
$key = [ |
|
73
|
6 |
|
$this->compilationLevel, |
|
74
|
6 |
|
$this->excludeDefaultExterns, |
|
75
|
6 |
|
$this->options |
|
76
|
|
|
]; |
|
77
|
6 |
|
if (isset($this->closureCompilerBin)) |
|
|
|
|
|
|
78
|
|
|
{ |
|
79
|
6 |
|
$key[] = $this->getClosureCompilerBinHash(); |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
6 |
|
if ($this->excludeDefaultExterns) |
|
83
|
|
|
{ |
|
84
|
6 |
|
$key[] = file_get_contents(__DIR__ . '/../externs.application.js'); |
|
85
|
|
|
} |
|
86
|
|
|
|
|
87
|
6 |
|
return $key; |
|
88
|
|
|
} |
|
89
|
|
|
|
|
90
|
|
|
/** |
|
91
|
|
|
* Compile given JavaScript source via the Closure Compiler application |
|
92
|
|
|
* |
|
93
|
|
|
* @param string $src JavaScript source |
|
94
|
|
|
* @return string Compiled source |
|
95
|
|
|
*/ |
|
96
|
4 |
|
public function minify($src) |
|
97
|
|
|
{ |
|
98
|
4 |
|
$this->testFilepaths(); |
|
99
|
2 |
|
$options = ($this->options) ? ' ' . $this->options : ''; |
|
100
|
|
|
|
|
101
|
|
|
// Add our custom externs if default externs are disabled |
|
102
|
2 |
|
if ($this->excludeDefaultExterns && $this->compilationLevel === 'ADVANCED_OPTIMIZATIONS') |
|
103
|
|
|
{ |
|
104
|
1 |
|
$options .= ' --externs ' . __DIR__ . '/../externs.application.js --env=CUSTOM'; |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
2 |
|
$crc = crc32($src); |
|
108
|
2 |
|
$inFile = sys_get_temp_dir() . '/' . $crc . '.js'; |
|
109
|
2 |
|
$outFile = sys_get_temp_dir() . '/' . $crc . '.min.js'; |
|
110
|
|
|
|
|
111
|
2 |
|
file_put_contents($inFile, $src); |
|
112
|
|
|
|
|
113
|
2 |
|
if (isset($this->command)) |
|
114
|
|
|
{ |
|
115
|
|
|
$cmd = $this->command; |
|
116
|
|
|
} |
|
117
|
|
|
else |
|
118
|
|
|
{ |
|
119
|
2 |
|
$cmd = escapeshellcmd($this->javaBin) . ' -jar ' . escapeshellarg($this->closureCompilerBin); |
|
|
|
|
|
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
2 |
|
$cmd .= ' --compilation_level ' . escapeshellarg($this->compilationLevel) |
|
123
|
2 |
|
. $options |
|
124
|
2 |
|
. ' --js ' . escapeshellarg($inFile) |
|
125
|
2 |
|
. ' --js_output_file ' . escapeshellarg($outFile); |
|
126
|
|
|
|
|
127
|
2 |
|
exec($cmd . ' 2>&1', $output, $return); |
|
128
|
2 |
|
unlink($inFile); |
|
129
|
|
|
|
|
130
|
2 |
|
if (file_exists($outFile)) |
|
131
|
|
|
{ |
|
132
|
2 |
|
$src = trim(file_get_contents($outFile)); |
|
133
|
2 |
|
unlink($outFile); |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
2 |
|
if (!empty($return)) |
|
137
|
|
|
{ |
|
138
|
|
|
throw new RuntimeException('An error occured during minification: ' . implode("\n", $output)); |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
2 |
|
return $src; |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
|
|
/** |
|
145
|
|
|
* Compute and return the hash for current Closure Compiler binary |
|
146
|
|
|
* |
|
147
|
|
|
* @return string |
|
148
|
|
|
*/ |
|
149
|
6 |
|
protected function getClosureCompilerBinHash() |
|
150
|
|
|
{ |
|
151
|
|
|
// Caching the value saves time during testing but has little to no real-world impact |
|
152
|
6 |
|
static $cache = []; |
|
153
|
6 |
|
if (!isset($cache[$this->closureCompilerBin])) |
|
|
|
|
|
|
154
|
|
|
{ |
|
155
|
2 |
|
$cache[$this->closureCompilerBin] = md5_file($this->closureCompilerBin); |
|
|
|
|
|
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
6 |
|
return $cache[$this->closureCompilerBin]; |
|
|
|
|
|
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* Test that the Closure Compiler file exists |
|
163
|
|
|
* |
|
164
|
|
|
* @return void |
|
165
|
|
|
*/ |
|
166
|
4 |
|
protected function testFilepaths() |
|
167
|
|
|
{ |
|
168
|
4 |
|
if (isset($this->command)) |
|
169
|
|
|
{ |
|
170
|
|
|
return; |
|
171
|
|
|
} |
|
172
|
4 |
|
if (!isset($this->closureCompilerBin)) |
|
|
|
|
|
|
173
|
|
|
{ |
|
174
|
1 |
|
throw new RuntimeException('No path set for Closure Compiler'); |
|
175
|
|
|
} |
|
176
|
3 |
|
if (!file_exists($this->closureCompilerBin)) |
|
|
|
|
|
|
177
|
|
|
{ |
|
178
|
1 |
|
throw new RuntimeException('Cannot find Closure Compiler at ' . $this->closureCompilerBin); |
|
|
|
|
|
|
179
|
|
|
} |
|
180
|
|
|
} |
|
181
|
|
|
} |
This property has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.