SchemaUpdate::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 2
crap 1
1
<?php
2
3
namespace Ablunier\Laravel\Database\Console\Commands;
4
5
use DB;
6
use Doctrine\DBAL\Schema\Comparator;
7
use Illuminate\Console\Command;
8
use Illuminate\Contracts\Console\Kernel as Console;
9
use Illuminate\Foundation\Application;
10
use Schema;
11
12
class SchemaUpdate extends Command
13
{
14
    const CONNECTION_NAME = 'schema-update';
15
16
    /**
17
     * The name and signature of the console command.
18
     *
19
     * @var string
20
     */
21
    protected $signature = 'db:schema-update {--force : Force execute queries}';
22
23
    /**
24
     * The console command description.
25
     *
26
     * @var string
27
     */
28
    protected $description = 'Updates database schema with any migration changes';
29
30
    /**
31
     * @var Application
32
     */
33
    protected $app;
34
35
    /**
36
     * @var Console
37
     */
38
    protected $artisan;
39
40
    /**
41
     * Create a new command instance.
42
     *
43
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
44
     */
45
    public function __construct(Application $app, Console $artisan)
46 4
    {
47
        parent::__construct();
48 4
49
        $this->app = $app;
50 4
        $this->artisan = $artisan;
51 4
    }
52 4
53
    /**
54
     * Execute the console command.
55
     *
56
     * @return mixed
57
     */
58
    public function handle()
59
    {
60
        $this->info('Retrieving schema differences...'.PHP_EOL);
61
62
        $this->createInMemoryDatabase();
63
64
        $defaultSm = $this->getSchemaManager();
65
        $inMemorySm = $this->getSchemaManager(self::CONNECTION_NAME);
66
67
        $fromSchema = $defaultSm->createSchema();
68
        $toSchema = $inMemorySm->createSchema();
69
70
        $comparator = new Comparator();
71
        $schemaDiff = $comparator->compare($fromSchema, $toSchema);
72
73
        $diffStatements = $schemaDiff->toSql($this->getDatabasePlatform());
74
75
        if (count($diffStatements) > 0) {
76
            $this->info('Statements that will be executed:'.PHP_EOL);
77
78
            foreach ($diffStatements as $statement) {
79
                $this->info('- '.$statement);
80
            }
81
        } else {
82
            $this->info('The schema is up to date with the migrations.'.PHP_EOL);
83
        }
84
85
        if ($this->option('force')) {
86
            DB::transaction(function () use ($diffStatements) {
87
                foreach ($diffStatements as $statement) {
88
                    DB::statement($statement);
89
                }
90
            });
91
        } else {
92
            $this->info(PHP_EOL.'To apply diff statements use the --force option');
93
        }
94
    }
95
96
    protected function createInMemoryDatabase()
97
    {
98
        $defaultConnection = $this->app['config']->get('database.default');
99
100
        $this->app['config']->set('database.connections.'.self::CONNECTION_NAME, [
101
            'driver'   => 'sqlite',
102
            'database' => ':memory:',
103
            'prefix'   => '',
104
        ]);
105
106
        // Makes sure the migrations table is created
107
        $this->artisan->call('migrate', [
108
            '--database' => self::CONNECTION_NAME,
109
        ]);
110
111
        // We empty all tables
112
        $this->artisan->call('migrate:reset');
113
114
        // Migrate
115
        $this->artisan->call('migrate', [
116
            '--database' => self::CONNECTION_NAME,
117
        ]);
118
119
        $this->app['config']->set('database.default', $defaultConnection);
120
    }
121
122
    /**
123
     * @param string $connection
124
     */
125
    protected function getSchemaManager($connection = null)
126
    {
127
        if (isset($connection)) {
128
            $connection = Schema::connection($connection)->getConnection();
129
        } else {
130
            $connection = Schema::getConnection();
131
        }
132
133
        return $connection->getDoctrineSchemaManager();
134
    }
135
136
    /**
137
     * @return \Doctrine\DBAL\Platforms\AbstractPlatform
138
     */
139
    protected function getDatabasePlatform($connection = null)
140
    {
141
        if (isset($connection)) {
142
            $connection = Schema::connection($connection)->getConnection();
143
        } else {
144
            $connection = Schema::getConnection();
145
        }
146
147
        return $connection->getDoctrineConnection()->getDatabasePlatform();
148
    }
149
}
150