1: <?php
2:
3: namespace Aurora\System\Console\Commands\Migrations;
4:
5: use Aurora\System\Console\Commands\BaseCommand;
6: use Illuminate\Database\Migrations\Migrator;
7: use Symfony\Component\Console\Command\Command;
8: use Symfony\Component\Console\Input\ArrayInput;
9: use Symfony\Component\Console\Input\InputInterface;
10: use Symfony\Component\Console\Input\InputOption;
11: use Symfony\Component\Console\Output\OutputInterface;
12: use Symfony\Component\Console\Question\ConfirmationQuestion;
13:
14: class MigrateCommand extends BaseCommand
15: {
16: /**
17: * The migrator instance.
18: *
19: * @var \Illuminate\Database\Migrations\Migrator
20: */
21: protected $migrator;
22:
23: /**
24: * Create a new migration command instance.
25: *
26: * @param \Illuminate\Database\Migrations\Migrator $migrator
27: * @return void
28: */
29: public function __construct(Migrator $migrator)
30: {
31: parent::__construct();
32:
33: $this->migrator = $migrator;
34: }
35:
36: protected function configure(): void
37: {
38: $this->setName('migrate')
39: ->setDescription('Run the database migrations')
40: ->addOption('force', null, InputOption::VALUE_OPTIONAL, 'Force the operation to run when in production')
41: ->addOption('path', null, InputOption::VALUE_OPTIONAL, 'The path(s) to the migrations files to be executed')
42: ->addOption('realpath', null, InputOption::VALUE_OPTIONAL, 'Indicate any provided migration file paths are pre-resolved absolute paths')
43: ->addOption('pretend', null, InputOption::VALUE_OPTIONAL, 'Dump the SQL queries that would be run')
44: ->addOption('seed', null, InputOption::VALUE_OPTIONAL, 'Indicates if the seed task should be re-run')
45: ->addOption('step', null, InputOption::VALUE_OPTIONAL, 'Force the migrations to be run so they can be rolled back individually')
46: ->addOption('database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use');
47: }
48:
49: /**
50: * Execute the console command.
51: *
52: * @return int
53: */
54: protected function execute(InputInterface $input, OutputInterface $output): int
55: {
56: $defaultAnswer = $input->getOption('no-interaction');
57: if (!$input->getOption('force')) {
58: $helper = $this->getHelper('question');
59: $question = new ConfirmationQuestion('Do you really wish to run this command? (Y/N)', $defaultAnswer);
60: if (!$helper->ask($input, $output, $question)) {
61: return Command::SUCCESS;
62: }
63: }
64:
65: $this->migrator->usingConnection($input->getOption('database'), function () use ($input, $output) {
66: $this->prepareDatabase($input, $output);
67:
68: // Next, we will check to see if a path option has been defined. If it has
69: // we will use the path relative to the root of this installation folder
70: // so that migrations may be run for any path within the applications.
71:
72: $this->migrator->setOutput($output)
73: ->run($this->getMigrationPaths($input), [
74: 'pretend' => $input->getOption('pretend'),
75: 'step' => $input->getOption('step'),
76: ]);
77:
78: // Finally, if the "seed" option has been given, we will re-run the database
79: // seed task to re-populate the database, which is convenient when adding
80: // a migration and a seed at the same time, as it is only this command.
81: if ($input->getOption('seed') && ! $input->getOption('pretend')) {
82: $seedInput = new ArrayInput([
83: '--force' => true,
84: ]);
85: $this->getApplication()->find('db:seed')->run($seedInput, $output);
86: }
87: });
88:
89: return Command::SUCCESS;
90: }
91:
92: /**
93: * Prepare the migration database for running.
94: *
95: * @return void
96: */
97: protected function prepareDatabase($input, $output)
98: {
99: if (!$this->migrator->repositoryExists()) {
100: $greetInput = new ArrayInput([
101: '--database' => $input->getOption('database'),
102: ]);
103: $this->getApplication()->find('migrate:install')->run($greetInput, $output);
104: }
105: }
106: }
107: