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 * Precompiles Handlebars templates for use in the Ember.js framework. This filter
20 * requires that the npm package ember-precompile be installed. You can find this
21 * package at https://github.com/gabrielgrant/node-ember-precompile.
22 *
23 * @link http://www.emberjs.com/
24 * @author Jarrod Nettles <jarrod.nettles@icloud.com>
25 */
26class EmberPrecompileFilter extends BaseNodeFilter
27{
28    private $emberBin;
29    private $nodeBin;
30
31    public function __construct($handlebarsBin = '/usr/bin/ember-precompile', $nodeBin = null)
32    {
33        $this->emberBin = $handlebarsBin;
34        $this->nodeBin = $nodeBin;
35    }
36
37    public function filterLoad(AssetInterface $asset)
38    {
39        $pb = $this->createProcessBuilder($this->nodeBin
40            ? array($this->nodeBin, $this->emberBin)
41            : array($this->emberBin));
42
43        if ($sourcePath = $asset->getSourcePath()) {
44            $templateName = basename($sourcePath);
45        } else {
46            throw new \LogicException('The embed-precompile filter requires that assets have a source path set');
47        }
48
49        $inputDirPath = FilesystemUtils::createThrowAwayDirectory('ember_in');
50        $inputPath = $inputDirPath.DIRECTORY_SEPARATOR.$templateName;
51        $outputPath = FilesystemUtils::createTemporaryFile('ember_out');
52
53        file_put_contents($inputPath, $asset->getContent());
54
55        $pb->add($inputPath)->add('-f')->add($outputPath);
56
57        $process = $pb->getProcess();
58        $returnCode = $process->run();
59
60        unlink($inputPath);
61        rmdir($inputDirPath);
62
63        if (127 === $returnCode) {
64            throw new \RuntimeException('Path to node executable could not be resolved.');
65        }
66
67        if (0 !== $returnCode) {
68            if (file_exists($outputPath)) {
69                unlink($outputPath);
70            }
71            throw FilterException::fromProcess($process)->setInput($asset->getContent());
72        }
73
74        if (!file_exists($outputPath)) {
75            throw new \RuntimeException('Error creating output file.');
76        }
77
78        $compiledJs = file_get_contents($outputPath);
79        unlink($outputPath);
80
81        $asset->setContent($compiledJs);
82    }
83
84    public function filterDump(AssetInterface $asset)
85    {
86    }
87}
88