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;
15use Assetic\Exception\FilterException;
16use Assetic\Util\FilesystemUtils;
17use Symfony\Component\Process\ProcessBuilder;
18
19/**
20 * Filter for the Google Closure Compiler JAR.
21 *
22 * @link https://developers.google.com/closure/compiler/
23 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
24 */
25class CompilerJarFilter extends BaseCompilerFilter
26{
27    private $jarPath;
28    private $javaPath;
29    private $flagFile;
30
31    public function __construct($jarPath, $javaPath = '/usr/bin/java')
32    {
33        $this->jarPath = $jarPath;
34        $this->javaPath = $javaPath;
35    }
36
37    public function setFlagFile($flagFile)
38    {
39        $this->flagFile = $flagFile;
40    }
41
42    public function filterDump(AssetInterface $asset)
43    {
44        $is64bit = PHP_INT_SIZE === 8;
45        $cleanup = array();
46
47        $pb = new ProcessBuilder(array_merge(
48            array($this->javaPath),
49            $is64bit
50                ? array('-server', '-XX:+TieredCompilation')
51                : array('-client', '-d32'),
52            array('-jar', $this->jarPath)
53        ));
54
55        if (null !== $this->timeout) {
56            $pb->setTimeout($this->timeout);
57        }
58
59        if (null !== $this->compilationLevel) {
60            $pb->add('--compilation_level')->add($this->compilationLevel);
61        }
62
63        if (null !== $this->jsExterns) {
64            $cleanup[] = $externs = FilesystemUtils::createTemporaryFile('google_closure');
65            file_put_contents($externs, $this->jsExterns);
66            $pb->add('--externs')->add($externs);
67        }
68
69        if (null !== $this->externsUrl) {
70            $cleanup[] = $externs = FilesystemUtils::createTemporaryFile('google_closure');
71            file_put_contents($externs, file_get_contents($this->externsUrl));
72            $pb->add('--externs')->add($externs);
73        }
74
75        if (null !== $this->excludeDefaultExterns) {
76            $pb->add('--use_only_custom_externs');
77        }
78
79        if (null !== $this->formatting) {
80            $pb->add('--formatting')->add($this->formatting);
81        }
82
83        if (null !== $this->useClosureLibrary) {
84            $pb->add('--manage_closure_dependencies');
85        }
86
87        if (null !== $this->warningLevel) {
88            $pb->add('--warning_level')->add($this->warningLevel);
89        }
90
91        if (null !== $this->language) {
92            $pb->add('--language_in')->add($this->language);
93        }
94
95        if (null !== $this->flagFile) {
96            $pb->add('--flagfile')->add($this->flagFile);
97        }
98
99        $pb->add('--js')->add($cleanup[] = $input = FilesystemUtils::createTemporaryFile('google_closure'));
100        file_put_contents($input, $asset->getContent());
101
102        $proc = $pb->getProcess();
103        $code = $proc->run();
104        array_map('unlink', $cleanup);
105
106        if (0 !== $code) {
107            throw FilterException::fromProcess($proc)->setInput($asset->getContent());
108        }
109
110        $asset->setContent($proc->getOutput());
111    }
112}
113