Test Failed
Push — master ( b3c371...4e1273 )
by Julien
06:25
created

Table   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Test Coverage

Coverage 5.21%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 76
c 2
b 0
f 0
dl 0
loc 158
ccs 5
cts 96
cp 0.0521
rs 10
wmc 14

6 Methods

Rating   Name   Duplication   Size   Complexity  
A afterSave() 0 4 1
A initialize() 0 7 1
A validation() 0 5 1
A createOrUpdateRealTable() 0 51 2
A syncColumnsAndIndexesWithRealTable() 0 41 3
A syncIndexes() 0 30 6
1
<?php
2
/**
3
 * This file is part of the Zemit Framework.
4
 *
5
 * (c) Zemit Team <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE.txt
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types=1);
12
13
namespace Zemit\Models;
14
15
use Phalcon\Db\Adapter\Pdo\AbstractPdo;
16
use Phalcon\Db\Index;
17
use Zemit\Models\Abstracts\TableAbstract;
18
use Zemit\Models\Interfaces\TableInterface;
19
use Zemit\Db\Column as DbColumn;
0 ignored issues
show
Bug introduced by
The type Zemit\Db\Column 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...
20
21
/**
22
 * Class Table
23
 *
24
 * This class represents a Table object.
25
 * It extends the TableAbstract class and implements the TableInterface.
26
 */
27
class Table extends TableAbstract implements TableInterface
28
{
29 2
    public function initialize(): void
30
    {
31 2
        parent::initialize();
32 2
        $this->addDefaultRelationships();
33
        
34 2
        $this->hasMany(['id', 'workspaceId'], Record::class, ['tableId', 'workspaceId'], ['alias' => 'RecordList']);
35 2
        $this->hasMany(['id', 'workspaceId'], Column::class, ['tableId', 'workspaceId'], ['alias' => 'ColumnList']);
36
    }
37
    
38
    public function validation(): bool
39
    {
40
        $validator = $this->genericValidation();
41
        $this->addDefaultValidations($validator);
42
        return $this->validate($validator);
43
    }
44
    
45
    public function afterSave()
46
    {
47
        // Create or update the actual table after saving a Table entity
48
        $this->createOrUpdateRealTable();
49
    }
50
    
51
    public function createOrUpdateRealTable()
52
    {
53
        $db = $this->getDI()->get('dbd');
54
        assert($db instanceof AbstractPdo);
55
        
56
        $tableUuid = self::findFirst('id = ' . (int)$this->getId())->getUuid();
0 ignored issues
show
Bug introduced by
'id = ' . (int)$this->getId() of type string is incompatible with the type array expected by parameter $parameters of Phalcon\Mvc\ModelInterface::findFirst(). ( Ignorable by Annotation )

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

56
        $tableUuid = self::findFirst(/** @scrutinizer ignore-type */ 'id = ' . (int)$this->getId())->getUuid();
Loading history...
57
        
58
        // Check if the table already exists
59
        $existingTable = $db->tableExists($tableUuid);
60
        
61
        if (!$existingTable) {
62
            // Create a new table if it doesn't exist
63
            $db->createTable($tableUuid, '', [
64
                'columns' => [
65
                    new DbColumn(
66
                        'id',
67
                        [
68
                            'type' => DbColumn::TYPE_INTEGER,
69
                            'size' => 11,
70
                            'unsigned' => true,
71
                            'notNull' => true,
72
                            'autoIncrement' => true,
73
                            'unique' => true,
74
                            'primary' => true,
75
                        ]
76
                    ),
77
                    new DbColumn(
78
                        'uuid',
79
                        [
80
                            'type' => DbColumn::TYPE_CHAR,
81
                            'size' => 36,
82
                            'notNull' => true,
83
                            'unique' => true,
84
                        ]
85
                    ),
86
                    new DbColumn(
87
                        'deleted',
88
                        [
89
                            'type' => DbColumn::TYPE_TINYINTEGER,
90
                            'size' => 1,
91
                            'notNull' => true,
92
                            'unique' => true,
93
                            'default' => 0,
94
                        ]
95
                    ),
96
                ],
97
            ]);
98
        }
99
        
100
        // Sync columns and indexes with the real table
101
        $this->syncColumnsAndIndexesWithRealTable();
102
    }
103
    
104
    public function syncColumnsAndIndexesWithRealTable()
105
    {
106
        $db = $this->getDI()->get('dbd');
107
        $tableUuid = self::findFirst('id = ' . (int)$this->getId())->getUuid();
0 ignored issues
show
Bug introduced by
'id = ' . (int)$this->getId() of type string is incompatible with the type array expected by parameter $parameters of Phalcon\Mvc\ModelInterface::findFirst(). ( Ignorable by Annotation )

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

107
        $tableUuid = self::findFirst(/** @scrutinizer ignore-type */ 'id = ' . (int)$this->getId())->getUuid();
Loading history...
108
        
109
        // Retrieve all columns associated with this table
110
        $columns = Column::find('tableId = ' . (int)$this->getId());
111
        
112
        // Fetch existing columns and indexes in one query
113
        $existingColumns = $db->describeColumns($tableUuid);
114
        $existingIndexes = $db->describeIndexes($tableUuid);
115
        
116
        $existingColumnNames = array_map(fn($col) => $col->getName(), $existingColumns);
117
        $existingIndexNames = array_keys($existingIndexes);
0 ignored issues
show
Unused Code introduced by
The assignment to $existingIndexNames is dead and can be removed.
Loading history...
118
        
119
        // Sync Columns
120
        foreach ($columns as $column) {
121
            assert($column instanceof Column);
122
            
123
            $columnUuid = $column->getUuid();
124
            
125
            // Define the column structure based on its type
126
            $defaultDefinitions = $column->getColumnDefinitions();
127
            $columnDefinition = new DbColumn(
128
                $columnUuid,
129
                [
130
                    'type' => $defaultDefinitions['type'],
131
                    'size' => $defaultDefinitions['size'],
132
                    'notNull' => true,
133
                    'comment' => $column->getName()
134
                ]
135
            );
136
            
137
            // Check if the column already exists
138
            if (in_array($columnUuid, $existingColumnNames)) {
139
                // Modify existing column if it has changed
140
                $db->modifyColumn($tableUuid, '', $columnDefinition);
141
            }
142
            else {
143
                // Add the new column
144
                $db->addColumn($tableUuid, '', $columnDefinition);
145
            }
146
        }
147
        
148
        // Sync Indexes
149
//        $this->syncIndexes($tableUuid, $existingIndexes);
150
    }
151
    
152
    /**
153
     * Sync indexes (primary key, unique, and standard indexes) with the real table.
154
     */
155
    public function syncIndexes(string $tableUuid, array $existingIndexes)
156
    {
157
        $db = $this->getDI()->get('dbd');
158
        $columns = Column::find('tableId = ' . (int)$this->getId());
159
        
160
        $indexDefinitions = [];
161
        
162
        foreach ($columns as $column) {
163
            // Check for index settings (you can modify this according to your logic)
164
            if ($column->isUnique()) {
165
                // Add a unique index
166
                $indexDefinitions[$column->getUuid()] = new Index(
167
                    $column->getUuid() . '_unique',
168
                    [$column->getUuid()],
169
                    'UNIQUE'
170
                );
171
            }
172
            else if ($column->isIndexed()) {
173
                // Add a standard index
174
                $indexDefinitions[$column->getUuid()] = new Index(
175
                    $column->getUuid() . '_index',
176
                    [$column->getUuid()]
177
                );
178
            }
179
        }
180
        
181
        // Sync new and modified indexes
182
        foreach ($indexDefinitions as $indexName => $indexDefinition) {
183
            if (!array_key_exists($indexName, $existingIndexes)) {
184
                $db->addIndex($tableUuid, $tableUuid, $indexDefinition);
185
            }
186
        }
187
    }
188
}
189