Completed
Push — master ( bb22e0...a8c1a4 )
by Iman
15s
created

DbInspector   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 222
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 222
rs 9.3999
c 0
b 0
f 0
wmc 33

11 Methods

Rating   Name   Duplication   Size   Complexity  
A isColNull() 0 18 4
B findPK() 0 23 5
A getForeignKey() 0 9 2
A findPKname() 0 14 3
A isForeignKey() 0 17 3
B listTables() 0 24 5
A getTableCols() 0 11 1
A colName() 0 13 4
A getFieldTypes() 0 10 2
A getPKforSqlServer() 0 20 2
A getTableForeignKey() 0 4 2
1
<?php
2
3
namespace crocodicstudio\crudbooster\helpers;
4
5
use Cache;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, crocodicstudio\crudbooster\helpers\Cache. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use crocodicstudio\crudbooster\helpers\Cache as CbCache;
7
use DB;
8
use Schema;
9
10
class DbInspector
11
{
12
    /**
13
     * @param $table
14
     * @return bool|null|string
15
     * @throws \Exception
16
     */
17
    public static function findPK($table)
18
    {
19
        if (! $table) {
20
            return 'id';
21
        }
22
23
        if (CbCache::get('table_'.$table, 'primaryKey')) {
24
            return CbCache::get('table_'.$table, 'primaryKey');
25
        }
26
        $table = CRUDBooster::parseSqlTable($table);
27
28
        if (! $table['table']) {
29
            throw new \Exception("parseSqlTable can't determine the table");
30
        }
31
32
        $primaryKey = self::findPKname($table);
33
34
        if (! $primaryKey) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $primaryKey of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
35
            return 'id';
36
        }
37
        CbCache::put('table_'.$table, 'primaryKey', $primaryKey);
38
39
        return $primaryKey;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $primaryKey returns the type array which is incompatible with the documented return type null|string|boolean.
Loading history...
40
    }
41
42
    /**
43
     * @param $table
44
     * @param $field
45
     * @return bool
46
     */
47
    public static function isColNull($table, $field)
48
    {
49
        $cacheKey = 'field_isNull_'.$table.'_'.$field;
50
51
        if (Cache::has($cacheKey)) {
52
            return Cache::get($cacheKey);
53
        }
54
55
        try {
56
            //MySQL & SQL Server
57
            $isNULL = DB::select(DB::raw("select IS_NULLABLE from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='$table' and COLUMN_NAME = '$field'"))[0]->IS_NULLABLE;
58
            $isNULL = ($isNULL == 'YES') ? true : false;
59
        } catch (\Exception $e) {
60
            $isNULL = false;
61
        }
62
        Cache::forever($cacheKey, $isNULL);
63
64
        return $isNULL;
65
    }
66
67
    /**
68
     * @param $columns
69
     * @return string
70
     */
71
    public static function colName($columns)
72
    {
73
        $nameColCandidate = explode(',', cbConfig('NAME_FIELDS_CANDIDATE'));
74
75
        foreach ($columns as $c) {
76
            foreach ($nameColCandidate as $cc) {
77
                if (strpos($c, $cc) !== false) {
78
                    return $c;
79
                }
80
            }
81
        }
82
83
        return 'id';
84
    }
85
86
    /**
87
     * @param $table
88
     * @return array
89
     */
90
    public static function getTableCols($table)
91
    {
92
        $table = CRUDBooster::parseSqlTable($table);
93
        $cols = collect(DB::select('SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = :database AND TABLE_NAME = :table', [
94
            'database' => $table['database'],
95
            'table' => $table['table'],
96
        ]))->map(function ($x) {
97
            return (array) $x;
98
        })->toArray();
99
100
        return array_column($cols, 'COLUMN_NAME');
101
    }
102
103
    /**
104
     * @param $table
105
     * @param $field
106
     * @return string
107
     */
108
    public static function getFieldTypes($table, $field)
109
    {
110
        $field = 'field_type_'.$table.'_'.$field;
111
112
        return Cache::rememberForever($field, function () use ($table, $field) {
113
            try {
114
                //MySQL & SQL Server
115
                return DB::select(DB::raw("select DATA_TYPE from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='$table' and COLUMN_NAME = '$field'"))[0]->DATA_TYPE;
116
            } catch (\Exception $e) {
117
                return 'varchar';
118
            }
119
        });
120
    }
121
122
    /**
123
     * @param $fieldName
124
     * @return bool
125
     */
126
    public static function isForeignKey($fieldName)
127
    {
128
        $cacheKey = 'isForeignKey_'.$fieldName;
129
130
        if (Cache::has($cacheKey)) {
131
            return Cache::get($cacheKey);
132
        }
133
134
        $table = self::getTableForeignKey($fieldName);
135
        if (! $table) {
136
            return false;
137
        }
138
139
        $hasTable = Schema::hasTable($table);
140
        Cache::forever($cacheKey, $hasTable);
141
142
        return $hasTable;
143
    }
144
145
    /**
146
     * @param $table
147
     * @return null
148
     */
149
    private static function getPKforSqlServer($table)
150
    {
151
        try {
152
            $query = "
153
						SELECT Col.Column_Name,Col.Table_Name from 
154
						    INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab, 
155
						    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col 
156
						WHERE 
157
						    Col.Constraint_Name = Tab.Constraint_Name
158
						    AND Col.Table_Name = Tab.Table_Name
159
						    AND Constraint_Type = 'PRIMARY KEY'
160
							AND Col.Table_Name = '$table[table]' 
161
					";
162
            $keys = DB::select($query);
163
            $primaryKey = $keys[0]->Column_Name;
164
        } catch (\Exception $e) {
165
            $primaryKey = null;
166
        }
167
168
        return $primaryKey;
169
    }
170
171
    /**
172
     * @param $table
173
     * @return array
174
     */
175
    private static function findPKname($table)
176
    {
177
        if (env('DB_CONNECTION') == 'sqlsrv') {
178
            return self::getPKforSqlServer($table);
0 ignored issues
show
Bug introduced by
Are you sure the usage of self::getPKforSqlServer($table) targeting crocodicstudio\crudboost...or::getPKforSqlServer() 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...
179
        }
180
        try {
181
            $query = "select * from information_schema.COLUMNS where TABLE_SCHEMA = '$table[database]' and TABLE_NAME = '$table[table]' and COLUMN_KEY = 'PRI'";
182
            $keys = DB::select($query);
183
            $primaryKey = $keys[0]->COLUMN_NAME;
184
        } catch (\Exception $e) {
185
            $primaryKey = null;
186
        }
187
188
        return $primaryKey;
189
    }
190
191
    public static function listTables()
192
    {
193
        $multiple_db = cbConfig('MULTIPLE_DATABASE_MODULE') ?: [];
194
        $db_database = cbConfig('MAIN_DB_DATABASE');
195
196
        if ($multiple_db) {
197
            try {
198
                $multiple_db[] = cbConfig('MAIN_DB_DATABASE');
199
                $query_table_schema = implode("','", $multiple_db);
200
                $tables = DB::select("SELECT CONCAT(TABLE_SCHEMA,'.',TABLE_NAME) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA != 'mysql' AND TABLE_SCHEMA != 'performance_schema' AND TABLE_SCHEMA != 'information_schema' AND TABLE_SCHEMA != 'phpmyadmin' AND TABLE_SCHEMA IN ('$query_table_schema')");
201
            } catch (\Exception $e) {
202
                $tables = [];
203
            }
204
205
            return $tables;
206
        }
207
208
        try {
209
            $tables = DB::select("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.Tables WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = '".$db_database."'");
210
        } catch (\Exception $e) {
211
            $tables = [];
212
        }
213
214
        return $tables;
215
    }
216
217
    public static function getForeignKey($parent_table, $child_table)
218
    {
219
        $parent_table = CRUDBooster::parseSqlTable($parent_table)['table'];
220
        $child_table = CRUDBooster::parseSqlTable($child_table)['table'];
221
222
        if (\Schema::hasColumn($child_table, 'id_'.$parent_table)) {
223
            return 'id_'.$parent_table;
224
        }
225
        return $parent_table.'_id';
226
    }
227
228
    public static function getTableForeignKey($fieldName)
229
    {
230
        if (self::isForeignKey($fieldName)) {
231
            return str_replace(['_id', 'id_'], '', $fieldName);
232
        }
233
    }
234
}