Passed
Branch stable (1a8d6d)
by Nuno
05:14 queued 02:47
created

Builder::getCompiler()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.2109

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 1
dl 0
loc 13
ccs 5
cts 8
cp 0.625
crap 2.2109
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace LaravelZero\Framework\Commands\App;
4
5
use Phar;
6
use FilesystemIterator;
7
use UnexpectedValueException;
8
use LaravelZero\Framework\Commands\Command;
9
10
/**
11
 * This is the Laravel Zero Framework builder command class.
12
 *
13
 * @author Nuno Maduro <[email protected]>
14
 */
15
class Builder extends Command
16
{
17
    /**
18
     * The directory that contains your application builds.
19
     */
20
    const BUILD_PATH = BASE_PATH.DIRECTORY_SEPARATOR.'builds';
21
22
    /**
23
     * Contains the default app structure.
24
     *
25
     * @var []string
26
     */
27
    protected $structure = [
28
        'app'.DIRECTORY_SEPARATOR,
29
        'bootstrap'.DIRECTORY_SEPARATOR,
30
        'vendor'.DIRECTORY_SEPARATOR,
31
        'config'.DIRECTORY_SEPARATOR,
32
        'composer.json',
33
    ];
34
35
    /**
36
     * {@inheritdoc}
37
     */
38
    protected $signature = 'app:build {name=application : The build name}';
39
40
    /**
41
     * {@inheritdoc}
42
     */
43
    protected $description = 'Perform an application build';
44
45
    /**
46
     * Holds the configuration on is original state.
47
     *
48
     * @var string
49
     */
50
    protected static $config;
51
52
    /**
53
     * {@inheritdoc}
54
     */
55 1
    public function handle(): void
56
    {
57 1
        $this->alert('Building the application...');
58
59 1
        if (Phar::canWrite()) {
60 1
            $this->build($this->input->getArgument('name') ?: self::BUILD_NAME);
61
        } else {
62
            $this->error(
63
                'Unable to compile a phar because of php\'s security settings. '.'phar.readonly must be disabled in php.ini. '.PHP_EOL.PHP_EOL.'You will need to edit '.php_ini_loaded_file(
64
                ).' and add or set'.PHP_EOL.PHP_EOL.'    phar.readonly = Off'.PHP_EOL.PHP_EOL.'to continue. Details here: http://php.net/manual/en/phar.configuration.php'
65
            );
66
        }
67 1
    }
68
69
    /**
70
     * Builds the application.
71
     *
72
     * @param string $name
73
     *
74
     * @return $this
75
     */
76 1
    protected function build(string $name): Builder
77
    {
78 1
        $this->prepare()
79 1
            ->compile($name)
80 1
            ->cleanUp($name)
81 1
            ->setPermissions($name)
82 1
            ->finish();
83
84 1
        $this->info('Standalone application compiled into: builds'.DIRECTORY_SEPARATOR.$name);
85
86 1
        return $this;
87
    }
88
89
    /**
90
     * Compiles the standalone application.
91
     *
92
     * @param string $name
93
     *
94
     * @return $this
95
     */
96 1
    protected function compile(string $name): Builder
97
    {
98 1
        $this->info('Compiling code...');
99
100 1
        $compiler = $this->makeFolder()
101 1
            ->getCompiler($name);
102
103 1
        $structure = config('app.structure') ?: $this->structure;
104
105 1
        $regex = '#'.implode('|', $structure).'#';
106
107 1
        if (stristr(PHP_OS, 'WINNT') !== false) {
108
            $compiler->buildFromDirectory(BASE_PATH, str_replace('\\', '/', $regex));
109
        } else {
110
            // Linux, OS X
111 1
            $compiler->buildFromDirectory(BASE_PATH, $regex);
112
        }
113 1
        $compiler->setStub(
114 1
            "#!/usr/bin/env php \n".$compiler->createDefaultStub('bootstrap'.DIRECTORY_SEPARATOR.'init.php')
115
        );
116
117 1
        return $this;
118
    }
119
120
    /**
121
     * Gets a new instance of the compiler.
122
     *
123
     * @param string $name
124
     *
125
     * @return \Phar
126
     */
127 1
    protected function getCompiler(string $name): \Phar
128
    {
129
        try {
130 1
            return new Phar(
131 1
                self::BUILD_PATH.DIRECTORY_SEPARATOR.$name.'.phar',
132 1
                FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_FILENAME,
133 1
                $name
134
            );
135
        } catch (UnexpectedValueException $e) {
136
            $this->error("You can't perform a build.");
137
            exit(0);
138
        }
139
    }
140
141
    /**
142
     * Creates the folder for the builds.
143
     *
144
     * @return $this
145
     */
146 1
    protected function makeFolder(): Builder
147
    {
148 1
        if (! file_exists(self::BUILD_PATH)) {
149 1
            mkdir(self::BUILD_PATH);
150
        }
151
152 1
        return $this;
153
    }
154
155
    /**
156
     * Moves the compiled files to the builds folder.
157
     *
158
     * @param string $name
159
     *
160
     * @return $this
161
     */
162 1
    protected function cleanUp(string $name): Builder
163
    {
164 1
        $file = self::BUILD_PATH.DIRECTORY_SEPARATOR.$name;
165 1
        rename("$file.phar", $file);
166
167 1
        return $this;
168
    }
169
170
    /**
171
     * Sets the executable mode on the standalone application file.
172
     *
173
     * @param string $name
174
     *
175
     * @return $this
176
     */
177 1
    protected function setPermissions($name): Builder
178
    {
179 1
        $file = self::BUILD_PATH.DIRECTORY_SEPARATOR.$name;
180 1
        chmod($file, 0755);
181
182 1
        return $this;
183
    }
184
185
    /**
186
     * Prepares the application for build.
187
     *
188
     * @return $this
189
     */
190 1
    protected function prepare(): Builder
191
    {
192 1
        $file = BASE_PATH.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'app.php';
193 1
        static::$config = file_get_contents($file);
194 1
        $config = include $file;
195
196 1
        $config['production'] = true;
197
198 1
        $this->info('Moving configuration to production mode...');
199
200 1
        file_put_contents($file, '<?php return '.var_export($config, true).';'.PHP_EOL);
201
202 1
        return $this;
203
    }
204
205
    /**
206
     * Prepares the application for build.
207
     *
208
     * @return $this
209
     */
210 1
    protected function finish(): Builder
211
    {
212 1
        file_put_contents(BASE_PATH.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'app.php', static::$config);
213
214 1
        static::$config = null;
215
216 1
        return $this;
217
    }
218
219
    /**
220
     * Makes sure that the finish is performed even
221
     * if the command fails.
222
     */
223
    public function __destruct()
224
    {
225
        if (static::$config !== null) {
226
            file_put_contents(BASE_PATH.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'app.php', static::$config);
227
        }
228
    }
229
}
230