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 | use Cycle\Database\Driver\DriverInterface; |
||||||
15 | use Cycle\Database\IndexInterface; |
||||||
16 | use Cycle\Database\Schema\Traits\ElementTrait; |
||||||
17 | |||||||
18 | /** |
||||||
19 | * Abstract index schema with read (see IndexInterface) and write abilities. Must be implemented |
||||||
20 | * by driver to support DBMS specific syntax and creation rules. |
||||||
21 | */ |
||||||
22 | abstract class AbstractIndex implements IndexInterface, ElementInterface |
||||||
23 | { |
||||||
24 | use ElementTrait; |
||||||
25 | |||||||
26 | /** |
||||||
27 | * Index types. |
||||||
28 | */ |
||||||
29 | public const NORMAL = 'INDEX'; |
||||||
30 | |||||||
31 | public const UNIQUE = 'UNIQUE'; |
||||||
32 | |||||||
33 | /** |
||||||
34 | * Index type, by default NORMAL and UNIQUE indexes supported, additional types can be |
||||||
35 | * implemented on database driver level. |
||||||
36 | */ |
||||||
37 | protected string $type = self::NORMAL; |
||||||
38 | |||||||
39 | /** |
||||||
40 | * Columns used to form index. |
||||||
41 | */ |
||||||
42 | protected array $columns = []; |
||||||
43 | |||||||
44 | /** |
||||||
45 | * Columns mapping to sorting order |
||||||
46 | */ |
||||||
47 | protected array $sort = []; |
||||||
48 | |||||||
49 | /** |
||||||
50 | * @psalm-param non-empty-string $table |
||||||
51 | * @psalm-param non-empty-string $name |
||||||
52 | 708 | */ |
|||||
53 | public function __construct( |
||||||
54 | protected string $table, |
||||||
55 | protected string $name, |
||||||
56 | 708 | ) {} |
|||||
57 | |||||||
58 | 458 | /** |
|||||
59 | * Parse column name and order from column expression |
||||||
60 | 458 | */ |
|||||
61 | public static function parseColumn(array|string $column): array |
||||||
62 | { |
||||||
63 | 680 | if (\is_array($column)) { |
|||||
0 ignored issues
–
show
introduced
by
![]() |
|||||||
64 | return $column; |
||||||
65 | 680 | } |
|||||
66 | |||||||
67 | // Contains ASC |
||||||
68 | if (\str_ends_with($column, ' ASC')) { |
||||||
69 | return [ |
||||||
70 | \substr($column, 0, -4), |
||||||
71 | 'ASC', |
||||||
72 | ]; |
||||||
73 | } |
||||||
74 | |||||||
75 | if (\str_ends_with($column, ' DESC')) { |
||||||
76 | 458 | return [ |
|||||
77 | \substr($column, 0, -5), |
||||||
78 | 458 | 'DESC', |
|||||
79 | 458 | ]; |
|||||
80 | 458 | } |
|||||
81 | 458 | ||||||
82 | return [ |
||||||
83 | $column, |
||||||
84 | null, |
||||||
85 | ]; |
||||||
86 | } |
||||||
87 | |||||||
88 | 210 | public function isUnique(): bool |
|||||
89 | { |
||||||
90 | 210 | return $this->type === self::UNIQUE; |
|||||
91 | } |
||||||
92 | 210 | ||||||
93 | public function getColumns(): array |
||||||
94 | { |
||||||
95 | return $this->columns; |
||||||
96 | } |
||||||
97 | |||||||
98 | public function getSort(): array |
||||||
99 | { |
||||||
100 | return $this->sort; |
||||||
101 | } |
||||||
102 | |||||||
103 | /** |
||||||
104 | * Will return columns list with their corresponding order expressions |
||||||
105 | */ |
||||||
106 | public function getColumnsWithSort(): array |
||||||
107 | 458 | { |
|||||
108 | $self = $this; |
||||||
109 | 458 | return \array_map( |
|||||
110 | static fn(string $column): string => ($order = $self->sort[$column] ?? null) ? "$column $order" : $column, |
||||||
111 | $this->columns, |
||||||
112 | ); |
||||||
113 | 458 | } |
|||||
114 | |||||||
115 | 458 | /** |
|||||
116 | * Declare index type and behaviour to unique/non-unique state. |
||||||
117 | */ |
||||||
118 | public function unique(bool $unique = true): self |
||||||
119 | { |
||||||
120 | $this->type = $unique ? self::UNIQUE : self::NORMAL; |
||||||
121 | |||||||
122 | return $this; |
||||||
123 | } |
||||||
124 | |||||||
125 | /** |
||||||
126 | * Change set of index forming columns. Method must support both array and string parameters. |
||||||
127 | * |
||||||
128 | 458 | * Example: |
|||||
129 | * $index->columns('key'); |
||||||
130 | 458 | * $index->columns('key', 'key2'); |
|||||
131 | * $index->columns(['key', 'key2']); |
||||||
132 | 458 | * |
|||||
133 | * @param array|string $columns Columns array or comma separated list of parameters. |
||||||
134 | * |
||||||
135 | */ |
||||||
136 | public function columns(string|array $columns): self |
||||||
137 | { |
||||||
138 | if (!\is_array($columns)) { |
||||||
0 ignored issues
–
show
|
|||||||
139 | $columns = \func_get_args(); |
||||||
140 | } |
||||||
141 | |||||||
142 | $this->columns = $columns; |
||||||
143 | 344 | ||||||
144 | return $this; |
||||||
145 | 344 | } |
|||||
146 | |||||||
147 | 344 | /** |
|||||
148 | * Change a columns order mapping if needed. |
||||||
149 | 344 | * |
|||||
150 | 344 | * Example: |
|||||
151 | * $index->sort(['key2' => 'DESC']); |
||||||
152 | * |
||||||
153 | * @param array $sort Associative array of columns to sort order. |
||||||
154 | 344 | * |
|||||
155 | 344 | */ |
|||||
156 | 344 | public function sort(array $sort): self |
|||||
157 | 344 | { |
|||||
158 | 12 | $this->sort = $sort; |
|||||
159 | |||||||
160 | return $this; |
||||||
161 | 344 | } |
|||||
162 | |||||||
163 | 344 | /** |
|||||
164 | * Index sql creation syntax. |
||||||
165 | 344 | * |
|||||
166 | * @param bool $includeTable Include table ON statement (not required for inline index creation). |
||||||
167 | 344 | * |
|||||
168 | * @psalm-return non-empty-string |
||||||
169 | */ |
||||||
170 | 458 | public function sqlStatement(DriverInterface $driver, bool $includeTable = true): string |
|||||
171 | { |
||||||
172 | 458 | $statement = [$this->isUnique() ? 'UNIQUE INDEX' : 'INDEX']; |
|||||
173 | |||||||
174 | $statement[] = $driver->identifier($this->name); |
||||||
0 ignored issues
–
show
The method
identifier() does not exist on Cycle\Database\Driver\DriverInterface . It seems like you code against a sub-type of Cycle\Database\Driver\DriverInterface such as Cycle\Database\Driver\Driver .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
175 | |||||||
176 | if ($includeTable) { |
||||||
177 | $statement[] = "ON {$driver->identifier($this->table)}"; |
||||||
178 | 706 | } |
|||||
179 | |||||||
180 | 706 | //Wrapping column names |
|||||
181 | $columns = []; |
||||||
182 | foreach ($this->columns as $column) { |
||||||
183 | $quoted = $driver->identifier($column); |
||||||
184 | if ($order = $this->sort[$column] ?? null) { |
||||||
185 | 706 | $quoted = "$quoted $order"; |
|||||
186 | } |
||||||
187 | |||||||
188 | $columns[] = $quoted; |
||||||
189 | } |
||||||
190 | $columns = \implode(', ', $columns); |
||||||
191 | |||||||
192 | 706 | $statement[] = "({$columns})"; |
|||||
193 | |||||||
194 | 16 | return \implode(' ', $statement); |
|||||
195 | 16 | } |
|||||
196 | |||||||
197 | public function compare(self $initial): bool |
||||||
198 | { |
||||||
199 | return $this == clone $initial; |
||||||
200 | 706 | } |
|||||
201 | } |
||||||
202 |