Completed
Push — master ( 9c1f83...0c1135 )
by Paulo Rodrigues
10:00
created

Command/SetupCommand.php (11 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Rj\FrontendBundle\Command;
4
5
use Rj\FrontendBundle\Command\Options\SimpleOptionHelper;
6
use Rj\FrontendBundle\Command\Options\ChoiceOptionHelper;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Input\ArrayInput;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Input\InputOption;
11
use Symfony\Component\Console\Output\OutputInterface;
12
use Symfony\Component\Templating\PhpEngine;
13
use Symfony\Component\Templating\TemplateNameParser;
14
use Symfony\Component\Templating\Loader\FilesystemLoader;
15
16
class SetupCommand extends Command
17
{
18
    private $templating;
19
    private $rootDir = null;
20
21 30
    public function __construct($name = null)
22
    {
23 30
        parent::__construct($name);
24
25 30
        $this->templating = new PhpEngine(
26 30
            new TemplateNameParser(),
27 30
            new FilesystemLoader(array(__DIR__.'/../Resources/blueprints/%name%'))
28
        );
29 30
    }
30
31 30
    public function setRootDir($path)
32
    {
33 30
        $this->rootDir = $path;
34 30
    }
35
36 30
    protected function configure()
37
    {
38
        $this
39 30
            ->setName('rj_frontend:setup')
40 30
            ->setDescription('Generate the configuration for the asset pipeline')
41 30
            ->addOption(
42 30
                'dry-run',
43 30
                null,
44 30
                InputOption::VALUE_NONE,
45 30
                'Output which commands would have been run instead of running them'
46
            )
47 30
            ->addOption(
48 30
                'force',
49 30
                null,
50 30
                InputOption::VALUE_NONE,
51 30
                'Force execution'
52
            )
53 30
            ->addOption(
54 30
                'src-dir',
55 30
                null,
56 30
                InputOption::VALUE_REQUIRED,
57 30
                'Path to the directory containing the source assets [e.g. '.$this->getDefaultOption('src-dir').']'
58
            )
59 30
            ->addOption(
60 30
                'dest-dir',
61 30
                null,
62 30
                InputOption::VALUE_REQUIRED,
63 30
                'Path to the directory containing the compiled assets [e.g. '.$this->getDefaultOption('dest-dir').']'
64
            )
65 30
            ->addOption(
66 30
                'pipeline',
67 30
                null,
68 30
                InputOption::VALUE_REQUIRED,
69 30
                'Asset pipeline to use [only gulp is available at the moment]'
70
            )
71 30
            ->addOption(
72 30
                'csspre',
73 30
                null,
74 30
                InputOption::VALUE_REQUIRED,
75 30
                'CSS preprocessor to use [sass, less or none]'
76
            )
77 30
            ->addOption(
78 30
                'coffee',
79 30
                null,
80 30
                InputOption::VALUE_REQUIRED,
81 30
                'Use the CoffeeScript compiler [true or false]'
82
            )
83
        ;
84 30
    }
85
86 4
    protected function interact(InputInterface $input, OutputInterface $output)
87
    {
88 4
        $simpleOptionHelper = new SimpleOptionHelper($this, $input, $output);
89 4
        $choiceOptionHelper = new ChoiceOptionHelper($this, $input, $output);
90
91
        $simpleOptionHelper
92 4
            ->setDefaultValue($this->getDefaultOption('src-dir'))
93 4
            ->setOption(
94 4
                'src-dir',
95 4
                'Path to the directory containing the source assets [default is '.$this->getDefaultOption('src-dir').']'
96
            )
97
        ;
98
99
        $simpleOptionHelper
100 4
            ->setDefaultValue($this->getDefaultOption('dest-dir'))
101 4
            ->setOption(
102 4
                'dest-dir',
103 4
                'Path to the directory containing the compiled assets [default is '.$this->getDefaultOption('dest-dir').']'
104
            )
105
        ;
106
107
        $choiceOptionHelper
108 4
            ->setAllowedValues(array('gulp'))
109 4
            ->setErrorMessage('%s is not a supported asset pipeline')
110 4
            ->setOption(
111 4
                'pipeline',
112 4
                'Asset pipeline to use [only gulp is available at the moment]'
113
            )
114
        ;
115
116
        $choiceOptionHelper
117 4
            ->setAllowedValues(array('sass', 'less', 'none'))
118 4
            ->setErrorMessage('%s is not a supported CSS preprocessor')
119 4
            ->setOption(
120 4
                'csspre',
121 4
                'CSS preprocessor to use [default is '.$this->getDefaultOption('csspre').']'
122
            )
123
        ;
124
125
        $choiceOptionHelper
126 4
            ->setAllowedValues(array('false', 'true'))
127 4
            ->setErrorMessage('%s is not a supported value for --coffee. Use either true or false')
128 4
            ->setOption(
129 4
                'coffee',
130 4
                'Whether to use the CoffeeScript compiler [default is '.$this->getDefaultOption('coffee').']'
131
            )
132
        ;
133
134 4
        $output->writeln('');
135 4
    }
136
137 30
    protected function execute(InputInterface $input, OutputInterface $output)
138
    {
139 30
        $this->processOptions($input);
140
141 30
        $output->writeln('<info>Selected options are:</info>');
142 30
        $output->writeln('src-dir:  '.$input->getOption('src-dir'));
143 30
        $output->writeln('dest-dir: '.$input->getOption('dest-dir'));
144 30
        $output->writeln('pipeline: '.$input->getOption('pipeline'));
145 30
        $output->writeln('csspre:   '.$input->getOption('csspre'));
146 30
        $output->writeln('coffee:   '.($input->getOption('coffee') ? 'true' : 'false'));
147
148 30
        if (!preg_match('|web/.+|', $input->getOption('dest-dir'))) {
149 6
            throw new \InvalidArgumentException("'dest-dir' must be a directory under web/");
150
        }
151
152 24
        $output->writeln('');
153 24
        $this->createSourceTree($input, $output);
154 24
        $this->createBuildFile($input, $output);
155 24
        $this->createPackageJson($input, $output);
156 24
        $this->createBowerJson($input, $output);
157
158 24
        $output->writeln('');
159 24
        $this->runInstallCommand($input, $output);
160 24
    }
161
162 24
    private function runInstallCommand($input, $output)
163
    {
164 24
        if ($input->getOption('dry-run')) {
165 12
            return $output->writeln('<info>Would have installed npm and bower dependencies</info>');
166
        }
167
168 12
        $this->getApplication()->find('rj_frontend:install')
169 12
            ->run(new ArrayInput(array('command' => 'rj_frontend:install')), $output);
170 12
    }
171
172 24
    private function createSourceTree($input, $output)
173
    {
174 24
        $blueprints = __DIR__.'/../Resources/blueprints';
175 24
        $dryRun = $input->getOption('dry-run');
176 24
        $base = $input->getOption('src-dir');
177
178 24
        $output->writeln($dryRun
179 12
            ? '<info>Would have created directory tree for source assets:</info>'
180 24
            : '<info>Creating directory tree for source assets:</info>'
181
        );
182
183 24
        $blueprintDir = "$blueprints/images";
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $blueprints instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
184 24
        $this->createDirFromBlueprint($input, $output, $blueprintDir, "$base/images");
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $base instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
185
186 24
        $blueprintDir = "$blueprints/stylesheets/".$input->getOption('csspre');
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $blueprints instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
187 24
        $this->createDirFromBlueprint($input, $output, $blueprintDir, "$base/stylesheets");
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $base instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
188
189 24
        $blueprintDir = "$blueprints/scripts/";
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $blueprints instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
190 24
        $blueprintDir .= $input->getOption('coffee') ? 'coffee' : 'js';
191 24
        $this->createDirFromBlueprint($input, $output, $blueprintDir, "$base/scripts");
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $base instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
192
193 24
        $output->writeln('');
194 24
    }
195
196 24 View Code Duplication
    private function createBuildFile($input, $output)
197
    {
198
        $files = array(
199 24
            'gulp' => 'gulp/gulpfile.js',
200
        );
201
202 24
        $this->createFileFromTemplate($input, $output, 'pipelines/'.$files[$input->getOption('pipeline')]);
203 24
    }
204
205 24 View Code Duplication
    private function createPackageJson($input, $output)
206
    {
207
        $files = array(
208 24
            'gulp' => 'gulp/package.json',
209
        );
210
211 24
        $this->createFileFromTemplate($input, $output, 'pipelines/'.$files[$input->getOption('pipeline')]);
212 24
    }
213
214 24
    private function createBowerJson($input, $output)
215
    {
216 24
        $this->createFileFromTemplate($input, $output, 'bower.json');
217 24
    }
218
219 24
    private function createDirFromBlueprint($input, $output, $blueprintDir, $targetDir)
220
    {
221 24
        $dryRun = $input->getOption('dry-run');
222
223 24
        if (!$dryRun && !file_exists($targetDir)) {
224 12
            mkdir($targetDir, 0777, true);
225
        }
226
227 24
        foreach (preg_grep('/^\.?\w+/', scandir($blueprintDir)) as $entry) {
228 24
            $target = $entry;
229
230 24
            $isPhpTemplate = substr($entry, strrpos($entry, '.')) === '.php';
231 24
            if ($isPhpTemplate) {
232 24
                $entry = str_replace('.php', '', $entry);
233 24
                $target = str_replace('.php', '', $target);
234
            }
235
236 24
            $entry = $blueprintDir.'/'.$entry;
237 24
            $target = $targetDir.'/'.$target;
238
239 24
            if (!$dryRun) {
240 12
                if ($isPhpTemplate) {
241 12
                    $this->renderTemplate($input, $output, $entry, $target);
242
                } else {
243 12
                    if (file_exists($target) && !$input->getOption('force')) {
244
                        $output->writeln(
245
                            "<error>$target already exists. Run this command with --force to overwrite</error>
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $target instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
246
                        ");
247
248
                        continue;
249
                    }
250
251 12
                    copy($entry, $target);
252
                }
253
            }
254
255 24
            $output->writeln($target);
256
        }
257 24
    }
258
259 24
    private function createFileFromTemplate($input, $output, $file)
260
    {
261 24
        $dryRun = $input->getOption('dry-run');
262
263 24
        $targetFile = basename($file);
264 24
        if (!empty($this->rootDir)) {
265 24
            $targetFile = $this->rootDir.'/'.$targetFile;
266
        }
267
268 24
        $output->writeln($dryRun
269 12
            ? "<info>Would have created file $targetFile</info>"
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $targetFile instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
270 24
            : "<info>Creating file $targetFile</info>"
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $targetFile instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
271
        );
272
273 24
        if ($dryRun) {
274 12
            return;
275
        }
276
277 12
        $this->renderTemplate($input, $output, $file, $targetFile);
278 12
    }
279
280 12
    private function renderTemplate($input, $output, $file, $target)
281
    {
282 12
        if (file_exists($target) && !$input->getOption('force')) {
283 2
            return $output->writeln(
284
                "<error>$target already exists. Run this command with --force to overwrite</error>
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $target instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
285 2
            ");
286
        }
287
288 12
        switch ($input->getOption('csspre')) {
289
            case 'sass':
290 10
                $stylesheetExtension = 'scss';
291 10
                break;
292
            case 'less':
293 2
                $stylesheetExtension = 'less';
294 2
                break;
295
            default:
296
                $stylesheetExtension = 'css';
297
                break;
298
        }
299
300 12
        file_put_contents($target, $this->templating->render("$file.php", array(
1 ignored issue
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $file instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
301 12
            'projectName'         => basename(getcwd()),
302 12
            'srcDir'              => $input->getOption('src-dir'),
303 12
            'destDir'             => $input->getOption('dest-dir'),
304 12
            'prefix'              => str_replace('web/', '', $input->getOption('dest-dir')),
305 12
            'coffee'              => $input->getOption('coffee'),
306 12
            'cssPre'              => $input->getOption('csspre'),
307 12
            'stylesheetExtension' => $stylesheetExtension,
308
        )));
309 12
    }
310
311 30
    private function processOptions($input)
312
    {
313 30
        foreach ($input->getOptions() as $name => $value) {
314 30
            if (!$input->isInteractive() && $value === null) {
315 26
                $value = $this->getDefaultOption($name);
316
            }
317
318 30
            if ($value === 'true') {
319 4
                $value = true;
320 30
            } elseif ($value === 'false') {
321 24
                $value = false;
322
            }
323
324 30
            $input->setOption($name, $value);
325
        }
326 30
    }
327
328 30
    private function getDefaultOption($name)
329
    {
330
        $defaults = array(
331 30
            'src-dir'  => empty($this->rootDir) ? 'app/Resources' : $this->rootDir.'/app/Resources',
332 30
            'dest-dir' => empty($this->rootDir) ? 'web/assets' : $this->rootDir.'/web/assets',
333 30
            'pipeline' => 'gulp',
334 30
            'csspre'   => 'sass',
335 30
            'coffee'   => 'false',
336
        );
337
338 30
        return $defaults[$name];
339
    }
340
}
341