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

Command/SetupCommand.php (11 issues)

Check for variable interpolation in double quoted strings.

Best Practice Coding Style Minor

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