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 * UglifyJs filter. 20 * 21 * @link https://github.com/mishoo/UglifyJS 22 * @author André Roaldseth <andre@roaldseth.net> 23 */ 24class UglifyJsFilter extends BaseNodeFilter 25{ 26 private $uglifyjsBin; 27 private $nodeBin; 28 29 private $noCopyright; 30 private $beautify; 31 private $unsafe; 32 private $mangle; 33 private $defines; 34 35 /** 36 * @param string $uglifyjsBin Absolute path to the uglifyjs executable 37 * @param string $nodeBin Absolute path to the folder containg node.js executable 38 */ 39 public function __construct($uglifyjsBin = '/usr/bin/uglifyjs', $nodeBin = null) 40 { 41 $this->uglifyjsBin = $uglifyjsBin; 42 $this->nodeBin = $nodeBin; 43 } 44 45 /** 46 * Removes the first block of comments as well 47 * @param bool $noCopyright True to enable 48 */ 49 public function setNoCopyright($noCopyright) 50 { 51 $this->noCopyright = $noCopyright; 52 } 53 54 /** 55 * Output indented code 56 * @param bool $beautify True to enable 57 */ 58 public function setBeautify($beautify) 59 { 60 $this->beautify = $beautify; 61 } 62 63 /** 64 * Enable additional optimizations that are known to be unsafe in some situations. 65 * @param bool $unsafe True to enable 66 */ 67 public function setUnsafe($unsafe) 68 { 69 $this->unsafe = $unsafe; 70 } 71 72 /** 73 * Safely mangle variable and function names for greater file compress. 74 * @param bool $mangle True to enable 75 */ 76 public function setMangle($mangle) 77 { 78 $this->mangle = $mangle; 79 } 80 81 public function setDefines(array $defines) 82 { 83 $this->defines = $defines; 84 } 85 86 /** 87 * @see Assetic\Filter\FilterInterface::filterLoad() 88 */ 89 public function filterLoad(AssetInterface $asset) 90 { 91 } 92 93 /** 94 * Run the asset through UglifyJs 95 * 96 * @see Assetic\Filter\FilterInterface::filterDump() 97 */ 98 public function filterDump(AssetInterface $asset) 99 { 100 $pb = $this->createProcessBuilder( 101 $this->nodeBin 102 ? array($this->nodeBin, $this->uglifyjsBin) 103 : array($this->uglifyjsBin) 104 ); 105 106 if ($this->noCopyright) { 107 $pb->add('--no-copyright'); 108 } 109 110 if ($this->beautify) { 111 $pb->add('--beautify'); 112 } 113 114 if ($this->unsafe) { 115 $pb->add('--unsafe'); 116 } 117 118 if (false === $this->mangle) { 119 $pb->add('--no-mangle'); 120 } 121 122 if ($this->defines) { 123 foreach ($this->defines as $define) { 124 $pb->add('-d')->add($define); 125 } 126 } 127 128 // input and output files 129 $input = FilesystemUtils::createTemporaryFile('uglifyjs_in'); 130 $output = FilesystemUtils::createTemporaryFile('uglifyjs_out'); 131 132 file_put_contents($input, $asset->getContent()); 133 $pb->add('-o')->add($output)->add($input); 134 135 $proc = $pb->getProcess(); 136 $code = $proc->run(); 137 unlink($input); 138 139 if (0 !== $code) { 140 if (file_exists($output)) { 141 unlink($output); 142 } 143 144 if (127 === $code) { 145 throw new \RuntimeException('Path to node executable could not be resolved.'); 146 } 147 148 throw FilterException::fromProcess($proc)->setInput($asset->getContent()); 149 } 150 151 if (!file_exists($output)) { 152 throw new \RuntimeException('Error creating output file.'); 153 } 154 155 $uglifiedJs = file_get_contents($output); 156 unlink($output); 157 158 $asset->setContent($uglifiedJs); 159 } 160} 161