Completed
Push — master ( 7723f5...13b1e1 )
by Adrian
16:41 queued 09:58
created

SchemaUpdate   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 8.93%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 4
dl 0
loc 140
ccs 5
cts 56
cp 0.0893
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B handle() 0 37 5
B createInMemoryDatabase() 0 25 1
A getSchemaManager() 0 10 2
A getDatabasePlatform() 0 10 2
1
<?php
2
namespace Ablunier\Laravel\Database\Console\Commands;
3
4
use Illuminate\Console\Command;
5
use Illuminate\Foundation\Application;
6
use Illuminate\Contracts\Console\Kernel as Console;
7
use Schema;
8
use DB;
9
use Doctrine\DBAL\Schema\Comparator;
10
11
class SchemaUpdate extends Command
12
{
13
    const CONNECTION_NAME = 'schema-update';
14
15
    /**
16
     * The name and signature of the console command.
17
     *
18
     * @var string
19
     */
20
    protected $signature = 'db:schema-update {--force : Force execute queries}';
21
22
    /**
23
     * The console command description.
24
     *
25
     * @var string
26
     */
27
    protected $description = 'Updates database schema with any migration changes';
28
29
    /**
30
     *
31
     * @var Application
32
     */
33
    protected $app;
34
35
    /**
36
     *
37
     * @var Console
38
     */
39
    protected $artisan;
40
41
    /**
42
     * Create a new command instance.
43
     *
44
     * @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...
45
     */
46 4
    public function __construct(Application $app, Console $artisan)
47
    {
48 4
        parent::__construct();
49
50 4
        $this->app = $app;
51 4
        $this->artisan = $artisan;
52 4
    }
53
54
    /**
55
     * Execute the console command.
56
     *
57
     * @return mixed
58
     */
59
    public function handle()
60
    {
61
        $this->info('Retrieving schema differences...'.PHP_EOL);
62
63
        $this->createInMemoryDatabase();
64
65
        $defaultSm = $this->getSchemaManager();
66
        $inMemorySm = $this->getSchemaManager(self::CONNECTION_NAME);
67
68
        $fromSchema = $defaultSm->createSchema();
69
        $toSchema = $inMemorySm->createSchema();
70
71
        $comparator = new Comparator();
72
        $schemaDiff = $comparator->compare($fromSchema, $toSchema);
73
74
        $diffStatements = $schemaDiff->toSql($this->getDatabasePlatform());
75
76
        if (count($diffStatements) > 0) {
77
            $this->info('Statements that will be executed:'.PHP_EOL);
78
79
            foreach ($diffStatements as $statement) {
80
                $this->info('- '.$statement);
81
            }
82
        } else {
83
            $this->info('The schema is up to date with the migrations.'.PHP_EOL);
84
        }
85
86
        if ($this->option('force')) {
87
            DB::transaction(function() use ($diffStatements) {
88
                foreach ($diffStatements as $statement) {
89
                    DB::statement($statement);
90
                }
91
            });
92
        } else {
93
            $this->info(PHP_EOL.'To apply diff statements use the --force option');
94
        }
95
    }
96
97
    protected function createInMemoryDatabase()
98
    {
99
        $defaultConnection = $this->app['config']->get('database.default');
100
101
        $this->app['config']->set('database.connections.'.self::CONNECTION_NAME, [
102
            'driver' => 'sqlite',
103
            'database' => ':memory:',
104
            'prefix' => ''
105
        ]);
106
107
        // Makes sure the migrations table is created
108
        $this->artisan->call('migrate', [
109
            '--database' => self::CONNECTION_NAME
110
        ]);
111
112
        // We empty all tables
113
        $this->artisan->call('migrate:reset');
114
115
        // Migrate
116
        $this->artisan->call('migrate', [
117
            '--database' => self::CONNECTION_NAME
118
        ]);
119
120
        $this->app['config']->set('database.default', $defaultConnection);
121
    }
122
123
    /**
124
     * @param string $connection
125
     */
126
    protected function getSchemaManager($connection = null)
127
    {
128
        if (isset($connection)) {
129
            $connection = Schema::connection($connection)->getConnection();
130
        } else {
131
            $connection = Schema::getConnection();
132
        }
133
134
        return $connection->getDoctrineSchemaManager();
135
    }
136
137
    /**
138
     * @return \Doctrine\DBAL\Platforms\AbstractPlatform
139
     */
140
    protected function getDatabasePlatform($connection = null)
141
    {
142
        if (isset($connection)) {
143
            $connection = Schema::connection($connection)->getConnection();
144
        } else {
145
            $connection = Schema::getConnection();
146
        }
147
148
        return $connection->getDoctrineConnection()->getDatabasePlatform();
149
    }
150
}
151