DatabaseTrait::insertAction()   C
last analyzed

Complexity

Conditions 17
Paths 14

Size

Total Lines 59
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 306

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 17
eloc 34
c 1
b 0
f 0
nc 14
nop 1
dl 0
loc 59
ccs 0
cts 33
cp 0
crap 306
rs 5.2166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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)
0 ignored issues
show
Bug introduced by
Are you sure the usage of $entity->columnMap() targeting Phalcon\Mvc\Model::__call() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
Bug introduced by
$entity->columnMap() of type null is incompatible with the type array expected by parameter $keys of array_combine(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

160
                    ? array_combine(/** @scrutinizer ignore-type */ $entity->columnMap(), $row)
Loading history...
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'])]);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $entity->hash($row['email']) targeting Phalcon\Mvc\Model::__call() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
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