State::findColumn()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 1
dl 0
loc 9
ccs 4
cts 4
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of Cycle ORM package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Cycle\Database\Schema;
13
14
/**
15
 * TableSchema helper used to store original table elements and run comparation between them.
16
 *
17
 * Attention: this state IS MUTABLE!
18
 */
19
final class State
20
{
21
    /** @var AbstractColumn[] */
22
    private array $columns = [];
23
24
    /** @var AbstractIndex[] */
25
    private array $indexes = [];
26
27
    /** @var AbstractForeignKey[] */
28
    private array $foreignKeys = [];
29
30
    /**
31
     * Primary key columns are stored separately from other indexes and
32
     * can only be modified during table creation.
33
     */
34
    private array $primaryKeys = [];
35
36
    /**
37
     * @psalm-param non-empty-string $name
38
     */
39 1974
    public function __construct(
40
        private string $name,
41
    ) {}
42 1974
43
    /**
44
     * Set table name. Operation will be applied at moment of saving.
45
     *
46
     * @psalm-param non-empty-string $name
47 1950
     */
48
    public function setName(string $name): void
49 1950
    {
50 1950
        $this->name = $name;
51
    }
52
53 1950
    /**
54 458
     * @psalm-return non-empty-string
55
     */
56
    public function getName(): string
57 1950
    {
58 224
        return $this->name;
59
    }
60 1950
61
    /**
62
     * @return AbstractColumn[]
63
     */
64
    public function getColumns(): array
65
    {
66
        return $this->columns;
67 1974
    }
68
69 1974
    /**
70 1974
     * @return AbstractIndex[]
71
     */
72
    public function getIndexes(): array
73
    {
74
        return $this->indexes;
75 1974
    }
76
77 1974
    /**
78
     * @return AbstractForeignKey[]
79
     */
80
    public function getForeignKeys(): array
81
    {
82
        return $this->foreignKeys;
83 1958
    }
84
85 1958
    public function setPrimaryKeys(array $columns): void
86
    {
87
        $this->primaryKeys = $columns;
88
    }
89
90
    /**
91 1952
     * Method combines primary keys with primary keys automatically calculated based on registered columns.
92
     *
93 1952
     * @return list<non-empty-string>
0 ignored issues
show
Bug introduced by
The type Cycle\Database\Schema\list 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...
94
     */
95
    public function getPrimaryKeys(): array
96
    {
97
        $primaryColumns = [];
98
        foreach ($this->getColumns() as $column) {
99 1954
            $type = $column->getAbstractType();
100
            if ($type === 'smallPrimary' || $type === 'primary' || $type === 'bigPrimary') {
101 1954
                if (!\in_array($column->getName(), $this->primaryKeys, true)) {
102
                    //Only columns not listed as primary keys already
103
                    $primaryColumns[] = $column->getName();
104 1928
                }
105
            }
106 1928
        }
107 1928
108
        return \array_unique(\array_merge($this->primaryKeys, $primaryColumns));
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_unique(arra...Keys, $primaryColumns)) returns the type array which is incompatible with the documented return type Cycle\Database\Schema\list.
Loading history...
109
    }
110
111
    /**
112 1954
     * @psalm-param non-empty-string $name
113
     */
114 1954
    public function hasColumn(string $name): bool
115 1954
    {
116 1946
        return $this->findColumn($name) !== null;
117 1946
    }
118 1366
119
    public function hasIndex(array $columns = []): bool
120 1364
    {
121
        return $this->findIndex($columns) !== null;
122
    }
123
124
    public function hasForeignKey(array $columns): bool
125 1954
    {
126
        return $this->findForeignKey($columns) !== null;
127
    }
128
129
    public function registerColumn(AbstractColumn $column): void
0 ignored issues
show
Bug introduced by
The type Cycle\Database\Schema\AbstractColumn 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...
130
    {
131 1950
        $this->columns[$column->getName()] = $column;
132
    }
133 1950
134
    public function registerIndex(AbstractIndex $index): void
135
    {
136 458
        $this->indexes[$index->getName()] = $index;
137
    }
138 458
139
    public function registerForeignKey(AbstractForeignKey $reference): void
140
    {
141 224
        $this->foreignKeys[$reference->getName()] = $reference;
142
    }
143 224
144
    /**
145
     * Drop column from table schema.
146 1950
     */
147
    public function forgetColumn(AbstractColumn $column): self
148 1950
    {
149 1950
        foreach ($this->columns as $name => $columnSchema) {
150
            // todo: need better compare
151 458
            if ($columnSchema == $column) {
152
                unset($this->columns[$name]);
153 458
                break;
154 458
            }
155
        }
156 224
157
        return $this;
158 224
    }
159 224
160
    /**
161
     * Drop index from table schema using it's name or forming columns.
162
     */
163
    public function forgetIndex(AbstractIndex $index): void
164 32
    {
165
        foreach ($this->indexes as $name => $indexSchema) {
166 32
            // todo: need better compare
167
            if ($indexSchema == $index) {
168 32
                unset($this->indexes[$name]);
169 32
                break;
170 32
            }
171
        }
172
    }
173
174 32
    /**
175
     * Drop foreign key from table schema using it's forming column.
176
     *
177
     * @deprecated Since cycle/database 2.2.0, use {@see forgetForeignKey()} instead.
178
     */
179
    public function forgerForeignKey(AbstractForeignKey $foreignKey): void
180 102
    {
181
        $this->forgetForeignKey($foreignKey);
182 102
    }
183
184 102
    /**
185 102
     * Drop foreign key from table schema using it's forming column.
186 102
     *
187
     * @since 2.2.0
188
     */
189 102
    public function forgetForeignKey(AbstractForeignKey $foreignKey): void
190
    {
191
        foreach ($this->foreignKeys as $name => $foreignSchema) {
192
            // todo: need better compare
193
            if ($foreignSchema == $foreignKey) {
194 224
                unset($this->foreignKeys[$name]);
195
                break;
196 224
            }
197
        }
198 224
    }
199 224
200 224
    /**
201
     * @psalm-param non-empty-string $name
202
     */
203 224
    public function findColumn(string $name): ?AbstractColumn
204
    {
205
        foreach ($this->columns as $column) {
206
            if ($column->getName() === $name) {
207
                return $column;
208 1950
            }
209
        }
210 1950
211 1926
        return null;
212 1682
    }
213
214
    /**
215
     * Find index by it's columns or return null.
216 1948
     */
217
    public function findIndex(array $columns): ?AbstractIndex
218
    {
219
        foreach ($this->indexes as $index) {
220
            if ($index->getColumnsWithSort() === $columns) {
221
                return $index;
222 458
            }
223
        }
224 458
225 458
        return null;
226 458
    }
227
228
    /**
229
     * Find foreign key by it's column or return null.
230 458
     */
231
    public function findForeignKey(array $columns): ?AbstractForeignKey
232
    {
233
        foreach ($this->foreignKeys as $fk) {
234
            if ($fk->getColumns() === $columns) {
235
                return $fk;
236 224
            }
237
        }
238 224
239 224
        return null;
240 224
    }
241
242
    /**
243
     * Remount elements under their current name.
244 224
     */
245
    public function remountElements(): void
246
    {
247
        $columns = [];
248
        foreach ($this->columns as $column) {
249
            $columns[$column->getName()] = $column;
250 1974
        }
251
252 1974
        $indexes = [];
253 1974
        foreach ($this->indexes as $index) {
254 1944
            $indexes[$index->getName()] = $index;
255
        }
256
257 1974
        $foreignKeys = [];
258 1974
        foreach ($this->foreignKeys as $fk) {
259 458
            $foreignKeys[$fk->getName()] = $fk;
260
        }
261
262 1974
        $this->columns = $columns;
263 1974
        $this->indexes = $indexes;
264 224
        $this->foreignKeys = $foreignKeys;
265
    }
266
267 1974
    /**
268 1974
     * Re-populate schema elements using other state as source. Elements will be cloned under their
269 1974
     * schema name.
270 1974
     */
271
    public function syncState(self $source): self
272
    {
273
        $this->name = $source->name;
274
        $this->primaryKeys = $source->primaryKeys;
275
276 1974
        $this->columns = [];
277
        foreach ($source->columns as $name => $column) {
278 1974
            $this->columns[$name] = clone $column;
279 1974
        }
280
281 1974
        $this->indexes = [];
282 1974
        foreach ($source->indexes as $name => $index) {
283 1944
            $this->indexes[$name] = clone $index;
284
        }
285
286 1974
        $this->foreignKeys = [];
287 1974
        foreach ($source->foreignKeys as $name => $foreignKey) {
288 458
            $this->foreignKeys[$name] = clone $foreignKey;
289
        }
290
291 1974
        $this->remountElements();
292 1974
293 224
        return $this;
294
    }
295
296 1974
    /**
297
     * Cloning all elements.
298 1974
     */
299
    public function __clone()
300
    {
301
        foreach ($this->columns as $name => $column) {
302
            $this->columns[$name] = clone $column;
303
        }
304
305
        foreach ($this->indexes as $name => $index) {
306
            $this->indexes[$name] = clone $index;
307
        }
308
309
        foreach ($this->foreignKeys as $name => $foreignKey) {
310
            $this->foreignKeys[$name] = clone $foreignKey;
311
        }
312
    }
313
}
314