1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Dbtlr\PHPEnvBuilder; |
4
|
|
|
|
5
|
|
|
use Dbtlr\PHPEnvBuilder\Exception\ConfigurationException; |
6
|
|
|
use Dbtlr\PHPEnvBuilder\Exception\WritableException; |
7
|
|
|
use Dbtlr\PHPEnvBuilder\IOHandler\CLImateHandler; |
8
|
|
|
use Dbtlr\PHPEnvBuilder\IOHandler\IOHandlerInterface; |
9
|
|
|
use League\CLImate\CLImate; |
10
|
|
|
|
11
|
|
|
class Builder |
12
|
|
|
{ |
13
|
|
|
/** @var array */ |
14
|
|
|
protected $questions = []; |
15
|
|
|
|
16
|
|
|
/** @var array */ |
17
|
|
|
protected $config = []; |
18
|
|
|
|
19
|
|
|
/** @var string */ |
20
|
|
|
protected $envFile; |
21
|
|
|
|
22
|
|
|
/** @var EnvLoader */ |
23
|
|
|
protected $envLoader; |
24
|
|
|
|
25
|
|
|
/** @var EnvWriter */ |
26
|
|
|
protected $envWriter; |
27
|
|
|
|
28
|
|
|
/** @var IO */ |
29
|
|
|
protected $io; |
30
|
|
|
|
31
|
|
|
/** @var array */ |
32
|
|
|
protected $answers = []; |
33
|
|
|
|
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Application constructor. |
37
|
|
|
* |
38
|
|
|
* This builds with the CLImateInterface as a default, but this |
39
|
|
|
* can be overridden by the setIOHandler() method. |
40
|
|
|
* |
41
|
|
|
* @throws ConfigurationException |
42
|
|
|
* @param string $envFile |
43
|
|
|
* @param array $config |
44
|
|
|
*/ |
45
|
|
|
public function __construct(string $envFile, array $config = []) |
46
|
|
|
{ |
47
|
|
|
$this->envFile = $envFile; |
48
|
|
|
|
49
|
|
|
// Set the config to it's defaults. |
50
|
|
|
$this->config = [ |
51
|
|
|
'verbose' => false, |
52
|
|
|
'loadEnv' => true, |
53
|
|
|
]; |
54
|
|
|
|
55
|
|
|
$this->setConfig($config); |
56
|
|
|
$this->setEnvLoader(new EnvLoader($envFile)); |
57
|
|
|
$this->setEnvWriter(new EnvWriter(dirname($envFile)), basename($envFile)); |
|
|
|
|
58
|
|
|
$this->setIO(new IO(new CLImateHandler(new CLImate()))); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Set some of the optional config elements. |
63
|
|
|
* |
64
|
|
|
* @throws ConfigurationException |
65
|
|
|
* @param array $config |
66
|
|
|
*/ |
67
|
|
|
public function setConfig(array $config) |
68
|
|
|
{ |
69
|
|
|
foreach ($config as $key => $value) { |
70
|
|
|
switch ($key) { |
71
|
|
|
case 'verbose': |
72
|
|
|
case 'loadEnv': |
73
|
|
|
if (!is_bool($value)) { |
74
|
|
|
throw new ConfigurationException($key, 'This should be a boolean value.'); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
$this->config[$key] = $value; |
78
|
|
|
break; |
79
|
|
|
|
80
|
|
|
default: |
81
|
|
|
throw new ConfigurationException($key, 'This is an unknown configuration option.'); |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Get the Builder's configuration options. |
88
|
|
|
* |
89
|
|
|
* @return array |
90
|
|
|
*/ |
91
|
|
|
public function getConfig() |
92
|
|
|
{ |
93
|
|
|
return $this->config; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Set the EnvLoader. |
98
|
|
|
* |
99
|
|
|
* @param EnvLoader $envLoader |
100
|
|
|
*/ |
101
|
|
|
public function setEnvLoader(EnvLoader $envLoader) |
102
|
|
|
{ |
103
|
|
|
$this->envLoader = $envLoader; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Add in an IOHanderInterface object. |
108
|
|
|
* |
109
|
|
|
* @param IOHandlerInterface $ioHandler |
110
|
|
|
*/ |
111
|
|
|
public function setIOHandler(IOHandlerInterface $ioHandler) |
112
|
|
|
{ |
113
|
|
|
$this->io->setHandler($ioHandler); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Set the IO. |
118
|
|
|
* |
119
|
|
|
* @param IO $io |
120
|
|
|
*/ |
121
|
|
|
public function setIO(IO $io) |
122
|
|
|
{ |
123
|
|
|
$this->io = $io; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Override the EnvWriter. |
128
|
|
|
* |
129
|
|
|
* @param EnvWriter $envWriter |
130
|
|
|
*/ |
131
|
|
|
public function setEnvWriter(EnvWriter $envWriter) |
132
|
|
|
{ |
133
|
|
|
$this->envWriter = $envWriter; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Run the builder |
138
|
|
|
* |
139
|
|
|
* @throws \Exception |
140
|
|
|
* @return array |
141
|
|
|
*/ |
142
|
|
|
public function run() |
143
|
|
|
{ |
144
|
|
|
$current = []; |
145
|
|
|
if ($this->config['loadEnv']) { |
146
|
|
|
$current = $this->envLoader->parse(); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
foreach ($this->questions as $name => $question) { |
150
|
|
|
// If We got an answer out of the loaded env, then let's use it. |
151
|
|
|
$default = isset($current[$name]) ? $current[$name] : $question['default']; |
152
|
|
|
|
153
|
|
|
// Ask the question. |
154
|
|
|
$this->answers[$name] = $this->io->ask($name, $question['prompt'], $default, $question['required']); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
return $this->answers; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Write the answers to a file. |
162
|
|
|
* |
163
|
|
|
* @return bool The status of the write operation. |
164
|
|
|
*/ |
165
|
|
|
public function write() |
166
|
|
|
{ |
167
|
|
|
try { |
168
|
|
|
$this->envWriter->save($this->answers); |
169
|
|
|
$this->io->out(sprintf('Answers saved to %s', $this->envFile)); |
170
|
|
|
return true; |
171
|
|
|
|
172
|
|
|
} catch (WritableException $e) { |
173
|
|
|
$this->io->out($e->getMessage()); |
174
|
|
|
return false; |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Set a question to ask the user. |
180
|
|
|
* |
181
|
|
|
* @param string $name The name of the env variable to read/use |
182
|
|
|
* @param string $prompt The prompt you want to give the user |
183
|
|
|
* @param string $default A default answer, if any. |
184
|
|
|
* @param bool $required Is a response required? |
185
|
|
|
*/ |
186
|
|
|
public function ask($name, $prompt, $default = '', $required = false) |
187
|
|
|
{ |
188
|
|
|
$this->questions[$name] = [ |
189
|
|
|
'prompt' => $prompt, |
190
|
|
|
'default' => $default, |
191
|
|
|
'required' => $required, |
192
|
|
|
]; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* Return all of the questions. |
197
|
|
|
* |
198
|
|
|
* @return array |
199
|
|
|
*/ |
200
|
|
|
public function getQuestions() |
201
|
|
|
{ |
202
|
|
|
return $this->questions; |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.