Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Manager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Manager, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
41 | class Manager |
||
42 | { |
||
43 | /** |
||
44 | * @var \Phinx\Config\ConfigInterface |
||
45 | */ |
||
46 | protected $config; |
||
47 | |||
48 | /** |
||
49 | * @var \Symfony\Component\Console\Input\InputInterface |
||
50 | */ |
||
51 | protected $input; |
||
52 | |||
53 | /** |
||
54 | * @var \Symfony\Component\Console\Output\OutputInterface |
||
55 | */ |
||
56 | protected $output; |
||
57 | |||
58 | /** |
||
59 | * @var array |
||
60 | */ |
||
61 | protected $environments; |
||
62 | |||
63 | /** |
||
64 | * @var array |
||
65 | */ |
||
66 | protected $migrations; |
||
67 | |||
68 | /** |
||
69 | * @var array |
||
70 | */ |
||
71 | protected $seeds; |
||
72 | |||
73 | /** |
||
74 | * @var null|MigrationLocatorInterface |
||
75 | */ |
||
76 | protected $migrationLocator; |
||
77 | |||
78 | /** |
||
79 | * @var integer |
||
80 | */ |
||
81 | const EXIT_STATUS_DOWN = 1; |
||
82 | |||
83 | /** |
||
84 | * @var integer |
||
85 | */ |
||
86 | const EXIT_STATUS_MISSING = 2; |
||
87 | |||
88 | /** |
||
89 | 432 | * Class Constructor. |
|
90 | * |
||
91 | 432 | * @param \Phinx\Config\ConfigInterface $config Configuration Object |
|
92 | 432 | * @param \Symfony\Component\Console\Input\InputInterface $input Console Input |
|
93 | 432 | * @param \Symfony\Component\Console\Output\OutputInterface $output Console Output |
|
94 | 432 | */ |
|
95 | public function __construct(ConfigInterface $config, InputInterface $input, OutputInterface $output) |
||
96 | { |
||
97 | $this->setConfig($config); |
||
98 | $this->setInput($input); |
||
99 | $this->setOutput($output); |
||
100 | } |
||
101 | |||
102 | /** |
||
103 | 22 | * Prints the specified environment's migration status. |
|
104 | * |
||
105 | 22 | * @param string $environment |
|
106 | 22 | * @param null $format |
|
107 | 22 | * @return int 0 if all migrations are up, or an error code |
|
108 | 22 | */ |
|
109 | 22 | public function printStatus($environment, $format = null) |
|
110 | 22 | { |
|
111 | $output = $this->getOutput(); |
||
112 | $migrations = []; |
||
|
|||
113 | 21 | $hasDownMigration = false; |
|
114 | $hasMissingMigration = false; |
||
115 | 21 | $migrations = $this->getMigrations($environment); |
|
116 | 21 | if (count($migrations)) { |
|
117 | 19 | // TODO - rewrite using Symfony Table Helper as we already have this library |
|
118 | 19 | // included and it will fix formatting issues (e.g drawing the lines) |
|
119 | 2 | $output->writeln(''); |
|
120 | 1 | ||
121 | 1 | switch ($this->getConfig()->getVersionOrder()) { |
|
122 | 1 | case \Phinx\Config\Config::VERSION_ORDER_CREATION_TIME: |
|
123 | 1 | $migrationIdAndStartedHeader = "<info>[Migration ID]</info> Started "; |
|
124 | 21 | break; |
|
125 | case \Phinx\Config\Config::VERSION_ORDER_EXECUTION_TIME: |
||
126 | 20 | $migrationIdAndStartedHeader = "Migration ID <info>[Started ]</info>"; |
|
127 | 20 | break; |
|
128 | default: |
||
129 | 20 | throw new \RuntimeException('Invalid version_order configuration option'); |
|
130 | 20 | } |
|
131 | |||
132 | $output->writeln(" Status $migrationIdAndStartedHeader Finished Migration Name "); |
||
133 | 17 | $output->writeln('----------------------------------------------------------------------------------'); |
|
134 | 20 | ||
135 | $env = $this->getEnvironment($environment); |
||
136 | 20 | $versions = $env->getVersionLog(); |
|
137 | |||
138 | 20 | $maxNameLength = $versions ? max(array_map(function ($version) { |
|
139 | return strlen($version['migration_name']); |
||
140 | }, $versions)) : 0; |
||
141 | 20 | ||
142 | $missingVersions = array_diff_key($versions, $migrations); |
||
143 | 20 | ||
144 | 17 | $hasMissingMigration = !empty($missingVersions); |
|
145 | 13 | ||
146 | 13 | // get the migrations sorted in the same way as the versions |
|
147 | 13 | $sortedMigrations = []; |
|
148 | 20 | ||
149 | foreach ($versions as $versionCreationTime => $version) { |
||
150 | 20 | if (isset($migrations[$versionCreationTime])) { |
|
151 | array_push($sortedMigrations, $migrations[$versionCreationTime]); |
||
152 | unset($migrations[$versionCreationTime]); |
||
153 | 4 | } |
|
154 | 4 | } |
|
155 | |||
156 | 4 | if (empty($sortedMigrations) && !empty($missingVersions)) { |
|
157 | 4 | // this means we have no up migrations, so we write all the missing versions already so they show up |
|
158 | 4 | // before any possible down migration |
|
159 | foreach ($missingVersions as $missingVersionCreationTime => $missingVersion) { |
||
160 | $this->printMissingVersion($missingVersion, $maxNameLength); |
||
161 | |||
162 | 20 | unset($missingVersions[$missingVersionCreationTime]); |
|
163 | 13 | } |
|
164 | 13 | } |
|
165 | |||
166 | 20 | // any migration left in the migrations (ie. not unset when sorting the migrations by the version order) is |
|
167 | 20 | // a migration that is down, so we add them to the end of the sorted migrations list |
|
168 | 20 | if (!empty($migrations)) { |
|
169 | $sortedMigrations = array_merge($sortedMigrations, $migrations); |
||
170 | 13 | } |
|
171 | 6 | ||
172 | 6 | foreach ($sortedMigrations as $migration) { |
|
173 | 4 | $version = array_key_exists($migration->getVersion(), $versions) ? $versions[$migration->getVersion()] : false; |
|
174 | if ($version) { |
||
175 | 3 | // check if there are missing versions before this version |
|
176 | foreach ($missingVersions as $missingVersionCreationTime => $missingVersion) { |
||
177 | if ($this->getConfig()->isVersionOrderCreationTime()) { |
||
178 | if ($missingVersion['version'] > $version['version']) { |
||
179 | break; |
||
180 | } |
||
181 | } else { |
||
182 | if ($missingVersion['start_time'] > $version['start_time']) { |
||
183 | break; |
||
184 | 3 | } elseif ($missingVersion['start_time'] == $version['start_time'] && |
|
185 | $missingVersion['version'] > $version['version']) { |
||
186 | 3 | break; |
|
187 | 13 | } |
|
188 | } |
||
189 | 13 | ||
190 | 13 | $this->printMissingVersion($missingVersion, $maxNameLength); |
|
191 | 13 | ||
192 | 13 | unset($missingVersions[$missingVersionCreationTime]); |
|
193 | } |
||
194 | 20 | ||
195 | $status = ' <info>up</info> '; |
||
196 | 20 | } else { |
|
197 | 20 | $hasDownMigration = true; |
|
198 | 20 | $status = ' <error>down</error> '; |
|
199 | 20 | } |
|
200 | 20 | $maxNameLength = max($maxNameLength, strlen($migration->getName())); |
|
201 | 20 | ||
202 | 20 | $output->writeln(sprintf( |
|
203 | 20 | '%s %14.0f %19s %19s <comment>%s</comment>', |
|
204 | $status, |
||
205 | 20 | $migration->getVersion(), |
|
206 | 1 | $version['start_time'], |
|
207 | 1 | $version['end_time'], |
|
208 | $migration->getName() |
||
209 | 20 | )); |
|
210 | 20 | ||
211 | 20 | if ($version && $version['breakpoint']) { |
|
212 | $output->writeln(' <error>BREAKPOINT SET</error>'); |
||
213 | } |
||
214 | 20 | ||
215 | 4 | $migrations[] = ['migration_status' => trim(strip_tags($status)), 'migration_id' => sprintf('%14.0f', $migration->getVersion()), 'migration_name' => $migration->getName()]; |
|
216 | unset($versions[$migration->getVersion()]); |
||
217 | 4 | } |
|
218 | 20 | ||
219 | 20 | // and finally add any possibly-remaining missing migrations |
|
220 | foreach ($missingVersions as $missingVersionCreationTime => $missingVersion) { |
||
221 | 1 | $this->printMissingVersion($missingVersion, $maxNameLength); |
|
222 | 1 | ||
223 | unset($missingVersions[$missingVersionCreationTime]); |
||
224 | } |
||
225 | } else { |
||
226 | 21 | // there are no migrations |
|
227 | 21 | $output->writeln(''); |
|
228 | $output->writeln('There are no available migrations. Try creating one using the <info>create</info> command.'); |
||
229 | } |
||
230 | |||
231 | // write an empty line |
||
232 | $output->writeln(''); |
||
233 | if ($format !== null) { |
||
234 | switch ($format) { |
||
235 | case 'json': |
||
236 | $output->writeln(json_encode( |
||
237 | [ |
||
238 | 'pending_count' => count($this->getMigrations($environment)), |
||
239 | 'migrations' => $migrations |
||
240 | ] |
||
241 | )); |
||
242 | 21 | break; |
|
243 | 10 | default: |
|
244 | 11 | $output->writeln('<info>Unsupported format: ' . $format . '</info>'); |
|
245 | 6 | } |
|
246 | } |
||
247 | 5 | ||
248 | if ($hasMissingMigration) { |
||
249 | return self::EXIT_STATUS_MISSING; |
||
250 | } elseif ($hasDownMigration) { |
||
251 | return self::EXIT_STATUS_DOWN; |
||
252 | } else { |
||
253 | return 0; |
||
254 | } |
||
255 | } |
||
256 | |||
257 | 10 | /** |
|
258 | * Print Missing Version |
||
259 | 10 | * |
|
260 | 10 | * @param array $version The missing version to print (in the format returned by Environment.getVersionLog). |
|
261 | 10 | * @param int $maxNameLength The maximum migration name length. |
|
262 | 10 | */ |
|
263 | 10 | private function printMissingVersion($version, $maxNameLength) |
|
264 | 10 | { |
|
265 | 10 | $this->getOutput()->writeln(sprintf( |
|
266 | ' <error>up</error> %14.0f %19s %19s <comment>%s</comment> <error>** MISSING **</error>', |
||
267 | 10 | $version['version'], |
|
268 | 1 | $version['start_time'], |
|
269 | 1 | $version['end_time'], |
|
270 | 10 | str_pad($version['migration_name'], $maxNameLength, ' ') |
|
271 | )); |
||
272 | |||
273 | if ($version && $version['breakpoint']) { |
||
274 | $this->getOutput()->writeln(' <error>BREAKPOINT SET</error>'); |
||
275 | } |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Migrate to the version of the database on a given date. |
||
280 | 4 | * |
|
281 | * @param string $environment Environment |
||
282 | 4 | * @param \DateTime $dateTime Date to migrate to |
|
283 | 4 | * |
|
284 | * @return void |
||
285 | */ |
||
286 | 4 | public function migrateToDateTime($environment, \DateTime $dateTime) |
|
287 | 4 | { |
|
288 | $versions = array_keys($this->getMigrations($environment)); |
||
289 | 4 | $dateString = $dateTime->format('YmdHis'); |
|
290 | 3 | ||
291 | 3 | $outstandingMigrations = array_filter($versions, function ($version) use ($dateString) { |
|
292 | 3 | return $version <= $dateString; |
|
293 | 3 | }); |
|
294 | 4 | ||
295 | if (count($outstandingMigrations) > 0) { |
||
296 | $migration = max($outstandingMigrations); |
||
297 | $this->getOutput()->writeln('Migrating to version ' . $migration); |
||
298 | $this->migrate($environment, $migration); |
||
299 | } |
||
300 | } |
||
301 | |||
302 | /** |
||
303 | 8 | * Migrate an environment to the specified version. |
|
304 | * |
||
305 | 8 | * @param string $environment Environment |
|
306 | 8 | * @param int $version |
|
307 | 8 | * @return void |
|
308 | 8 | */ |
|
309 | public function migrate($environment, $version = null) |
||
310 | 8 | { |
|
311 | $migrations = $this->getMigrations($environment); |
||
312 | $env = $this->getEnvironment($environment); |
||
313 | $versions = $env->getVersions(); |
||
314 | 8 | $current = $env->getCurrentVersion(); |
|
315 | 5 | ||
316 | 5 | if (empty($versions) && empty($migrations)) { |
|
317 | 3 | return; |
|
318 | } |
||
319 | |||
320 | if ($version === null) { |
||
321 | $version = max(array_merge($versions, array_keys($migrations))); |
||
322 | View Code Duplication | } else { |
|
323 | if (0 != $version && !isset($migrations[$version])) { |
||
324 | $this->output->writeln(sprintf( |
||
325 | '<comment>warning</comment> %s is not a valid version', |
||
326 | $version |
||
327 | 8 | )); |
|
328 | |||
329 | 8 | return; |
|
330 | } |
||
331 | } |
||
332 | |||
333 | // are we migrating up or down? |
||
334 | $direction = $version > $current ? MigrationInterface::UP : MigrationInterface::DOWN; |
||
335 | |||
336 | if ($direction === MigrationInterface::DOWN) { |
||
337 | // run downs first |
||
338 | krsort($migrations); |
||
339 | View Code Duplication | foreach ($migrations as $migration) { |
|
340 | if ($migration->getVersion() <= $version) { |
||
341 | break; |
||
342 | } |
||
343 | 8 | ||
344 | 8 | if (in_array($migration->getVersion(), $versions)) { |
|
345 | 8 | $this->executeMigration($environment, $migration, MigrationInterface::DOWN); |
|
346 | 2 | } |
|
347 | } |
||
348 | } |
||
349 | 8 | ||
350 | 5 | ksort($migrations); |
|
351 | 5 | View Code Duplication | foreach ($migrations as $migration) { |
352 | 8 | if ($migration->getVersion() > $version) { |
|
353 | 8 | break; |
|
354 | } |
||
355 | |||
356 | if (!in_array($migration->getVersion(), $versions)) { |
||
357 | $this->executeMigration($environment, $migration, MigrationInterface::UP); |
||
358 | } |
||
359 | } |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | 119 | * Execute a migration against the specified environment. |
|
364 | * |
||
365 | 119 | * @param string $name Environment Name |
|
366 | 119 | * @param \Phinx\Migration\MigrationInterface $migration Migration |
|
367 | * @param string $direction Direction |
||
368 | 119 | * @return void |
|
369 | 119 | */ |
|
370 | 119 | public function executeMigration($name, MigrationInterface $migration, $direction = MigrationInterface::UP) |
|
371 | { |
||
372 | $this->getOutput()->writeln(''); |
||
373 | 119 | $this->getOutput()->writeln( |
|
374 | 119 | ' ==' . |
|
375 | 119 | ' <info>' . $migration->getVersion() . ' ' . $migration->getName() . ':</info>' . |
|
376 | ' <comment>' . ($direction === MigrationInterface::UP ? 'migrating' : 'reverting') . '</comment>' |
||
377 | 119 | ); |
|
378 | |||
379 | 119 | // Execute the migration and log the time elapsed. |
|
380 | 119 | $start = microtime(true); |
|
381 | 119 | $this->getEnvironment($name)->executeMigration($migration, $direction); |
|
382 | 119 | $end = microtime(true); |
|
383 | 119 | ||
384 | $this->getOutput()->writeln( |
||
385 | ' ==' . |
||
386 | ' <info>' . $migration->getVersion() . ' ' . $migration->getName() . ':</info>' . |
||
387 | ' <comment>' . ($direction === MigrationInterface::UP ? 'migrated' : 'reverted') . |
||
388 | ' ' . sprintf('%.4fs', $end - $start) . '</comment>' |
||
389 | ); |
||
390 | } |
||
391 | |||
392 | 6 | /** |
|
393 | * Execute a seeder against the specified environment. |
||
394 | 6 | * |
|
395 | 6 | * @param string $name Environment Name |
|
396 | * @param \Phinx\Seed\SeedInterface $seed Seed |
||
397 | 6 | * @return void |
|
398 | 6 | */ |
|
399 | 6 | public function executeSeed($name, SeedInterface $seed) |
|
400 | { |
||
401 | $this->getOutput()->writeln(''); |
||
402 | 6 | $this->getOutput()->writeln( |
|
403 | 6 | ' ==' . |
|
404 | 6 | ' <info>' . $seed->getName() . ':</info>' . |
|
405 | ' <comment>seeding</comment>' |
||
406 | 6 | ); |
|
407 | |||
408 | 6 | // Execute the seeder and log the time elapsed. |
|
409 | 6 | $start = microtime(true); |
|
410 | 6 | $this->getEnvironment($name)->executeSeed($seed); |
|
411 | 6 | $end = microtime(true); |
|
412 | 6 | ||
413 | $this->getOutput()->writeln( |
||
414 | ' ==' . |
||
415 | ' <info>' . $seed->getName() . ':</info>' . |
||
416 | ' <comment>seeded' . |
||
417 | ' ' . sprintf('%.4fs', $end - $start) . '</comment>' |
||
418 | ); |
||
419 | } |
||
420 | |||
421 | /** |
||
422 | * Rollback an environment to the specified version. |
||
423 | 349 | * |
|
424 | * @param string $environment Environment |
||
425 | * @param int|string $target |
||
426 | 349 | * @param bool $force |
|
427 | * @param bool $targetMustMatchVersion |
||
428 | * @return void |
||
429 | 349 | */ |
|
430 | public function rollback($environment, $target = null, $force = false, $targetMustMatchVersion = true) |
||
431 | { |
||
432 | 349 | // note that the migrations are indexed by name (aka creation time) in ascending order |
|
433 | $migrations = $this->getMigrations($environment); |
||
434 | 349 | ||
435 | // note that the version log are also indexed by name with the proper ascending order according to the version order |
||
436 | $executedVersions = $this->getEnvironment($environment)->getVersionLog(); |
||
437 | 349 | ||
438 | 48 | // get a list of migrations sorted in the opposite way of the executed versions |
|
439 | 48 | $sortedMigrations = []; |
|
440 | 48 | ||
441 | foreach ($executedVersions as $versionCreationTime => &$executedVersion) { |
||
442 | 349 | // if we have a date (ie. the target must not match a version) and we are sorting by execution time, we |
|
443 | 349 | // convert the version start time so we can compare directly with the target date |
|
444 | 349 | if (!$this->getConfig()->isVersionOrderCreationTime() && !$targetMustMatchVersion) { |
|
445 | $dateTime = \DateTime::createFromFormat('Y-m-d H:i:s', $executedVersion['start_time']); |
||
446 | $executedVersion['start_time'] = $dateTime->format('YmdHis'); |
||
447 | 47 | } |
|
448 | |||
449 | 349 | if (isset($migrations[$versionCreationTime])) { |
|
450 | array_unshift($sortedMigrations, $migrations[$versionCreationTime]); |
||
451 | 349 | } else { |
|
452 | 23 | // this means the version is missing so we unset it so that we don't consider it when rolling back |
|
453 | 349 | // migrations (or choosing the last up version as target) |
|
454 | unset($executedVersions[$versionCreationTime]); |
||
455 | 20 | } |
|
456 | 20 | } |
|
457 | 20 | ||
458 | 20 | if ($target === 'all' || $target === '0') { |
|
459 | $target = 0; |
||
460 | } elseif (!is_numeric($target) && !is_null($target)) { // try to find a target version based on name |
||
461 | 20 | // search through the migrations using the name |
|
462 | 20 | $migrationNames = array_map(function ($item) { |
|
463 | 20 | return $item['migration_name']; |
|
464 | }, $executedVersions); |
||
465 | $found = array_search($target, $migrationNames); |
||
466 | |||
467 | 20 | // check on was found |
|
468 | if ($found !== false) { |
||
469 | $target = (string)$found; |
||
470 | 349 | } else { |
|
471 | 349 | $this->getOutput()->writeln("<error>No migration found with name ($target)</error>"); |
|
472 | 53 | ||
473 | 53 | return; |
|
474 | } |
||
475 | } |
||
476 | |||
477 | 296 | // Check we have at least 1 migration to revert |
|
478 | $executedVersionCreationTimes = array_keys($executedVersions); |
||
479 | 94 | if (empty($executedVersionCreationTimes) || $target == end($executedVersionCreationTimes)) { |
|
480 | 94 | $this->getOutput()->writeln('<error>No migrations to rollback</error>'); |
|
481 | 94 | ||
482 | return; |
||
483 | } |
||
484 | 296 | ||
485 | 46 | // If no target was supplied, revert the last migration |
|
486 | 46 | if ($target === null) { |
|
487 | // Get the migration before the last run migration |
||
488 | $prev = count($executedVersionCreationTimes) - 2; |
||
489 | $target = $prev >= 0 ? $executedVersionCreationTimes[$prev] : 0; |
||
490 | 250 | } |
|
491 | |||
492 | 250 | // If the target must match a version, check the target version exists |
|
493 | 250 | if ($targetMustMatchVersion && 0 !== $target && !isset($migrations[$target])) { |
|
494 | 70 | $this->getOutput()->writeln("<error>Target version ($target) not found</error>"); |
|
495 | |||
496 | return; |
||
497 | 250 | } |
|
498 | 250 | ||
499 | // Rollback all versions until we find the wanted rollback target |
||
500 | 250 | $rollbacked = false; |
|
501 | 96 | ||
502 | 96 | foreach ($sortedMigrations as $migration) { |
|
503 | 42 | if ($targetMustMatchVersion && $migration->getVersion() == $target) { |
|
504 | break; |
||
505 | 68 | } |
|
506 | |||
507 | 222 | if (in_array($migration->getVersion(), $executedVersionCreationTimes)) { |
|
508 | 121 | $executedVersion = $executedVersions[$migration->getVersion()]; |
|
509 | 121 | ||
510 | if (!$targetMustMatchVersion) { |
||
511 | 117 | if (($this->getConfig()->isVersionOrderCreationTime() && $executedVersion['version'] <= $target) || |
|
512 | 117 | (!$this->getConfig()->isVersionOrderCreationTime() && $executedVersion['start_time'] <= $target)) { |
|
513 | 117 | break; |
|
514 | 250 | } |
|
515 | } |
||
516 | 250 | ||
517 | 133 | if (0 != $executedVersion['breakpoint'] && !$force) { |
|
518 | 133 | $this->getOutput()->writeln('<error>Breakpoint reached. Further rollbacks inhibited.</error>'); |
|
519 | 250 | break; |
|
520 | } |
||
521 | $this->executeMigration($environment, $migration, MigrationInterface::DOWN); |
||
522 | $rollbacked = true; |
||
523 | } |
||
524 | } |
||
525 | |||
526 | if (!$rollbacked) { |
||
527 | $this->getOutput()->writeln('<error>No migrations to rollback</error>'); |
||
528 | 9 | } |
|
529 | } |
||
530 | 9 | ||
531 | /** |
||
532 | 9 | * Run database seeders against an environment. |
|
533 | * |
||
534 | 3 | * @param string $environment Environment |
|
535 | 3 | * @param string $seed Seeder |
|
536 | 3 | * @return void |
|
537 | 3 | */ |
|
538 | 3 | public function seed($environment, $seed = null) |
|
539 | 3 | { |
|
540 | $seeds = $this->getSeeds(); |
||
541 | 6 | ||
542 | 3 | if ($seed === null) { |
|
543 | 3 | // run all seeders |
|
544 | 3 | foreach ($seeds as $seeder) { |
|
545 | if (array_key_exists($seeder->getName(), $seeds)) { |
||
546 | $this->executeSeed($environment, $seeder); |
||
547 | 6 | } |
|
548 | } |
||
549 | } else { |
||
550 | // run only one seeder |
||
551 | if (array_key_exists($seed, $seeds)) { |
||
552 | $this->executeSeed($environment, $seeds[$seed]); |
||
553 | } else { |
||
554 | throw new \InvalidArgumentException(sprintf('The seed class "%s" does not exist', $seed)); |
||
555 | 381 | } |
|
556 | } |
||
557 | 381 | } |
|
558 | 381 | ||
559 | /** |
||
560 | * Sets the environments. |
||
561 | * |
||
562 | * @param array $environments Environments |
||
563 | * @return \Phinx\Migration\Manager |
||
564 | */ |
||
565 | public function setEnvironments($environments = []) |
||
566 | { |
||
567 | $this->environments = $environments; |
||
568 | 382 | ||
569 | return $this; |
||
570 | 382 | } |
|
571 | 380 | ||
572 | /** |
||
573 | * Gets the manager class for the given environment. |
||
574 | * |
||
575 | 7 | * @param string $name Environment Name |
|
576 | 1 | * @throws \InvalidArgumentException |
|
577 | 1 | * @return \Phinx\Migration\Manager\Environment |
|
578 | */ |
||
579 | 1 | public function getEnvironment($name) |
|
580 | { |
||
581 | if (isset($this->environments[$name])) { |
||
582 | return $this->environments[$name]; |
||
583 | 6 | } |
|
584 | 6 | ||
585 | // check the environment exists |
||
586 | 6 | if (!$this->getConfig()->hasEnvironment($name)) { |
|
587 | 6 | throw new \InvalidArgumentException(sprintf( |
|
588 | 6 | 'The environment "%s" does not exist', |
|
589 | 6 | $name |
|
590 | )); |
||
591 | 6 | } |
|
592 | |||
593 | // create an environment instance and cache it |
||
594 | $envOptions = $this->getConfig()->getEnvironment($name); |
||
595 | $envOptions['version_order'] = $this->getConfig()->getVersionOrder(); |
||
596 | |||
597 | $environment = new Environment($name, $envOptions); |
||
598 | $this->environments[$name] = $environment; |
||
599 | $environment->setInput($this->getInput()); |
||
600 | 400 | $environment->setOutput($this->getOutput()); |
|
601 | |||
602 | 400 | return $environment; |
|
603 | 400 | } |
|
604 | |||
605 | /** |
||
606 | * Sets the console input. |
||
607 | * |
||
608 | * @param \Symfony\Component\Console\Input\InputInterface $input Input |
||
609 | * @return \Phinx\Migration\Manager |
||
610 | */ |
||
611 | 393 | public function setInput(InputInterface $input) |
|
612 | { |
||
613 | 393 | $this->input = $input; |
|
614 | |||
615 | return $this; |
||
616 | } |
||
617 | |||
618 | /** |
||
619 | * Gets the console input. |
||
620 | * |
||
621 | * @return \Symfony\Component\Console\Input\InputInterface |
||
622 | 400 | */ |
|
623 | public function getInput() |
||
624 | 400 | { |
|
625 | 400 | return $this->input; |
|
626 | } |
||
627 | |||
628 | /** |
||
629 | * Sets the console output. |
||
630 | * |
||
631 | * @param \Symfony\Component\Console\Output\OutputInterface $output Output |
||
632 | * @return \Phinx\Migration\Manager |
||
633 | 395 | */ |
|
634 | public function setOutput(OutputInterface $output) |
||
635 | 395 | { |
|
636 | $this->output = $output; |
||
637 | |||
638 | return $this; |
||
639 | } |
||
640 | |||
641 | /** |
||
642 | * Gets the console output. |
||
643 | * |
||
644 | 379 | * @return \Symfony\Component\Console\Output\OutputInterface |
|
645 | */ |
||
646 | 379 | public function getOutput() |
|
647 | 379 | { |
|
648 | return $this->output; |
||
649 | } |
||
650 | |||
651 | /** |
||
652 | * Sets the database migrations. |
||
653 | * |
||
654 | * @param array $migrations Migrations |
||
655 | * @return \Phinx\Migration\Manager |
||
656 | */ |
||
657 | 388 | public function setMigrations(array $migrations) |
|
658 | { |
||
659 | 388 | $this->migrations = $migrations; |
|
660 | 388 | ||
661 | return $this; |
||
662 | } |
||
663 | 388 | ||
664 | /** |
||
665 | 388 | * Gets an array of the database migrations, indexed by migration name (aka creation time) and sorted in ascending |
|
666 | * order |
||
667 | 388 | * |
|
668 | 387 | * @param string $environment Environment |
|
669 | 387 | * @throws \InvalidArgumentException |
|
670 | * @return \Phinx\Migration\AbstractMigration[] |
||
671 | 387 | */ |
|
672 | 3 | public function getMigrations($environment) |
|
673 | { |
||
674 | if ($this->migrations === null) { |
||
675 | 387 | $phpFiles = $this->getMigrationFiles(); |
|
676 | 387 | ||
677 | // filter the files to only get the ones that match our naming scheme |
||
678 | $fileNames = []; |
||
679 | 387 | /** @var \Phinx\Migration\AbstractMigration[] $versions */ |
|
680 | $versions = []; |
||
681 | 387 | ||
682 | 2 | foreach ($phpFiles as $filePath) { |
|
683 | 2 | if (null !== $definition = $this->getMigrationLocator()->locate($filePath)) { |
|
684 | 2 | $version = $definition->getVersion(); |
|
685 | 2 | $class = $definition->getClass(); |
|
686 | 2 | ||
687 | if (isset($versions[$definition->getVersion()])) { |
||
688 | throw new \InvalidArgumentException(sprintf('Duplicate migration - "%s" has the same version as "%s"', $filePath, $versions[$version]->getVersion())); |
||
689 | 387 | } |
|
690 | |||
691 | $config = $this->getConfig(); |
||
692 | |||
693 | 387 | if (isset($fileNames[$class])) { |
|
694 | 387 | throw new \InvalidArgumentException(sprintf( |
|
695 | 2 | 'Migration "%s" has the same name as "%s"', |
|
696 | 2 | basename($filePath), |
|
697 | 2 | $fileNames[$class] |
|
698 | )); |
||
699 | 2 | } |
|
700 | |||
701 | $fileNames[$class] = basename($filePath); |
||
702 | |||
703 | 385 | // load the migration file |
|
704 | /** @noinspection PhpIncludeInspection */ |
||
705 | 385 | require_once $filePath; |
|
706 | 2 | if (!class_exists($class)) { |
|
707 | 2 | throw new \InvalidArgumentException(sprintf( |
|
708 | 2 | 'Could not find class "%s" in file "%s"', |
|
709 | $class, |
||
710 | 2 | $filePath |
|
711 | )); |
||
712 | } |
||
713 | 383 | ||
714 | 383 | // instantiate it |
|
715 | 384 | $migration = new $class($environment, $version, $this->getInput(), $this->getOutput()); |
|
716 | |||
717 | 379 | if (!($migration instanceof AbstractMigration)) { |
|
718 | 379 | throw new \InvalidArgumentException(sprintf( |
|
719 | 379 | 'The class "%s" in file "%s" must extend \Phinx\Migration\AbstractMigration', |
|
720 | $class, |
||
721 | 379 | $filePath |
|
722 | )); |
||
723 | } |
||
724 | |||
725 | $versions[$version] = $migration; |
||
726 | } |
||
727 | } |
||
728 | |||
729 | 388 | ksort($versions); |
|
730 | $this->setMigrations($versions); |
||
731 | 388 | } |
|
732 | 388 | ||
733 | 388 | return $this->migrations; |
|
734 | } |
||
735 | 388 | ||
736 | 388 | /** |
|
737 | 388 | * Returns a list of migration files found in the provided migration paths. |
|
738 | 388 | * |
|
739 | 388 | * @return string[] |
|
740 | 388 | */ |
|
741 | View Code Duplication | protected function getMigrationFiles() |
|
742 | 388 | { |
|
743 | $config = $this->getConfig(); |
||
744 | $paths = $config->getMigrationPaths(); |
||
745 | $files = []; |
||
746 | |||
747 | foreach ($paths as $path) { |
||
748 | $files = array_merge( |
||
749 | $files, |
||
750 | Util::glob($path . DIRECTORY_SEPARATOR . '*.php') |
||
751 | 11 | ); |
|
752 | } |
||
753 | 11 | // glob() can return the same file multiple times |
|
754 | 11 | // This will cause the migration to fail with a |
|
755 | // false assumption of duplicate migrations |
||
756 | // http://php.net/manual/en/function.glob.php#110340 |
||
757 | $files = array_unique($files); |
||
758 | |||
759 | return $files; |
||
760 | } |
||
761 | |||
762 | /** |
||
763 | 11 | * Sets the database seeders. |
|
764 | * |
||
765 | 11 | * @param array $seeds Seeders |
|
766 | 11 | * @return \Phinx\Migration\Manager |
|
767 | */ |
||
768 | public function setSeeds(array $seeds) |
||
769 | 11 | { |
|
770 | $this->seeds = $seeds; |
||
771 | 11 | ||
772 | return $this; |
||
773 | 11 | } |
|
774 | 11 | ||
775 | 11 | /** |
|
776 | 11 | * Get seed dependencies instances from seed dependency array |
|
777 | * |
||
778 | * @param AbstractSeed $seed Seed |
||
779 | 11 | * |
|
780 | 11 | * @return AbstractSeed[] |
|
781 | */ |
||
782 | private function getSeedDependenciesInstances(AbstractSeed $seed) |
||
783 | { |
||
784 | 11 | $dependenciesInstances = []; |
|
785 | 11 | $dependencies = $seed->getDependencies(); |
|
786 | if (!empty($dependencies)) { |
||
787 | foreach ($dependencies as $dependency) { |
||
788 | foreach ($this->seeds as $seed) { |
||
789 | if (get_class($seed) === $dependency) { |
||
790 | $dependenciesInstances[get_class($seed)] = $seed; |
||
791 | } |
||
792 | } |
||
793 | } |
||
794 | 11 | } |
|
795 | |||
796 | 11 | return $dependenciesInstances; |
|
797 | } |
||
798 | |||
799 | /** |
||
800 | * Order seeds by dependencies |
||
801 | * |
||
802 | * @param AbstractSeed[] $seeds Seeds |
||
803 | * |
||
804 | 11 | * @return AbstractSeed[] |
|
805 | 11 | */ |
|
806 | 11 | private function orderSeedsByDependencies(array $seeds) |
|
822 | 11 | ||
823 | 11 | /** |
|
824 | 11 | * Gets an array of database seeders. |
|
825 | * |
||
826 | 11 | * @throws \InvalidArgumentException |
|
827 | 11 | * @return \Phinx\Seed\AbstractSeed[] |
|
828 | 11 | */ |
|
829 | 11 | public function getSeeds() |
|
881 | 2 | ||
882 | 1 | /** |
|
883 | 1 | * Returns a list of seed files found in the provided seed paths. |
|
884 | * |
||
885 | 1 | * @return string[] |
|
886 | 1 | */ |
|
887 | View Code Duplication | protected function getSeedFiles() |
|
888 | { |
||
889 | 1 | $config = $this->getConfig(); |
|
890 | $paths = $config->getSeedPaths(); |
||
891 | 1 | $files = []; |
|
892 | |||
893 | 1 | foreach ($paths as $path) { |
|
894 | 1 | $files = array_merge( |
|
895 | 1 | $files, |
|
896 | 1 | Util::glob($path . DIRECTORY_SEPARATOR . '*.php') |
|
897 | 1 | ); |
|
898 | 1 | } |
|
899 | // glob() can return the same file multiple times |
||
900 | // This will cause the migration to fail with a |
||
901 | // false assumption of duplicate migrations |
||
902 | // http://php.net/manual/en/function.glob.php#110340 |
||
903 | $files = array_unique($files); |
||
904 | |||
905 | return $files; |
||
906 | 1 | } |
|
907 | |||
908 | 1 | /** |
|
909 | 1 | * Sets the config. |
|
910 | 1 | * |
|
911 | 1 | * @param \Phinx\Config\ConfigInterface $config Configuration Object |
|
912 | 1 | * @return \Phinx\Migration\Manager |
|
913 | */ |
||
914 | public function setConfig(ConfigInterface $config) |
||
920 | |||
921 | /** |
||
922 | * Gets the config. |
||
923 | * |
||
924 | * @return \Phinx\Config\ConfigInterface |
||
925 | */ |
||
926 | public function getConfig() |
||
930 | |||
931 | /** |
||
932 | * Toggles the breakpoint for a specific version. |
||
933 | * |
||
934 | * @param string $environment |
||
935 | * @param int $version |
||
936 | * @return void |
||
937 | */ |
||
938 | public function toggleBreakpoint($environment, $version) |
||
939 | { |
||
940 | $migrations = $this->getMigrations($environment); |
||
941 | $this->getMigrations($environment); |
||
942 | $env = $this->getEnvironment($environment); |
||
943 | $versions = $env->getVersionLog(); |
||
944 | |||
945 | if (empty($versions) || empty($migrations)) { |
||
946 | return; |
||
947 | } |
||
948 | |||
949 | if ($version === null) { |
||
950 | $lastVersion = end($versions); |
||
951 | $version = $lastVersion['version']; |
||
952 | } |
||
953 | |||
954 | View Code Duplication | if (0 != $version && !isset($migrations[$version])) { |
|
955 | $this->output->writeln(sprintf( |
||
956 | '<comment>warning</comment> %s is not a valid version', |
||
957 | $version |
||
958 | )); |
||
959 | |||
960 | return; |
||
961 | } |
||
962 | |||
963 | $env->getAdapter()->toggleBreakpoint($migrations[$version]); |
||
964 | |||
965 | $versions = $env->getVersionLog(); |
||
966 | |||
967 | $this->getOutput()->writeln( |
||
968 | ' Breakpoint ' . ($versions[$version]['breakpoint'] ? 'set' : 'cleared') . |
||
969 | ' for <info>' . $version . '</info>' . |
||
970 | ' <comment>' . $migrations[$version]->getName() . '</comment>' |
||
971 | ); |
||
972 | } |
||
973 | |||
974 | /** |
||
975 | * Remove all breakpoints |
||
976 | * |
||
977 | * @param string $environment |
||
978 | * @return void |
||
979 | */ |
||
980 | public function removeBreakpoints($environment) |
||
981 | { |
||
982 | $this->getOutput()->writeln(sprintf( |
||
983 | ' %d breakpoints cleared.', |
||
984 | $this->getEnvironment($environment)->getAdapter()->resetAllBreakpoints() |
||
985 | )); |
||
986 | } |
||
987 | |||
988 | /** |
||
989 | * @return MigrationLocatorInterface |
||
990 | */ |
||
991 | protected function getMigrationLocator() |
||
1001 | } |
||
1002 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.