Passed
Branch main (5746ae)
by Sammy
02:23
created

Description   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 205
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 71
dl 0
loc 205
rs 8.8798
c 0
b 0
f 0
wmc 44

19 Methods

Rating   Name   Duplication   Size   Complexity  
A columns() 0 3 1
A name() 0 3 1
A column() 0 3 1
A singleForeignKeyTo() 0 9 2
A uniqueKeysByName() 0 3 1
B primaryKeys() 0 19 7
A addUniqueKey() 0 4 2
A foreignKeysByTable() 0 3 1
A foreignKeysByName() 0 3 1
A addColumn() 0 8 3
A uniqueKeysMatch() 0 18 6
A addPrimaryKey() 0 3 1
A __construct() 0 4 1
B primaryKeysMatch() 0 21 7
A autoIncrementedPrimaryKey() 0 3 2
A __toString() 0 3 1
A addForeignKey() 0 6 1
A matchUniqueness() 0 15 4
A connection() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Description often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Description, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace HexMakina\Crudites\Table;
4
5
use HexMakina\Crudites\CruditesException;
6
use HexMakina\BlackBox\Database\ConnectionInterface;
7
use HexMakina\BlackBox\Database\TableDescriptionInterface;
8
use HexMakina\BlackBox\Database\TableColumnInterface;
9
10
class Description implements TableDescriptionInterface
11
{
12
    protected $connection = null;
13
14
    protected $name = null;
15
    // protected $ORM_class_name = null;
16
17
    protected $columns = [];
18
19
    // auto_incremented_primary_key
20
    protected $aipk = null;
21
22
    protected $primary_keys = [];
23
    protected $foreign_keys_by_name = [];
24
    protected $foreign_keys_by_table = [];
25
    protected $unique_keys = [];
26
27
    public function __construct($table_name, ConnectionInterface $c)
28
    {
29
        $this->name = $table_name;
30
        $this->connection = $c;
31
    }
32
33
    public function __toString()
34
    {
35
        return $this->name;
36
    }
37
38
    public function connection(): ConnectionInterface
39
    {
40
        return $this->connection;
41
    }
42
43
    public function addColumn(TableColumnInterface $column)
44
    {
45
        $this->columns[$column->name()] = $column;
46
47
        if ($column->isPrimary()) {
48
            $this->addPrimaryKey($column);
49
            if ($column->isAutoIncremented()) {
50
                $this->autoIncrementedPrimaryKey($column);
51
            }
52
        }
53
    }
54
55
    public function addPrimaryKey(TableColumnInterface $column)
56
    {
57
        $this->primary_keys[$column->name()] = $column;
58
    }
59
60
    public function addUniqueKey($constraint_name, $columns)
61
    {
62
        if (!isset($this->unique_keys[$constraint_name])) {
63
            $this->unique_keys[$constraint_name] = $columns;
64
        }
65
    }
66
67
    public function addForeignKey(TableColumnInterface $column)
68
    {
69
        $this->foreign_keys_by_table[$column->foreignTableName()] = $this->foreign_keys_by_table[$column->foreignTableName()] ?? [];
70
        $this->foreign_keys_by_table[$column->foreignTableName()] [] = $column;
71
72
        $this->foreign_keys_by_name[$column->name()] = $column;
73
    }
74
75
    //getsetter of AIPK, default get is null, cant set to null
76
    public function autoIncrementedPrimaryKey(TableColumnInterface $setter = null)
77
    {
78
        return is_null($setter) ? $this->aipk : ($this->aipk = $setter);
79
    }
80
81
    //------------------------------------------------------------  getters
82
    // TableDescriptionInterface implementation
83
    public function name(): string
84
    {
85
        return $this->name;
86
    }
87
88
    // TableDescriptionInterface implementation
89
    public function columns(): array
90
    {
91
        return $this->columns;
92
    }
93
94
    // TableDescriptionInterface implementation
95
    public function column($name)
96
    {
97
        return $this->columns[$name] ?? null;
98
    }
99
100
    // TableDescriptionInterface implementation
101
    public function uniqueKeysByName(): array
102
    {
103
        return $this->unique_keys;
104
    }
105
106
    // TableDescriptionInterface implementation
107
    public function primaryKeys($with_values = null): array
108
    {
109
        if (is_null($with_values)) {
110
            return $this->primary_keys;
111
        }
112
113
        if (!is_array($with_values) && count($this->primary_keys) === 1) {
114
            $with_values = [current($this->primary_keys)->name() => $with_values];
115
        }
116
117
        $valid_dat_ass = [];
118
        foreach ($this->primary_keys as $pk_name => $pk_field) {
119
            if (!isset($with_values[$pk_name]) && !$pk_field->isNullable()) {
120
                return [];
121
            }
122
123
            $valid_dat_ass[$pk_name] = $with_values[$pk_name];
124
        }
125
        return $valid_dat_ass;
126
    }
127
128
    public function matchUniqueness($dat_ass): array
129
    {
130
        if (!is_array($dat_ass)) { // aipk value
131
            return $this->primaryKeysMatch($dat_ass);
132
        }
133
134
        if (!empty($ret = $this->primaryKeysMatch($dat_ass))) {
135
            return $ret;
136
        }
137
138
        if (!empty($ret = $this->uniqueKeysMatch($dat_ass))) {
139
            return $ret;
140
        }
141
142
        return [];
143
    }
144
145
    /*
146
    * @return array, empty on mismatch
147
    * @return array, assoc of column_name => $value on match
148
    * @throws CruditesException if no pk defined
149
    */
150
151
    public function primaryKeysMatch($dat_ass): array
152
    {
153
        if (count($this->primaryKeys()) === 0) {
154
            throw new CruditesException('NO_PRIMARY_KEYS_DEFINED');
155
        }
156
157
        if (!is_array($dat_ass) && count($this->primaryKeys()) === 1) {
158
            $dat_ass = [current($this->primaryKeys())->name() => $dat_ass];
159
        }
160
161
        $valid_dat_ass = [];
162
        foreach ($this->primary_keys as $pk_name => $pk_field) {
163
            // empty ensures non existing keys, null and empty values
164
            if (empty($dat_ass[$pk_name]) && !$pk_field->isNullable()) {
165
                return [];
166
            }
167
168
            $valid_dat_ass[$pk_name] = $dat_ass[$pk_name] ?? null;
169
        }
170
171
        return $valid_dat_ass;
172
    }
173
174
    public function uniqueKeysMatch($dat_ass): array
175
    {
176
        if (count($this->uniqueKeysByName()) === 0 || !is_array($dat_ass)) {
177
            return [];
178
        }
179
180
        $keys = array_keys($dat_ass);
181
182
        foreach ($this->uniqueKeysByName() as $constraint_name => $column_names) {
183
            if (!is_array($column_names)) {
184
                $column_names = [$column_names];
185
            }
186
187
            if (empty(array_diff($keys, $column_names))) {
188
                return $dat_ass;
189
            }
190
        }
191
        return [];
192
    }
193
194
    // TableDescriptionInterface implementation
195
    public function foreignKeysByName(): array
196
    {
197
        return $this->foreign_keys_by_name;
198
    }
199
200
    // TableDescriptionInterface implementation
201
    public function foreignKeysByTable(): array
202
    {
203
        return $this->foreign_keys_by_table;
204
    }
205
206
    public function singleForeignKeyTo($other_table)
207
    {
208
        $bonding_column_candidates = $this->foreignKeysByTable()[$other_table->name()] ?? [];
209
210
        if (count($bonding_column_candidates) === 1) {
211
            return current($bonding_column_candidates);
212
        }
213
214
        return null;
215
    }
216
}
217