Completed
Push — master ( ee52d8...696270 )
by Alexander
04:27
created

Migrator::handleLaravelCommand()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
4
namespace Quantick\DeployMigration\Lib\Service;
5
6
use Carbon\Carbon;
7
use Illuminate\Console\OutputStyle;
8
use Illuminate\Container\Container;
9
use Illuminate\Contracts\Console\Kernel;
10
use Illuminate\Database\Connection;
11
use Illuminate\Support\Collection;
12
13
class Migrator
14
{
15
    /**
16
     * @var Connection
17
     */
18
    private $connection;
19
    /**
20
     * @var Container
21
     */
22
    private $container;
23
    /**
24
     * @var Kernel
25
     */
26
    private $kernel;
27
28
29
    /**
30
     * Migrator constructor.
31
     * @param Connection $connection
32
     * @param Container $container
33
     * @param Kernel $kernel
34
     */
35
    public function __construct(
36
        Connection $connection,
37
        Container $container,
38
        Kernel $kernel
39
    )
40
    {
41
        $this->connection = $connection;
42
        $this->container  = $container;
43
        $this->kernel     = $kernel;
44
    }
45
46
    /**
47
     * @param Collection $migrations
48
     * @param OutputStyle $deployCommandOutput
49
     * @throws \Throwable
50
     */
51
    public function run(Collection $migrations, OutputStyle $deployCommandOutput)
52
    {
53
        foreach ($migrations as $migration) {
54
            $outputs = [];
55
            $currentMigration = $migration;
56
            $currentCommand = null;
57
58
            try {
59
                $this->connection->beginTransaction();
60
61
                $tableQuery = $this->getTableQuery();
62
63
                $alreadyExecuted = $tableQuery->where('migration', '=', get_class($migration))->count() > 0;
64
65
                if ($alreadyExecuted === true) {
66
                    continue;
67
                }
68
69
                $commands = $migration->getCommands();
70
71
                foreach ($commands as $commandName => $arguments) {
72
                    $currentCommand        = $arguments instanceof \Closure ? 'Closure#' . $commandName : $commandName;
73
                    $output                = $this->handleCommand($commandName, $arguments);
74
                    $outputs[$commandName] = $output;
75
                }
76
77
                $deployCommandOutput->progressAdvance();
78
79
                $tableQuery->insert([
80
                    'migration' => get_class($migration),
81
                    'created_at' => Carbon::now()
82
83
                ]);
84
85
                $this->getInfoTableQuery()->insert([
86
                    'migration' => get_class($migration),
87
                    'output' => json_encode($outputs),
88
                    'created_at' => Carbon::now()
89
                ]);
90
91
                $this->connection->commit();
92
            } catch (\Throwable $e) {
93
                $migrationClass = $currentMigration !== null ? get_class($currentMigration) : null;
94
                $commandClass = $currentCommand;
95
96
                $deployCommandOutput->writeln('');
97
                $deployCommandOutput->writeln(sprintf('<error>Error during %s migration; %s command</error>', $migrationClass, $commandClass));
98
                $deployCommandOutput->writeln(sprintf('<error>%s</error>', (string)$e));
99
                $this->connection->rollBack();
100
101
                $this->getInfoTableQuery()->insert([
102
                    'migration' => $migrationClass,
103
                    'output' => json_encode($outputs),
104
                    'error' => json_encode([
105
                        'trace'         => $e->getTraceAsString(),
106
                        'message'       => $e->getMessage(),
107
                        'code'          => $e->getCode(),
108
                        'file'          => $e->getFile(),
109
                        'line'          => $e->getLine(),
110
                        'error_command' => $commandClass
111
                    ]),
112
                    'created_at' => Carbon::now()
113
                ]);
114
115
                throw $e;
116
            }
117
118
        }
119
    }
120
121
    private function handleClosure(callable $closure)
122
    {
123
        return $this->container->call($closure);
124
    }
125
126
    private function handleLaravelCommand(string $commandName, array $arguments = [])
127
    {
128
        $signature = $this->getSignature($commandName);
129
130
        $this->kernel->call($signature, $arguments);
131
        return $this->kernel->output();
132
    }
133
134
    private function handleCommand($commandName, $arguments)
135
    {
136
        switch (true) {
137
            case $arguments instanceof \Closure:
138
                return $this->handleClosure($arguments);
139
            default:
140
                return $this->handleLaravelCommand($commandName, $arguments);
141
        }
142
    }
143
144
    /**
145
     * @param string $className
146
     * @return string|null
147
     * @throws \ReflectionException
148
     */
149
    private function getSignature(string $className): ?string
150
    {
151
        $migrationReflection = new \ReflectionClass($className);
152
        $properties          = $migrationReflection->getDefaultProperties();
153
154
        return $properties['signature'] ?? $properties['name'] ?? null;
155
    }
156
157
    /**
158
     * @return \Illuminate\Database\Query\Builder
159
     */
160
    private function getTableQuery(): \Illuminate\Database\Query\Builder
161
    {
162
        return $this->connection->table('deploy_migrations');
163
    }
164
165
166
    /**
167
     * @return \Illuminate\Database\Query\Builder
168
     */
169
    private function getInfoTableQuery(): \Illuminate\Database\Query\Builder
170
    {
171
        return $this->connection->table('deploy_migrations_info');
172
    }
173
}
174