Passed
Push — master ( 7e7a3a...c54c1a )
by Paul
12:25 queued 05:17
created

SqlSchema   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 285
Duplicated Lines 0 %

Test Coverage

Coverage 8.73%

Importance

Changes 2
Bugs 1 Features 1
Metric Value
wmc 36
eloc 107
c 2
b 1
f 1
dl 0
loc 285
ccs 11
cts 126
cp 0.0873
rs 9.52

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A createAssignedTermsTable() 0 13 2
A isInnodb() 0 10 2
A addAssignedPostsTableConstraints() 0 20 4
A addAssignedUsersTableConstraints() 0 20 4
A createAssignedPostsTable() 0 14 2
A addReviewsTableConstraints() 0 11 3
A createTables() 0 6 1
A tableExists() 0 9 2
A createRatingTable() 0 24 2
A table() 0 6 2
A prefix() 0 3 1
A addAssignedTermsTableConstraints() 0 20 4
A createAssignedUsersTable() 0 13 2
A addTableConstraints() 0 7 2
A tableConstraintExists() 0 10 2
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Database;
4
5
use GeminiLabs\SiteReviews\Database;
6
use GeminiLabs\SiteReviews\Helpers\Str;
7
8
class SqlSchema
9
{
10
    protected $constraints;
11
    protected $db;
12
    protected $tables;
13
14 14
    public function __construct()
15
    {
16 14
        require_once ABSPATH.'wp-admin/includes/upgrade.php';
17 14
        global $wpdb;
18 14
        $this->db = $wpdb;
19 14
    }
20
21
    /**
22
     * @return void
23
     */
24
    public function addAssignedPostsTableConstraints()
25
    {
26
        if (!$this->tableConstraintExists($ratingIdConstraint = $this->prefix('assigned_posts').'_rating_id_foreign')) {
27
            glsr(Database::class)->dbQuery(glsr(Query::class)->sql("
28
                ALTER TABLE {$this->table('assigned_posts')}
29
                ADD CONSTRAINT {$ratingIdConstraint}
30
                FOREIGN KEY (rating_id)
31
                REFERENCES {$this->table('ratings')} (ID)
32
                ON DELETE CASCADE
33
            "));
34
        }
35
        if (!$this->isInnodb('posts')) {
36
            return;
37
        }
38
        if (!$this->tableConstraintExists($postIdConstraint = $this->prefix('assigned_posts').'_post_id_foreign')) {
39
            glsr(Database::class)->dbQuery(glsr(Query::class)->sql("
40
                ALTER TABLE {$this->table('assigned_posts')}
41
                ADD CONSTRAINT {$postIdConstraint}
42
                FOREIGN KEY (post_id)
43
                REFERENCES {$this->db->posts} (ID)
44
                ON DELETE CASCADE
45
            "));
46
        }
47
    }
48
49
    /**
50
     * @return void
51
     */
52
    public function addAssignedTermsTableConstraints()
53
    {
54
        if (!$this->tableConstraintExists($ratingIdConstraint = $this->prefix('assigned_terms').'_rating_id_foreign')) {
55
            glsr(Database::class)->dbQuery(glsr(Query::class)->sql("
56
                ALTER TABLE {$this->table('assigned_terms')}
57
                ADD CONSTRAINT {$ratingIdConstraint}
58
                FOREIGN KEY (rating_id)
59
                REFERENCES {$this->table('ratings')} (ID)
60
                ON DELETE CASCADE
61
            "));
62
        }
63
        if (!$this->isInnodb('terms')) {
64
            return;
65
        }
66
        if (!$this->tableConstraintExists($termIdConstraint = $this->prefix('assigned_terms').'_term_id_foreign')) {
67
            glsr(Database::class)->dbQuery(glsr(Query::class)->sql("
68
                ALTER TABLE {$this->table('assigned_terms')}
69
                ADD CONSTRAINT {$termIdConstraint}
70
                FOREIGN KEY (term_id)
71
                REFERENCES {$this->db->terms} (term_id)
72
                ON DELETE CASCADE
73
            "));
74
        }
75
    }
76
77
    /**
78
     * @return void
79
     */
80
    public function addAssignedUsersTableConstraints()
81
    {
82
        if (!$this->tableConstraintExists($ratingIdConstraint = $this->prefix('assigned_users').'_rating_id_foreign')) {
83
            glsr(Database::class)->dbQuery(glsr(Query::class)->sql("
84
                ALTER TABLE {$this->table('assigned_users')}
85
                ADD CONSTRAINT {$ratingIdConstraint}
86
                FOREIGN KEY (rating_id)
87
                REFERENCES {$this->table('ratings')} (ID)
88
                ON DELETE CASCADE
89
            "));
90
        }
91
        if (!$this->isInnodb('users')) {
92
            return;
93
        }
94
        if (!$this->tableConstraintExists($userIdConstraint = $this->prefix('assigned_users').'_user_id_foreign')) {
95
            glsr(Database::class)->dbQuery(glsr(Query::class)->sql("
96
                ALTER TABLE {$this->table('assigned_users')}
97
                ADD CONSTRAINT {$userIdConstraint}
98
                FOREIGN KEY (user_id)
99
                REFERENCES {$this->db->users} (ID)
100
                ON DELETE CASCADE
101
            "));
102
        }
103
    }
104
105
    /**
106
     * @return void
107
     */
108
    public function addReviewsTableConstraints()
109
    {
110
        if (!$this->isInnodb('posts')) {
111
            return;
112
        }
113
        if (!$this->tableConstraintExists($reviewIdConstraint = $this->prefix('assigned_posts').'_review_id_foreign')) {
114
            glsr(Database::class)->dbQuery(glsr(Query::class)->sql("
115
                ALTER TABLE {$this->table('ratings')}
116
                ADD CONSTRAINT {$reviewIdConstraint}
117
                FOREIGN KEY (review_id)
118
                REFERENCES {$this->db->posts} (ID)
119
                ON DELETE CASCADE
120
            "));
121
        }
122
    }
123
124
    /**
125
     * @return void
126
     */
127
    public function addTableConstraints()
128
    {
129
        if (!defined('GLSR_UNIT_TESTS')) {
130
            $this->addAssignedPostsTableConstraints();
131
            $this->addAssignedTermsTableConstraints();
132
            $this->addAssignedUsersTableConstraints();
133
            $this->addReviewsTableConstraints();
134
        }
135
    }
136
137
    /**
138
     * @return bool
139
     */
140
    public function createAssignedPostsTable()
141
    {
142
        if ($this->tableExists('assigned_posts')) {
143
            return false;
144
        }
145
        dbDelta(glsr(Query::class)->sql("
146
            CREATE TABLE {$this->table('assigned_posts')} (
147
                rating_id bigint(20) unsigned NOT NULL,
148
                post_id bigint(20) unsigned NOT NULL,
149
                is_published tinyint(1) NOT NULL DEFAULT '1',
150
                UNIQUE KEY {$this->prefix('assigned_posts')}_rating_id_post_id_unique (rating_id,post_id)
151
            ) {$this->db->get_charset_collate()};
152
        "));
153
        return true;
154
    }
155
156
    /**
157
     * @return bool
158
     */
159
    public function createAssignedTermsTable()
160
    {
161
        if ($this->tableExists('assigned_terms')) {
162
            return false;
163
        }
164
        dbDelta(glsr(Query::class)->sql("
165
            CREATE TABLE {$this->table('assigned_terms')} (
166
                rating_id bigint(20) unsigned NOT NULL,
167
                term_id bigint(20) unsigned NOT NULL,
168
                UNIQUE KEY {$this->prefix('assigned_terms')}_rating_id_term_id_unique (rating_id,term_id)
169
            ) {$this->db->get_charset_collate()};
170
        "));
171
        return true;
172
    }
173
174
    /**
175
     * @return bool
176
     */
177
    public function createAssignedUsersTable()
178
    {
179
        if ($this->tableExists('assigned_users')) {
180
            return false;
181
        }
182
        dbDelta(glsr(Query::class)->sql("
183
            CREATE TABLE {$this->table('assigned_users')} (
184
                rating_id bigint(20) unsigned NOT NULL,
185
                user_id bigint(20) unsigned NOT NULL,
186
                UNIQUE KEY {$this->prefix('assigned_users')}_rating_id_user_id_unique (rating_id,user_id)
187
            ) {$this->db->get_charset_collate()};
188
        "));
189
        return true;
190
    }
191
192
    /**
193
     * @return bool
194
     */
195
    public function createRatingTable()
196
    {
197
        if ($this->tableExists('ratings')) {
198
            return false;
199
        }
200
        dbDelta(glsr(Query::class)->sql("
201
            CREATE TABLE {$this->table('ratings')} (
202
                ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
203
                review_id bigint(20) unsigned NOT NULL,
204
                rating int(11) NOT NULL DEFAULT '0',
205
                type varchar(20) DEFAULT 'local',
206
                is_approved tinyint(1) NOT NULL DEFAULT '0',
207
                is_pinned tinyint(1) NOT NULL DEFAULT '0',
208
                name varchar(250) DEFAULT NULL,
209
                email varchar(100) DEFAULT NULL,
210
                avatar varchar(200) DEFAULT NULL,
211
                ip_address varchar(100) DEFAULT NULL,
212
                url varchar(250) DEFAULT NULL,
213
                PRIMARY KEY (ID),
214
                UNIQUE KEY {$this->prefix('ratings')}_review_id_unique (review_id),
215
                KEY {$this->prefix('ratings')}_rating_type_is_pinned_index (rating,type,is_pinned)
216
            ) {$this->db->get_charset_collate()};
217
        "));
218
        return true;
219
    }
220
221
    /**
222
     * @return void
223
     */
224
    public function createTables()
225
    {
226
        $this->createAssignedPostsTable();
227
        $this->createAssignedTermsTable();
228
        $this->createAssignedUsersTable();
229
        $this->createRatingTable();
230
    }
231
232
    /**
233
     * @return bool
234
     */
235
    public function isInnodb($table)
236
    {
237
        $tableStatus = $this->db->get_row("
238
            SHOW TABLE STATUS WHERE Name = '{$this->table($table)}'
239
        ");
240
        if (!isset($tableStatus->Engine)) {
241
            glsr_log()->warning(sprintf('The %s database table does not exist.', $this->table($table)));
242
            return false;
243
        }
244
        return 'innodb' === strtolower($tableStatus->Engine);
245
    }
246
247
    /**
248
     * @return string
249
     */
250 14
    public function prefix($table)
251
    {
252 14
        return Str::prefix($table, glsr()->prefix);
253
    }
254
255
    /**
256
     * @return string
257
     */
258 14
    public function table($table)
259
    {
260 14
        if (Str::endsWith(['ratings', 'assigned_posts', 'assigned_terms', 'assigned_users'], $table)) {
261 14
            $table = $this->prefix($table);
262
        }
263 14
        return $this->db->prefix.$table;
264
    }
265
266
    /**
267
     * @return bool
268
     */
269
    public function tableExists($table)
270
    {
271
        if (!isset($this->tables)) {
272
            $prefix = $this->db->prefix.glsr()->prefix;
273
            $this->tables = $this->db->get_col(
274
                $this->db->prepare("SHOW TABLES LIKE %s", $this->db->esc_like($prefix).'%')
275
            );
276
        }
277
        return in_array($this->table($table), $this->tables);
278
    }
279
280
    /**
281
     * @return bool
282
     */
283
    public function tableConstraintExists($constraint)
284
    {
285
        if (!isset($this->constraints)) {
286
            $this->constraints = $this->db->get_col("
287
                SELECT CONSTRAINT_NAME
288
                FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
289
                WHERE CONSTRAINT_SCHEMA = '{$this->db->dbname}'
290
            ");
291
        }
292
        return in_array($constraint, $this->constraints);
293
    }
294
}
295