Schema   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 70
c 3
b 0
f 0
dl 0
loc 164
rs 10
wmc 27

16 Methods

Rating   Name   Duplication   Size   Complexity  
A schemaUnsyncedColumns() 0 4 1
A dbColumns() 0 5 1
A schemaUnsyncedColumnsOutput() 0 3 1
A process() 0 5 2
A columnsList() 0 18 5
A syncChoices() 0 4 2
A getName() 0 9 3
A schemaEmpty() 0 3 1
A create() 0 11 2
A dropSchema() 0 5 2
A dbUnsyncedColumns() 0 4 1
A __construct() 0 7 1
A sync() 0 15 2
A output() 0 4 1
A columnsTypes() 0 14 1
A tabeExist() 0 3 1
1
<?php
2
3
namespace Awssat\SyncMigration;
4
5
use Illuminate\Database\Schema\Blueprint;
0 ignored issues
show
Bug introduced by
The type Illuminate\Database\Schema\Blueprint was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Illuminate\Support\Collection;
7
use Illuminate\Support\Facades\DB;
8
use Spatie\Regex\Regex;
9
use Illuminate\Support\Facades\Schema as LaravelSchema;
10
use Illuminate\Support\Str;
11
12
class Schema
13
{
14
    public $schema;
15
    public $name;
16
    public $table;
17
    public $writeIn;
18
    public $synced = false;
19
20
    /**
21
     * Schema constructor.
22
     * @param $schema
23
     * @param $writeIn
24
     */
25
    public function __construct($schema, SyncMigrateCommand $writeIn)
26
    {
27
        $this->schema = $schema;
28
        $this->writeIn = $writeIn;
29
30
        $this->name = $this->getName($schema->group(1));
31
        $this->table = DB::getTablePrefix() . $this->name;
32
    }
33
34
    public function process()
35
    {
36
        $action = $this->tabeExist() ? 'sync' : 'create';
37
38
        $this->$action();
39
    }
40
41
    public function output()
42
    {
43
        $this->synced = true;
44
        return $this->writeIn;
45
    }
46
47
    protected function create()
48
    {
49
        if($this->columnsList()->isEmpty()) {
50
            return $this->output()->error("Table <fg=black;bg=white> {$this->table} </> does not have any columns");
51
        }
52
53
        LaravelSchema::create($this->name, function (Blueprint $table) {
54
            eval($this->schema->group(2));
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
55
        });
56
57
        $this->output()->warn("New table <fg=white;bg=green> {$this->table} </> was created");
58
    }
59
60
    protected function sync()
61
    {
62
        if($this->schemaEmpty()) {
63
            return $this->dropSchema();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->dropSchema() targeting Awssat\SyncMigration\Schema::dropSchema() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
64
        }
65
66
        $this->dbUnsyncedColumns()->each(function ($type, $column)  {
67
            $this->output()->info("Column <fg=black;bg=yellow> {$this->table}->{$column} </> is renamed or deleted !!");
68
            $action = $this->output()->choice('What we should do ?', $this->syncChoices(), 0);
69
70
            (new Column($this))->$action($column);
71
        });
72
73
        $this->schemaUnsyncedColumns()->each(function ($column, $line) {
74
            (new Column($this))->create($line, $column);
75
        });
76
    }
77
78
    protected function dropSchema()
79
    {
80
        $this->output()->error("Table <fg=black;bg=yellow> {$this->table} </> does not have any columns");
81
        $this->output()->confirm("Do you want to drop <fg=white;bg=red> {$this->table} </> ?",
82
            true) && LaravelSchema::dropIfExists($this->name);
83
    }
84
85
    protected function schemaEmpty()
86
    {
87
        return $this->dbColumns()->diffKeys($this->dbUnsyncedColumns())->isEmpty();
88
    }
89
90
    protected function getName($name)
91
    {
92
        //TODO: https://github.com/awssat/laravel-sync-migration/issues/2
93
        if(preg_match('/[\'|"]\s?\.\s?\$/', $name) || preg_match('/\$[a-zA-z0-9-_]+\s?\.\s?[\'|"]/', $name)) {
94
            $this->output()->error("Using variables as table names (<fg=black;bg=white> {$name} </>) is not supported currentlly, see <href=https://github.com/awssat/laravel-sync-migration/issues/2> issue#2 </>");
95
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
96
        }
97
98
        return str_replace(['\'', '"'], '', $name);
99
    }
100
101
    public function schemaUnsyncedColumnsOutput()
102
    {
103
        return $this->schemaUnsyncedColumns()->values()->flatten()->toArray();
104
    }
105
106
    protected function dbUnsyncedColumns()
107
    {
108
        return $this->dbColumns()->reject(function ($type, $column) {
109
            return $this->columnsList()->values()->flatten()->contains($column);
110
        });
111
    }
112
113
    protected function schemaUnsyncedColumns()
114
    {
115
        return $this->columnsList()->reject(function ($column) {
116
            return $this->dbColumns()->has($column);
117
        });
118
    }
119
120
    protected function syncChoices()
121
    {
122
        return $this->schemaUnsyncedColumns()->isEmpty() ? ['Delete', 'Ignore'] :
123
            ['Delete', 'Rename', 'Ignore'];
124
    }
125
126
    protected function dbColumns()
127
    {
128
        return Collection::make(DB::select('DESCRIBE ' . $this->table))
129
            ->mapWithKeys(function ($column) {
130
            return [$column->Field => $column->Type];
131
        });
132
    }
133
134
    protected function columnsList()
135
    {
136
        return Collection::make(explode(';', $this->schema->group(2)))->mapWithKeys(function ($line) {
137
            $line = trim($line);
138
139
            if(Str::startsWith($line, ['//', '#', '/*'])) {
140
                return [];
141
            }
142
143
            try {
144
                $column = Regex::match('~(["\'])([^"\']+)\1~', $line);
145
                $column = $column->hasMatch() ? $column->group(2) : null;
146
                $types = $this->columnsTypes($column);
147
                $type = Regex::match('/\$.*->(.*)\(/', $line)->group(1);
148
149
                return [$line => in_array($type, array_keys($types)) ? $types[$type] : [$column]];
150
            } catch (\Exception $e) {
151
                return [];
152
            }
153
        });
154
    }
155
156
    protected function columnsTypes($column)
157
    {
158
        return  [
159
            'id' => ['id'],
160
            'rememberToken' => ['remember_token'],
161
            'softDeletes' => ['deleted_at'],
162
            'softDeletesTz' => ['deleted_at'],
163
            'timestamps' => ['created_at', 'updated_at'],
164
            'timestampsTz' => ['created_at', 'updated_at'],
165
            'nullableTimestamps' => ['created_at', 'updated_at'],
166
            'morphs' => ["{$column}_id", "{$column}_type"],
167
            'uuidMorphs' => ["{$column}_id", "{$column}_type"],
168
            'nullableUuidMorphs' => ["{$column}_id", "{$column}_type"],
169
            'nullableMorphs' => ["{$column}_id", "{$column}_type"],
170
        ];
171
    }
172
    
173
    protected function tabeExist()
174
    {
175
        return DB::getSchemaBuilder()->hasTable($this->name);
176
    }
177
}
178