PluginProbe
Import WP – CSV & XML Import Export for WordPress / trunk
Import WP – CSV & XML Import Export for WordPress vtrunk
2.14.24 2.14.23 2.7.0 2.7.1 2.7.10 2.7.11 2.7.12 2.7.13 2.7.14 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 2.9.1 trunk 0.1.6 All 142 releases
jc-importer / class / Common / Migration / Migrations.php

Migrations.php in Import WP – CSV & XML Import Export for WordPress trunk, at class/Common/Migration/Migrations.php

999 lines 39.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ImportWP\Common\Migration;
4
5 use ImportWP\Common\Filesystem\Filesystem;
6 use ImportWP\Common\Importer\ImporterManager;
7 use ImportWP\Common\Model\ImporterModel;
8 use ImportWP\Common\Util\Logger;
9 use ImportWP\Container;
10
11 class Migrations
12 {
13 private $_version = 0;
14 private $_migrations = array();
15
16 public function __construct()
17 {
18
19 $starting_version = intval(get_option('iwp_db_version', 0));
20 if ($starting_version <= 3 && $starting_version > 0) {
21 // v1 migrations
22 $this->_migrations[] = array($this, 'migration_01');
23 $this->_migrations[] = array($this, 'migration_02');
24 $this->_migrations[] = array($this, 'migration_03');
25 $this->_migrations[] = array($this, 'migration_04_migrate_v1_to_v2_data');
26 } else {
27 // skip v1 migrations
28 $this->_migrations[] = null;
29 $this->_migrations[] = null;
30 $this->_migrations[] = null;
31 $this->_migrations[] = null;
32 }
33
34 // v2 migrations
35 $this->_migrations[] = array($this, 'migration_05_multiple_crons');
36 $this->_migrations[] = array($this, 'migration_06_cron_update');
37 $this->_migrations[] = array($this, 'migration_07_add_session_table');
38 $this->_migrations[] = array($this, 'migration_08_migrate_taxonomy_settings');
39 $this->_migrations[] = array($this, 'migration_09_migrate_attachment_settings');
40 $this->_migrations[] = array($this, 'migration_10_relative_importer_file_paths');
41
42 $this->_version = count($this->_migrations);
43 }
44
45 public function isSetup()
46 {
47 $version = intval(get_option('iwp_db_version', get_option('jci_db_version', 0)));
48 if ($version < count($this->_migrations)) {
49 return false;
50 }
51 return true;
52 }
53
54 public function install()
55 {
56
57 //run through schema migrations only
58 $this->migrate(false);
59 }
60
61 public function uninstall()
62 {
63 global $wpdb;
64 $wpdb->query("DROP TABLE IF EXISTS `" . $wpdb->prefix . "importer_log`;");
65 $wpdb->query("DROP TABLE IF EXISTS `" . $wpdb->prefix . "importer_files`;");
66 delete_option('iwp_db_version');
67 delete_option('jci_db_version');
68 delete_option('iwp_is_migrating');
69 }
70
71 public function migrate($migrate_data = true)
72 {
73
74 $verion_key = 'iwp_db_version';
75 $version = intval(get_option('iwp_db_version', get_option('jci_db_version', 0)));
76 $migrating = get_option('iwp_is_migrating', 'no');
77 if ('yes' === $migrating) {
78 return;
79 }
80
81 if ($version < count($this->_migrations)) {
82
83 require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
84
85 for ($i = 0; $i < count($this->_migrations); $i++) {
86
87 $migration_version = $i + 1;
88 if ($version < $migration_version) {
89
90 update_option('iwp_is_migrating', 'yes');
91
92 set_time_limit(0);
93
94 // Run migration
95 if (!is_null($this->_migrations[$i])) {
96 call_user_func($this->_migrations[$i], $migrate_data);
97 }
98
99 // Flag as migrated
100 update_option($verion_key, $migration_version);
101 update_option('iwp_is_migrating', 'no');
102 }
103 }
104 }
105
106 // update_option('iwp_is_setup', 'yes');
107 }
108
109 public function get_charset()
110 {
111
112 global $wpdb;
113 $charset_collate = "";
114
115 if (!empty($wpdb->charset)) {
116 $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
117 }
118 if (!empty($wpdb->collate)) {
119 $charset_collate .= " COLLATE $wpdb->collate";
120 }
121 return $charset_collate;
122 }
123
124 public function migration_01($migrate_data = true)
125 {
126
127 global $wpdb;
128 $charset_collate = $this->get_charset();
129
130 $sql = "CREATE TABLE `" . $wpdb->prefix . "importer_log` (
131 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
132 `importer_name` varchar(255) DEFAULT NULL,
133 `object_id` int(11) DEFAULT NULL,
134 `template` varchar(255) DEFAULT NULL,
135 `type` varchar(255) DEFAULT NULL,
136 `file` varchar(255) DEFAULT NULL,
137 `version` int(11) DEFAULT NULL,
138 `row` int(11) DEFAULT NULL,
139 `src` text,
140 `value` text,
141 `created` datetime DEFAULT NULL,
142 `import_settings` TEXT NULL,
143 `mapped_fields` TEXT NULL,
144 `attachments` TEXT NULL,
145 `taxonomies` TEXT NULL,
146 `parser_settings` TEXT NULL,
147 `template_settings` TEXT NULL,
148 PRIMARY KEY (`id`)
149 ) $charset_collate; ";
150
151 dbDelta($sql);
152
153 $sql = "CREATE TABLE `" . $wpdb->prefix . "importer_files`(
154 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
155 `importer_id` INT(11),
156 `author_id` INT(11),
157 `mime_type` VARCHAR(255),
158 `name` VARCHAR(255),
159 `src` VARCHAR(255),
160 `created` DATETIME,
161 PRIMARY KEY (`id`)
162 ) $charset_collate;";
163 dbDelta($sql);
164 }
165
166 public function migration_02($migrate_data = true)
167 {
168
169 if (!$migrate_data) {
170 return;
171 }
172
173 global $wpdb;
174
175 // return list of importer file links
176 $importer_file_ids = $this->migration_02_get_importer_file_ids();
177
178 // get ids of all importers and fetch all their import files
179 $importers = $wpdb->get_col("SELECT id FROM " . $wpdb->posts . " WHERE post_type = 'jc-imports'");
180
181 //
182 $or_query = '';
183 if (!empty($importers)) {
184 $or_query = "
185 OR (
186 post_type = 'attachment'
187 AND post_parent IN ( " . implode(',', $importers) . ")
188 )
189 ";
190 }
191
192 $results = $wpdb->get_results("
193 SELECT ID, guid, post_parent, post_author, post_mime_type, post_name, post_date
194 FROM " . $wpdb->posts . "
195 WHERE
196 (post_type = 'jc-import-files')
197 " . $or_query . "
198 ");
199
200
201 if (!empty($results)) {
202
203 // print_r($importer_attachments);
204 $upload_dir = wp_upload_dir();
205 $baseurl = $upload_dir['baseurl'];
206 $records = array();
207
208 foreach ($results as $importer) {
209
210 $src = $importer->guid;
211 if (strpos($src, $baseurl) === 0) {
212 $src = substr($src, strlen($baseurl));
213 }
214 // $record = array(
215 $importer_id = $importer->post_parent;
216 $author_id = $importer->post_author;
217 $mime = $importer->post_mime_type;
218 $name = $importer->post_name;
219 $attachment_src = $src;
220 $created = $importer->post_date;
221 // );
222
223 $query_result = $wpdb->query($wpdb->prepare("INSERT INTO `" . $wpdb->prefix . "importer_files`(importer_id, author_id, mime_type, name, src, created) VALUES(%d, %d, %s, %s, %s, %s)", $importer_id, $author_id, $mime, $name, $attachment_src, $created));
224
225 // check if importer_file_id exists in importer settings array
226 if (is_array($importer_file_ids) && array_key_exists($importer->ID, $importer_file_ids)) {
227 $importer_file_ids[$importer->ID] = $wpdb->insert_id;
228 set_transient('jci_db_import_file_ids', $importer_file_ids);
229 }
230
231 if ($query_result) {
232 wp_delete_post($importer->ID, true);
233 }
234 }
235 }
236
237 // loop through all importer_file meta data
238 $importer_settings = $wpdb->get_results("SELECT * FROM `" . $wpdb->prefix . "postmeta` WHERE meta_key='_import_settings'");
239 if ($importer_settings) {
240
241 foreach ($importer_settings as $settings) {
242
243 $post_id = $settings->post_id;
244 $value = maybe_unserialize($settings->meta_value);
245
246 if (is_array($importer_file_ids) && array_key_exists($value['import_file'], $importer_file_ids)) {
247 $value['import_file'] = $importer_file_ids[$value['import_file']];
248 update_post_meta($post_id, '_import_settings', $value);
249 continue;
250 }
251 }
252 }
253 }
254
255 /**
256 * Fetch list of current importer_file id's
257 * @return array
258 */
259 private function migration_02_get_importer_file_ids()
260 {
261 global $wpdb;
262
263 $transient = get_transient('jci_db_import_file_ids');
264 if (get_transient('jci_db_import_file_ids') === false) {
265
266 $importer_files = array();
267
268 $importer_settings = $wpdb->get_results("SELECT * FROM `" . $wpdb->prefix . "postmeta` WHERE meta_key='_import_settings'");
269 if ($importer_settings) {
270
271 foreach ($importer_settings as $settings) {
272 $value = maybe_unserialize($settings->meta_value);
273 $importer_files[$value['import_file']] = null;
274 }
275 }
276 set_transient('jci_db_import_file_ids', $importer_files);
277
278 return $importer_files;
279 } else {
280 return $transient;
281 }
282 }
283
284 /**
285 * Migration 03
286 * Refactor logs table, so duplication of data.
287 *
288 * @since 1.1.0
289 */
290 public function migration_03($migrate_data = true)
291 {
292
293 global $wpdb;
294 $wpdb->query("ALTER TABLE `" . $wpdb->prefix . "importer_log`
295 DROP COLUMN importer_name,
296 DROP COLUMN src,
297 DROP COLUMN template,
298 DROP COLUMN type,
299 DROP COLUMN import_settings,
300 DROP COLUMN mapped_fields,
301 DROP COLUMN attachments,
302 DROP COLUMN taxonomies,
303 DROP COLUMN parser_settings,
304 DROP COLUMN template_settings");
305 }
306
307 public function migration_04_migrate_v1_to_v2_data($migrate_data = true)
308 {
309 global $wpdb;
310 // remove log table
311 // $wpdb->query("DROP TABLE `" . $wpdb->prefix . "importer_log`");
312
313 $query = new \WP_Query([
314 'post_type' => 'jc-imports',
315 'posts_per_page' => -1
316 ]);
317
318 /**
319 * @var ImporterManager $importer_manager
320 */
321 $importer_manager = Container::getInstance()->get('importer_manager');
322
323 if ($query->have_posts()) {
324 foreach ($query->posts as $post) {
325 $v2_id = get_post_meta($post->ID, '_iwp_v2_importer', true);
326 $import_settings = get_post_meta($post->ID, '_import_settings', true);
327 $mapped_fields = get_post_meta($post->ID, '_mapped_fields', true);
328 $attachments = get_post_meta($post->ID, '_attachments', true);
329 $taxonomies = get_post_meta($post->ID, '_taxonomies', true);
330 $parser_settings = get_post_meta($post->ID, '_parser_settings', true);
331 $field_permissions = get_post_meta($post->ID, 'field_permissions', true);
332
333 $import_file_id = $import_settings['import_file'];
334
335
336 $file_result = $wpdb->get_var($wpdb->prepare("SELECT src FROM {$wpdb->prefix}importer_files WHERE id=%d", [$import_file_id]));
337 $filepath = false;
338 if ($file_result) {
339 $wp_upload_dir = wp_upload_dir();
340 $filepath = $wp_upload_dir['basedir'] . $file_result;
341 }
342
343 $post_type = '';
344 $template = $import_settings['template'];
345 if ($template === 'taxonomy') {
346 // Skip taxonomy template as this is now term (same but without the taxonomy column)
347 continue;
348 }
349
350 if ($template === 'page') {
351 $post_type = 'page';
352 } elseif ($template === 'post') {
353 $post_type = 'post';
354 } elseif ($template === 'custom-post-type') {
355 $post_type = $import_settings['general']['custom_post_type'];
356 }
357
358 $settings = [
359 'post_type' => $post_type,
360 'max_row' => intval($import_settings['row_count']) > 0 ? intval($import_settings['row_count']) : '',
361 'start_row' => intval($import_settings['start_line']) > 1 ? intval($import_settings['start_line']) : '',
362 ];
363
364 $converted_mapped_fields = [];
365 $enabled = [];
366 foreach ($mapped_fields as $group => $field_data) {
367 foreach ($field_data as $k => $v) {
368
369 $group_id = $group;
370 if ($group === 'page') {
371 $group_id = 'post';
372 }
373
374 switch ($k) {
375
376 // TODO: Migrate user fields
377 case 'generate_pass':
378 $settings['generate_pass'] = boolval($v) === true ? true : false;
379 break;
380 case 'notify_reg':
381 $settings['notify_users'] = boolval($v) === true ? true : false;
382 break;
383 case 'enable_user_nicename':
384 $enabled[$group_id . '.user_nicename'] = boolval($v) === true ? true : false;
385 break;
386 case 'enable_display_name':
387 $enabled[$group_id . '.display_name'] = boolval($v) === true ? true : false;
388 break;
389 case 'enable_description':
390 $enabled[$group_id . '.description'] = boolval($v) === true ? true : false;
391 break;
392 case 'enable_role':
393 $enabled[$group_id . '.role'] = boolval($v) === true ? true : false;
394 break;
395 case 'enable_pass':
396 $enabled[$group_id . '.user_pass'] = boolval($v) === true ? true : false;
397 break;
398 case 'user_url':
399 if (!empty($v)) {
400 $enabled[$group_id . '.user_url'] = true;
401 $converted_mapped_fields[$group_id . '.' . $k] = $v;
402 }
403 break;
404
405 // post_type
406 case 'post_author':
407 $converted_mapped_fields[$group_id . '._author.post_author'] = $v;
408 break;
409 case 'post_author_field_type':
410 $converted_mapped_fields[$group_id . '._author._author_type'] = $v;
411 break;
412 case 'post_parent':
413 $converted_mapped_fields[$group_id . '._parent.parent'] = $v;
414 break;
415 case 'post_parent_field_type':
416 $converted_mapped_fields[$group_id . '._parent._parent_type'] = $v;
417 break;
418 case 'post_parent_ref':
419 $converted_mapped_fields[$group_id . '._parent._parent_ref'] = $v;
420 break;
421 case 'post_excerpt':
422 $converted_mapped_fields[$group_id . '.' . $k] = $v;
423 if (!empty($v)) {
424 $enabled[$group_id . '.post_excerpt'] = true;
425 }
426 break;
427 case 'post_name':
428 $converted_mapped_fields[$group_id . '.' . $k] = $v;
429 if (!empty($v)) {
430 $enabled[$group_id . '.post_name'] = true;
431 }
432 break;
433 // Enable Fields
434 case 'enable_post_parent':
435 $enabled[$group_id . '._parent'] = boolval($v) === true ? true : false;
436 break;
437 case 'enable_post_status':
438 $enabled[$group_id . '.post_status'] = boolval($v) === true ? true : false;
439 break;
440 case 'enable_post_author':
441 $enabled[$group_id . '._author'] = boolval($v) === true ? true : false;
442 break;
443 case 'enable_menu_order':
444 $enabled[$group_id . '.menu_order'] = boolval($v) === true ? true : false;
445 break;
446 case 'enable_post_password':
447 $enabled[$group_id . '.post_password'] = boolval($v) === true ? true : false;
448 break;
449 case 'enable_post_date':
450 $enabled[$group_id . '.post_date'] = boolval($v) === true ? true : false;
451 break;
452 case 'enable_comment_status':
453 $enabled[$group_id . '.comment_status'] = boolval($v) === true ? true : false;
454 break;
455 case 'enable_ping_status':
456 $enabled[$group_id . '.ping_status'] = boolval($v) === true ? true : false;
457 break;
458 case 'enable_page_template':
459 $enabled[$group_id . '._wp_page_template'] = boolval($v) === true ? true : false;
460 break;
461 default:
462 $converted_mapped_fields[$group_id . '.' . $k] = $v;
463 break;
464 }
465 }
466 }
467
468 if ($taxonomies) {
469 foreach ($taxonomies as $group => $field_data) {
470 foreach ($field_data['tax'] as $row_id => $tax) {
471
472 $term = $field_data['term'][$row_id];
473
474 // TODO: what do we do with permissions
475 $permissions = $field_data['permissions'][$row_id];
476
477 $converted_mapped_fields['taxonomies.' . $row_id . '.tax'] = $tax;
478 $converted_mapped_fields['taxonomies.' . $row_id . '.term'] = $term;
479 }
480 }
481
482 $converted_mapped_fields['taxonomies._index'] = count($taxonomies);
483 }
484
485 if ($attachments) {
486 foreach ($attachments as $group => $field_data) {
487
488 // attachments used to be gloablly set ftp|remote|local
489 $type = $field_data['type'];
490 $ftp_server = $field_data['ftp']['server'];
491 $ftp_user = $field_data['ftp']['user'];
492 $ftp_pass = $field_data['ftp']['pass'];
493 $local_base_path = $field_data['local']['base_path'];
494
495 if ($type === 'url') {
496 $type = 'remote';
497 }
498
499 foreach ($field_data['location'] as $row_id => $location) {
500 $alt = $field_data['alt'][$row_id];
501 $title = $field_data['title'][$row_id];
502 $caption = $field_data['caption'][$row_id];
503 $description = $field_data['description'][$row_id];
504 $permissions = $field_data['permissions'][$row_id];
505 $featured_image = $field_data['featured_image'][$row_id];
506
507 $converted_mapped_fields['attachments.' . $row_id . '.location'] = $location;
508 $converted_mapped_fields['attachments.' . $row_id . '._featured'] = $featured_image == 1 ? 'yes' : 'no';
509 $converted_mapped_fields['attachments.' . $row_id . '._download'] = $type;
510 $converted_mapped_fields['attachments.' . $row_id . '._ftp_host'] = $ftp_server;
511 $converted_mapped_fields['attachments.' . $row_id . '._ftp_user'] = $ftp_user;
512 $converted_mapped_fields['attachments.' . $row_id . '._ftp_pass'] = $ftp_pass;
513 $converted_mapped_fields['attachments.' . $row_id . '._ftp_path'] = '';
514 $converted_mapped_fields['attachments.' . $row_id . '._remote_url'] = '';
515 $converted_mapped_fields['attachments.' . $row_id . '._local_url'] = $local_base_path;
516
517 $converted_mapped_fields['attachments.' . $row_id . '._meta._enabled'] = 'yes';
518 $converted_mapped_fields['attachments.' . $row_id . '._meta._alt'] = $alt;
519 $converted_mapped_fields['attachments.' . $row_id . '._meta._title'] = $title;
520 $converted_mapped_fields['attachments.' . $row_id . '._meta._caption'] = $caption;
521 $converted_mapped_fields['attachments.' . $row_id . '._meta._description'] = $description;
522 }
523 }
524
525 $converted_mapped_fields['attachments._index'] = count($attachments);
526 }
527
528 // custom fields
529 $custom_fields = isset($import_settings['_custom_fields'], $import_settings['_custom_fields'][$template]) ? $import_settings['_custom_fields'][$template] : [];
530 if (!empty($custom_fields)) {
531 $row_id = 0;
532 foreach ($custom_fields as $custom_field) {
533
534 $cf_prefix = 'custom_fields.' . $row_id . '.';
535 $converted_mapped_fields[$cf_prefix . 'key'] = $custom_field['key'];
536 $converted_mapped_fields[$cf_prefix . 'value'] = $custom_field['value'];
537 $converted_mapped_fields[$cf_prefix . '_field_type'] = $custom_field['type'];
538
539 if ('attachment' === $custom_field['type']) {
540 $converted_mapped_fields[$cf_prefix . '_return'] = $custom_field['settings']['attachment_return'];
541
542 $converted_mapped_fields[$cf_prefix . '_ftp_host'] = $custom_field['settings']['attachment_ftp_server'];
543 $converted_mapped_fields[$cf_prefix . '_ftp_user'] = $custom_field['settings']['attachment_ftp_user'];
544 $converted_mapped_fields[$cf_prefix . '_ftp_pass'] = $custom_field['settings']['attachment_ftp_pass'];
545
546
547 $converted_mapped_fields[$cf_prefix . '_ftp_path'] = '';
548 $converted_mapped_fields[$cf_prefix . '_remote_url'] = '';
549 $converted_mapped_fields[$cf_prefix . '_local_url'] = '';
550
551 switch ($custom_field['settings']['attachment_download']) {
552 case 'ftp':
553 $converted_mapped_fields[$cf_prefix . '_download'] = 'ftp';
554 $converted_mapped_fields[$cf_prefix . '_ftp_path'] = $custom_field['settings']['attachment_base_url'];
555 break;
556 case 'url':
557 $converted_mapped_fields[$cf_prefix . '_download'] = 'remote';
558 $converted_mapped_fields[$cf_prefix . '_remote_url'] = $custom_field['settings']['attachment_base_url'];
559 break;
560 case 'local':
561 $converted_mapped_fields[$cf_prefix . '_download'] = 'local';
562 $converted_mapped_fields[$cf_prefix . '_local_url'] = $custom_field['settings']['attachment_base_url'];
563 break;
564 }
565
566 $converted_mapped_fields[$cf_prefix . '_enabled'] = 'no';
567 $converted_mapped_fields[$cf_prefix . '_alt'] = '';
568 $converted_mapped_fields[$cf_prefix . '_title'] = '';
569 $converted_mapped_fields[$cf_prefix . '_caption'] = '';
570 $converted_mapped_fields[$cf_prefix . '_description'] = '';
571 }
572 $row_id++;
573 }
574
575 $converted_mapped_fields['custom_fields._index'] = $row_id;
576 }
577
578 // TODO: Migrate cron
579 // _jci_cron_enabled: yes
580 // _jci_cron_minutes: 60
581 // _jci_cron_last_ran: 1579960020
582 // _cron_last_updated: 1579960020
583
584 $cron_enabled = get_post_meta($post->ID, '_jci_cron_enabled', true);
585 if ($cron_enabled === 'yes') {
586 $settings['import_method'] = 'schedule';
587 $settings['cron_day'] = 0;
588 $settings['cron_hour'] = 0;
589 $settings['cron_minute'] = 0;
590
591 $minutes = intval(get_post_meta($post->ID, '_jci_cron_minutes', true));
592 if ($minutes < 60) {
593 // Hourly
594 $settings['cron_schedule'] = 'hour';
595 } elseif ($minutes < 60 * 24) {
596 $settings['cron_schedule'] = 'day';
597 } elseif ($minutes < 60 * 24 * 7) {
598 $settings['cron_schedule'] = 'week';
599 } else {
600 $settings['cron_schedule'] = 'month';
601 }
602 } else {
603 $settings['import_method'] = 'run';
604 }
605
606
607
608 $importer_model_data = [
609 'name' => $post->post_title,
610 'template' => $import_settings['template'],
611 'template_type' => '',
612 'parser' => $import_settings['template_type'],
613 'permissions' => [
614 'create' => [
615 'enabled' => $import_settings['permissions']['create'] === 1 ? true : false,
616 'type' => $field_permissions['create_type'],
617 'fields' => $field_permissions['create_fields']
618 ],
619 'update' => [
620 'enabled' => $import_settings['permissions']['update'] === 1 ? true : false,
621 'type' => $field_permissions['update_type'],
622 'fields' => $field_permissions['update_fields']
623 ],
624 'remove' => [
625 'enabled' => $import_settings['permissions']['delete'] === 1 ? true : false
626 ],
627 ],
628 'datasource' => [
629 'type' => $import_settings['import_type'],
630 'settings' => [
631 'remoute_url' => '',
632 'local_url' => ''
633 ]
634 ],
635 'settings' => $settings,
636 'file' => [
637 'id' => null,
638 'settings' => [
639 'count' => 0,
640 'processed' => false,
641 'setup' => false,
642 // csv
643 'delimiter' => stripslashes($parser_settings['csv_delimiter']),
644 'enclosure' => stripslashes($parser_settings['csv_enclosure']),
645 'show_headings' => false,
646 // xml
647 'base_path' => $parser_settings['import_base'],
648 'nodes' => [],
649 ]
650 ],
651 'map' => $converted_mapped_fields,
652 'enabled' => $enabled
653 ];
654
655 if (intval($v2_id) > 0) {
656 $importer_model_data['id'] = intval($v2_id);
657 }
658
659 $importer_model = new ImporterModel($importer_model_data);
660 $result = $importer_model->save();
661
662 if (!is_wp_error($result)) {
663
664 // clear existing importer files
665 $query = "DELETE FROM {$wpdb->postmeta} WHERE post_id={$result} AND meta_key LIKE '_importer_file%'";
666 $wpdb->query($query);
667
668 if ($filepath && file_exists($filepath)) {
669 $file_id = $importer_manager->link_importer_file($result, $filepath);
670 $importer_model->setFileId($file_id);
671 $importer_model->save();
672 }
673
674 update_post_meta($result, '_iwp_v1_importer', $post->ID);
675 update_post_meta($post->ID, '_iwp_v2_importer', $result);
676 }
677 }
678 }
679 }
680
681 public function migration_05_multiple_crons()
682 {
683
684 /**
685 * @var \wpdb $wpdb
686 */
687 global $wpdb;
688
689 // TODO: loop through serialsed post_content, switching from single cron to array
690 $importers = $wpdb->get_results("SELECT * FROM {$wpdb->posts} WHERE post_type='" . IWP_POST_TYPE . "'", ARRAY_A);
691 foreach ($importers as $importer) {
692 $id = $importer['ID'];
693 $data = unserialize($importer['post_content']);
694 if ($data['settings']['import_method'] !== 'schedule') {
695 continue;
696 }
697
698 $cron = [[
699 'setting_cron_schedule' => $data['settings']['cron_schedule'],
700 'setting_cron_day' => $data['settings']['cron_day'],
701 'setting_cron_hour' => $data['settings']['cron_hour'],
702 'setting_cron_minute' => $data['settings']['cron_minute'],
703 'setting_cron_disabled' => $data['settings']['cron_disabled'],
704 ]];
705
706 unset($data['settings']['cron_schedule']);
707 unset($data['settings']['cron_day']);
708 unset($data['settings']['cron_hour']);
709 unset($data['settings']['cron_minute']);
710 unset($data['settings']['cron_disabled']);
711
712 $data['settings']['cron'] = $cron;
713
714 remove_filter('content_save_pre', 'wp_filter_post_kses');
715 wp_update_post(['ID' => $id, 'post_content' => serialize($data)]);
716 add_filter('content_save_pre', 'wp_filter_post_kses');
717 }
718 }
719
720 public function migration_06_cron_update()
721 {
722 wp_unschedule_hook('iwp_runner');
723
724 /**
725 * @var \wpdb $wpdb
726 */
727 global $wpdb;
728
729 // TODO: loop through serialsed post_content, switching from single cron to array
730 $importers = $wpdb->get_results("SELECT * FROM {$wpdb->posts} WHERE post_type='" . IWP_POST_TYPE . "'", ARRAY_A);
731 foreach ($importers as $importer) {
732
733 $id = $importer['ID'];
734 $data = unserialize($importer['post_content']);
735 if ($data['settings']['import_method'] !== 'schedule') {
736 continue;
737 }
738
739 delete_post_meta($id, '_iwp_session');
740 delete_post_meta($id, '_iwp_cron_updated');
741 delete_post_meta($id, '_iwp_cron_status');
742 delete_post_meta($id, '_iwp_cron_version');
743 wp_update_post(['ID' => $id, 'post_excerpt' => '']);
744
745 Logger::write(__CLASS__ . '::migration_06_cron_update -rest', $id);
746 }
747 }
748
749 public function migration_07_add_session_table($migrate_data = true)
750 {
751 /**
752 * @var \WPDB $wpdb
753 */
754 global $wpdb;
755 $charset_collate = $this->get_charset();
756
757 $sql = "CREATE TABLE `" . $wpdb->prefix . "iwp_sessions` (
758 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
759 `site_id` int(11) DEFAULT NULL,
760 `importer_id` int(11) DEFAULT NULL,
761 `item_id` int(11) DEFAULT NULL,
762 `item_type` varchar(255) DEFAULT NULL,
763 `session` varchar(255) DEFAULT NULL,
764 PRIMARY KEY (`id`)
765 ) $charset_collate; ";
766
767 dbDelta($sql);
768
769 if (!$migrate_data) {
770 return;
771 }
772
773 // Migrate post sessions
774 $posts = $wpdb->get_results("SELECT {$wpdb->postmeta}.*, {$wpdb->posts}.post_type FROM {$wpdb->postmeta} INNER JOIN {$wpdb->posts} ON {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID WHERE meta_key LIKE '\_iwp\_session\_%'", ARRAY_A);
775 if (!empty($posts)) {
776 foreach ($posts as $post) {
777
778 if (preg_match('/_iwp_session_(\d+)/', $post['meta_key'], $matches) !== 1) {
779 continue;
780 }
781
782 $data = [
783 'importer_id' => $matches[1],
784 'item_id' => $post['post_id'],
785 'item_type' => 'pt-' . $post['post_type'],
786 'session' => $post['meta_value']
787 ];
788 $format = ['%d', '%d', '%s', '%s'];
789
790 // TODO: is this needed as blog_id is more relevant since there is a sessions table per site?
791 if (is_multisite()) {
792 $data['site_id'] = $wpdb->siteid;
793 $format[] = '%d';
794 }
795
796 $wpdb->insert($wpdb->prefix . 'iwp_sessions', $data, $format);
797 }
798 }
799
800 // Migrate term sessions
801 $terms = $wpdb->get_results("SELECT {$wpdb->termmeta}.*, {$wpdb->term_taxonomy}.taxonomy FROM {$wpdb->termmeta} INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->termmeta}.term_id = {$wpdb->term_taxonomy}.term_id WHERE meta_key LIKE '\_iwp\_session\_%'", ARRAY_A);
802 if (!empty($terms)) {
803 foreach ($terms as $post) {
804
805 if (preg_match('/_iwp_session_(\d+)/', $post['meta_key'], $matches) !== 1) {
806 continue;
807 }
808
809 $data = [
810 'importer_id' => $matches[1],
811 'item_id' => $post['term_id'],
812 'item_type' => 't-' . $post['taxonomy'],
813 'session' => $post['meta_value']
814 ];
815 $format = ['%d', '%d', '%s', '%s'];
816
817 // TODO: is this needed as blog_id is more relevant since there is a sessions table per site?
818 if (is_multisite()) {
819 $data['site_id'] = $wpdb->siteid;
820 $format[] = '%d';
821 }
822
823 $wpdb->insert($wpdb->prefix . 'iwp_sessions', $data, $format);
824 }
825 }
826
827 // Migrate user sessions
828 $users = $wpdb->get_results("SELECT * FROM {$wpdb->usermeta} WHERE meta_key LIKE '\_iwp\_session\_%'", ARRAY_A);
829 if (!empty($users)) {
830 foreach ($users as $post) {
831
832 if (preg_match('/_iwp_session_(\d+)/', $post['meta_key'], $matches) !== 1) {
833 continue;
834 }
835
836 $data = [
837 'importer_id' => $matches[1],
838 'item_id' => $post['user_id'],
839 'item_type' => 'user',
840 'session' => $post['meta_value']
841 ];
842 $format = ['%d', '%d', '%s', '%s'];
843
844 // TODO: is this needed as blog_id is more relevant since there is a sessions table per site?
845 if (is_multisite()) {
846 $data['site_id'] = $wpdb->siteid;
847 $format[] = '%d';
848 }
849
850 $wpdb->insert($wpdb->prefix . 'iwp_sessions', $data, $format);
851 }
852 }
853 }
854
855 public function migration_08_migrate_taxonomy_settings($migrate_data = true)
856 {
857 /**
858 * @var \wpdb $wpdb
859 */
860 global $wpdb;
861
862 // TODO: loop through serialsed post_content, switching from single cron to array
863 $importers = $wpdb->get_results("SELECT * FROM {$wpdb->posts} WHERE post_type='" . IWP_POST_TYPE . "'", ARRAY_A);
864
865 foreach ($importers as $importer) {
866
867 $data = maybe_unserialize($importer['post_content']);
868 $modified = false;
869
870 $tmp = [];
871 foreach ($data['map'] as $field_id => $field_value) {
872 $count = 0;
873 $tmp[preg_replace('/^(taxonomies\.\d+\.)(_.*?)$/', '$1settings.$2', $field_id, -1, $count)] = $field_value;
874 if ($count > 0) {
875 $modified = true;
876 }
877 }
878
879 if (!$modified) {
880 continue;
881 }
882
883 $data['map'] = $tmp;
884
885
886 remove_filter('content_save_pre', 'wp_filter_post_kses');
887 wp_update_post(['ID' => $importer['ID'], 'post_content' => serialize($data)]);
888 add_filter('content_save_pre', 'wp_filter_post_kses');
889 }
890 }
891
892 // TODO: do we need this? can we get around this with manipulating the data if it exists?
893 public function migration_09_migrate_attachment_settings($migrate_data = true)
894 {
895 /**
896 * @var \wpdb $wpdb
897 */
898 global $wpdb;
899
900 $importers = $wpdb->get_results("SELECT * FROM {$wpdb->posts} WHERE post_type='" . IWP_POST_TYPE . "'", ARRAY_A);
901
902 foreach ($importers as $importer) {
903
904 $data = maybe_unserialize($importer['post_content']);
905 $modified = false;
906
907 $tmp = [];
908 foreach ($data['map'] as $field_id => $field_value) {
909 $count = 0;
910
911 $ends_with = [
912 '_download',
913 '_enable_image_hash',
914 '_featured',
915 '_ftp_host',
916 '_ftp_pass',
917 '_ftp_path',
918 '_ftp_user',
919 '_local_url',
920 '_meta\._alt',
921 '_meta\._caption',
922 '_meta\._description',
923 '_meta\._enabled',
924 '_meta\._title',
925 '_remote_url',
926 '_return'
927 ];
928
929 $tmp[preg_replace('/^(.+)(?<!\.settings)\.(' . implode('|', $ends_with) . ')$/', '$1.settings.$2', $field_id, -1, $count)] = $field_value;
930
931 if ($count > 0) {
932 $modified = true;
933 }
934 }
935
936 if (!$modified) {
937 continue;
938 }
939
940 $data['map'] = $tmp;
941
942
943 remove_filter('content_save_pre', 'wp_filter_post_kses');
944 wp_update_post(['ID' => $importer['ID'], 'post_content' => serialize($data)]);
945 add_filter('content_save_pre', 'wp_filter_post_kses');
946 }
947 }
948
949 /**
950 * Convert stored absolute importer file paths to uploads-relative paths.
951 *
952 * Prevents open_basedir warnings after hosting path / WordPress root changes.
953 *
954 * @param bool $migrate_data
955 * @return void
956 */
957 public function migration_10_relative_importer_file_paths($migrate_data = true)
958 {
959 if (!$migrate_data) {
960 return;
961 }
962
963 /**
964 * @var \wpdb $wpdb
965 */
966 global $wpdb;
967
968 $results = $wpdb->get_results(
969 "SELECT meta_id, post_id, meta_key, meta_value
970 FROM {$wpdb->postmeta}
971 WHERE meta_key LIKE '\\_importer\\_file\\_%'",
972 ARRAY_A
973 );
974
975 if (empty($results)) {
976 return;
977 }
978
979 foreach ($results as $row) {
980 $stored = $row['meta_value'];
981 if (!Filesystem::is_absolute_path($stored)) {
982 continue;
983 }
984
985 $resolved = Filesystem::resolve_importer_file_path($stored);
986 if (!$resolved) {
987 continue;
988 }
989
990 $relative = Filesystem::to_uploads_relative_path($resolved);
991 if ($relative === '' || $relative === $stored) {
992 continue;
993 }
994
995 update_post_meta((int) $row['post_id'], $row['meta_key'], $relative);
996 }
997 }
998 }
999