DotEnv::finish()   B
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 30
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 4
Bugs 1 Features 0
Metric Value
c 4
b 1
f 0
dl 0
loc 30
ccs 8
cts 8
cp 1
rs 8.8571
cc 2
eloc 7
nc 2
nop 1
crap 2
1
<?php namespace Lanin\Laravel\SetupWizard\Commands\Steps;
2
3
use Illuminate\Support\Str;
4
5
class DotEnv extends AbstractStep
6
{
7
    const RANDOM = 'random';
8
    const SELECT = 'select';
9
    const INPUT  = 'input';
10
11
    /**
12
     * Array of bootstrappers to reload Application config.
13
     *
14
     * @var array
15
     */
16
    protected $boostrappers = [
17
        'Lanin\Laravel\SetupWizard\Support\Bootstrap\DetectEnvironment',
18
        'Lanin\Laravel\SetupWizard\Support\Bootstrap\LoadConfiguration',
19
        'Illuminate\Foundation\Bootstrap\ConfigureLogging',
20
    ];
21
22
    /**
23
     * Return short command description.
24
     *
25
     * @return string
26
     */
27 4
    public function prompt()
28
    {
29 4
        return 'Do you want to ' . ($this->envFileExist() ? 'update' : 'create') . ' .env file?';
30
    }
31
32
    /**
33
     * Check if .env file exist
34
     *
35
     * @return bool
36
     */
37 4
    protected function envFileExist()
38
    {
39 4
        return file_exists($this->envFilePath('.env'));
40
    }
41
42
    /**
43
     * Return path where to search .env files.
44
     *
45
     * @param  string $file
46
     * @return string
47
     */
48 6
    protected function envFilePath($file = '')
49
    {
50 6
        return base_path($file);
51
    }
52
53
    /**
54
     * Proceed step.
55
     *
56
     * @return array
57
     */
58 2
    public function prepare()
59
    {
60 2
        $result = [];
61
62 2
        $file = $this->envFileToUseForDefaults();
63
64 2
        \Lanin\Laravel\SetupWizard\Support\DotEnv::load($this->envFilePath(), $file);
65
66 2
        foreach (\Lanin\Laravel\SetupWizard\Support\DotEnv::$variables as $name => $default)
67
        {
68 2
            $options = $this->getVariableOptions($name);
69
70 2
            $result[$name] = $this->{'run' . $options['type']}($name, $options, $default);
71 2
        }
72
73 2
        return $result;
74
    }
75
76
    /**
77
     * Get variable options from configs.
78
     *
79
     * @param  string $name
80
     * @return array
81
     */
82 2
    protected function getVariableOptions($name)
83
    {
84 2
        $options = config(
85 2
            'setup.dot_env.variables.' . $name,
86 2
            ['type' => self::INPUT, 'prompt' => 'Provide value for environment variable']
87 2
        );
88
89 2
        return $options;
90
    }
91
92
    /**
93
     * Chooses what env file to use.
94
     *
95
     * @return string
96
     */
97 2
    protected function envFileToUseForDefaults()
98
    {
99 2
        $file = config('setup.dot_env.default_file');
100
101 2
        if ($this->envFileExist() &&
102 2
            $this->command->confirm('Existing .env file was found. Use it for defaults?', true)
103 2
        )
104 2
        {
105 2
            $file = '.env';
106 2
        }
107
108 2
        return $file;
109
    }
110
111
    /**
112
     * Run input prompt.
113
     *
114
     * @param  string $name
115
     * @param  array $options
116
     * @param  string|null $default
117
     * @return string
118
     */
119 4
    protected function runInput($name, array $options, $default = null)
120
    {
121 4
        return $this->command->ask($this->generatePrompt($name, $options['prompt']), $default);
122
    }
123
124
    /**
125
     * Run select prompt.
126
     *
127
     * @param  string $name
128
     * @param  array $options
129
     * @param  string|null $default
130
     * @return string
131
     */
132 4
    protected function runSelect($name, array $options, $default = null)
133
    {
134 4
        return $this->command->choice(
135 4
            $this->generatePrompt($name, $options['prompt']),
136 4
            $options['options'],
137 4
            array_search($default, $options['options'])
138 4
        );
139
    }
140
141
    /**
142
     * Run random prompt.
143
     *
144
     * @param  string $name
145
     * @param  array $options
146
     * @param  string $default
147
     * @return string
148
     */
149 6
    protected function runRandom($name, array $options, $default = 'SomeRandomString')
150
    {
151 6
        $value = $this->command->ask($this->generatePrompt($name, $options['prompt']), $default);
152
153 6
        if ($value === 'SomeRandomString')
154 6
        {
155 2
            $value = $this->getRandomKey(config('app.cipher'));
156 2
        }
157
158 6
        return $value;
159
    }
160
161
    /**
162
     * Generate a random key for the application.
163
     *
164
     * @param  string $cipher
165
     * @return string
166
     */
167 4
    protected function getRandomKey($cipher)
168
    {
169 4
        if ($cipher === 'AES-128-CBC')
170 4
        {
171 2
            return Str::random(16);
172
        }
173
174 4
        return Str::random(32);
175
    }
176
177
    /**
178
     * Preview results.
179
     *
180
     * @param  mixed $results
181
     * @return void
182
     */
183 2
    public function preview($results)
184
    {
185 2
        $this->command->table(['Variable', 'Value'], $this->arrayToTable($results));
186 2
    }
187
188
    /**
189
     * Generate prompt text.
190
     *
191
     * @param  string $name
192
     * @param  string $prompt
193
     * @return string
194
     */
195 12
    protected function generatePrompt($name, $prompt)
196
    {
197 12
        return $prompt . ' <comment>' . $name . '=?</comment>';
198
    }
199
200
    /**
201
     * Finish step.
202
     *
203
     * @param  mixed $results
204
     * @return bool
205
     */
206 4
    public function finish($results)
207
    {
208 4
        if ($return = $this->saveFile($results))
209 4
        {
210 2
            $this->command->info('New .env file was saved.');
211
212
            /*
213
             * "Rebootstrap" Application to load new env variables to the config
214
             * using native Application::bootstrapWith([]) method with custom bootstrappers.
215
             *
216
             * First of all we have to make Dotenv mutable in order to overwrite environment variables.
217
             *
218
             * Next we have to update config.
219
             * In current Laravel implementation there is no method to reload Application config fully or Application itself.
220
             * Problem is that after reloading Config Repository it looses data from packages' config files
221
             * that are not currently published in /config directory. They are loaded only once after Application is bootstrapped.
222
             * And you can't force it to "rebootstrap" fully manually from outside (protected methods/properties).
223
             *
224
             * So the only way to "rebootstrap" it partly with custom Bootstrapper that uses existing Config Repository to
225
             * reload all /config files.
226
             */
227 2
            $this->command->getLaravel()->bootstrapWith($this->boostrappers);
228 2
        }
229
        else
230
        {
231 2
            $this->command->error('Failed to save .env file. Check permissions please.');
232
        }
233
234 4
        return $return;
235
    }
236
237
    /**
238
     * Save .env file.
239
     *
240
     * @param $results
241
     * @return bool
242
     */
243 2
    protected function saveFile($results)
244
    {
245 2
        $file = fopen($this->envFilePath('.env'), 'w+');
246 2
        foreach ($results as $variable => $value)
247
        {
248 2
            fwrite($file, $variable . '=' . $value . PHP_EOL);
249 2
        }
250
251 2
        return fclose($file);
252
    }
253
}
254