1 | <?php |
||
15 | class InstallCommand extends Command |
||
16 | { |
||
17 | use StringUtilsTrait; |
||
18 | |||
19 | const DATABASE_DRIVERS = [ |
||
20 | 'MySQL' => 'pdo_mysql', |
||
21 | 'PostgreSQL' => 'pdo_pgsql', |
||
22 | 'SQLite' => 'pdo_sqlite', |
||
23 | ]; |
||
24 | const SUPPORTED_LANGUAGES = ['en', 'es']; |
||
25 | |||
26 | /** |
||
27 | * @var InputInterface |
||
28 | */ |
||
29 | private $input; |
||
30 | /** |
||
31 | * @var OutputInterface |
||
32 | */ |
||
33 | private $output; |
||
34 | /** |
||
35 | * @var QuestionHelper |
||
36 | */ |
||
37 | private $questionHelper; |
||
38 | /** |
||
39 | * @var ProcessHelper |
||
40 | */ |
||
41 | private $processHelper; |
||
42 | /** |
||
43 | * @var WriterInterface |
||
44 | */ |
||
45 | private $configWriter; |
||
46 | |||
47 | /** |
||
48 | * InstallCommand constructor. |
||
49 | * @param WriterInterface $configWriter |
||
50 | * @param callable|null $databaseCreationLogic |
||
|
|||
51 | */ |
||
52 | 1 | public function __construct(WriterInterface $configWriter) |
|
57 | |||
58 | 1 | public function configure() |
|
63 | |||
64 | 1 | public function execute(InputInterface $input, OutputInterface $output) |
|
118 | |||
119 | 1 | protected function askDatabase() |
|
120 | { |
||
121 | 1 | $params = []; |
|
122 | 1 | $this->printTitle('DATABASE'); |
|
123 | |||
124 | // Select database type |
||
125 | 1 | $databases = array_keys(self::DATABASE_DRIVERS); |
|
126 | 1 | $dbType = $this->questionHelper->ask($this->input, $this->output, new ChoiceQuestion( |
|
127 | 1 | '<question>Select database type (defaults to ' . $databases[0] . '):</question>', |
|
128 | 1 | $databases, |
|
129 | 0 |
||
130 | 1 | )); |
|
131 | 1 | $params['DRIVER'] = self::DATABASE_DRIVERS[$dbType]; |
|
132 | |||
133 | // Ask for connection params if database is not SQLite |
||
134 | 1 | if ($params['DRIVER'] !== self::DATABASE_DRIVERS['SQLite']) { |
|
135 | 1 | $params['NAME'] = $this->ask('Database name', 'shlink'); |
|
136 | 1 | $params['USER'] = $this->ask('Database username'); |
|
137 | 1 | $params['PASSWORD'] = $this->ask('Database password'); |
|
138 | 1 | $params['HOST'] = $this->ask('Database host', 'localhost'); |
|
139 | 1 | $params['PORT'] = $this->ask('Database port', $this->getDefaultDbPort($params['DRIVER'])); |
|
140 | 1 | } |
|
141 | |||
142 | 1 | return $params; |
|
143 | } |
||
144 | |||
145 | 1 | protected function getDefaultDbPort($driver) |
|
149 | |||
150 | 1 | protected function askUrlShortener() |
|
151 | { |
||
152 | 1 | $this->printTitle('URL SHORTENER'); |
|
153 | |||
154 | // Ask for URL shortener params |
||
155 | return [ |
||
156 | 1 | 'SCHEMA' => $this->questionHelper->ask($this->input, $this->output, new ChoiceQuestion( |
|
157 | 1 | '<question>Select schema for generated short URLs (defaults to http):</question>', |
|
158 | 1 | ['http', 'https'], |
|
159 | 0 |
||
160 | 1 | )), |
|
161 | 1 | 'HOSTNAME' => $this->ask('Hostname for generated URLs'), |
|
162 | 1 | 'CHARS' => $this->ask( |
|
163 | 1 | 'Character set for generated short codes (leave empty to autogenerate one)', |
|
164 | 1 | null, |
|
165 | true |
||
166 | 1 | ) ?: str_shuffle(UrlShortener::DEFAULT_CHARS) |
|
167 | 1 | ]; |
|
168 | } |
||
169 | |||
170 | 1 | protected function askLanguage() |
|
171 | { |
||
172 | 1 | $this->printTitle('LANGUAGE'); |
|
173 | |||
174 | return [ |
||
175 | 1 | 'DEFAULT' => $this->questionHelper->ask($this->input, $this->output, new ChoiceQuestion( |
|
176 | '<question>Select default language for the application in general (defaults to ' |
||
177 | 1 | . self::SUPPORTED_LANGUAGES[0] . '):</question>', |
|
178 | 1 | self::SUPPORTED_LANGUAGES, |
|
179 | 0 |
||
180 | 1 | )), |
|
181 | 1 | 'CLI' => $this->questionHelper->ask($this->input, $this->output, new ChoiceQuestion( |
|
182 | '<question>Select default language for CLI executions (defaults to ' |
||
183 | 1 | . self::SUPPORTED_LANGUAGES[0] . '):</question>', |
|
184 | 1 | self::SUPPORTED_LANGUAGES, |
|
185 | 0 |
||
186 | 1 | )), |
|
187 | 1 | ]; |
|
188 | } |
||
189 | |||
190 | 1 | protected function askApplication() |
|
202 | |||
203 | /** |
||
204 | * @param string $text |
||
205 | */ |
||
206 | 1 | protected function printTitle($text) |
|
207 | { |
||
208 | 1 | $text = trim($text); |
|
209 | 1 | $length = strlen($text) + 4; |
|
210 | 1 | $header = str_repeat('*', $length); |
|
211 | |||
212 | 1 | $this->output->writeln([ |
|
213 | 1 | '', |
|
214 | 1 | '<info>' . $header . '</info>', |
|
215 | 1 | '<info>* ' . strtoupper($text) . ' *</info>', |
|
216 | 1 | '<info>' . $header . '</info>', |
|
217 | 1 | ]); |
|
218 | 1 | } |
|
219 | |||
220 | /** |
||
221 | * @param string $text |
||
222 | * @param string|null $default |
||
223 | * @param bool $allowEmpty |
||
224 | * @return string |
||
225 | */ |
||
226 | 1 | protected function ask($text, $default = null, $allowEmpty = false) |
|
227 | { |
||
228 | 1 | if (isset($default)) { |
|
229 | 1 | $text .= ' (defaults to ' . $default . ')'; |
|
230 | 1 | } |
|
231 | do { |
||
232 | 1 | $value = $this->questionHelper->ask($this->input, $this->output, new Question( |
|
233 | 1 | '<question>' . $text . ':</question> ', |
|
234 | $default |
||
235 | 1 | )); |
|
236 | 1 | if (empty($value) && ! $allowEmpty) { |
|
237 | $this->output->writeln('<error>Value can\'t be empty</error>'); |
||
238 | } |
||
239 | 1 | } while (empty($value) && empty($default) && ! $allowEmpty); |
|
240 | |||
241 | 1 | return $value; |
|
242 | } |
||
243 | |||
244 | /** |
||
245 | * @param array $params |
||
246 | * @return array |
||
247 | */ |
||
248 | 1 | protected function buildAppConfig(array $params) |
|
249 | { |
||
250 | // Build simple config |
||
251 | $config = [ |
||
252 | 'app_options' => [ |
||
253 | 1 | 'secret_key' => $params['APP']['SECRET'], |
|
254 | 1 | ], |
|
255 | 'entity_manager' => [ |
||
256 | 'connection' => [ |
||
257 | 1 | 'driver' => $params['DATABASE']['DRIVER'], |
|
258 | 1 | ], |
|
259 | 1 | ], |
|
260 | 'translator' => [ |
||
261 | 1 | 'locale' => $params['LANGUAGE']['DEFAULT'], |
|
262 | 1 | ], |
|
263 | 'cli' => [ |
||
264 | 1 | 'locale' => $params['LANGUAGE']['CLI'], |
|
265 | 1 | ], |
|
266 | 'url_shortener' => [ |
||
267 | 'domain' => [ |
||
268 | 1 | 'schema' => $params['URL_SHORTENER']['SCHEMA'], |
|
269 | 1 | 'hostname' => $params['URL_SHORTENER']['HOSTNAME'], |
|
270 | 1 | ], |
|
271 | 1 | 'shortcode_chars' => $params['URL_SHORTENER']['CHARS'], |
|
272 | 1 | ], |
|
273 | 1 | ]; |
|
274 | |||
275 | // Build dynamic database config |
||
276 | 1 | if ($params['DATABASE']['DRIVER'] === 'pdo_sqlite') { |
|
277 | $config['entity_manager']['connection']['path'] = 'data/database.sqlite'; |
||
278 | } else { |
||
279 | 1 | $config['entity_manager']['connection']['user'] = $params['DATABASE']['USER']; |
|
280 | 1 | $config['entity_manager']['connection']['password'] = $params['DATABASE']['PASSWORD']; |
|
281 | 1 | $config['entity_manager']['connection']['dbname'] = $params['DATABASE']['NAME']; |
|
282 | 1 | $config['entity_manager']['connection']['host'] = $params['DATABASE']['HOST']; |
|
283 | 1 | $config['entity_manager']['connection']['port'] = $params['DATABASE']['PORT']; |
|
284 | |||
285 | 1 | if ($params['DATABASE']['DRIVER'] === 'pdo_mysql') { |
|
286 | 1 | $config['entity_manager']['connection']['driverOptions'] = [ |
|
287 | 1 | \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', |
|
288 | ]; |
||
289 | 1 | } |
|
290 | } |
||
291 | |||
292 | 1 | return $config; |
|
293 | } |
||
294 | |||
295 | 1 | protected function createDatabase() |
|
300 | |||
301 | /** |
||
302 | * @param string $command |
||
303 | * @param string $errorMessage |
||
304 | * @return bool |
||
305 | */ |
||
306 | 1 | protected function runCommand($command, $errorMessage) |
|
322 | } |
||
323 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.
Consider the following example. The parameter
$italy
is not defined by the methodfinale(...)
.The most likely cause is that the parameter was removed, but the annotation was not.