MigrationExecutor::up()   A
last analyzed

Complexity

Conditions 5
Paths 13

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 0
cts 21
cp 0
rs 9.1448
c 0
b 0
f 0
cc 5
nc 13
nop 1
crap 30
1
<?php
2
/**
3
 * File was created 05.07.2016 16:34
4
 */
5
6
namespace PeekAndPoke\Component\Slumber\Data\Migration;
7
8
use PeekAndPoke\Component\Slumber\Data\Migration\DomainModel\ExecutedMigration;
9
use PeekAndPoke\Component\Slumber\Data\Migration\Exception\MigrationException;
10
use PeekAndPoke\Component\Toolbox\ExceptionUtil;
11
use Psr\Log\LoggerInterface;
12
13
/**
14
 * @author Karsten J. Gerber <[email protected]>
15
 */
16
class MigrationExecutor
17
{
18
    /** @var MigrationRepository */
19
    private $repository;
20
21
    /** @var Migration[] */
22
    private $migrations = [];
23
    /** @var LoggerInterface */
24
    private $logger;
25
26
    /**
27
     * MigrationExecutor constructor.
28
     *
29
     * @param MigrationRepository $repository
30
     * @param LoggerInterface     $logger
31
     */
32
    public function __construct(MigrationRepository $repository, LoggerInterface $logger)
33
    {
34
        $this->repository = $repository;
35
        $this->logger     = $logger;
36
    }
37
38
    /**
39
     * @param Migration $migration
40
     *
41
     * @return $this
42
     */
43
    public function registerMigration(Migration $migration)
44
    {
45
        $name = $this->normalizeName($migration);
46
47
        if (isset($this->migrations[$name])) {
48
            throw new \InvalidArgumentException("Migration $name is already registered");
49
        }
50
51
        $this->migrations[$name] = $migration;
52
53
        return $this;
54
    }
55
56
    public function logStats()
57
    {
58
        $all  = $this->repository->findAll();
59
        $open = array_keys($this->migrations);
60
61
        $this->logger->info('===== EXECUTED MIGRATIONS =====');
62
63
        foreach ($all as $item) {
64
            $this->logger->info(str_pad($item->getName(), 80, ' ', STR_PAD_RIGHT) . ' on ' . $item->getCreatedAt()->format('c'));
65
66
            $open = array_filter(
67
                $open,
68
                function ($name) use ($item) {
69
                    return $name !== $item->getName();
70
                }
71
            );
72
        }
73
74
        $this->logger->info('===== AVAILABLE MIGRATIONS =====');
75
76
        foreach ($open as $name) {
77
            $this->logger->info("$name  (created {$this->migrations[$name]->getCreationDate()->format()})");
78
        }
79
    }
80
81
    /**
82
     * @param string $name
83
     */
84
    public function up($name)
85
    {
86
        if (! isset($this->migrations[$name])) {
87
            throw new MigrationException("There is no migration registered with the name '$name'");
88
        }
89
90
        if ($this->repository->countByName($name) > 0) {
91
            throw new MigrationException("Cannot 'up' the migration '$name' since it was already executed");
92
        }
93
94
        $migration = $this->migrations[$name];
95
96
        try {
97
            $this->logger->info('Migrating ' . $name . ' UP now');
98
99
            $executed = $migration->up();
100
            $executed = $executed ?: new ExecutedMigration();
101
            $executed->setName($name);
102
103
            $this->repository->store($executed);
104
            $this->logger->info('... done with migrating ' . $name . ' UP');
105
106
        } catch (\Exception $e) {
107
            ExceptionUtil::log($this->logger, $e, '[SlumberMigration] Error running migration ' . $name);
108
109
            throw new MigrationException('Error running migration ' . $name, 0, $e);
110
        }
111
112
    }
113
114
    /**
115
     */
116
    public function upAll()
117
    {
118
        $numExecuted = 0;
119
120
        foreach ($this->migrations as $name => $migration) {
121
122
            if ($this->repository->countByName($name) === 0) {
123
                $this->up($name);
124
                $numExecuted++;
125
            }
126
        }
127
128
        $this->logger->info("Done migrating. Executed $numExecuted migrations");
129
    }
130
131
    /**
132
     * @param string $name
133
     */
134
    public function down($name)
135
    {
136
        if (! isset($this->migrations[$name])) {
137
            throw new MigrationException("There is no migration registered with the name '$name'");
138
        }
139
140
        $executed = $this->repository->findOneByName($name);
141
142
        if ($executed === null) {
143
            throw new MigrationException("Cannot 'down' the migration '$name' since it was not executed yet");
144
        }
145
146
        $migration = $this->migrations[$name];
147
148
        try {
149
            $this->logger->info('Migrating ' . $name . ' DOWN now');
150
151
            $migration->down($executed);
152
            $this->repository->delete($executed);
153
154
            $this->logger->info('... done with migrating ' . $name . ' DOWN');
155
        } catch (\Exception $e) {
156
            ExceptionUtil::log($this->logger, $e, '[SlumberMigration] Error running migration ' . $name);
157
158
            throw new MigrationException('Error running migration ' . $name, 0, $e);
159
        }
160
    }
161
162
    /**
163
     * @param Migration $migration
164
     *
165
     * @return string
166
     */
167
    private function normalizeName(Migration $migration)
168
    {
169
        return $migration->getName();
170
    }
171
}
172