Passed
Push — master ( 2da942...d633d7 )
by Paul
15:03 queued 05:40
created

MigrateReviews::parseRatings()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 25
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 19
dl 0
loc 25
ccs 0
cts 20
cp 0
rs 9.3222
c 1
b 0
f 0
cc 5
nc 8
nop 1
crap 30
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules\Migrations\Migrate_5_0_0;
4
5
use GeminiLabs\SiteReviews\Database;
6
use GeminiLabs\SiteReviews\Database\Query;
7
use GeminiLabs\SiteReviews\Defaults\RatingDefaults;
8
use GeminiLabs\SiteReviews\Helpers\Arr;
9
use GeminiLabs\SiteReviews\Install;
10
11
class MigrateReviews
12
{
13
    public $db;
14
    public $limit;
15
16 7
    public function __construct()
17
    {
18 7
        global $wpdb;
19 7
        $this->db = $wpdb;
20 7
        $this->limit = 250;
21 7
    }
22
23
    /**
24
     * @return void
25
     */
26 7
    public function run()
27
    {
28 7
        $this->createDatabaseTable();
29 7
        $this->migrateRatings();
30 7
        $this->migrateAssignedTo();
31 7
        $this->migrateTerms();
32 7
        $this->migrateCustom();
33 7
    }
34
35
    /**
36
     * @return void
37
     */
38 7
    protected function createDatabaseTable()
39
    {
40 7
        glsr(Install::class)->run();
41 7
    }
42
43
    /**
44
     * @return array
45
     */
46
    protected function filterCustomValues(array $values)
47
    {
48
        $filtered = [];
49
        foreach ($values as $postId => $meta) {
50
            $custom = Arr::consolidate(maybe_unserialize(Arr::get($meta, '_custom')));
51
            if (!empty($custom)) {
52
                $custom = Arr::prefixKeys($custom, '_custom_');
53
                $filtered[$postId] = array_diff_key($custom, $meta);
54
            }
55
        }
56
        return array_filter($filtered);
57
    }
58
59
    /**
60
     * @return array
61
     */
62
    protected function groupCustomValues(array $values)
63
    {
64
        $grouped = [];
65
        foreach ($values as $result) {
66
            if (empty($grouped[$result->post_id])) {
67
                $grouped[$result->post_id] = [];
68
            }
69
            $grouped[$result->post_id][$result->meta_key] = $result->meta_value;
70
        }
71
        return $grouped;
72
    }
73
74
    /**
75
     * @return void
76
     */
77 7
    protected function migrateAssignedTo()
78
    {
79 7
        glsr(Database::class)->beginTransaction('assigned_posts');
80 7
        $offset = 0;
81 7
        $table = glsr(Query::class)->table('ratings');
82 7
        while (true) {
83 7
            $sql = glsr(Query::class)->sql($this->db->prepare("
84
                SELECT r.ID AS rating_id, m.meta_value AS post_id, CAST(IF(p.post_status = 'publish', 1, 0) AS UNSIGNED) AS is_published
85 7
                FROM {$table} AS r
86 7
                INNER JOIN {$this->db->posts} AS p ON r.review_id = p.ID
87 7
                INNER JOIN {$this->db->postmeta} AS m ON r.review_id = m.post_id
88
                WHERE m.meta_key = '_assigned_to' AND m.meta_value > 0 
89
                ORDER BY r.ID
90
                LIMIT %d, %d
91 7
            ", $offset, $this->limit), 'migrate-assigned-posts');
92 7
            $results = glsr(Database::class)->dbGetResults($sql, ARRAY_A);
93 7
            if (empty($results)) {
94 7
                break;
95
            }
96
            glsr(Database::class)->insertBulk('assigned_posts', $results, [
97
                'rating_id',
98
                'post_id',
99
                'is_published',
100
            ]);
101
            $offset += $this->limit;
102
        }
103 7
        glsr(Database::class)->finishTransaction('assigned_posts');
104 7
    }
105
106
    /**
107
     * @return void
108
     */
109 7
    protected function migrateCustom()
110
    {
111 7
        glsr(Database::class)->beginTransaction('postmeta');
112 7
        $offset = 0;
113 7
        while (true) {
114 7
            $sql = glsr(Query::class)->sql($this->db->prepare("
115
                SELECT m1.post_id, m1.meta_key, m1.meta_value
116 7
                FROM {$this->db->postmeta} AS m1
117 7
                INNER JOIN {$this->db->posts} AS p ON m1.post_id = p.ID
118 7
                LEFT JOIN {$this->db->postmeta} AS m2 ON (m1.post_id = m2.post_id AND m1.meta_key = m2.meta_key AND m1.meta_id < m2.meta_id)
119
                WHERE m2.meta_id IS NULL
120
                AND p.post_type = '%s'
121
                AND m1.meta_value != '%s'
122
                AND m1.meta_key LIKE '_custom%%'
123
                ORDER BY m1.meta_id
124
                LIMIT %d, %d
125 7
            ", glsr()->post_type, serialize([]), $offset, $this->limit), 'migrate-custom');
126 7
            $results = glsr(Database::class)->dbGetResults($sql, OBJECT);
127 7
            if (empty($results)) {
128 7
                break;
129
            }
130
            if ($values = $this->prepareCustomValuesForInsert($results)) {
131
                glsr(Database::class)->insertBulk('postmeta', $values, [
132
                    'post_id',
133
                    'meta_key',
134
                    'meta_value',
135
                ]);
136
            }
137
            $offset += $this->limit;
138
        }
139 7
        glsr(Database::class)->finishTransaction('postmeta');
140 7
    }
141
142
    /**
143
     * @return void
144
     */
145 7
    protected function migrateRatings()
146
    {
147 7
        glsr(Database::class)->beginTransaction('ratings');
148 7
        $offset = 0;
149 7
        $table = glsr(Query::class)->table('ratings');
150 7
        while (true) {
151 7
            $sql = glsr(Query::class)->sql($this->db->prepare("
152
                SELECT p.ID, m.meta_key AS mk, m.meta_value AS mv, CAST(IF(p.post_status = 'publish', 1, 0) AS UNSIGNED) AS is_approved
153 7
                FROM {$this->db->posts} AS p
154 7
                LEFT JOIN {$this->db->postmeta} AS m ON p.ID = m.post_id
155
                WHERE p.ID IN (
156
                    SELECT * FROM (
157
                        SELECT ID
158 7
                        FROM {$this->db->posts}
159
                        WHERE post_type = '%s'
160
                        ORDER BY ID
161
                        LIMIT %d, %d
162
                    ) AS post_ids
163
                )
164
                AND NOT EXISTS (
165
                    SELECT r.review_id
166 7
                    FROM {$table} AS r
167
                    WHERE r.review_id = p.ID
168
                )
169 7
            ", glsr()->post_type, $offset, $this->limit), 'migrate-ratings');
170 7
            $results = glsr(Database::class)->dbGetResults($sql, OBJECT);
171 7
            if (empty($results)) {
172 7
                break;
173
            }
174
            $values = $this->parseRatings($results);
175
            $fields = array_keys(glsr(RatingDefaults::class)->defaults());
176
            glsr(Database::class)->insertBulk('ratings', $values, $fields);
177
            $offset += $this->limit;
178
        }
179 7
        glsr(Database::class)->finishTransaction('ratings');
180 7
    }
181
182
    /**
183
     * @return void
184
     */
185 7
    protected function migrateTerms()
186
    {
187 7
        glsr(Database::class)->beginTransaction('assigned_terms');
188 7
        $offset = 0;
189 7
        $table = glsr(Query::class)->table('ratings');
190 7
        while (true) {
191 7
            $sql = glsr(Query::class)->sql($this->db->prepare("
192
                SELECT r.ID AS rating_id, tt.term_id AS term_id
193 7
                FROM {$table} AS r
194 7
                INNER JOIN {$this->db->term_relationships} AS tr ON r.review_id = tr.object_id
195 7
                INNER JOIN {$this->db->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
196
                ORDER BY r.ID
197
                LIMIT %d, %d
198 7
            ", $offset, $this->limit), 'migrate-assigned-terms');
199 7
            $results = glsr(Database::class)->dbGetResults($sql, ARRAY_A);
200 7
            if (empty($results)) {
201 7
                break;
202
            }
203
            glsr(Database::class)->insertBulk('assigned_terms', $results, [
204
                'rating_id',
205
                'term_id',
206
            ]);
207
            $offset += $this->limit;
208
        }
209 7
        glsr(Database::class)->finishTransaction('assigned_terms');
210 7
    }
211
212
    /**
213
     * @return array
214
     */
215
    protected function parseRatings(array $results)
216
    {
217
        $values = [];
218
        foreach ($results as $result) {
219
            $value = maybe_unserialize($result->mv);
220
            if (is_array($value)) {
221
                continue;
222
            }
223
            if (!isset($values[$result->ID])) {
224
                $values[$result->ID] = ['is_approved' => (int) $result->is_approved];
225
            }
226
            $values[$result->ID][$result->mk] = $value;
227
        }
228
        $results = [];
229
        foreach ($values as $postId => $value) {
230
            $meta = Arr::unprefixKeys($value);
231
            $meta['name'] = Arr::get($meta, 'author');
232
            $meta['is_pinned'] = Arr::get($meta, 'pinned');
233
            $meta['review_id'] = $postId;
234
            $meta['type'] = Arr::get($meta, 'review_type', 'local');
235
            $meta = Arr::removeEmptyValues($meta);
236
            $meta = glsr(RatingDefaults::class)->restrict($meta);
237
            $results[] = $meta;
238
        }
239
        return $results;
240
    }
241
242
    /**
243
     * @return array
244
     */
245
    protected function prepareCustomValuesForInsert(array $results)
246
    {
247
        $filtered = $this->filterCustomValues(
248
            $this->groupCustomValues($results)
249
        );
250
        $values = [];
251
        foreach ($filtered as $postId => $meta) {
252
            foreach ($meta as $metaKey => $metaValue) {
253
                $values[] = [
254
                    'post_id' => $postId,
255
                    'meta_key' => $metaKey,
256
                    'meta_value' => $metaValue,
257
                ];
258
            }
259
        }
260
        return $values;
261
    }
262
}
263