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;
13
14use Assetic\Asset\AssetInterface;
15use Assetic\Exception\FilterException;
16use Assetic\Util\FilesystemUtils;
17
18/**
19 * UglifyJs2 filter.
20 *
21 * @link http://lisperator.net/uglifyjs
22 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
23 */
24class UglifyJs2Filter extends BaseNodeFilter
25{
26    private $uglifyjsBin;
27    private $nodeBin;
28    private $compress;
29    private $beautify;
30    private $mangle;
31    private $screwIe8;
32    private $comments;
33    private $wrap;
34    private $defines;
35
36    public function __construct($uglifyjsBin = '/usr/bin/uglifyjs', $nodeBin = null)
37    {
38        $this->uglifyjsBin = $uglifyjsBin;
39        $this->nodeBin = $nodeBin;
40    }
41
42    public function setCompress($compress)
43    {
44        $this->compress = $compress;
45    }
46
47    public function setBeautify($beautify)
48    {
49        $this->beautify = $beautify;
50    }
51
52    public function setMangle($mangle)
53    {
54        $this->mangle = $mangle;
55    }
56
57    public function setScrewIe8($screwIe8)
58    {
59        $this->screwIe8 = $screwIe8;
60    }
61
62    public function setComments($comments)
63    {
64        $this->comments = $comments;
65    }
66
67    public function setWrap($wrap)
68    {
69        $this->wrap = $wrap;
70    }
71
72    public function setDefines(array $defines)
73    {
74        $this->defines = $defines;
75    }
76
77    public function filterLoad(AssetInterface $asset)
78    {
79    }
80
81    public function filterDump(AssetInterface $asset)
82    {
83        $pb = $this->createProcessBuilder(
84            $this->nodeBin
85            ? array($this->nodeBin, $this->uglifyjsBin)
86            : array($this->uglifyjsBin)
87        );
88
89        if ($this->compress) {
90            $pb->add('--compress');
91
92            if (is_string($this->compress) && !empty($this->compress)) {
93                $pb->add($this->compress);
94            }
95        }
96
97        if ($this->beautify) {
98            $pb->add('--beautify');
99        }
100
101        if ($this->mangle) {
102            $pb->add('--mangle');
103        }
104
105        if ($this->screwIe8) {
106            $pb->add('--screw-ie8');
107        }
108
109        if ($this->comments) {
110            $pb->add('--comments')->add(true === $this->comments ? 'all' : $this->comments);
111        }
112
113        if ($this->wrap) {
114            $pb->add('--wrap')->add($this->wrap);
115        }
116
117        if ($this->defines) {
118            $pb->add('--define')->add(implode(',', $this->defines));
119        }
120
121        // input and output files
122        $input  = FilesystemUtils::createTemporaryFile('uglifyjs2_in');
123        $output = FilesystemUtils::createTemporaryFile('uglifyjs2_out');
124
125        file_put_contents($input, $asset->getContent());
126        $pb->add('-o')->add($output)->add($input);
127
128        $proc = $pb->getProcess();
129        $code = $proc->run();
130        unlink($input);
131
132        if (0 !== $code) {
133            if (file_exists($output)) {
134                unlink($output);
135            }
136
137            if (127 === $code) {
138                throw new \RuntimeException('Path to node executable could not be resolved.');
139            }
140
141            throw FilterException::fromProcess($proc)->setInput($asset->getContent());
142        }
143
144        if (!file_exists($output)) {
145            throw new \RuntimeException('Error creating output file.');
146        }
147
148        $asset->setContent(file_get_contents($output));
149
150        unlink($output);
151    }
152}
153