PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.3.2
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.3.2
3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 All 111 releases
← All changes | includes/Core/Importer/WPImport.php +153 -164 3.1.103.3.2 View file →
@@ -2,8 +2,9 @@
2 2
3 3 namespace Templately\Core\Importer;
4 4
5 5 use Templately\Core\Importer\Parsers\WXR_Parser;
6 +use Templately\Core\Importer\Runners\Loop;
6 7 use Templately\Core\Importer\Utils\Utils;
7 8 use Templately\Utils\Helper;
8 9 use WP_Error;
9 10 use WP_Importer;
@@ -47,8 +48,11 @@
47 48 }
48 49 }
49 50
50 51 class WPImport extends WP_Importer {
52 + use LogHelper;
53 + use Loop;
54 +
51 55 const DEFAULT_BUMP_REQUEST_TIMEOUT = 60;
52 56 const DEFAULT_ALLOW_CREATE_USERS = true;
53 57 const DEFAULT_IMPORT_ATTACHMENT_SIZE_LIMIT = 0; // 0 = unlimited.
54 58
@@ -119,8 +123,25 @@
119 123 private $terms_meta = [];
120 124
121 125 public static $_replace_image_ids = [];
122 126
127 +
128 + public $backup_attributes = [
129 + 'output',
130 + 'url_remap',
131 + '_replace_image_ids',
132 + 'menu_item_orphans',
133 + 'processed_menu_items',
134 + 'post_orphans',
135 + 'processed_posts',
136 + 'featured_images',
137 + 'mapped_terms_slug',
138 + 'processed_terms',
139 + 'processed_authors',
140 + 'author_mapping',
141 + ];
142 +
143 +
123 144 /**
124 145 * Parses filename from a Content-Disposition header value.
125 146 *
126 147 * As per RFC6266:
@@ -352,30 +373,8 @@
352 373 }
353 374 }
354 375 }
355 376
356 - private function retrieve_attributes($attributes){
357 - $params = $this->origin->get_request_params();
358 - $attr_values = $params["imported_data"][$this->import_data_key] ?? [];
359 - foreach ($attributes as $attribute) {
360 - if(isset($attr_values[$attribute])){
361 - $this->$attribute = $attr_values[$attribute];
362 - }
363 - }
364 - }
365 -
366 - private function backup_attributes($attributes){
367 - $params = $this->origin->get_request_params();
368 - $attr_values = $params["imported_data"][$this->import_data_key] ?? [];
369 -
370 - foreach ($attributes as $attribute) {
371 - if(isset($this->$attribute)){
372 - $attr_values[$attribute] = $this->$attribute;
373 - }
374 - }
375 - $this->origin->update_progress( null, [$this->import_data_key => $attr_values]);
376 - }
377 -
378 377 /**
379 378 * Map old author logins to local user IDs based on decisions made
380 379 * in import options form. Can map to an existing user, create a new user
381 380 * or falls back to the current user in case of error with either of the previous
@@ -384,17 +383,11 @@
384 383 if ( ! isset( $this->args['imported_authors'] ) ) {
385 384 return;
386 385 }
387 386
388 - $attributes = [
389 - 'processed_authors',
390 - 'author_mapping',
391 - 'output',
392 - ];
393 387
394 - $processed_templates = $this->origin->get_progress([], $this->import_data_key);
388 + $processed_templates = $this->get_progress([], $this->import_data_key);
395 389 if (!empty($processed_templates)) {
396 - $this->retrieve_attributes($attributes);
397 390 return;
398 391 }
399 392
400 393 $create_users = apply_filters( 'import_allow_create_users', self::DEFAULT_ALLOW_CREATE_USERS );
@@ -453,10 +446,9 @@
453 446 $this->author_mapping[ $santized_old_login ] = (int) get_current_user_id();
454 447 }
455 448 }
456 449
457 - $this->backup_attributes($attributes);
458 - $this->origin->update_progress( true, null, $this->import_data_key );
450 + $this->update_progress( true, null, $this->import_data_key );
459 451 }
460 452
461 453 /**
462 454 * Create new terms based on import information
@@ -465,23 +457,16 @@
465 457 *
466 458 * @return array|array[] the ids of succeed/failed imported terms.
467 459 */
468 460 private function process_terms(): array {
469 - $params = $this->origin->get_request_params();
470 - $result = $params["imported_data"]["wp_import_terms_" . $this->import_data_key] ?? [
461 + $result = [
471 462 'succeed' => [],
472 463 'failed' => [],
473 464 ];
474 465
475 - $attributes = [
476 - 'terms',
477 - 'output',
478 - 'mapped_terms_slug',
479 - 'processed_terms',
480 - ];
481 - $processed_templates = $this->origin->get_progress([], $this->import_data_key);
466 + $processed_templates = $this->get_progress([], "wp_import_terms_" . $this->import_data_key);
482 467 if (!empty($processed_templates)) {
483 - $this->retrieve_attributes($attributes);
468 + $result = $this->get_result([], "wp_import_terms_" . $this->import_data_key);
484 469 return $result;
485 470 }
486 471
487 472 $this->terms = apply_filters( 'wp_import_terms', $this->terms );
@@ -564,11 +549,10 @@
564 549 }
565 550
566 551 unset( $this->terms );
567 552
568 - $this->backup_attributes($attributes);
569 553 // Add the template to the processed templates and update the session data
570 - $this->origin->update_progress( true, [ "wp_import_terms_" . $this->import_data_key => $result ]);
554 + $this->update_progress( true, $result, "wp_import_terms_" . $this->import_data_key);
571 555 return $result;
572 556 }
573 557
574 558 /**
@@ -638,39 +622,18 @@
638 622 *
639 623 * @return array the ids of succeed/failed imported posts.
640 624 */
641 625 private function process_posts(): array {
642 - $backup_key = "wp_import_" . $this->import_data_key;
643 - $params = $this->origin->get_request_params();
644 - $result = $params["imported_data"][$backup_key] ?? [
645 - 'succeed' => [],
646 - 'failed' => [],
647 - ];
626 + $backup_key = "wp_import_post_" . $this->import_data_key;
648 627
649 - $attributes = [
650 - 'posts',
651 - 'output',
652 - 'menu_item_orphans',
653 - 'processed_menu_items',
654 - 'post_orphans',
655 - 'processed_posts',
656 - 'featured_images',
657 - ];
658 - $this->retrieve_attributes($attributes);
659 -
660 628 $this->posts = apply_filters( 'wp_import_posts', $this->posts );
661 629
662 - $processed_templates = $this->origin->get_progress([], $this->import_data_key);
630 + $results = $this->loop( $this->posts, function($key, $post, $result ) {
663 631
664 - foreach ( $this->posts as $key => $post ) {
665 - if (in_array($key, $processed_templates)) {
666 - continue;
667 - }
668 -
669 - // Add the template to the processed templates and update the session data
670 - $processed_templates[] = $key;
671 - $this->origin->update_progress( $processed_templates, null, $this->import_data_key);
672 -
632 + $result = !empty($result) ? $result : [
633 + 'succeed' => [],
634 + 'failed' => [],
635 + ];
673 636 $post = apply_filters( 'wp_import_post_data_raw', $post );
674 637
675 638 if ( ! post_type_exists( $post['post_type'] ) ) {
676 639 /* translators: 1: Post title, 2: Post type. */
@@ -675,17 +638,17 @@
675 638 if ( ! post_type_exists( $post['post_type'] ) ) {
676 639 /* translators: 1: Post title, 2: Post type. */
677 640 $this->output['errors'][] = sprintf( esc_html__( 'Failed to import %1$s: Invalid post type %2$s', 'elementor' ), $post['post_title'], $post['post_type'] );
678 641 do_action( 'wp_import_post_exists', $post );
679 - continue;
642 + return $result;
680 643 }
681 644
682 645 if ( isset( $this->processed_posts[ $post['post_id'] ] ) && ! empty( $post['post_id'] ) ) {
683 - continue;
646 + return $result;
684 647 }
685 648
686 649 if ( 'auto-draft' === $post['status'] ) {
687 - continue;
650 + return $result;
688 651 }
689 652
690 653 if(!empty($post['post_content']) && !empty($post['post_id'])){
691 654 $post['post_content'] = Utils::import_and_replace_attachments($post['post_content'], $post['post_id']);
@@ -692,15 +655,15 @@
692 655 }
693 656
694 657 if ( 'nav_menu_item' === $post['post_type'] ) {
695 658 $result['succeed'] += $this->process_menu_item( $post );
696 - continue;
659 + return $result;
697 660 }
698 661
699 662 if ( 'wp_navigation' === $post['post_type'] ) {
700 663 $processed = $this->process_navigation( $post );
701 664 if ( ! $processed ) {
702 - continue;
665 + return $result;
703 666 }
704 667 }
705 668
706 669 $post_type_object = get_post_type_object( $post['post_type'] );
@@ -747,9 +710,9 @@
747 710 $postdata = wp_slash( $postdata );
748 711
749 712 if ( 'attachment' === $postdata['post_type'] ) {
750 713 $remote_url = ! empty( $post['attachment_url'] ) ? $post['attachment_url'] : $post['guid'];
751 -
714 + $attachment_sizes = [];
752 715 // try to use _wp_attached file for upload folder placement to ensure the same location as the export site
753 716 // e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload()
754 717 $postdata['upload_date'] = $post['post_date'];
755 718 if ( isset( $post['postmeta'] ) ) {
@@ -757,14 +720,19 @@
757 720 if ( '_wp_attached_file' === $meta['key'] ) {
758 721 if ( preg_match( '%^[0-9]{4}/[0-9]{2}%', $meta['value'], $matches ) ) {
759 722 $postdata['upload_date'] = $matches[0];
760 723 }
761 - break;
724 + // break;
762 725 }
726 + else if ( '_wp_attachment_metadata' === $meta['key'] ) {
727 + $attachment_metadata = maybe_unserialize( $meta['value'] );
728 + $attachment_sizes = $attachment_metadata['sizes'] ?? [];
729 + // break;
730 + }
763 731 }
764 732 }
765 733
766 - $post_id = $this->process_attachment( $postdata, $remote_url );
734 + $post_id = $this->process_attachment( $postdata, $remote_url, $attachment_sizes, $original_post_id );
767 735 $comment_post_id = $post_id;
768 736 } else {
769 737 $post_id = wp_insert_post( $postdata, true );
770 738
@@ -785,22 +753,13 @@
785 753 $result['failed'][] = $original_post_id;
786 754
787 755 $this->output['errors'][] = $error;
788 756
789 - // Add the template to the processed templates and update the session data
790 - $this->backup_attributes($attributes);
791 - $this->origin->update_progress( null, [ $backup_key => $result ], $this->import_data_key);
757 + if ( 'attachment' === $postdata['post_type'] ) {
758 + do_action( 'templately_import.process_post', $post, $result, $this );
759 + }
792 760
793 - // If it's not the last item, send the SSE message and exit
794 - if( end($this->posts) !== $post) {
795 - $this->origin->sse_message( [
796 - 'type' => 'continue',
797 - 'action' => 'continue',
798 - 'results' => __METHOD__ . '::' . __LINE__,
799 - ] );
800 - exit;
801 - }
802 - continue;
761 + return $result;
803 762 }
804 763
805 764 $result['succeed'][ $original_post_id ] = $post_id;
806 765
@@ -955,26 +914,14 @@
955 914 }
956 915
957 916 do_action( 'templately_import.process_post', $post, $result, $this );
958 917
959 - // Add the template to the processed templates and update the session data
960 - $this->backup_attributes($attributes);
961 - $this->origin->update_progress( null, [ $backup_key => $result ], $this->import_data_key);
918 + return $result;
919 + }, $backup_key); //, true
962 920
963 - // If it's not the last item, send the SSE message and exit
964 - if( end($this->posts) !== $post) {
965 - $this->origin->sse_message( [
966 - 'type' => 'continue',
967 - 'action' => 'continue',
968 - 'results' => __METHOD__ . '::' . __LINE__,
969 - ] );
970 - exit;
971 - }
972 - }
973 -
974 921 unset( $this->posts );
975 922
976 - return $result;
923 + return $results;
977 924 }
978 925
979 926 /**
980 927 * Attempt to create a new menu item from import data
@@ -1155,9 +1102,9 @@
1155 1102 * @param string $url URL to fetch attachment from
1156 1103 *
1157 1104 * @return int|WP_Error Post ID on success, WP_Error otherwise
1158 1105 */
1159 - public function process_attachment( $post, $url, $sizes = [] ) {
1106 + public function process_attachment( $post, $url, $sizes = [], $original_post_id = null ) {
1160 1107 if ( ! $this->fetch_attachments ) {
1161 1108 return new WP_Error( 'attachment_processing_error', esc_html__( 'Fetching attachments is not enabled', 'elementor' ) );
1162 1109 }
1163 1110 if ( ! function_exists( 'wp_crop_image' ) ) {
@@ -1170,8 +1117,13 @@
1170 1117
1171 1118 if($saved_image = $this->get_saved_image($url)){
1172 1119 $this->url_remap[ $url ] = wp_get_attachment_url( $saved_image );
1173 1120 $this->url_remap[ $this->remove_extension($url) ] = $this->remove_extension(wp_get_attachment_url( $saved_image ));
1121 +
1122 + $full_size_path = get_attached_file($saved_image);
1123 + $metadata = wp_get_attachment_metadata($saved_image);
1124 + $metadata = $this->import_sizes($sizes, $metadata, $full_size_path, $saved_image);
1125 + wp_update_attachment_metadata( $saved_image, $metadata );
1174 1126 return $saved_image;
1175 1127 }
1176 1128
1177 1129 // Check if the URL is from the wp-includes/images directory
@@ -1193,10 +1145,19 @@
1193 1145 // Move the file to the uploads dir.
1194 1146 $file_name = basename( parse_url( $url, PHP_URL_PATH ) );
1195 1147 $file_name = wp_unique_filename( $upload_dir['path'], $file_name );
1196 1148 $dest_file = $upload_dir['path'] . "/$file_name";
1197 - $upload = $this->fetch_remote_file( $url, $dest_file, $upload_dir );
1149 + $start = microtime(true);
1198 1150
1151 + $upload = apply_filters( 'templately_import_copy_attachment', null, $original_post_id, $dest_file, $upload_dir );
1152 + if ( null === $upload ) {
1153 + $upload = $this->fetch_remote_file( $url, $dest_file, $upload_dir );
1154 + }
1155 +
1156 + $end = microtime(true);
1157 + $duration = $end - $start;
1158 + error_log('Duration: ' . $duration);
1159 +
1199 1160 if ( is_wp_error( $upload ) ) {
1200 1161 return $upload;
1201 1162 }
1202 1163
@@ -1212,8 +1173,12 @@
1212 1173
1213 1174 // As per wp-admin/includes/upload.php.
1214 1175 $post_id = wp_insert_attachment( $post, $upload['file'] );
1215 1176
1177 + if(is_wp_error($post_id)){
1178 + return $post_id;
1179 + }
1180 +
1216 1181 $this->update_post_meta( $post_id );
1217 1182
1218 1183 // Generate attachment metadata
1219 1184 $metadata = wp_generate_attachment_metadata( $post_id, $upload['file'] );
@@ -1220,9 +1185,9 @@
1220 1185
1221 1186 // error_log('Metadata: ' . print_r($metadata, true));
1222 1187
1223 1188 // For gutenberg pages
1224 - $metadata = $this->import_sizes($sizes, $metadata, $upload, $upload_dir, $post_id);
1189 + $metadata = $this->import_sizes($sizes, $metadata, $upload['file'], $post_id);
1225 1190
1226 1191 // error_log('Metadata: ' . print_r($metadata, true));
1227 1192 wp_update_attachment_metadata( $post_id, $metadata );
1228 1193
@@ -1425,9 +1390,9 @@
1425 1390 );
1426 1391
1427 1392 if ( $post_id ) {
1428 1393 self::$_replace_image_ids[ $hash ] = $post_id;
1429 - return $post_id;
1394 + return (int) $post_id;
1430 1395 }
1431 1396
1432 1397 return false;
1433 1398 }
@@ -1432,69 +1397,92 @@
1432 1397 return false;
1433 1398 }
1434 1399
1435 1400
1436 - public function extract_sizes($sizes) {
1437 - return array_reduce($sizes, function($carry, $url) {
1438 - if (preg_match('/-((\d+)x(\d+))\./', $url, $matches)) {
1439 - $carry[$matches[1]] = $url;
1440 - }
1441 - return $carry;
1442 - }, []);
1443 - }
1401 + public function import_sizes($sizes, $metadata, $full_size_file, $post_id) {
1402 + if (!empty($sizes)) {
1403 + do_action('templately_import.finalize_gutenberg_attachment', $post_id);
1444 1404
1445 - public function size_exists_in_metadata($size_dimension, $metadata) {
1446 - foreach ($metadata['sizes'] as $size => $size_info) {
1447 - if (strpos($size_info['file'], $size_dimension) !== false) {
1448 - return true;
1449 - }
1450 - }
1451 - return false;
1452 - }
1405 + foreach ($sizes as $size_name => $size) {
1406 + $size_dimension = $size['width'] . 'x' . $size['height'];
1407 + $size_name = !is_string($size_name) ? $size_dimension : $size_name;
1408 + $unique_destination_file = $this->create_unique_destination_file($full_size_file, $size);
1409 + // check non cropped sizes. with dynamic height
1410 + if (!$this->size_exists_in_metadata(basename($unique_destination_file), $metadata)) {
1411 + if ($unique_destination_file) {
1412 + $missing_size = $this->generate_missing_size_from_full($full_size_file, $unique_destination_file, $size);
1413 + if ($missing_size && !is_wp_error($missing_size)) {
1414 + unset($missing_size['path']);
1415 + $metadata['sizes'][$size_name] = $missing_size;
1416 + do_action('templately_import.finalize_gutenberg_attachment', $post_id, $size_dimension);
1417 + }
1418 + }
1419 + }
1420 + }
1421 + }
1422 + return $metadata;
1423 + }
1453 1424
1454 - public function create_unique_destination_file($upload_file, $size_dimension) {
1455 - $destination_file = preg_replace('/(\.[^.]+)$/', '-' . $size_dimension . '$1', $upload_file);
1456 - $destination_dir = pathinfo($destination_file, PATHINFO_DIRNAME);
1457 - $destination_filename = pathinfo($destination_file, PATHINFO_BASENAME);
1458 - $unique_filename = wp_unique_filename($destination_dir, $destination_filename);
1459 - return $destination_dir . '/' . $unique_filename;
1460 - }
1425 + public function generate_missing_size_from_full($full_size_file, $destination_file, $size) {
1426 + // Generate the missing size from the full-size image
1427 + $editor = wp_get_image_editor($full_size_file);
1428 + if (is_wp_error($editor)) {
1429 + return $editor;
1430 + }
1461 1431
1462 - public function create_size_array($destination_file, $size_dimension) {
1463 - list($width, $height) = explode('x', $size_dimension);
1464 - return array(
1465 - 'file' => basename($destination_file),
1466 - 'width' => $width,
1467 - 'height' => $height,
1468 - 'mime-type' => wp_check_filetype($destination_file)['type'],
1469 - 'filesize' => filesize($destination_file),
1470 - 'resized' => false,
1471 - );
1472 - }
1432 + $resized = $editor->resize($size['width'], $size['height'], true);
1433 + if (is_wp_error($resized)) {
1434 + return $resized;
1435 + }
1473 1436
1474 - public function import_sizes($sizes, $metadata, $upload, $upload_dir, $post_id) {
1475 - if (!empty($sizes)) {
1476 - do_action( 'templately_import.finalize_gutenberg_attachment', $post_id );
1437 + $saved = $editor->save($destination_file);
1438 + if (is_wp_error($saved)) {
1439 + return $saved;
1440 + }
1477 1441
1478 - $size_dimensions = $this->extract_sizes($sizes);
1479 - $size_dimensions = array_filter($size_dimensions);
1442 + return $saved;
1443 + }
1480 1444
1481 - foreach ($size_dimensions as $size_dimension => $__url) {
1482 - if (!$this->size_exists_in_metadata($size_dimension, $metadata)) {
1483 - $unique_destination_file = $this->create_unique_destination_file($upload['file'], $size_dimension);
1484 - $missing_size = $this->fetch_remote_file($__url, $unique_destination_file, $upload_dir);
1445 + public function size_exists_in_metadata($size_file, $metadata) {
1446 + if (isset($metadata['sizes']) && is_array($metadata['sizes'])) {
1447 + foreach ($metadata['sizes'] as $size => $size_info) {
1448 + if ($size_info['file'] == $size_file) {
1449 + return true;
1450 + }
1451 + }
1452 + }
1453 + return false;
1454 + }
1485 1455
1486 - if($missing_size && !is_wp_error($missing_size)) {
1487 - $metadata['sizes'][$size_dimension] = $this->create_size_array($unique_destination_file, $size_dimension);
1488 - do_action( 'templately_import.finalize_gutenberg_attachment', $post_id, $size_dimension );
1489 - }
1490 - }
1491 - }
1456 + public function create_unique_destination_file($full_size_file, $size) {
1457 + $pathinfo = pathinfo($full_size_file);
1458 + $directory = $pathinfo['dirname'];
1459 + $filename = $pathinfo['filename'];
1460 + $extension = $pathinfo['extension'];
1492 1461
1493 - }
1494 - return $metadata;
1495 - }
1462 + $destination_file = $directory . '/' . $filename . '-' . $size['width'] . 'x' . $size['height'] . '.' . $extension;
1496 1463
1464 + // Skip if the file already exists
1465 + if (file_exists($destination_file)) {
1466 + // return false;
1467 + }
1468 +
1469 + return $destination_file;
1470 + }
1471 +
1472 + public function create_size_array($destination_file, $size_dimension) {
1473 + list($width, $height) = explode('x', $size_dimension);
1474 + return array(
1475 + 'file' => basename($destination_file),
1476 + 'width' => $width,
1477 + 'height' => $height,
1478 + 'mime-type' => wp_check_filetype($destination_file)['type'],
1479 + 'filesize' => filesize($destination_file),
1480 + 'resized' => false,
1481 + );
1482 + }
1483 +
1484 +
1497 1485 /**
1498 1486 * Attempt to associate posts and menu items with previously missing parents
1499 1487 *
1500 1488 * An imported post's parent may not have been imported when it was first created
@@ -1612,9 +1600,9 @@
1612 1600 */
1613 1601 private function is_valid_meta_key( $key ) {
1614 1602 // Skip attachment metadata since we'll regenerate it from scratch.
1615 1603 // Skip _edit_lock as not relevant for import
1616 - if ( in_array( $key, [ '_wp_attached_file', '_wp_attachment_metadata', '_edit_lock' ] ) ) {
1604 + if ( in_array( $key, [ '_wp_attached_file', '_wp_attachment_metadata', '_edit_lock', '_elementor_source_image_hash', 'sm_cloud' ] ) ) {
1617 1605 return false;
1618 1606 }
1619 1607
1620 1608 return $key;
@@ -1680,9 +1668,10 @@
1680 1668 */
1681 1669 public function __construct( $file, array $args = [] ) {
1682 1670 parent::__construct();
1683 1671
1684 - $this->args = $args;
1672 + $this->args = $args;
1673 + $this->session_id = $args['session_id'];
1685 1674
1686 1675 if ( ! empty( $args['json'] ) ) {
1687 1676 $this->json = $args['json'];
1688 1677 }