Passed
Push — master ( 636d9d...66682c )
by Alexander
01:58
created

DownCommand::execute()   B

Complexity

Conditions 7
Paths 42

Size

Total Lines 44
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 28
nc 42
nop 2
dl 0
loc 44
ccs 0
cts 28
cp 0
crap 56
rs 8.5386
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Cycle\Command\Migration;
6
7
use Psr\EventDispatcher\EventDispatcherInterface;
8
use Spiral\Migrations\MigrationInterface;
9
use Spiral\Migrations\State;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Output\OutputInterface;
12
use Symfony\Component\Console\Question\ConfirmationQuestion;
13
use Yiisoft\Yii\Console\ExitCode;
14
use Yiisoft\Yii\Cycle\Command\CycleDependencyProxy;
15
use Yiisoft\Yii\Cycle\Event\AfterMigrate;
16
use Yiisoft\Yii\Cycle\Event\BeforeMigrate;
17
18
final class DownCommand extends BaseMigrationCommand
19
{
20
    protected static $defaultName = 'migrate/down';
21
22
    private EventDispatcherInterface $eventDispatcher;
23
24
    public function __construct(CycleDependencyProxy $promise, EventDispatcherInterface $eventDispatcher)
25
    {
26
        $this->eventDispatcher = $eventDispatcher;
27
        parent::__construct($promise);
28
    }
29
30
    public function configure(): void
31
    {
32
        $this
33
            ->setDescription('Rollback last migration');
34
    }
35
36
    protected function execute(InputInterface $input, OutputInterface $output): int
37
    {
38
        $migrations = $this->findMigrations($output);
39
        // check any executed migration
40
        $exist = false;
41
        foreach (array_reverse($migrations) as $migration) {
42
            if ($migration->getState()->getStatus() === State::STATUS_EXECUTED) {
43
                $exist = true;
44
                break;
45
            }
46
        }
47
        if (!$exist) {
48
            $output->writeln('<fg=red>No migration found for rollback</>');
49
            return ExitCode::OK;
50
        }
51
52
        $migrator = $this->promise->getMigrator();
53
54
        // Confirm
55
        if (!$migrator->getConfig()->isSafe()) {
56
            $output->writeln('<fg=yellow>Migration to be reverted:</>');
57
            $output->writeln('— <fg=cyan>' . $migration->getState()->getName() . '</>');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $migration seems to be defined by a foreach iteration on line 41. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
58
            $question = new ConfirmationQuestion('Revert the above migration? (yes|no) ', false);
59
            if (!$this->getHelper('question')->ask($input, $output, $question)) {
60
                return ExitCode::OK;
61
            }
62
        }
63
64
        $this->eventDispatcher->dispatch(new BeforeMigrate());
65
        try {
66
            $migrator->rollback();
67
            if (!$migration instanceof MigrationInterface) {
68
                throw new \Exception('Migration not found');
69
            }
70
71
            $state = $migration->getState();
72
            $status = $state->getStatus();
73
            $output->writeln(
74
                sprintf('<fg=cyan>%s</>: %s', $state->getName(), static::MIGRATION_STATUS[$status] ?? $status)
75
            );
76
        } finally {
77
            $this->eventDispatcher->dispatch(new AfterMigrate());
78
        }
79
        return ExitCode::OK;
80
    }
81
}
82