Passed
Pull Request — master (#7124)
by
unknown
09:48
created

Version20251130011600   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 87
dl 0
loc 172
rs 10
c 1
b 0
f 0
wmc 17

5 Methods

Rating   Name   Duplication   Size   Complexity  
B down() 0 58 9
A removeNewResourceTypes() 0 4 1
A declareNewResourceTypes() 0 27 1
A getDescription() 0 3 1
A up() 0 56 5
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
8
9
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
10
use Doctrine\DBAL\Schema\Schema;
11
12
final class Version20251130011600 extends AbstractMigrationChamilo
13
{
14
    public function getDescription(): string
15
    {
16
        return 'Add resource_node_id to attempt_file/attempt_feedback and declare new resource types for them.';
17
    }
18
19
    public function up(Schema $schema): void
20
    {
21
        // --- attempt_file ---
22
        if ($schema->hasTable('attempt_file')) {
23
            $table = $schema->getTable('attempt_file');
24
25
            if (!$table->hasColumn('resource_node_id')) {
26
                // Add nullable FK column. We place it after asset_id to keep legacy column nearby.
27
                $this->addSql(
28
                    'ALTER TABLE attempt_file
29
                     ADD resource_node_id INT DEFAULT NULL AFTER asset_id'
30
                );
31
32
                // Index for FK performance.
33
                $this->addSql(
34
                    'CREATE INDEX IDX_ATTEMPT_FILE_RESOURCE_NODE
35
                     ON attempt_file (resource_node_id)'
36
                );
37
38
                // FK to resource_node.id.
39
                $this->addSql(
40
                    'ALTER TABLE attempt_file
41
                     ADD CONSTRAINT FK_ATTEMPT_FILE_RESOURCE_NODE
42
                     FOREIGN KEY (resource_node_id)
43
                     REFERENCES resource_node (id)
44
                     ON DELETE CASCADE'
45
                );
46
            }
47
        }
48
49
        // --- attempt_feedback ---
50
        if ($schema->hasTable('attempt_feedback')) {
51
            $table = $schema->getTable('attempt_feedback');
52
53
            if (!$table->hasColumn('resource_node_id')) {
54
                $this->addSql(
55
                    'ALTER TABLE attempt_feedback
56
                     ADD resource_node_id INT DEFAULT NULL AFTER asset_id'
57
                );
58
59
                $this->addSql(
60
                    'CREATE INDEX IDX_ATTEMPT_FEEDBACK_RESOURCE_NODE
61
                     ON attempt_feedback (resource_node_id)'
62
                );
63
64
                $this->addSql(
65
                    'ALTER TABLE attempt_feedback
66
                     ADD CONSTRAINT FK_ATTEMPT_FEEDBACK_RESOURCE_NODE
67
                     FOREIGN KEY (resource_node_id)
68
                     REFERENCES resource_node (id)
69
                     ON DELETE CASCADE'
70
                );
71
            }
72
        }
73
74
        $this->declareNewResourceTypes();
75
    }
76
77
    public function down(Schema $schema): void
78
    {
79
        // --- attempt_file ---
80
        if ($schema->hasTable('attempt_file')) {
81
            $table = $schema->getTable('attempt_file');
82
83
            if ($table->hasColumn('resource_node_id')) {
84
                // Drop FK if it exists.
85
                if ($table->hasForeignKey('FK_ATTEMPT_FILE_RESOURCE_NODE')) {
86
                    $this->addSql(
87
                        'ALTER TABLE attempt_file
88
                         DROP FOREIGN KEY FK_ATTEMPT_FILE_RESOURCE_NODE'
89
                    );
90
                }
91
92
                // Drop index if it exists.
93
                if ($table->hasIndex('IDX_ATTEMPT_FILE_RESOURCE_NODE')) {
94
                    $this->addSql(
95
                        'DROP INDEX IDX_ATTEMPT_FILE_RESOURCE_NODE
96
                         ON attempt_file'
97
                    );
98
                }
99
100
                // Drop the column.
101
                $this->addSql(
102
                    'ALTER TABLE attempt_file
103
                     DROP COLUMN resource_node_id'
104
                );
105
            }
106
        }
107
108
        // --- attempt_feedback ---
109
        if ($schema->hasTable('attempt_feedback')) {
110
            $table = $schema->getTable('attempt_feedback');
111
112
            if ($table->hasColumn('resource_node_id')) {
113
                if ($table->hasForeignKey('FK_ATTEMPT_FEEDBACK_RESOURCE_NODE')) {
114
                    $this->addSql(
115
                        'ALTER TABLE attempt_feedback
116
                         DROP FOREIGN KEY FK_ATTEMPT_FEEDBACK_RESOURCE_NODE'
117
                    );
118
                }
119
120
                if ($table->hasIndex('IDX_ATTEMPT_FEEDBACK_RESOURCE_NODE')) {
121
                    $this->addSql(
122
                        'DROP INDEX IDX_ATTEMPT_FEEDBACK_RESOURCE_NODE
123
                         ON attempt_feedback'
124
                    );
125
                }
126
127
                $this->addSql(
128
                    'ALTER TABLE attempt_feedback
129
                     DROP COLUMN resource_node_id'
130
                );
131
            }
132
        }
133
134
        $this->removeNewResourceTypes();
135
    }
136
137
    /**
138
     * Declare new resource types for attempt_file and attempt_feedback.
139
     *
140
     * They are linked to the "quiz" tool so that ResourceNode::getResourceType()->getTool()
141
     * is always initialized correctly.
142
     */
143
    private function declareNewResourceTypes(): void
144
    {
145
        // Create resource_type "attempt_file" if it does not exist yet.
146
        $this->addSql(
147
            "INSERT INTO resource_type (title, tool_id, created_at, updated_at)
148
         SELECT 'attempt_file', t.id, NOW(), NOW()
149
         FROM tool t
150
         WHERE t.title = 'quiz'
151
           AND NOT EXISTS (
152
               SELECT 1 FROM resource_type WHERE title = 'attempt_file'
153
           )"
154
        );
155
156
        // Create resource_type "attempt_feedback" if it does not exist yet.
157
        $this->addSql(
158
            "INSERT INTO resource_type (title, tool_id, created_at, updated_at)
159
         SELECT 'attempt_feedback', t.id, NOW(), NOW()
160
         FROM tool t
161
         WHERE t.title = 'quiz'
162
           AND NOT EXISTS (
163
               SELECT 1 FROM resource_type WHERE title = 'attempt_feedback'
164
           )"
165
        );
166
167
        // Safety net: if rows already exist but have tool_id = NULL, link them to quiz as well.
168
        $this->addSql(
169
            "UPDATE resource_type rt
170
         JOIN tool t ON t.title = 'quiz'
171
         SET rt.tool_id = t.id
172
         WHERE rt.title IN ('attempt_file', 'attempt_feedback')
173
           AND (rt.tool_id IS NULL OR rt.tool_id = 0)"
174
        );
175
    }
176
177
    /**
178
     * Remove the newly declared resource types (used in down()).
179
     */
180
    private function removeNewResourceTypes(): void
181
    {
182
        $this->addSql(
183
            "DELETE FROM resource_type
184
             WHERE title IN ('attempt_file', 'attempt_feedback')"
185
        );
186
    }
187
}
188