Passed
Branch develop (1ecfd6)
by Nuno
02:37
created

BuildCommand::__destruct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of Laravel Zero.
7
 *
8
 * (c) Nuno Maduro <[email protected]>
9
 *
10
 *  For the full copyright and license information, please view the LICENSE
11
 *  file that was distributed with this source code.
12
 */
13
14
namespace LaravelZero\Framework\Commands\App;
15
16
use Illuminate\Support\Facades\File;
17
use Symfony\Component\Process\Process;
18
use LaravelZero\Framework\Commands\Command;
19
use Symfony\Component\Console\Output\NullOutput;
20
use Symfony\Component\Console\Helper\ProgressBar;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Output\OutputInterface;
23
24
final class BuildCommand extends Command
25
{
26
    /**
27
     * {@inheritdoc}
28
     */
29
    protected $signature = 'app:build {name? : The build name}';
30
31
    /**
32
     * {@inheritdoc}
33
     */
34
    protected $description = 'Compile your application into a single file';
35
36
    /**
37
     * Holds the configuration on is original state.
38
     *
39
     * @var string|null
40
     */
41
    private static $config;
42
43
    /**
44
     * Holds the command original output.
45
     *
46
     * @var \Symfony\Component\Console\Output\OutputInterface
47
     */
48
    private $originalOutput;
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 2
    public function handle(): void
54
    {
55 2
        $this->title('Building process');
56
57 2
        $this->build($this->input->getArgument('name') ?? ARTISAN_BINARY);
58 1
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 2
    public function run(InputInterface $input, OutputInterface $output)
64
    {
65 2
        parent::run($input, $this->originalOutput = $output);
66 1
    }
67
68
    /**
69
     * Builds the application into a single file.
70
     *
71
     * @param string $name The file name.
72
     *
73
     * @return $this
74
     */
75 2
    private function build(string $name): BuildCommand
76
    {
77
        /*
78
         * We prepare the application for a build, moving it to production. Then,
79
         * after compile all the code to a single file, we move the built file
80
         * to the builds folder with the correct permissions.
81
         */
82 2
        $this->prepare()
83 2
            ->compile($name)
84 1
            ->clear();
85
86 1
        $this->output->writeln(
87 1
            sprintf('    Compiled successfully: <fg=green>%s</>', $this->app->buildsPath($name))
0 ignored issues
show
Bug introduced by
The method buildsPath() does not exist on Illuminate\Contracts\Foundation\Application. It seems like you code against a sub-type of Illuminate\Contracts\Foundation\Application such as LaravelZero\Framework\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

87
            sprintf('    Compiled successfully: <fg=green>%s</>', $this->app->/** @scrutinizer ignore-call */ buildsPath($name))
Loading history...
Bug introduced by
The method buildsPath() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

87
            sprintf('    Compiled successfully: <fg=green>%s</>', $this->app->/** @scrutinizer ignore-call */ buildsPath($name))

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
88
        );
89
90 1
        return $this;
91
    }
92
93
    /**
94
     * @param string $name
95
     *
96
     * @return $this
97
     */
98 2
    private function compile(string $name): BuildCommand
99
    {
100 2
        if (! File::exists($this->app->buildsPath())) {
101 2
            File::makeDirectory($this->app->buildsPath());
102
        }
103
104 2
        $process = new Process(
105 2
            './box compile' . ' --working-dir=' . base_path() . ' --config=' . base_path('box.json'),
106 2
            dirname(dirname(dirname(__DIR__))) . '/bin'
107
        );
108
109 2
        $section = tap($this->originalOutput->section())->write('');
0 ignored issues
show
Bug introduced by
The method section() does not exist on Symfony\Component\Console\Output\OutputInterface. It seems like you code against a sub-type of Symfony\Component\Console\Output\OutputInterface such as Symfony\Component\Console\Style\OutputStyle or Symfony\Component\Console\Output\ConsoleOutput or anonymous//tests/BuildCommandTest.php$1 or anonymous//tests/BuildCommandTest.php$3 or Symfony\Component\Console\Output\ConsoleOutput. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

109
        $section = tap($this->originalOutput->/** @scrutinizer ignore-call */ section())->write('');
Loading history...
110
111 2
        $progressBar = tap(
112 2
            new ProgressBar(
113 2
                $this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL ? new NullOutput() : $section, 25
114
            )
115 2
        )->setProgressCharacter("\xF0\x9F\x8D\xBA");
116
117 2
        foreach (tap($process)->start() as $type => $data) {
118 2
            $progressBar->advance();
119
120 2
            if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) {
121 2
                $process::OUT === $type ? $this->info("$data") : $this->error("$data");
122
            }
123
        }
124
125 2
        $progressBar->finish();
126
127 2
        $section->clear();
128
129 1
        $this->task('   2. <fg=yellow>Compile</> into a single file');
0 ignored issues
show
Bug introduced by
The method task() does not exist on LaravelZero\Framework\Commands\App\BuildCommand. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

129
        $this->/** @scrutinizer ignore-call */ 
130
               task('   2. <fg=yellow>Compile</> into a single file');
Loading history...
130
131 1
        $this->output->newLine();
132
133 1
        File::move($this->app->basePath(ARTISAN_BINARY) . '.phar', $this->app->buildsPath($name));
134
135 1
        return $this;
136
    }
137
138
    /**
139
     * @return $this
140
     */
141 2
    private function prepare(): BuildCommand
142
    {
143 2
        $file = $this->app->configPath('app.php');
144 2
        static::$config = File::get($file);
0 ignored issues
show
Bug introduced by
Since $config is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $config to at least protected.
Loading history...
145 2
        $config = include $file;
146
147 2
        $config['production'] = true;
148
149 2
        $this->task(
150 2
            '   1. Moving application to <fg=yellow>production mode</>',
151
            function () use ($file, $config) {
152 2
                File::put($file, '<?php return ' . var_export($config, true) . ';' . PHP_EOL);
153 2
            }
154
        );
155
156 2
        return $this;
157
    }
158
159
    /**
160
     * @return $this
161
     */
162 2
    private function clear(): BuildCommand
163
    {
164 2
        File::put($this->app->configPath('app.php'), static::$config);
0 ignored issues
show
Bug introduced by
Since $config is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $config to at least protected.
Loading history...
165
166 2
        static::$config = null;
167
168 2
        return $this;
169
    }
170
171
    /**
172
     * Makes sure that the `clear` is performed even
173
     * if the command fails.
174
     *
175
     * @return void
176
     */
177 21
    public function __destruct()
178
    {
179 21
        if (static::$config !== null) {
0 ignored issues
show
Bug introduced by
Since $config is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $config to at least protected.
Loading history...
180 1
            $this->clear();
181
        }
182 21
    }
183
}
184