1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of the Zemit Framework. |
5
|
|
|
* |
6
|
|
|
* (c) Zemit Team <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE.txt |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Zemit\Modules\Cli\Tasks\Traits; |
13
|
|
|
|
14
|
|
|
use Phalcon\Config\Exception; |
15
|
|
|
use Phalcon\Mvc\Model; |
16
|
|
|
use Zemit\Exception\CliException; |
17
|
|
|
use Zemit\Mvc\Controller\Traits\Abstracts\AbstractInjectable; |
18
|
|
|
use Zemit\Mvc\Model\Interfaces\HashInterface; |
19
|
|
|
|
20
|
|
|
trait DatabaseTrait |
21
|
|
|
{ |
22
|
|
|
use AbstractInjectable; |
23
|
|
|
|
24
|
|
|
public array $drop = []; |
25
|
|
|
public array $truncate = []; |
26
|
|
|
public array $engine = []; |
27
|
|
|
public array $insert = []; |
28
|
|
|
public array $optimize = []; |
29
|
|
|
public array $analyze = []; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Default action |
33
|
|
|
* @throws CliException |
34
|
|
|
*/ |
35
|
|
|
public function mainAction(): ?array |
36
|
|
|
{ |
37
|
|
|
$response = []; |
38
|
|
|
|
39
|
|
|
$response ['engine'] = $this->fixEngineAction(); |
40
|
|
|
$response ['optimize'] = $this->optimizeAction(); |
41
|
|
|
$response ['analyze'] = $this->analyzeAction(); |
42
|
|
|
|
43
|
|
|
return $response; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* The resetAction method is responsible for resetting the state of the application by performing |
48
|
|
|
* the following actions: |
49
|
|
|
* |
50
|
|
|
* 1. Truncate database tables using the truncateAction method. |
51
|
|
|
* 2. Insert initial data into the database using the insertAction method. |
52
|
|
|
* |
53
|
|
|
* Use Case: |
54
|
|
|
* |
55
|
|
|
* This method can be used when you need to reset the state of the application to its initial state. |
56
|
|
|
* It is commonly used for testing or when you want to re-populate the database with initial data. |
57
|
|
|
* |
58
|
|
|
* @return array |
59
|
|
|
*/ |
60
|
|
|
public function resetAction(): array |
61
|
|
|
{ |
62
|
|
|
$response = []; |
63
|
|
|
|
64
|
|
|
$response ['truncate'] = $this->truncateAction(); |
65
|
|
|
$response ['insert'] = $this->insertAction(); |
66
|
|
|
|
67
|
|
|
return $response; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* The truncateAction method is responsible for truncating (emptying) database tables specified in the |
72
|
|
|
* $this->truncate array. Truncating a table removes all of its data, effectively resetting it to an |
73
|
|
|
* empty state. This method iterates through a list of table names and executes an SQL TRUNCATE TABLE |
74
|
|
|
* command for each of them. |
75
|
|
|
* |
76
|
|
|
* Use Case: |
77
|
|
|
* This method is often used when you need to reset the data in database tables without deleting |
78
|
|
|
* the table itself. Truncating tables is a quicker alternative to deleting all rows one by one. |
79
|
|
|
*/ |
80
|
|
|
public function truncateAction(): array |
81
|
|
|
{ |
82
|
|
|
$response = []; |
83
|
|
|
|
84
|
|
|
foreach ($this->truncate as $table) { |
85
|
|
|
$response [] = $this->db->execute('TRUNCATE TABLE ' . $this->db->escapeIdentifier($table)); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
return $response; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* The dropAction method is responsible for dropping database tables specified in the $this->drop array. |
93
|
|
|
* Dropping a table means permanently removing it from the database schema. This method iterates through |
94
|
|
|
* a list of table names and executes an SQL DROP TABLE command for each of them, with a safety check to |
95
|
|
|
* ensure that the table is only dropped if it exists. |
96
|
|
|
* |
97
|
|
|
* Use Case: |
98
|
|
|
* This method is commonly used when performing database schema changes or cleanup tasks, where you need |
99
|
|
|
* to remove tables that are no longer needed. The IF EXISTS clause is a safety measure to prevent |
100
|
|
|
* accidental deletion of tables. |
101
|
|
|
*/ |
102
|
|
|
public function dropAction(): array |
103
|
|
|
{ |
104
|
|
|
$response = []; |
105
|
|
|
|
106
|
|
|
foreach ($this->drop as $table) { |
107
|
|
|
$response [] = $this->db->execute('DROP TABLE IF EXISTS ' . $this->db->escapeIdentifier($table)); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
return $response; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* The fixEngineAction method is responsible for fixing or changing the storage engine for database tables |
115
|
|
|
* specified in the $this->engine array. A storage engine determines how data is stored and managed within |
116
|
|
|
* a database table. This method iterates through a list of table names and their corresponding desired |
117
|
|
|
* storage engines and executes SQL ALTER TABLE commands to make the necessary changes. |
118
|
|
|
* |
119
|
|
|
* Use Case: |
120
|
|
|
* This method is useful when you need to adjust the storage engine of database tables to optimize performance, |
121
|
|
|
* compatibility, or for other specific requirements. Different storage engines have different characteristics, |
122
|
|
|
* and choosing the right one can impact table performance and functionality. |
123
|
|
|
*/ |
124
|
|
|
public function fixEngineAction(): array |
125
|
|
|
{ |
126
|
|
|
$response = []; |
127
|
|
|
|
128
|
|
|
foreach ($this->engine as $table => $engine) { |
129
|
|
|
$response [] = $this->db->execute('ALTER TABLE ' . $this->db->escapeIdentifier($table) . ' ENGINE = ' . $engine); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
return $response; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Insert records |
137
|
|
|
* @throws CliException |
138
|
|
|
*/ |
139
|
|
|
public function insertAction(?string $models = null): array |
140
|
|
|
{ |
141
|
|
|
$response = [ |
142
|
|
|
'saved' => 0, |
143
|
|
|
'error' => [], |
144
|
|
|
'message' => [], |
145
|
|
|
]; |
146
|
|
|
|
147
|
|
|
$models = (!empty($models)) ? explode(',', $models) : null; |
148
|
|
|
|
149
|
|
|
foreach ($this->insert as $modelName => $insert) { |
150
|
|
|
if (is_array($models) && !in_array($modelName, $models, true)) { |
151
|
|
|
continue; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
foreach ($insert as $key => $row) { |
155
|
|
|
assert(is_string($modelName) && class_exists($modelName)); |
156
|
|
|
$entity = new $modelName(); |
157
|
|
|
assert($entity instanceof Model); |
158
|
|
|
|
159
|
|
|
$assign = isset($row[0]) && method_exists($entity, 'columnMap') |
160
|
|
|
? array_combine($entity->columnMap(), $row) |
|
|
|
|
161
|
|
|
: $row; |
162
|
|
|
|
163
|
|
|
if (!$assign) { |
164
|
|
|
throw new CliException('Can\'t assign row #' . $key . ' for model `' . $modelName . '`.'); |
165
|
|
|
} |
166
|
|
|
else { |
167
|
|
|
$entity->assign($assign); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
// Automagically fill passwords |
171
|
|
|
if (property_exists($entity, 'password')) { |
172
|
|
|
if (empty($row['password']) && property_exists($entity, 'email')) { |
173
|
|
|
if (method_exists($entity, 'hash')) { |
174
|
|
|
$entity->assign(['password' => $entity->hash($row['email'])]); |
|
|
|
|
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
try { |
180
|
|
|
if (!$entity->save()) { |
181
|
|
|
$response['error'][$modelName][] = $entity->toArray(); |
182
|
|
|
|
183
|
|
|
foreach ($entity->getMessages() as $message) { |
184
|
|
|
$response['message'][$modelName][] = $message; |
185
|
|
|
} |
186
|
|
|
} |
187
|
|
|
else { |
188
|
|
|
$response['saved']++; |
189
|
|
|
} |
190
|
|
|
} catch (\Exception $e) { |
191
|
|
|
$response['error'][$modelName][] = $entity->toArray(); |
192
|
|
|
$response['message'][$modelName][] = $e->getMessage(); |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
return $response; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* The optimizeAction method is responsible for optimizing database tables specified in the |
202
|
|
|
* $this->optimize array. Database table optimization is a maintenance task aimed at improving |
203
|
|
|
* the performance and storage efficiency of database tables. This method iterates through a |
204
|
|
|
* list of table names and executes an SQL OPTIMIZE TABLE command for each of them. |
205
|
|
|
* |
206
|
|
|
* Use Case: |
207
|
|
|
* This method is typically used in the context of database maintenance and optimization routines. |
208
|
|
|
* It allows you to automate the process of optimizing database tables, which can help reclaim storage |
209
|
|
|
* space and improve query performance by reorganizing table data and indexes. |
210
|
|
|
*/ |
211
|
|
|
public function optimizeAction(): array |
212
|
|
|
{ |
213
|
|
|
$response = []; |
214
|
|
|
|
215
|
|
|
foreach ($this->optimize as $table) { |
216
|
|
|
$response [] = $this->db->query('OPTIMIZE TABLE ' . $this->db->escapeIdentifier($table))->fetchAll(); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
return $response; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* This method is responsible for analyzing database tables specified in the $this->analyse array. |
224
|
|
|
* Table analysis is an essential database maintenance task that helps optimize the performance |
225
|
|
|
* of database queries. Analyzing a table refreshes statistics and metadata about the table's |
226
|
|
|
* structure, which can lead to improved query execution plans. |
227
|
|
|
* |
228
|
|
|
* Use Case: |
229
|
|
|
* This method can be used in the context of database optimization and maintenance scripts. |
230
|
|
|
* It allows you to automate the process of analyzing database tables, ensuring that the database's |
231
|
|
|
* query optimizer has up-to-date statistics to make informed decisions about query execution plans. |
232
|
|
|
*/ |
233
|
|
|
public function analyzeAction(): array |
234
|
|
|
{ |
235
|
|
|
$response = []; |
236
|
|
|
|
237
|
|
|
foreach ($this->analyze as $table) { |
238
|
|
|
$response [] = $this->db->query('ANALYZE TABLE ' . $this->db->escapeIdentifier($table))->fetchAll(); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
return $response; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* @throws Exception |
246
|
|
|
*/ |
247
|
|
|
public function addModelsPermissions(?array $tables = null): void |
248
|
|
|
{ |
249
|
|
|
$permissions = []; |
250
|
|
|
$tables ??= $this->insert; |
251
|
|
|
foreach ($tables as $model => $entity) { |
252
|
|
|
$permissions[$model] = ['*']; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
$this->config->merge([ |
256
|
|
|
'permissions' => [ |
257
|
|
|
'roles' => [ |
258
|
|
|
'cli' => [ |
259
|
|
|
'models' => $permissions, |
260
|
|
|
], |
261
|
|
|
], |
262
|
|
|
], |
263
|
|
|
], true); |
264
|
|
|
$this->acl->setOption('permissions', $this->config->pathToArray('permissions') ?? []); |
265
|
|
|
} |
266
|
|
|
} |
267
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
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.