PluginProbe
Media Cloud Sync / trunk
Media Cloud Sync vtrunk
1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 All 34 releases
← All changes | includes/base/db.php +293 -17 1.2.12trunk View file →
@@ -46,24 +46,43 @@
46 46 $charset_collate = $wpdb->get_charset_collate();
47 47 if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
48 48 $queries[] = "
49 49 CREATE TABLE {$table_name} (
50 - id BIGINT(20) NOT NULL AUTO_INCREMENT,
51 - provider varchar(18) NOT NULL,
52 - region varchar(255) NOT NULL,
53 - storage varchar(255) NOT NULL,
54 - source_id bigint(20) NOT NULL,
55 - source_path varchar(1024) NOT NULL,
56 - source_type varchar(18) NOT NULL,
57 - url varchar(1024) NOT NULL,
58 - `key` varchar(1024) NOT NULL,
59 - is_private tinyint(1) NOT NULL DEFAULT 0,
60 - extra longtext DEFAULT NULL,
61 - PRIMARY KEY (id),
62 - UNIQUE KEY uidx_url (url(190), id),
63 - UNIQUE KEY uidx_key (`key`(190), id),
64 - UNIQUE KEY uidx_source_path (source_path(190), id)
65 - ) $charset_collate;";
50 + id BIGINT(20) NOT NULL AUTO_INCREMENT,
51 + provider VARCHAR(18) NOT NULL,
52 + region VARCHAR(255) NOT NULL,
53 + storage VARCHAR(255) NOT NULL,
54 + source_id BIGINT(20) NOT NULL,
55 + source_path VARCHAR(1024) NOT NULL,
56 + source_type VARCHAR(18) NOT NULL,
57 + url VARCHAR(1024) NOT NULL,
58 + `key` VARCHAR(1024) NOT NULL,
59 + original_source_path VARCHAR(1024) NOT NULL,
60 + original_key VARCHAR(1024) NOT NULL,
61 + is_private TINYINT(1) NOT NULL DEFAULT 0,
62 + extra LONGTEXT DEFAULT NULL,
63 +
64 + PRIMARY KEY (id),
65 +
66 + UNIQUE KEY uidx_url (url(190), id),
67 + UNIQUE KEY uidx_key (`key`(190), id),
68 + UNIQUE KEY uidx_source_path (source_path(190), id),
69 + UNIQUE KEY uidx_original_source_path (original_source_path(190), id),
70 + UNIQUE KEY uidx_original_key (original_key(190), id),
71 + KEY idx_item_lookup (
72 + source_id,
73 + source_type,
74 + provider,
75 + storage,
76 + region
77 + ),
78 + KEY idx_source_path_provider (
79 + provider,
80 + storage,
81 + region,
82 + source_path(190)
83 + )
84 + ) $charset_collate;";
66 85 }
67 86 dbDelta( $queries );
68 87 }
69 88
@@ -97,9 +116,14 @@
97 116 public function do_database_upgrade() {
98 117 global $wpdb;
99 118 $table_name = self::get_table_name();
100 119 $current_version = get_option( $this->token.'_db_version' );
120 + $latest_version = WPMCS_DB_VERSION;
101 121
122 + if ( $current_version === false ) {
123 + $current_version = $latest_version;
124 + }
125 +
102 126 /**
103 127 * If DB version below 1.0.1
104 128 * @since 1.2.11
105 129 *
@@ -139,9 +163,261 @@
139 163 Utils::update_option('', ['media_library' => $media_library ?? []], $settings_key);
140 164 }
141 165 }
142 166
143 - update_option( $this->token.'_db_version', WPMCS_DB_VERSION, true );
167 +
168 + /**
169 + * If DB version below 1.0.3
170 + *
171 + * @since 1.2.13
172 + * This is to handle the migration of media library counter from the global settings to the specific media library key.
173 + * Re-Create plugin specific upload directory
174 + */
175 + if (version_compare($current_version, '1.0.3', '<')) {
176 + Counter::instance()->fetch_and_update();
177 + }
178 +
179 + /**
180 + * If DB version below 1.0.4
181 + *
182 + * @since 1.3.1
183 + * This is to handle the removal of htaccess from uploads folder and adding htaccess to plugin specific upload directory
184 + */
185 + if (version_compare($current_version, '1.0.4', '<')) {
186 + $upload_dir = wp_upload_dir();
187 + $upload_base = $upload_dir['basedir'];
188 +
189 + if (is_dir($upload_base)) {
190 + $files_to_delete = array(
191 + $upload_base . '/.htaccess',
192 + $upload_base . '/' . Schema::getConstant('UPLOADS') . '/.htaccess',
193 + $upload_base . '/' . Schema::getConstant('UPLOADS') .'/index.php',
194 + );
195 + foreach ($files_to_delete as $file) {
196 + if (file_exists($file)) {
197 + @unlink($file); // deletes the file
198 + }
199 + }
200 + }
201 +
202 + // Re-Create plugin specific upload directory
203 + do_action('wpmcs_create_plugin_dir');
204 + }
205 +
206 +
207 + /**
208 + * If DB version below 1.0.5
209 + *
210 + * @since 1.3.5
211 + * Schema adjustments:
212 + * - Add original_source_path AFTER `key`
213 + * - Add original_key AFTER original_source_path
214 + * - Add required indexes
215 + */
216 + if ( version_compare( $current_version, '1.0.5', '<' ) ) {
217 + global $wpdb;
218 +
219 + $table_name = self::get_table_name();
220 +
221 + /**
222 + * 1. Add original_source_path AFTER `key`
223 + */
224 + $exists = $wpdb->get_var(
225 + $wpdb->prepare(
226 + "SHOW COLUMNS FROM {$table_name} LIKE %s",
227 + 'original_source_path'
228 + )
229 + );
230 +
231 + if ( ! $exists ) {
232 + $wpdb->query(
233 + "ALTER TABLE {$table_name}
234 + ADD COLUMN original_source_path VARCHAR(1024) NOT NULL
235 + AFTER `key`"
236 + );
237 + }
238 +
239 + /**
240 + * 2. Add original_key AFTER original_source_path
241 + */
242 + $exists = $wpdb->get_var(
243 + $wpdb->prepare(
244 + "SHOW COLUMNS FROM {$table_name} LIKE %s",
245 + 'original_key'
246 + )
247 + );
248 +
249 + if ( ! $exists ) {
250 + $wpdb->query(
251 + "ALTER TABLE {$table_name}
252 + ADD COLUMN original_key VARCHAR(1024) NOT NULL
253 + AFTER original_source_path"
254 + );
255 + }
256 +
257 + /**
258 + * 3. Unique index for original_source_path
259 + */
260 + $exists = $wpdb->get_var(
261 + $wpdb->prepare(
262 + "SHOW INDEX FROM {$table_name} WHERE Key_name = %s",
263 + 'uidx_original_source_path'
264 + )
265 + );
266 +
267 + if ( ! $exists ) {
268 + $wpdb->query(
269 + "ALTER TABLE {$table_name}
270 + ADD UNIQUE KEY uidx_original_source_path (original_source_path(190), id)"
271 + );
272 + }
273 +
274 + /**
275 + * 4. Unique index for original_key
276 + */
277 + $exists = $wpdb->get_var(
278 + $wpdb->prepare(
279 + "SHOW INDEX FROM {$table_name} WHERE Key_name = %s",
280 + 'uidx_original_key'
281 + )
282 + );
283 +
284 + if ( ! $exists ) {
285 + $wpdb->query(
286 + "ALTER TABLE {$table_name}
287 + ADD UNIQUE KEY uidx_original_key (original_key(190), id)"
288 + );
289 + }
290 +
291 + /**
292 + * 5. Item lookup index (get by source_id)
293 + */
294 + $exists = $wpdb->get_var(
295 + $wpdb->prepare(
296 + "SHOW INDEX FROM {$table_name} WHERE Key_name = %s",
297 + 'idx_item_lookup'
298 + )
299 + );
300 +
301 + if ( ! $exists ) {
302 + $wpdb->query(
303 + "ALTER TABLE {$table_name}
304 + ADD KEY idx_item_lookup (
305 + source_id,
306 + source_type,
307 + provider,
308 + storage,
309 + region
310 + )"
311 + );
312 + }
313 +
314 + /**
315 + * 6. Provider-aware source_path prefix index
316 + */
317 + $exists = $wpdb->get_var(
318 + $wpdb->prepare(
319 + "SHOW INDEX FROM {$table_name} WHERE Key_name = %s",
320 + 'idx_source_path_provider'
321 + )
322 + );
323 +
324 + if ( ! $exists ) {
325 + $wpdb->query(
326 + "ALTER TABLE {$table_name}
327 + ADD KEY idx_source_path_provider (
328 + provider,
329 + storage,
330 + region,
331 + source_path(190)
332 + )"
333 + );
334 + }
335 +
336 + // Update upgrade version option only for who had previous version to trigger initial upgrade tracking
337 + update_option( $this->token . '_db_upgrade_version', '0.0.0', false );
338 + }
339 +
340 + /**
341 + * If DB version below 1.0.6
342 + *
343 + * @since 1.3.12
344 + * Flatten recursively nested wpmcs_status_data caused by legacy set_status writes.
345 + */
346 + if ( version_compare( $current_version, '1.0.6', '<' ) ) {
347 + $this->repair_nested_status_data();
348 + }
349 +
350 +
351 +
352 + update_option( $this->token.'_db_version', $latest_version, true );
353 + }
354 +
355 + /**
356 + * One-time repair for recursively nested wpmcs_status_data.
357 + * Flattens status entries caused by legacy set_status writes that used get_option directly.
358 + *
359 + * @since 1.3.12
360 + * @return void
361 + */
362 + private function repair_nested_status_data() {
363 + $meta_name = Schema::getConstant('STATUS_KEY');
364 + $current_settings = Utils::get_option('status', [], $meta_name);
365 +
366 + if (!is_array($current_settings) || empty($current_settings)) {
367 + return;
368 + }
369 +
370 + $known_keys = ['cdnRead', 'storageCredentials'];
371 + $collected = [];
372 + $this->collect_status_entries($current_settings, $collected);
373 +
374 + if (empty($collected)) {
375 + return;
376 + }
377 +
378 + $normalized = [];
379 + foreach ($known_keys as $key) {
380 + if (isset($collected[$key])) {
381 + $normalized[$key] = $collected[$key];
382 + }
383 + }
384 +
385 + if (empty($normalized) || $normalized === $current_settings) {
386 + return;
387 + }
388 +
389 + Utils::update_option('status', $normalized, $meta_name);
390 + }
391 +
392 + /**
393 + * Collect status entries from all nesting levels, preferring the latest check.
394 + * @since 1.3.12
395 + * @param array $settings
396 + * @param array $collected
397 + * @return void
398 + */
399 + private function collect_status_entries($settings, &$collected) {
400 + if (!is_array($settings)) {
401 + return;
402 + }
403 +
404 + $known_keys = ['cdnRead', 'storageCredentials'];
405 +
406 + foreach ($known_keys as $key) {
407 + if (isset($settings[$key]) && is_array($settings[$key]) && array_key_exists('status', $settings[$key])) {
408 + $entry = $settings[$key];
409 + $checked = isset($entry['lastChecked']) ? (int) $entry['lastChecked'] : 0;
410 +
411 + if (!isset($collected[$key]) || $checked >= ($collected[$key]['lastChecked'] ?? 0)) {
412 + $collected[$key] = $entry;
413 + }
414 + }
415 + }
416 +
417 + if (isset($settings['status']) && is_array($settings['status'])) {
418 + $this->collect_status_entries($settings['status'], $collected);
419 + }
144 420 }
145 421
146 422 /**
147 423 * Ensures only one instance of Class is loaded or can be loaded.