Passed
Push — master ( f371aa...d7ec00 )
by Julien
19:30
created

DatabaseTrait::resetAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 3
cp 0
crap 2
rs 10
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 void
59
     */
60
    public function resetAction(): void
61
    {
62
        $response ['truncate'] = $this->truncateAction();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$response was never initialized. Although not strictly required by PHP, it is generally a good practice to add $response = array(); before regardless.
Loading history...
63
        $response ['insert'] = $this->insertAction();
64
    }
65
    
66
    /**
67
     * The truncateAction method is responsible for truncating (emptying) database tables specified in the
68
     * $this->truncate array. Truncating a table removes all of its data, effectively resetting it to an
69
     * empty state. This method iterates through a list of table names and executes an SQL TRUNCATE TABLE
70
     * command for each of them.
71
     *
72
     * Use Case:
73
     * This method is often used when you need to reset the data in database tables without deleting
74
     * the table itself. Truncating tables is a quicker alternative to deleting all rows one by one.
75
     */
76
    public function truncateAction(): array
77
    {
78
        $response = [];
79
        
80
        foreach ($this->truncate as $table) {
81
            $response [] = $this->db->execute('TRUNCATE TABLE ' . $this->db->escapeIdentifier($table));
82
        }
83
        
84
        return $response;
85
    }
86
    
87
    /**
88
     * The dropAction method is responsible for dropping database tables specified in the $this->drop array.
89
     * Dropping a table means permanently removing it from the database schema. This method iterates through
90
     * a list of table names and executes an SQL DROP TABLE command for each of them, with a safety check to
91
     * ensure that the table is only dropped if it exists.
92
     *
93
     * Use Case:
94
     * This method is commonly used when performing database schema changes or cleanup tasks, where you need
95
     * to remove tables that are no longer needed. The IF EXISTS clause is a safety measure to prevent
96
     * accidental deletion of tables.
97
     */
98
    public function dropAction(): array
99
    {
100
        $response = [];
101
        
102
        foreach ($this->drop as $table) {
103
            $response [] = $this->db->execute('DROP TABLE IF EXISTS ' . $this->db->escapeIdentifier($table));
104
        }
105
        
106
        return $response;
107
    }
108
    
109
    /**
110
     * The fixEngineAction method is responsible for fixing or changing the storage engine for database tables
111
     * specified in the $this->engine array. A storage engine determines how data is stored and managed within
112
     * a database table. This method iterates through a list of table names and their corresponding desired
113
     * storage engines and executes SQL ALTER TABLE commands to make the necessary changes.
114
     *
115
     * Use Case:
116
     * This method is useful when you need to adjust the storage engine of database tables to optimize performance,
117
     * compatibility, or for other specific requirements. Different storage engines have different characteristics,
118
     * and choosing the right one can impact table performance and functionality.
119
     */
120
    public function fixEngineAction(): array
121
    {
122
        $response = [];
123
        
124
        foreach ($this->engine as $table => $engine) {
125
            $response [] = $this->db->execute('ALTER TABLE ' . $this->db->escapeIdentifier($table) . ' ENGINE = ' . $engine);
126
        }
127
        
128
        return $response;
129
    }
130
    
131
    /**
132
     * Insert records
133
     * @throws CliException
134
     */
135
    public function insertAction(?string $models = null): array
136
    {
137
        $response = [
138
            'saved' => 0,
139
            'error' => [],
140
            'message' => [],
141
        ];
142
        
143
        $models = (!empty($models)) ? explode(',', $models) : null;
144
        
145
        foreach ($this->insert as $modelName => $insert) {
146
            if (is_array($models) && !in_array($modelName, $models, true)) {
147
                continue;
148
            }
149
            
150
            foreach ($insert as $key => $row) {
151
                assert(is_string($modelName) && class_exists($modelName));
152
                $entity = new $modelName();
153
                assert($entity instanceof Model);
154
                
155
                $assign = isset($row[0]) && method_exists($entity, 'columnMap')
156
                    ? array_combine($entity->columnMap(), $row)
157
                    : $row;
158
                
159
                if (!$assign) {
160
                    throw new CliException('Can\'t assign row #' . $key . ' for model `' . $modelName . '`.');
161
                }
162
                else {
163
                    $entity->assign($assign);
164
                }
165
                
166
                // Automagically fill passwords
167
                if (property_exists($entity, 'password')) {
168
                    if (empty($row['password']) && property_exists($entity, 'email')) {
169
                        if (method_exists($entity, 'hash')) {
170
                            $entity->assign(['password' => $entity->hash($row['email'])]);
171
                        }
172
                    }
173
                }
174
                
175
                try {
176
                    if (!$entity->save()) {
177
                        $response['error'][$modelName][] = $entity->toArray();
178
                        
179
                        foreach ($entity->getMessages() as $message) {
180
                            $response['message'][$modelName][] = $message;
181
                        }
182
                    }
183
                    else {
184
                        $response['saved']++;
185
                    }
186
                } catch (\Exception $e) {
187
                    $response['error'][$modelName][] = $entity->toArray();
188
                    $response['message'][$modelName][] = $e->getMessage();
189
                }
190
            }
191
        }
192
        
193
        return $response;
194
    }
195
    
196
    /**
197
     * The optimizeAction method is responsible for optimizing database tables specified in the
198
     * $this->optimize array. Database table optimization is a maintenance task aimed at improving
199
     * the performance and storage efficiency of database tables. This method iterates through a
200
     * list of table names and executes an SQL OPTIMIZE TABLE command for each of them.
201
     *
202
     * Use Case:
203
     * This method is typically used in the context of database maintenance and optimization routines.
204
     * It allows you to automate the process of optimizing database tables, which can help reclaim storage
205
     * space and improve query performance by reorganizing table data and indexes.
206
     */
207
    public function optimizeAction(): array
208
    {
209
        $response = [];
210
        
211
        foreach ($this->optimize as $table) {
212
            $response [] = $this->db->query('OPTIMIZE TABLE ' . $this->db->escapeIdentifier($table))->fetchAll();
213
        }
214
        
215
        return $response;
216
    }
217
    
218
    /**
219
     * This method is responsible for analyzing database tables specified in the $this->analyse array.
220
     * Table analysis is an essential database maintenance task that helps optimize the performance
221
     * of database queries. Analyzing a table refreshes statistics and metadata about the table's
222
     * structure, which can lead to improved query execution plans.
223
     *
224
     * Use Case:
225
     * This method can be used in the context of database optimization and maintenance scripts.
226
     * It allows you to automate the process of analyzing database tables, ensuring that the database's
227
     * query optimizer has up-to-date statistics to make informed decisions about query execution plans.
228
     */
229
    public function analyzeAction(): array
230
    {
231
        $response = [];
232
        
233
        foreach ($this->analyze as $table) {
234
            $response [] = $this->db->query('ANALYZE TABLE ' . $this->db->escapeIdentifier($table))->fetchAll();
235
        }
236
        
237
        return $response;
238
    }
239
    
240
    /**
241
     * @throws Exception
242
     */
243
    public function addModelsPermissions(?array $tables = null): void
244
    {
245
        $permissions = [];
246
        $tables ??= $this->insert;
247
        foreach ($tables as $model => $entity) {
248
            $permissions[$model] = ['*'];
249
        }
250
        
251
        $this->config->merge([
252
            'permissions' => [
253
                'roles' => [
254
                    'cli' => [
255
                        'models' => $permissions,
256
                    ],
257
                ],
258
            ],
259
        ], true);
260
        $this->acl->setOption('permissions', $this->config->pathToArray('permissions') ?? []);
261
    }
262
}
263