diff --git a/framework/yii/web/AssetConverter.php b/framework/yii/web/AssetConverter.php index 75a3106..3b654e5 100644 --- a/framework/yii/web/AssetConverter.php +++ b/framework/yii/web/AssetConverter.php @@ -47,17 +47,46 @@ class AssetConverter extends Component implements AssetConverterInterface list ($ext, $command) = $this->commands[$ext]; $result = substr($asset, 0, $pos + 1) . $ext; if (@filemtime("$basePath/$result") < filemtime("$basePath/$asset")) { - $output = []; - $command = strtr($command, [ - '{from}' => escapeshellarg("$basePath/$asset"), - '{to}' => escapeshellarg("$basePath/$result"), - ]); - exec($command, $output); - Yii::trace("Converted $asset into $result: " . implode("\n", $output), __METHOD__); + $this->runCommand($command, $basePath, $asset, $result); } return $result; } } return $asset; } + + /** + * Runs a command to convert asset files. + * @param string $command the command to run + * @param string $basePath asset base path and command working directory + * @param string $asset the name of the asset file + * @param string $result the name of the file to be generated by the converter command + * @return bool true on success, false on failure. Failures will be logged. + */ + protected function runCommand($command, $basePath, $asset, $result) + { + $command = strtr($command, [ + '{from}' => escapeshellarg("$basePath/$asset"), + '{to}' => escapeshellarg("$basePath/$result"), + ]); + $descriptor = array( + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w'), + ); + $pipes = array(); + $proc = proc_open($command, $descriptor, $pipes, $basePath); + $stdout = stream_get_contents($pipes[1]); + $stderr = stream_get_contents($pipes[2]); + foreach($pipes as $pipe) { + fclose($pipe); + } + $status = proc_close($proc); + + if ($status !== 0) { + Yii::error("AssetConverter command '$command' failed with exit code $status:\nSTDOUT:\n$stdout\nSTDERR:\n$stderr\n"); + } else { + Yii::trace("Converted $asset into $result:\nSTDOUT:\n$stdout\nSTDERR:\n$stderr", __METHOD__); + } + return $status === 0; + } } diff --git a/tests/unit/framework/web/AssetConverterTest.php b/tests/unit/framework/web/AssetConverterTest.php new file mode 100644 index 0000000..54669b3 --- /dev/null +++ b/tests/unit/framework/web/AssetConverterTest.php @@ -0,0 +1,42 @@ + + */ + +namespace yiiunit\framework\web; +use yii\web\AssetConverter; + +/** + * @group web + */ +class AssetConverterTest extends \yiiunit\TestCase +{ + protected function setUp() + { + parent::setUp(); + $this->mockApplication(); + } + + + public function testConvert() + { + $tmpPath = \Yii::$app->runtimePath . '/assetConverterTest'; + if (!is_dir($tmpPath)) { + mkdir($tmpPath, 0777, true); + } + file_put_contents($tmpPath . '/test.php', <<commands['php'] = ['txt', 'php {from} > {to}']; + $this->assertEquals('test.txt', $converter->convert('test.php', $tmpPath)); + + $this->assertTrue(file_exists($tmpPath . '/test.txt'), 'Failed asserting that asset output file exists.'); + $this->assertEquals("Hello World!\nHello Yii!", file_get_contents($tmpPath . '/test.txt')); + } +} \ No newline at end of file