Import any XML or CSV File to WordPress - Version 3.6.6

Version Description

  • bug fix: jQuery nestedSortable compatibility with WordPress 5.9
Download this release

Release Info

Developer soflyy
Plugin Icon 128x128 Import any XML or CSV File to WordPress
Version 3.6.6
Comparing to
See all releases

Code changes from version 3.6.5 to 3.6.6

helpers/wp_all_import_base64_decode_image.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if( !function_exists('wp_all_import_base64_decode_image')){
3
+ function wp_all_import_base64_decode_image( $image ){
4
+ // Only check the base64 portion of image references.
5
+ $matches = [];
6
+ preg_match('@(data:image/.{1,6};base64,)(.*)@', $image, $matches);
7
+
8
+ // Set image to only the base64 encoded portion if detected.
9
+ $image = isset($matches[2]) ? $matches[2] : $image;
10
+
11
+ return base64_decode($image);
12
+ }
13
+ }
helpers/wp_all_import_is_base64_encoded.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( !function_exists('wp_all_import_is_base64_encoded')){
4
+ function wp_all_import_is_base64_encoded($data){
5
+
6
+ // Only check the base64 portion of image references.
7
+ $matches = [];
8
+ preg_match('@(data:image/.{1,6};base64,)(.*)@', $data, $matches);
9
+
10
+ // Set data to only the base64 encoded portion if detected.
11
+ $data = isset($matches[2]) ? $matches[2] : $data;
12
+
13
+ $decoded = base64_decode($data, true);
14
+
15
+ // Check if there is no invalid character in string
16
+ if (!preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $data)) return false;
17
+
18
+ // Decode the string in strict mode and send the response
19
+ if (!$decoded) return false;
20
+
21
+ // Encode and compare it to original one
22
+ if (base64_encode($decoded) != $data) return false;
23
+
24
+ return true;
25
+
26
+ }
27
+ }
models/import/record.php CHANGED
@@ -4,17 +4,17 @@ class PMXI_Import_Record extends PMXI_Model_Record {
4
 
5
  public static $cdata = array();
6
 
7
- protected $errors;
8
-
9
  /**
10
  * Some pre-processing logic, such as removing control characters from xml to prevent parsing errors
11
  * @param string $xml
12
  */
13
  public static function preprocessXml( &$xml ) {
14
-
15
- if ( empty(PMXI_Plugin::$session->is_csv) and empty(PMXI_Plugin::$is_csv)){
16
-
17
- self::$cdata = array();
18
 
19
  $is_preprocess_enabled = apply_filters('is_xml_preprocess_enabled', true);
20
 
@@ -29,8 +29,8 @@ class PMXI_Import_Record extends PMXI_Model_Record {
29
  $xml = str_replace('{{CPLACE_' . ($key + 1) . '}}', $val, $xml);
30
  }
31
  }
32
- }
33
- }
34
  }
35
 
36
  /**
@@ -43,16 +43,16 @@ class PMXI_Import_Record extends PMXI_Model_Record {
43
  if (FALSE === $xml or '' == $xml) {
44
  $errors and $errors->add('form-validation', __('WP All Import can\'t read your file.<br/><br/>Probably, you are trying to import an invalid XML feed. Try opening the XML feed in a web browser (Google Chrome is recommended for opening XML files) to see if there is an error message.<br/>Alternatively, run the feed through a validator: http://validator.w3.org/<br/>99% of the time, the reason for this error is because your XML feed isn\'t valid.<br/>If you are 100% sure you are importing a valid XML feed, please contact WP All Import support.', 'wp_all_import_plugin'));
45
  } else {
46
-
47
- PMXI_Import_Record::preprocessXml($xml);
48
 
49
  if ( function_exists('simplexml_load_string')){
50
  libxml_use_internal_errors(true);
51
  libxml_clear_errors();
52
  $_x = @simplexml_load_string($xml);
53
- $xml_errors = libxml_get_errors();
54
  libxml_clear_errors();
55
- if ($xml_errors) {
56
  $error_msg = '<strong>' . __('Invalid XML', 'wp_all_import_plugin') . '</strong><ul>';
57
  foreach($xml_errors as $error) {
58
  $error_msg .= '<li>';
@@ -63,14 +63,14 @@ class PMXI_Import_Record extends PMXI_Model_Record {
63
  $error_msg .= '</li>';
64
  }
65
  $error_msg .= '</ul>';
66
- $errors and $errors->add('form-validation', $error_msg);
67
  } else {
68
  return true;
69
  }
70
  }
71
  else{
72
- $errors and $errors->add('form-validation', __('Required PHP components are missing.', 'wp_all_import_plugin'));
73
- $errors and $errors->add('form-validation', __('WP All Import requires the SimpleXML PHP module to be installed. This is a standard feature of PHP, and is necessary for WP All Import to read the files you are trying to import.<br/>Please contact your web hosting provider and ask them to install and activate the SimpleXML PHP module.', 'wp_all_import_plugin'));
74
  }
75
  }
76
  return false;
@@ -673,7 +673,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
673
 
674
  return $result;
675
  }
676
-
677
  public $post_meta_to_insert = array();
678
 
679
  public function is_parsing_required( $option ){
@@ -694,15 +694,15 @@ class PMXI_Import_Record extends PMXI_Model_Record {
694
  $cxpath = $xpath_prefix . $this->xpath;
695
 
696
  $this->options += PMXI_Plugin::get_default_import_options(); // make sure all options are defined
697
-
698
  $avoid_pingbacks = PMXI_Plugin::getInstance()->getOption('pingbacks');
699
 
700
  $cron_sleep = (int) PMXI_Plugin::getInstance()->getOption('cron_sleep');
701
-
702
  if ( $avoid_pingbacks and ! defined( 'WP_IMPORTING' ) ) define( 'WP_IMPORTING', true );
703
 
704
- $postRecord = new PMXI_Post_Record();
705
-
706
  $tmp_files = array();
707
  // compose records to import
708
  $records = array();
@@ -725,7 +725,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
725
 
726
  $chunk == 1 and $logger and call_user_func($logger, __('Composing titles...', 'wp_all_import_plugin'));
727
  if ( ! empty($this->options['title'])){
728
- $titles = XmlImportParser::factory($xml, $cxpath, $this->options['title'], $file)->parse($records); $tmp_files[] = $file;
729
  }
730
  else{
731
  $loop and $titles = array_fill(0, $loop, '');
@@ -771,18 +771,18 @@ class PMXI_Import_Record extends PMXI_Model_Record {
771
  }
772
 
773
  if ( "xpath" == $this->options['status'] ){
774
- $chunk == 1 and $logger and call_user_func($logger, __('Composing statuses...', 'wp_all_import_plugin'));
775
  $post_status = array();
776
  if ( ! empty($this->options['status_xpath']) && $this->is_parsing_required('is_update_status') ){
777
- $post_status = XmlImportParser::factory($xml, $cxpath, $this->options['status_xpath'], $file)->parse($records); $tmp_files[] = $file;
778
  }
779
  else{
780
  count($titles) and $post_status = array_fill(0, count($titles), 'publish');
781
  }
782
  }
783
-
784
  if ( "xpath" == $this->options['comment_status'] ){
785
- $chunk == 1 and $logger and call_user_func($logger, __('Composing comment statuses...', 'wp_all_import_plugin'));
786
  $comment_status = array();
787
  if (!empty($this->options['comment_status_xpath']) && $this->is_parsing_required('is_update_comment_status') ){
788
  $comment_status = XmlImportParser::factory($xml, $cxpath, $this->options['comment_status_xpath'], $file)->parse($records); $tmp_files[] = $file;
@@ -793,7 +793,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
793
  }
794
 
795
  if ( "xpath" == $this->options['ping_status'] ){
796
- $chunk == 1 and $logger and call_user_func($logger, __('Composing ping statuses...', 'wp_all_import_plugin'));
797
  $ping_status = array();
798
  if (!empty($this->options['ping_status_xpath'])){
799
  $ping_status = XmlImportParser::factory($xml, $cxpath, $this->options['ping_status_xpath'], $file)->parse($records); $tmp_files[] = $file;
@@ -804,7 +804,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
804
  }
805
 
806
  if ( "xpath" == $this->options['post_format'] ){
807
- $chunk == 1 and $logger and call_user_func($logger, __('Composing post formats...', 'wp_all_import_plugin'));
808
  $post_format = array();
809
  if (!empty($this->options['post_format_xpath'])){
810
  $post_format = XmlImportParser::factory($xml, $cxpath, $this->options['post_format_xpath'], $file)->parse($records); $tmp_files[] = $file;
@@ -827,7 +827,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
827
  }
828
 
829
  if ( "no" == $this->options['is_multiple_page_template'] ){
830
- $chunk == 1 and $logger and call_user_func($logger, __('Composing page templates...', 'wp_all_import_plugin'));
831
  $page_template = array();
832
  if (!empty($this->options['single_page_template'])){
833
  $page_template = XmlImportParser::factory($xml, $cxpath, $this->options['single_page_template'], $file)->parse($records); $tmp_files[] = $file;
@@ -835,7 +835,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
835
  else{
836
  count($titles) and $page_template = array_fill(0, count($titles), 'default');
837
  }
838
- }
839
 
840
  if ( $this->options['is_override_post_type'] and ! empty($this->options['post_type_xpath']) ){
841
  $chunk == 1 and $logger and call_user_func($logger, __('Composing post types...', 'wp_all_import_plugin'));
@@ -852,7 +852,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
852
  }
853
 
854
  if ( "no" == $this->options['is_multiple_page_parent'] ){
855
- $chunk == 1 and $logger and call_user_func($logger, __('Composing page parent...', 'wp_all_import_plugin'));
856
  $page_parent = array();
857
  if ( ! empty($this->options['single_page_parent']) && $this->is_parsing_required('is_update_parent') ){
858
  $page_parent = XmlImportParser::factory($xml, $cxpath, $this->options['single_page_parent'], $file)->parse($records); $tmp_files[] = $file;
@@ -903,7 +903,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
903
  count($titles) and $post_author = array_fill(0, count($titles), $current_user->ID);
904
  }
905
 
906
- $chunk == 1 and $logger and call_user_func($logger, __('Composing slugs...', 'wp_all_import_plugin'));
907
  $post_slug = array();
908
  if (!empty($this->options['post_slug']) && $this->is_parsing_required('is_update_slug') ){
909
  $post_slug = XmlImportParser::factory($xml, $cxpath, $this->options['post_slug'], $file)->parse($records); $tmp_files[] = $file;
@@ -920,7 +920,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
920
  count($titles) and $is_image_featured = array_fill(0, count($titles), '');
921
  }
922
 
923
- $chunk == 1 and $logger and call_user_func($logger, __('Composing menu order...', 'wp_all_import_plugin'));
924
  $menu_order = array();
925
  if (!empty($this->options['order']) && $this->is_parsing_required('is_update_menu_order')){
926
  $menu_order = XmlImportParser::factory($xml, $cxpath, $this->options['order'], $file)->parse($records); $tmp_files[] = $file;
@@ -929,19 +929,19 @@ class PMXI_Import_Record extends PMXI_Model_Record {
929
  count($titles) and $menu_order = array_fill(0, count($titles), '');
930
  }
931
 
932
- $chunk == 1 and $logger and call_user_func($logger, __('Composing contents...', 'wp_all_import_plugin'));
933
  if (!empty($this->options['content']) && $this->is_parsing_required('is_update_content') ){
934
  $contents = XmlImportParser::factory(
935
  ((!empty($this->options['is_keep_linebreaks']) and intval($this->options['is_keep_linebreaks'])) ? $xml : preg_replace('%\r\n?|\n%', ' ', $xml)),
936
  $cxpath,
937
  $this->options['content'],
938
  $file)->parse($records
939
- ); $tmp_files[] = $file;
940
  }
941
  else{
942
  count($titles) and $contents = array_fill(0, count($titles), '');
943
  }
944
-
945
  $chunk == 1 and $logger and call_user_func($logger, __('Composing dates...', 'wp_all_import_plugin'));
946
  if ( $this->is_parsing_required('is_update_dates') ){
947
  if ('specific' == $this->options['date_type']) {
@@ -981,11 +981,11 @@ class PMXI_Import_Record extends PMXI_Model_Record {
981
  else{
982
  count($titles) and $dates = array_fill(0, count($titles), date('Y-m-d H:i:s', strtotime(current_time('mysql'))));
983
  }
984
-
985
  // [custom taxonomies]
986
  require_once(ABSPATH . 'wp-admin/includes/taxonomy.php');
987
 
988
- $taxonomies = array();
989
  $exclude_taxonomies = apply_filters('pmxi_exclude_taxonomies', (class_exists('PMWI_Plugin')) ? array('post_format', 'product_type', 'product_shipping_class', 'product_visibility') : array('post_format'));
990
  $post_taxonomies = array_diff_key(get_taxonomies_by_object_type(array($this->options['custom_type']), 'object'), array_flip($exclude_taxonomies));
991
  if ( $this->is_parsing_required('is_update_categories') && ! empty($post_taxonomies) && ! in_array($this->options['custom_type'], array('import_users', 'taxonomies', 'shop_customer', 'comments', 'woo_reviews')) ):
@@ -998,7 +998,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
998
  switch ($this->options['tax_logic'][$tx_name]){
999
  case 'single':
1000
  if ( isset($this->options['tax_single_xpath'][$tx_name]) && $this->options['tax_single_xpath'][$tx_name] !== "" ){
1001
- $txes = XmlImportParser::factory($xml, $cxpath, $this->options['tax_single_xpath'][$tx_name], $file)->parse($records); $tmp_files[] = $file;
1002
  foreach ($txes as $i => $tx) {
1003
  $taxonomies[$tx_name][$i][] = wp_all_import_ctx_mapping(array(
1004
  'name' => $tx,
@@ -1008,28 +1008,28 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1008
  'hierarchy_level' => 1,
1009
  'max_hierarchy_level' => 1
1010
  ), $mapping_rules, $tx_name);
1011
- }
1012
  }
1013
  break;
1014
  case 'multiple':
1015
  if ( ! empty($this->options['tax_multiple_xpath'][$tx_name]) ){
1016
- $txes = XmlImportParser::factory($xml, $cxpath, $this->options['tax_multiple_xpath'][$tx_name], $file)->parse($records); $tmp_files[] = $file;
1017
  foreach ($txes as $i => $tx) {
1018
  $_tx = $tx;
1019
  // apply mapping rules before splitting via separator symbol
1020
- if ( ! empty($this->options['tax_enable_mapping'][$tx_name]) and ! empty($this->options['tax_logic_mapping'][$tx_name]) ){
1021
- if ( ! empty( $mapping_rules) ){
1022
  foreach ($mapping_rules as $rule) {
1023
- if ( ! empty($rule[trim($_tx)])){
1024
  $_tx = trim($rule[trim($_tx)]);
1025
  break;
1026
  }
1027
  }
1028
  }
1029
- }
1030
- $delimeted_taxonomies = explode( ! empty($this->options['tax_multiple_delim'][$tx_name]) ? $this->options['tax_multiple_delim'][$tx_name] : ',', $_tx);
1031
  if ( ! empty($delimeted_taxonomies) ){
1032
- foreach ($delimeted_taxonomies as $cc) {
1033
  $taxonomies[$tx_name][$i][] = wp_all_import_ctx_mapping(array(
1034
  'name' => $cc,
1035
  'parent' => false,
@@ -1039,28 +1039,28 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1039
  'max_hierarchy_level' => 1
1040
  ), $mapping_rules, $tx_name);
1041
  }
1042
- }
1043
  }
1044
  }
1045
  break;
1046
  case 'hierarchical':
1047
- if ( ! empty($this->options['tax_hierarchical_logic_entire'][$tx_name])){
1048
  if (! empty($this->options['tax_hierarchical_xpath'][$tx_name]) and is_array($this->options['tax_hierarchical_xpath'][$tx_name])){
1049
  count($titles) and $iterator = array_fill(0, count($titles), 0);
1050
  $taxonomies_hierarchy_groups = array_fill(0, count($titles), array());
1051
-
1052
  // separate hierarchy groups via symbol
1053
  if ( ! empty($this->options['is_tax_hierarchical_group_delim'][$tx_name]) and ! empty($this->options['tax_hierarchical_group_delim'][$tx_name])){
1054
- foreach ($this->options['tax_hierarchical_xpath'][$tx_name] as $k => $tx_xpath) {
1055
  if (empty($tx_xpath)) continue;
1056
- $txes = XmlImportParser::factory($xml, $cxpath, $tx_xpath, $file)->parse($records); $tmp_files[] = $file;
1057
  foreach ($txes as $i => $tx) {
1058
  $_tx = $tx;
1059
  // apply mapping rules before splitting via separator symbol
1060
- if ( ! empty($this->options['tax_enable_mapping'][$tx_name]) and ! empty($this->options['tax_logic_mapping'][$tx_name]) ){
1061
- if ( ! empty( $mapping_rules) ){
1062
  foreach ($mapping_rules as $rule) {
1063
- if ( ! empty($rule[trim($_tx)])){
1064
  $_tx = trim($rule[trim($_tx)]);
1065
  break;
1066
  }
@@ -1073,27 +1073,27 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1073
  if ( ! empty($group) ) array_push($taxonomies_hierarchy_groups[$i], $group);
1074
  }
1075
  }
1076
- }
1077
  }
1078
  }
1079
  else{
1080
  foreach ($this->options['tax_hierarchical_xpath'][$tx_name] as $k => $tx_xpath) {
1081
  if (empty($tx_xpath)) continue;
1082
- $txes = XmlImportParser::factory($xml, $cxpath, $tx_xpath, $file)->parse($records); $tmp_files[] = $file;
1083
- foreach ($txes as $i => $tx) {
1084
  array_push($taxonomies_hierarchy_groups[$i], $tx);
1085
  }
1086
  }
1087
  }
1088
-
1089
  foreach ($taxonomies_hierarchy_groups as $i => $groups) { if (empty($groups)) continue;
1090
- foreach ($groups as $kk => $tx) {
1091
  $_tx = $tx;
1092
  // apply mapping rules before splitting via separator symbol
1093
- if ( ! empty($this->options['tax_enable_mapping'][$tx_name]) and ! empty($this->options['tax_logic_mapping'][$tx_name]) ){
1094
- if ( ! empty( $mapping_rules) ){
1095
- foreach ($mapping_rules as $rule) {
1096
- if ( ! empty($rule[trim($_tx)])){
1097
  $_tx = trim($rule[trim($_tx)]);
1098
  break;
1099
  }
@@ -1101,8 +1101,8 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1101
  }
1102
  }
1103
  $delimeted_taxonomies = array_filter(array_filter(explode( ! empty($this->options['tax_hierarchical_delim'][$tx_name]) ? $this->options['tax_hierarchical_delim'][$tx_name] : ',', $_tx)));
1104
- if ( ! empty($delimeted_taxonomies) ){
1105
- foreach ($delimeted_taxonomies as $j => $cc) {
1106
  $is_assign_term = true;
1107
  if ( ! empty($this->options['tax_hierarchical_last_level_assign'][$tx_name]) ){
1108
  $is_assign_term = (count($delimeted_taxonomies) == $j + 1) ? 1 : 0;
@@ -1115,52 +1115,52 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1115
  'hierarchy_level' => $j + 1,
1116
  'max_hierarchy_level' => count($delimeted_taxonomies)
1117
  ), $mapping_rules, $tx_name);
1118
- $iterator[$i]++;
1119
  }
1120
- }
1121
  }
1122
- }
1123
  }
1124
  }
1125
- if ( ! empty($this->options['tax_hierarchical_logic_manual'][$tx_name])){
1126
  if ( ! empty($this->options['post_taxonomies'][$tx_name]) ){
1127
  $taxonomies_hierarchy = json_decode($this->options['post_taxonomies'][$tx_name], true);
1128
-
1129
- foreach ($taxonomies_hierarchy as $k => $taxonomy){ if ("" == $taxonomy['xpath']) continue;
1130
- $txes_raw = XmlImportParser::factory($xml, $cxpath, $taxonomy['xpath'], $file)->parse($records); $tmp_files[] = $file;
1131
  $warned = array();
1132
-
1133
  foreach ($txes_raw as $i => $cc) {
1134
 
1135
  $_tx = $cc;
1136
  // apply mapping rules before splitting via separator symbol
1137
- if ( ! empty($this->options['tax_enable_mapping'][$tx_name]) and ! empty($this->options['tax_logic_mapping'][$tx_name]) ){
1138
- if ( ! empty( $mapping_rules) ){
1139
  foreach ($mapping_rules as $rule) {
1140
- if ( ! empty($rule[trim($_tx)])){
1141
  $_tx = trim($rule[trim($_tx)]);
1142
  break;
1143
  }
1144
  }
1145
  }
1146
  }
1147
-
1148
  if ( ! empty($this->options['tax_manualhierarchy_delim'][$tx_name])){
1149
  $delimeted_taxonomies = explode($this->options['tax_manualhierarchy_delim'][$tx_name], $_tx);
1150
  }
1151
-
1152
  if ( empty($delimeted_taxonomies) ) continue;
1153
 
1154
  if (empty($taxonomies_hierarchy[$k]['txn_names'][$i])) $taxonomies_hierarchy[$k]['txn_names'][$i] = array();
1155
  if (empty($taxonomies[$tx_name][$i])) $taxonomies[$tx_name][$i] = array();
1156
- $count_cats = count($taxonomies[$tx_name][$i]);
1157
-
1158
  foreach ($delimeted_taxonomies as $j => $dc) {
1159
-
1160
- if (!empty($taxonomy['parent_id'])) {
1161
  foreach ($taxonomies_hierarchy as $key => $value){
1162
- if ($value['item_id'] == $taxonomy['parent_id'] and !empty($value['txn_names'][$i])){
1163
- foreach ($value['txn_names'][$i] as $parent) {
1164
  $taxonomies[$tx_name][$i][] = wp_all_import_ctx_mapping(array(
1165
  'name' => trim($dc),
1166
  'parent' => $parent,
@@ -1171,11 +1171,11 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1171
  ), $mapping_rules, $tx_name);
1172
 
1173
  $taxonomies_hierarchy[$k]['txn_names'][$i][] = $taxonomies[$tx_name][$i][count($taxonomies[$tx_name][$i]) - 1];
1174
- }
1175
  }
1176
- }
1177
  }
1178
- else {
1179
  $taxonomies[$tx_name][$i][] = wp_all_import_ctx_mapping(array(
1180
  'name' => trim($dc),
1181
  'parent' => false,
@@ -1187,35 +1187,35 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1187
 
1188
  $taxonomies_hierarchy[$k]['txn_names'][$i][] = $taxonomies[$tx_name][$i][count($taxonomies[$tx_name][$i]) - 1];
1189
  }
1190
- }
1191
  }
1192
  }
1193
  }
1194
- }
1195
  break;
1196
 
1197
  default:
1198
-
1199
  break;
1200
  }
1201
  }
1202
  endforeach;
1203
- endif;
1204
  // [/custom taxonomies]
1205
 
1206
  // Composing featured images
1207
- $image_sections = apply_filters('wp_all_import_image_sections', array(
1208
  array(
1209
  'slug' => '',
1210
  'title' => __('Images', 'wp_all_import_plugin'),
1211
  'type' => 'images'
1212
  )
1213
- ));
1214
 
1215
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
1216
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'wp_all_import_plugin') . ': ' . $uploads['error']);
1217
- $logger and call_user_func($logger, __('<b>WARNING</b>: No featured images will be created. Uploads folder is not found.', 'wp_all_import_plugin'));
1218
- $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1219
  } else {
1220
  $images_bundle = array();
1221
  $auto_rename_images_bundle = array();
@@ -1331,8 +1331,8 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1331
 
1332
  // Composing attachments
1333
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
1334
- $logger and call_user_func($logger, __('<b>WARNING</b>', 'wp_all_import_plugin') . ': ' . $uploads['error']);
1335
- $logger and call_user_func($logger, __('<b>WARNING</b>: No attachments will be created', 'wp_all_import_plugin'));
1336
  $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1337
  } else {
1338
  $chunk == 1 and $logger and call_user_func($logger, __('Composing URLs for attachments files...', 'wp_all_import_plugin'));
@@ -1346,12 +1346,12 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1346
  foreach($atchs as $atch) if (!preg_match("/{.*}/", trim($atch))) $parse_multiple = false;
1347
  if ($parse_multiple) {
1348
  foreach($atchs as $atch) {
1349
- $posts_attachments = XmlImportParser::factory($xml, $cxpath, trim($atch), $file)->parse($records); $tmp_files[] = $file;
1350
- foreach($posts_attachments as $i => $val) $attachments[$i][] = $val;
1351
  }
1352
  }
1353
  else {
1354
- $attachments = XmlImportParser::factory($xml, $cxpath, $this->options['attachments'], $file)->parse($records); $tmp_files[] = $file;
1355
  }
1356
  }
1357
  } else {
@@ -1367,7 +1367,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1367
  count($titles) and $unique_keys = array_fill(0, count($titles), '');
1368
  }
1369
 
1370
- $chunk == 1 and $logger and call_user_func($logger, __('Processing posts...', 'wp_all_import_plugin'));
1371
 
1372
  $addons = array();
1373
  $addons_data = array();
@@ -1380,32 +1380,32 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1380
  'xml' => $xml,
1381
  'logger' => $logger,
1382
  'chunk' => $chunk,
1383
- 'xpath_prefix' => $xpath_prefix
1384
  );
1385
  $parse_functions = apply_filters('wp_all_import_addon_parse', array());
1386
- foreach (PMXI_Admin_Addons::get_active_addons() as $class) {
1387
- $model_class = str_replace("_Plugin", "_Import_Record", $class);
1388
- if (class_exists($model_class)){
1389
  $addons[$class] = new $model_class();
1390
- $addons_data[$class] = ( method_exists($addons[$class], 'parse') ) ? $addons[$class]->parse($parsingData) : false;
1391
  } else {
1392
  if ( ! empty($parse_functions[$class]) ){
1393
  if ( is_array($parse_functions[$class]) and is_callable($parse_functions[$class]) or ! is_array($parse_functions[$class]) and function_exists($parse_functions[$class]) ){
1394
- $addons_data[$class] = call_user_func($parse_functions[$class], $parsingData);
1395
  }
1396
  }
1397
  }
1398
  }
1399
 
1400
- // save current import state to variables before import
1401
  $created = $this->created;
1402
  $updated = $this->updated;
1403
- $skipped = $this->skipped;
1404
-
1405
  $specified_records = array();
1406
 
1407
  $simpleXml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
1408
-
1409
  $rootNodes = $simpleXml->xpath($cxpath);
1410
 
1411
  if ($this->options['is_import_specified']) {
@@ -1436,21 +1436,21 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1436
  break;
1437
  }
1438
 
1439
- if ($is_cron and $cron_sleep) sleep($cron_sleep);
1440
 
1441
  $logger and call_user_func($logger, __('---', 'wp_all_import_plugin'));
1442
  $logger and call_user_func($logger, sprintf(__('Record #%s', 'wp_all_import_plugin'), $this->imported + $this->skipped + $i + 1));
1443
 
1444
- if ( "manual" == $this->options['duplicate_matching']
1445
- and ! empty($specified_records)
1446
  and ! in_array($created + $updated + $skipped + 1, $specified_records) )
1447
  {
1448
- $skipped++;
1449
  $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'wp_all_import_plugin'));
1450
- $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1451
  $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1452
- $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1453
- continue;
1454
  }
1455
 
1456
  $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_before_post_import ...', 'wp_all_import_plugin'));
@@ -1468,7 +1468,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1468
  $logger and call_user_func($logger, __('<b>WARNING</b>: title is empty.', 'wp_all_import_plugin'));
1469
  $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1470
  }
1471
- }
1472
 
1473
  switch ($this->options['custom_type']){
1474
  case 'import_users':
@@ -1578,19 +1578,19 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1578
  // }
1579
  break;
1580
  }
1581
-
1582
  // Re-import Records Matching
1583
  $post_to_update = false; $post_to_update_id = false;
1584
 
1585
  // An array representation of current XML node
1586
- $current_xml_node = wp_all_import_xml2array($rootNodes[$i]);
1587
 
1588
  $check_for_duplicates = apply_filters('wp_all_import_is_check_duplicates', true, $this->id);
1589
 
1590
  if ( $check_for_duplicates ) {
1591
  // if Auto Matching re-import option selected
1592
  if ( "manual" != $this->options['duplicate_matching'] ) {
1593
- // find corresponding article among previously imported
1594
  $logger and call_user_func($logger, sprintf(__('Find corresponding article among previously imported for post `%s`...', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1595
  $postList = new PMXI_Post_List();
1596
  $args = array(
@@ -1622,17 +1622,17 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1622
  if (empty($post_to_update)) {
1623
  $logger and call_user_func($logger, sprintf(__('Duplicate post wasn\'t found with unique key `%s`...', 'wp_all_import_plugin'), wp_all_import_clear_xss($unique_keys[$i])));
1624
  }
1625
-
1626
  // if Manual Matching re-import option seleted
1627
  } else {
1628
-
1629
  if ('custom field' == $this->options['duplicate_indicator']) {
1630
  $custom_duplicate_value = XmlImportParser::factory($xml, $cxpath, $this->options['custom_duplicate_value'], $file)->parse($records); $tmp_files[] = $file;
1631
  $custom_duplicate_name = XmlImportParser::factory($xml, $cxpath, $this->options['custom_duplicate_name'], $file)->parse($records); $tmp_files[] = $file;
1632
  } else {
1633
  count($titles) and $custom_duplicate_name = $custom_duplicate_value = array_fill(0, count($titles), '');
1634
  }
1635
-
1636
  $logger and call_user_func($logger, sprintf(__('Find corresponding article among database for post `%s`...', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1637
 
1638
  $duplicates = array();
@@ -1676,7 +1676,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1676
  $logger and call_user_func($logger, sprintf(__('Duplicate post wasn\'t found for post `%s`...', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1677
  }
1678
  }
1679
- }
1680
 
1681
  $is_post_to_skip = apply_filters('wp_all_import_is_post_to_skip', false, $this->id, $current_xml_node, $i, $post_to_update_id, $simpleXml);
1682
 
@@ -1685,25 +1685,25 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1685
  $postRecord->set(array('iteration' => $this->iteration))->update();
1686
  }
1687
  $skipped++;
1688
- $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1689
  $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1690
- $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1691
- continue;
1692
- }
1693
 
1694
  if ( ! empty($specified_records) ) {
1695
  if ( ! in_array($created + $updated + $skipped + 1, $specified_records) ) {
1696
  if ( ! $postRecord->isEmpty() ) {
1697
  $postRecord->set(array('iteration' => $this->iteration))->update();
1698
  }
1699
- $skipped++;
1700
  $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'wp_all_import_plugin'));
1701
- $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1702
  $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1703
- $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1704
  continue;
1705
- }
1706
- }
1707
 
1708
  $missing_images = array();
1709
  // Duplicate record is found
@@ -1715,13 +1715,13 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1715
 
1716
  if ( ! $continue_import ){
1717
 
1718
- if ( ! $postRecord->isEmpty() ) $postRecord->set(array('iteration' => $this->iteration))->update();
1719
 
1720
  $skipped++;
1721
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: By filter wp_all_import_is_post_to_update `%s`', 'wp_all_import_plugin'), $articleData['post_title']));
1722
- $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1723
- $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1724
- $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1725
  do_action('wp_all_import_post_skipped', $post_to_update_id, $this->id, $current_xml_node);
1726
  continue;
1727
  }
@@ -1729,17 +1729,17 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1729
  //$logger and call_user_func($logger, sprintf(__('Duplicate record is found for `%s`', 'wp_all_import_plugin'), $articleData['post_title']));
1730
 
1731
  // Do not update already existing records option selected
1732
- if ("yes" == $this->options['is_keep_former_posts']) {
1733
 
1734
- if ( ! $postRecord->isEmpty() ) $postRecord->set(array('iteration' => $this->iteration))->update();
1735
 
1736
  do_action('pmxi_do_not_update_existing', $post_to_update_id, $this->id, $this->iteration, $xml, $i);
1737
 
1738
  $skipped++;
1739
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: Previously imported record found for `%s`', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1740
- $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1741
- $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1742
- $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1743
  do_action('wp_all_import_post_skipped', $post_to_update_id, $this->id, $current_xml_node);
1744
  continue;
1745
  }
@@ -1963,29 +1963,29 @@ class PMXI_Import_Record extends PMXI_Model_Record {
1963
  }
1964
  }
1965
  elseif ( ! $postRecord->isEmpty() ){
1966
-
1967
  // existing post not found though it's track was found... clear the leftover, plugin will continue to treat record as new
1968
  $postRecord->clear();
1969
-
1970
- }
1971
 
1972
  $logger and call_user_func($logger, sprintf(__('Applying filter `pmxi_article_data` for `%s`', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1973
  $articleData = apply_filters('pmxi_article_data', $articleData, $this, $post_to_update, $current_xml_node);
1974
-
1975
  // no new records are created. it will only update posts it finds matching duplicates for
1976
- if ( ! $this->options['create_new_records'] and empty($articleData['ID']) ){
1977
-
1978
  if ( ! $postRecord->isEmpty() ) $postRecord->set(array('iteration' => $this->iteration))->update();
1979
 
1980
  $logger and call_user_func($logger, __('<b>SKIPPED</b>: The option \'Create new posts from records newly present in your file\' is disabled in your import settings.', 'wp_all_import_plugin'));
1981
- $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1982
  $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1983
- $skipped++;
1984
- $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1985
  do_action('wp_all_import_post_skipped', 0, $this->id, $current_xml_node);
1986
  continue;
1987
  }
1988
-
1989
  // cloak urls with `WP Wizard Cloak` if corresponding option is set
1990
  if ( ! empty($this->options['is_cloak']) and class_exists('PMLC_Plugin')) {
1991
  if (preg_match_all('%<a\s[^>]*href=(?(?=")"([^"]*)"|(?(?=\')\'([^\']*)\'|([^\s>]*)))%is', $articleData['post_content'], $matches, PREG_PATTERN_ORDER)) {
@@ -2061,9 +2061,9 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2061
  }
2062
  }
2063
  }
2064
- }
2065
 
2066
- // insert article being imported
2067
  if ($this->options['is_fast_mode']){
2068
  foreach (array('transition_post_status', 'save_post', 'pre_post_update', 'add_attachment', 'edit_attachment', 'edit_post', 'post_updated', 'wp_insert_post', 'save_post_' . $post_type[$i]) as $act) {
2069
  remove_all_actions($act);
@@ -2075,12 +2075,12 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2075
  $continue_import = true;
2076
  $continue_import = apply_filters('wp_all_import_is_post_to_create', $continue_import, $current_xml_node, $this->id);
2077
 
2078
- if ( ! $continue_import ){
2079
  $skipped++;
2080
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: By filter wp_all_import_is_post_to_create `%s`', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
2081
- $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
2082
- $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
2083
- $logger and !$is_cron and PMXI_Plugin::$session->save_data();
2084
  do_action('wp_all_import_post_skipped', 0, $this->id, $current_xml_node);
2085
  continue;
2086
  }
@@ -2205,7 +2205,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2205
  $pid = (empty($articleData['ID'])) ? wp_insert_post($articleData, true) : wp_update_post($articleData, true);
2206
  break;
2207
  }
2208
-
2209
  if (empty($pid)) {
2210
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'wp_all_import_plugin') . ': something wrong, ID = 0 was generated.');
2211
  $logger and !$is_cron and PMXI_Plugin::$session->errors++;
@@ -2227,7 +2227,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2227
  $is_images_to_update = apply_filters('pmxi_is_images_to_update', true, $articleData, $current_xml_node, $pid);
2228
 
2229
  if ("manual" != $this->options['duplicate_matching'] or empty($articleData['ID'])){
2230
- // associate post with import
2231
  $product_key = (($post_type[$i] == "product" and PMXI_Admin_Addons::get_addon('PMWI_Plugin')) ? $addons_data['PMWI_Plugin']['single_product_ID'][$i] : '');
2232
  if ($post_type[$i] == "taxonomies"){
2233
  $product_key = 'taxonomy_term';
@@ -2313,12 +2313,12 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2313
  // Deligate import operation to addons.
2314
  foreach (PMXI_Admin_Addons::get_active_addons() as $class) {
2315
  if (class_exists($class)) {
2316
- if ( method_exists($addons[$class], 'import') ) $addons[$class]->import($importData);
2317
  } else {
2318
  if (!empty($import_functions[$class])) {
2319
  if (is_array($import_functions[$class]) and is_callable($import_functions[$class]) or ! is_array($import_functions[$class]) and function_exists($import_functions[$class]) ) {
2320
- call_user_func($import_functions[$class], $importData, $addons_data[$class]);
2321
- }
2322
  }
2323
  }
2324
  }
@@ -2330,7 +2330,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2330
  if ( ! empty($articleData['post_type']) && !in_array($articleData['post_type'], array('taxonomies', 'comments', 'woo_reviews')) && ('page' == $articleData['post_type'] || version_compare($wp_version, '4.7.0', '>=')) && wp_all_import_is_update_cf('_wp_page_template', $this->options) && ( !empty($this->options['page_template']) || "no" == $this->options['is_multiple_page_template']) ){
2331
  update_post_meta($pid, '_wp_page_template', ("no" == $this->options['is_multiple_page_template']) ? $page_template[$i] : $this->options['page_template']);
2332
  }
2333
-
2334
  // [featured image]
2335
 
2336
  $featuredImage = false;
@@ -2441,7 +2441,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2441
  }
2442
  }
2443
 
2444
- if (empty($image) || !preg_match('%^(http|ftp)s?://%i', $image)) continue;
2445
 
2446
  $attid = false;
2447
 
@@ -2580,8 +2580,8 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2580
  if ( $is_images_to_update and ! empty($images_uploads) and false === $images_uploads['error'] and ( ! empty($articleData['post_type']) and in_array($articleData['post_type'], ["product", "product_variation"]) and class_exists('PMWI_Plugin') or $is_allow_import_images) and (empty($articleData['ID']) or $this->options['update_all_data'] == "yes" or ( $this->options['update_all_data'] == "no" and $this->options['is_update_images'])) ) {
2581
 
2582
  if ( ! empty($images_bundle) ){
2583
-
2584
- require_once(ABSPATH . 'wp-admin/includes/image.php');
2585
 
2586
  $is_show_add_new_images = apply_filters('wp_all_import_is_show_add_new_images', true, $post_type[$i]);
2587
 
@@ -2590,12 +2590,12 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2590
  foreach ($images_bundle as $slug => $bundle_data) {
2591
 
2592
  if ( ! $is_images_section_enabled && $slug == 'pmxi_gallery_image' ) continue;
2593
-
2594
  $featured_images = $bundle_data['files'];
2595
 
2596
  $option_slug = ($slug == 'pmxi_gallery_image') ? '' : $slug;
2597
 
2598
- $gallery_attachment_ids = array();
2599
 
2600
  if ( ! empty($featured_images[$i]) ){
2601
 
@@ -2605,10 +2605,10 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2605
  if ( ! @is_writable($targetDir) ){
2606
  $logger and call_user_func($logger, sprintf(__('<b>ERROR</b>: Target directory %s is not writable', 'wp_all_import_plugin'), $targetDir));
2607
  }
2608
- else{
2609
-
2610
- $success_images = false;
2611
-
2612
  $imgs = array();
2613
 
2614
  switch ($this->options[$option_slug . 'download_images']) {
@@ -2617,40 +2617,40 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2617
  break;
2618
  case 'gallery':
2619
  $featured_delim = $this->options[$option_slug . 'gallery_featured_delim'];
2620
- break;
2621
  default: // yes
2622
  $featured_delim = $this->options[$option_slug . 'download_featured_delim'];
2623
  break;
2624
- }
2625
 
2626
  $line_imgs = explode("\n", $featured_images[$i]);
2627
  if ( ! empty($line_imgs) )
2628
  foreach ($line_imgs as $line_img)
2629
- $imgs = array_merge($imgs, ( ! empty($featured_delim) ) ? str_getcsv($line_img, $featured_delim) : array($line_img) );
2630
 
2631
  // keep existing and add newest images
2632
  if ( ! empty($articleData['ID']) and $this->options['is_update_images'] and $this->options['update_images_logic'] == "add_new" and $this->options['update_all_data'] == "no" and $is_show_add_new_images){
2633
-
2634
  $logger and call_user_func($logger, __('- Keep existing and add newest images ...', 'wp_all_import_plugin'));
2635
 
2636
- $attachment_imgs = get_attached_media( 'image', $pid );
2637
 
2638
  if ( $post_type[$i] == "product" ){
2639
  $gallery_attachment_ids = array_filter(explode(",", get_post_meta($pid, '_product_image_gallery', true)));
2640
  }
2641
 
2642
- if ( $attachment_imgs ) {
2643
- foreach ( $attachment_imgs as $attachment_img ) {
2644
  $post_thumbnail_id = get_post_thumbnail_id( $pid );
2645
  if ( empty($post_thumbnail_id) and $this->options[$option_slug . 'is_featured'] ) {
2646
  set_post_thumbnail($pid, $attachment_img->ID);
2647
  }
2648
  elseif(!in_array($attachment_img->ID, $gallery_attachment_ids) and $post_thumbnail_id != $attachment_img->ID) {
2649
- $gallery_attachment_ids[] = $attachment_img->ID;
2650
- }
2651
- }
2652
- $success_images = true;
2653
- }
2654
 
2655
  if ( ! empty($gallery_attachment_ids) ){
2656
  foreach ($gallery_attachment_ids as $aid){
@@ -2658,43 +2658,43 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2658
  }
2659
  }
2660
  }
2661
-
2662
  if ( ! empty($imgs) ) {
2663
 
2664
- if ( $this->options[$option_slug . 'set_image_meta_title'] and !empty($image_meta_titles_bundle[$slug])){
2665
- $img_titles = array();
2666
  $line_img_titles = explode("\n", $image_meta_titles_bundle[$slug][$i]);
2667
  if ( ! empty($line_img_titles) )
2668
  foreach ($line_img_titles as $line_img_title)
2669
  $img_titles = array_merge($img_titles, ( ! empty($this->options[$option_slug . 'image_meta_title_delim']) ) ? explode($this->options[$option_slug . 'image_meta_title_delim'], $line_img_title) : array($line_img_title) );
2670
-
2671
  }
2672
- if ( $this->options[$option_slug . 'set_image_meta_caption'] and !empty($image_meta_captions_bundle[$slug])){
2673
- $img_captions = array();
2674
  $line_img_captions = explode("\n", $image_meta_captions_bundle[$slug][$i]);
2675
  if ( ! empty($line_img_captions) )
2676
  foreach ($line_img_captions as $line_img_caption)
2677
  $img_captions = array_merge($img_captions, ( ! empty($this->options[$option_slug . 'image_meta_caption_delim']) ) ? explode($this->options[$option_slug . 'image_meta_caption_delim'], $line_img_caption) : array($line_img_caption) );
2678
 
2679
  }
2680
- if ( $this->options[$option_slug . 'set_image_meta_alt'] and !empty($image_meta_alts_bundle[$slug])){
2681
- $img_alts = array();
2682
  $line_img_alts = explode("\n", $image_meta_alts_bundle[$slug][$i]);
2683
  if ( ! empty($line_img_alts) )
2684
  foreach ($line_img_alts as $line_img_alt)
2685
  $img_alts = array_merge($img_alts, ( ! empty($this->options[$option_slug . 'image_meta_alt_delim']) ) ? explode($this->options[$option_slug . 'image_meta_alt_delim'], $line_img_alt) : array($line_img_alt) );
2686
 
2687
  }
2688
- if ( $this->options[$option_slug . 'set_image_meta_description'] and !empty($image_meta_descriptions_bundle[$slug])){
2689
- $img_descriptions = array();
2690
  $line_img_descriptions = ($this->options[$option_slug . 'image_meta_description_delim_logic'] == 'line' or empty($this->options[$option_slug . 'image_meta_description_delim'])) ? explode("\n", $image_meta_descriptions_bundle[$slug][$i]) : array($image_meta_descriptions_bundle[$slug][$i]);
2691
  if ( ! empty($line_img_descriptions) )
2692
  foreach ($line_img_descriptions as $line_img_description)
2693
  $img_descriptions = array_merge($img_descriptions, ($this->options[$option_slug . 'image_meta_description_delim_logic'] == 'separate' and ! empty($this->options[$option_slug . 'image_meta_description_delim']) ) ? explode($this->options[$option_slug . 'image_meta_description_delim'], $line_img_description) : array($line_img_description) );
2694
 
2695
- }
2696
 
2697
- $is_keep_existing_images = ( ! empty($articleData['ID']) and $this->options['is_update_images'] and $this->options['update_images_logic'] == "add_new" and $this->options['update_all_data'] == "no" and $is_show_add_new_images);
2698
 
2699
  foreach ($imgs as $k => $img_url) {
2700
 
@@ -2713,14 +2713,14 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2713
  continue;
2714
  }
2715
 
2716
- $attid = false;
2717
 
2718
- $attch = null;
2719
 
2720
  // remove encoded quotes from url (&#34; and &#39;)
2721
  $url = html_entity_decode(trim($img_url), ENT_QUOTES);
2722
 
2723
- if (empty($url)) continue;
2724
 
2725
  $bn = wp_all_import_sanitize_filename(urldecode(wp_all_import_basename($url)));
2726
  $default_extension = pmxi_getExtension($bn);
@@ -2731,7 +2731,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2731
  else {
2732
  $img_ext = pmxi_getExtensionFromStr($url);
2733
 
2734
- if ($img_ext == "") $img_ext = pmxi_get_remote_image_ext($url);
2735
  }
2736
 
2737
  $logger and call_user_func($logger, sprintf(__('- Importing image `%s` for `%s` ...', 'wp_all_import_plugin'), $img_url, $this->getRecordTitle($articleData)));
@@ -2740,14 +2740,14 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2740
  $image_name = urldecode(($this->options[$option_slug . 'auto_rename_images'] and !empty($auto_rename_images_bundle[$slug][$i])) ? sanitize_file_name(($img_ext) ? str_replace("." . $default_extension, "", $auto_rename_images_bundle[$slug][$i]) : $auto_rename_images_bundle[$slug][$i]) : (($img_ext) ? str_replace("." . $default_extension, "", $bn) : $bn)) . (("" != $img_ext) ? '.' . $img_ext : '');
2741
  $image_name = apply_filters("wp_all_import_image_filename", $image_name, empty($img_titles[$k]) ? '' : $img_titles[$k], empty($img_captions[$k]) ? '' : $img_captions[$k], empty($img_alts[$k]) ? '' : $img_alts[$k], $articleData, $this->id, $img_url);
2742
 
2743
- // if wizard store image data to custom field
2744
  $create_image = false;
2745
  $download_image = true;
2746
  $wp_filetype = false;
2747
 
2748
- $is_base64_images_allowed = apply_filters("wp_all_import_is_base64_images_allowed", true, $url, $this->id);
2749
 
2750
- if ( $bundle_data['type'] == 'images' and base64_encode(base64_decode($url)) == $url and $is_base64_images_allowed ){
2751
  $image_name = empty($this->options[$option_slug . 'auto_rename_images']) ? md5($url) . '.jpg' : sanitize_file_name($auto_rename_images_bundle[$slug][$i]) . '.jpg';
2752
  $image_name = apply_filters("wp_all_import_image_filename", $image_name, empty($img_titles[$k]) ? '' : $img_titles[$k], empty($img_captions[$k]) ? '' : $img_captions[$k], empty($img_alts[$k]) ? '' : $img_alts[$k], $articleData, $this->id, $img_url);
2753
 
@@ -2788,22 +2788,22 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2788
  }
2789
  }
2790
  }
2791
- }
 
 
2792
 
2793
- if ( ! $create_image ) {
2794
-
2795
  if ($this->options[$option_slug . 'auto_rename_images'] and !empty($auto_rename_images_bundle[$slug][$i])) {
2796
  if ($k) {
2797
  $image_name = str_replace('.' . pmxi_getExtension($image_name), '', $image_name) . '-' . $k . '.' . pmxi_getExtension($image_name);
2798
- }
2799
  }
2800
-
2801
  $image_filename = wp_unique_filename($targetDir, $image_name);
2802
  $image_filepath = $targetDir . '/' . $image_filename;
2803
 
2804
  // search existing attachment
2805
  if ($this->options[$option_slug . 'search_existing_images'] or "gallery" == $this->options[$option_slug . 'download_images']){
2806
-
2807
  $image_filename = $image_name;
2808
 
2809
  // trying to find existing image in images table
@@ -2853,7 +2853,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2853
  if ($imageRecord->isEmpty()){
2854
  $imageRecord->set(array(
2855
  'attachment_id' => $attid,
2856
- 'image_url' => (base64_encode(base64_decode($url)) == $url && $is_base64_images_allowed) ? '' : $url,
2857
  'image_filename' => $image_name
2858
  ))->insert();
2859
  }
@@ -2863,7 +2863,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2863
  // update image URL if it was not set
2864
  if (empty($imageRecord->image_url)){
2865
  $imageRecord->set(array(
2866
- 'image_url' => (base64_encode(base64_decode($url)) == $url && $is_base64_images_allowed) ? '' : $url,
2867
  ))->update();
2868
  }
2869
  break;
@@ -2884,18 +2884,18 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2884
  if ($download_image && "gallery" != $this->options[$option_slug . 'download_images']){
2885
 
2886
  // do not download images
2887
- if ( "no" == $this->options[$option_slug . 'download_images'] ){
2888
 
2889
  $image_filename = wp_unique_filename($targetDir, $image_name);
2890
- $image_filepath = $targetDir . '/' . $image_filename;
2891
-
2892
  $wpai_uploads = $uploads['basedir'] . DIRECTORY_SEPARATOR . PMXI_Plugin::FILES_DIRECTORY . DIRECTORY_SEPARATOR;
2893
  $wpai_image_path = $wpai_uploads . str_replace('%20', ' ', $url);
2894
 
2895
  $logger and call_user_func($logger, sprintf(__('- Searching for existing image `%s`', 'wp_all_import_plugin'), $wpai_image_path));
2896
 
2897
  if ( @file_exists($wpai_image_path) and @copy( $wpai_image_path, $image_filepath )){
2898
- $download_image = false;
2899
  // validate import attachments
2900
  if ($bundle_data['type'] == 'files'){
2901
  if( ! $wp_filetype = wp_check_filetype(wp_all_import_basename($image_filepath), null )) {
@@ -2904,14 +2904,14 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2904
  @unlink($image_filepath);
2905
  }
2906
  else {
2907
- $create_image = true;
2908
  $logger and call_user_func($logger, sprintf(__('- File `%s` has been successfully found', 'wp_all_import_plugin'), $wpai_image_path));
2909
  }
2910
  }
2911
  // validate import images
2912
  elseif($bundle_data['type'] == 'images'){
2913
  if( preg_match('%\W(svg)$%i', wp_all_import_basename($image_filepath)) or $image_info = apply_filters('pmxi_getimagesize', @getimagesize($image_filepath), $image_filepath) and in_array($image_info[2], wp_all_import_supported_image_types())) {
2914
- $create_image = true;
2915
  $logger and call_user_func($logger, sprintf(__('- Image `%s` has been successfully found', 'wp_all_import_plugin'), $wpai_image_path));
2916
  }
2917
  else
@@ -2919,10 +2919,10 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2919
  $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: File %s is not a valid image and cannot be set as featured one', 'wp_all_import_plugin'), $image_filepath));
2920
  $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
2921
  @unlink($image_filepath);
2922
- }
2923
  }
2924
- }
2925
- }
2926
  else {
2927
  $image_info = $this->downloadFile($url, $image_filepath, $is_cron, $logger, $bundle_data['type']);
2928
  if ( ! $image_info ) {
@@ -2935,7 +2935,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2935
  }
2936
  }
2937
  $create_image = empty($image_info) ? false : true;
2938
- }
2939
  }
2940
  }
2941
 
@@ -2949,7 +2949,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2949
  if ($bundle_data['type'] == 'images') {
2950
  if ( ! empty($image_info) && is_array($image_info) ) {
2951
  $file_mime_type = image_type_to_mime_type($image_info[2]);
2952
- }
2953
  $file_mime_type = apply_filters('wp_all_import_image_mime_type', $file_mime_type, $image_filepath);
2954
  }
2955
  else {
@@ -2973,7 +2973,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2973
  if ($imageRecord->isEmpty()){
2974
  $imageRecord->set(array(
2975
  'attachment_id' => $attid,
2976
- 'image_url' => (base64_encode(base64_decode($url)) == $url && $is_base64_images_allowed) ? '' : $url,
2977
  'image_filename' => $image_name
2978
  ))->insert();
2979
  }
@@ -2984,7 +2984,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
2984
  // update image URL if it was not set
2985
  if (empty($imageRecord->image_url)){
2986
  $imageRecord->set(array(
2987
- 'image_url' => (base64_encode(base64_decode($url)) == $url && $is_base64_images_allowed) ? '' : $url
2988
  ))->update();
2989
  }
2990
  break;
@@ -3006,7 +3006,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3006
  if ($attch != null && empty($attch->post_parent) && ! in_array($post_type[$i], array('taxonomies'))){
3007
  wp_update_post(
3008
  array(
3009
- 'ID' => $attch->ID,
3010
  'post_parent' => $pid
3011
  )
3012
  );
@@ -3017,7 +3017,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3017
  if ( $this->options[$option_slug . 'set_image_meta_caption'] and ! empty($img_captions[$k]) ) $update_attachment_meta['post_excerpt'] = trim($img_captions[$k]);
3018
  if ( $this->options[$option_slug . 'set_image_meta_description'] and ! empty($img_descriptions[$k]) ) $update_attachment_meta['post_content'] = trim($img_descriptions[$k]);
3019
  if ( $this->options[$option_slug . 'set_image_meta_alt'] and ! empty($img_alts[$k]) ) update_post_meta($attid, '_wp_attachment_image_alt', trim($img_alts[$k]));
3020
-
3021
  if ( !empty($update_attachment_meta)) {
3022
  $update_attachment_meta['ID'] = $attid;
3023
  $gallery_post = wp_update_post( $update_attachment_meta, true );
@@ -3026,8 +3026,8 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3026
  }
3027
  }
3028
 
3029
- $logger and call_user_func($logger, __('- <b>ACTION</b>: ' . $slug, 'wp_all_import_plugin'));
3030
- do_action( $slug, $pid, $attid, ($handle_image) ? $handle_image['file'] : $image_filepath, $is_keep_existing_images ? 'add_images' : 'update_images');
3031
 
3032
  $success_images = true;
3033
 
@@ -3047,14 +3047,14 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3047
 
3048
  if ($attch != null and empty($attch->post_parent)) {
3049
  $logger and call_user_func($logger, sprintf(__('- Attachment with ID: `%s` has been successfully updated for image `%s`', 'wp_all_import_plugin'), $attid, ($handle_image) ? $handle_image['url'] : $targetUrl . '/' . $image_filename));
3050
- }
3051
  elseif(empty($attch)) {
3052
  $logger and call_user_func($logger, sprintf(__('- Attachment with ID: `%s` has been successfully created for image `%s`', 'wp_all_import_plugin'), $attid, ($handle_image) ? $handle_image['url'] : $targetUrl . '/' . $image_filename));
3053
  }
3054
- }
3055
- }
3056
  }
3057
-
3058
  // Set product gallery images
3059
  if ( $post_type[$i] == "product" ){
3060
  update_post_meta($pid, '_product_image_gallery', (!empty($gallery_attachment_ids)) ? implode(',', $gallery_attachment_ids) : '');
@@ -3065,12 +3065,12 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3065
  if ( ! $success_images and "yes" == $this->options[$option_slug . 'create_draft'] and $final_post_type != 'product_variation' and ! in_array($post_type[$i], array('taxonomies', 'comments', 'woo_reviews'))) {
3066
  $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $pid) );
3067
  $logger and call_user_func($logger, sprintf(__('- Post `%s` saved as Draft, because no images are downloaded successfully', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
3068
- }
3069
  }
3070
  }
3071
- else{
3072
  // Create entry as Draft if no images are downloaded successfully
3073
- $final_post_type = get_post_type($pid);
3074
  if ( "yes" == $this->options[$option_slug . 'create_draft'] and $final_post_type != 'product_variation' and ! in_array($post_type[$i], array('taxonomies', 'comments', 'woo_reviews'))){
3075
  $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $pid) );
3076
  $logger and call_user_func($logger, sprintf(__('Post `%s` saved as Draft, because no images are downloaded successfully', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
@@ -3121,7 +3121,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3121
  {
3122
  $logger and call_user_func($logger, sprintf(__('Images import skipped for post `%s` according to \'pmxi_is_images_to_update\' filter...', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
3123
  }
3124
- // [/featured image]
3125
 
3126
  // [attachments]
3127
  $is_attachments_to_update = apply_filters('pmxi_is_attachments_to_update', true, $articleData, $current_xml_node);
@@ -3309,38 +3309,38 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3309
  // [custom taxonomies]
3310
  if ( ! empty($taxonomies) ){
3311
 
3312
- $logger and call_user_func($logger, __('<b>TAXONOMIES:</b>', 'wp_all_import_plugin'));
3313
 
3314
- foreach ($taxonomies as $tx_name => $txes) {
3315
 
3316
  // Skip updating product attributes
3317
  if ( PMXI_Admin_Addons::get_addon('PMWI_Plugin') and strpos($tx_name, "pa_") === 0 ) continue;
3318
 
3319
  if ( empty($articleData['ID']) or $this->options['update_all_data'] == "yes" or ( $this->options['update_all_data'] == "no" and $this->options['is_update_categories'] )) {
3320
-
3321
- $logger and call_user_func($logger, sprintf(__('- Importing taxonomy `%s` ...', 'wp_all_import_plugin'), $tx_name));
3322
 
3323
  if ( ! empty($this->options['tax_logic'][$tx_name]) and $this->options['tax_logic'][$tx_name] == 'hierarchical' and ! empty($this->options['tax_hierarchical_logic'][$tx_name]) and $this->options['tax_hierarchical_logic'][$tx_name] == 'entire'){
3324
  $logger and call_user_func($logger, sprintf(__('- Auto-nest enabled with separator `%s` ...', 'wp_all_import_plugin'), ( ! empty($this->options['tax_hierarchical_delim'][$tx_name]) ? $this->options['tax_hierarchical_delim'][$tx_name] : ',')));
3325
  }
3326
 
3327
  if (!empty($articleData['ID'])){
3328
- if ($this->options['update_all_data'] == "no" and $this->options['update_categories_logic'] == "all_except" and !empty($this->options['taxonomies_list'])
3329
- and is_array($this->options['taxonomies_list']) and in_array($tx_name, $this->options['taxonomies_list'])){
3330
  $logger and call_user_func($logger, sprintf(__('- %s %s has been skipped attempted to `Leave these taxonomies alone, update all others`...', 'wp_all_import_plugin'), $custom_type_details->labels->singular_name, $tx_name));
3331
  continue;
3332
- }
3333
- if ($this->options['update_all_data'] == "no" and $this->options['update_categories_logic'] == "only" and ((!empty($this->options['taxonomies_list'])
3334
- and is_array($this->options['taxonomies_list']) and ! in_array($tx_name, $this->options['taxonomies_list'])) or empty($this->options['taxonomies_list']))){
3335
  $logger and call_user_func($logger, sprintf(__('- %s %s has been skipped attempted to `Update only these taxonomies, leave the rest alone`...', 'wp_all_import_plugin'), $custom_type_details->labels->singular_name, $tx_name));
3336
  continue;
3337
  }
3338
- }
3339
 
3340
  $assign_taxes = array();
3341
 
3342
  if ($this->options['update_categories_logic'] == "add_new" and !empty($existing_taxonomies[$tx_name][$i])){
3343
- $assign_taxes = $existing_taxonomies[$tx_name][$i];
3344
  unset($existing_taxonomies[$tx_name][$i]);
3345
  }
3346
  elseif(!empty($existing_taxonomies[$tx_name][$i])){
@@ -3384,9 +3384,9 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3384
  }
3385
  }
3386
  }
3387
- }
3388
-
3389
- if ( is_wp_error($term) ){
3390
  $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: `%s`', 'wp_all_import_plugin'), $term->get_error_message()));
3391
  $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
3392
  }
@@ -3401,23 +3401,23 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3401
  if (!in_array($p, $assign_taxes)) $assign_taxes[] = $p;
3402
  }
3403
  }
3404
- }
3405
- if (!in_array($term->term_taxonomy_id, $assign_taxes)) $assign_taxes[] = $term->term_taxonomy_id;
3406
- if (!$is_created_term){
3407
- if ( empty($parent_id) ){
3408
- $logger and call_user_func($logger, sprintf(__('- Attempted to create parent %s %s `%s`, duplicate detected. Importing %s to existing `%s` %s, ID %d, slug `%s` ...', 'wp_all_import_plugin'), $custom_type_details->labels->singular_name, $tx_name, $single_tax['name'], $custom_type_details->labels->singular_name, $term->name, $tx_name, $term->term_id, $term->slug));
 
 
 
3409
  }
3410
- else{
3411
- $logger and call_user_func($logger, sprintf(__('- Attempted to create child %s %s `%s`, duplicate detected. Importing %s to existing `%s` %s, ID %d, slug `%s` ...', 'wp_all_import_plugin'), $custom_type_details->labels->singular_name, $tx_name, $single_tax['name'], $custom_type_details->labels->singular_name, $term->name, $tx_name, $term->term_id, $term->slug));
3412
- }
3413
  }
3414
- }
3415
- }
3416
  }
3417
- }
3418
  endif;
3419
  $assign_taxes = apply_filters('wp_all_import_set_post_terms', $assign_taxes, $tx_name, $pid, $this->id);
3420
- // associate taxes with post
3421
  $this->associate_terms($pid, ( empty($assign_taxes) ? false : $assign_taxes ), $tx_name, $logger, $is_cron, $articleData['post_status']);
3422
  }
3423
  else {
@@ -3425,23 +3425,23 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3425
  }
3426
  }
3427
  if ( $this->options['update_all_data'] == "no" and ( ($this->options['is_update_categories'] and $this->options['update_categories_logic'] != 'full_update') or ( ! $this->options['is_update_categories'] and ( is_object_in_taxonomy( $post_type[$i], 'category' ) or is_object_in_taxonomy( $post_type[$i], 'post_tag' ) ) ) ) ) {
3428
-
3429
  if ( ! empty($existing_taxonomies) ){
3430
  foreach ($existing_taxonomies as $tx_name => $txes) {
3431
  // Skip updating product attributes
3432
  if ( PMXI_Admin_Addons::get_addon('PMWI_Plugin') and strpos($tx_name, "pa_") === 0 ) continue;
3433
 
3434
- if (!empty($txes[$i]))
3435
  $this->associate_terms($pid, $txes[$i], $tx_name, $logger, $is_cron, $articleData['post_status']);
3436
  }
3437
  }
3438
  }
3439
- }
3440
- // [/custom taxonomies]
3441
 
3442
- if (empty($articleData['ID'])) {
3443
  $logger and call_user_func($logger, sprintf(__('<b>CREATED</b> `%s` `%s` (ID: %s)', 'wp_all_import_plugin'), $this->getRecordTitle($articleData), $custom_type_details->labels->singular_name, $pid));
3444
- } else {
3445
  $logger and call_user_func($logger, sprintf(__('<b>UPDATED</b> `%s` `%s` (ID: %s)', 'wp_all_import_plugin'), $this->getRecordTitle($articleData), $custom_type_details->labels->singular_name, $pid));
3446
  }
3447
 
@@ -3461,39 +3461,39 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3461
 
3462
  // prepare data for import
3463
  $importData = array(
3464
- 'pid' => $pid,
3465
- 'import' => $this,
3466
  'logger' => $logger,
3467
- 'is_update' => $is_update
3468
  );
3469
 
3470
  $saved_functions = apply_filters('wp_all_import_addon_saved_post', array());
3471
 
3472
  // deligate operation to addons
3473
- foreach (PMXI_Admin_Addons::get_active_addons() as $class){
3474
  if (class_exists($class)){
3475
- if ( method_exists($addons[$class], 'saved_post') ) $addons[$class]->saved_post($importData);
3476
  } else {
3477
  if ( ! empty($saved_functions[$class]) ){
3478
  if ( is_array($saved_functions[$class]) and is_callable($saved_functions[$class]) or ! is_array($saved_functions[$class]) and function_exists($saved_functions[$class]) ){
3479
- call_user_func($saved_functions[$class], $importData);
3480
- }
3481
- }
3482
  }
3483
  }
3484
-
3485
- // [/addons import]
3486
  $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_saved_post', 'wp_all_import_plugin'));
3487
  do_action( 'pmxi_saved_post', $pid, $rootNodes[$i], $is_update ); // hook that was triggered immediately after post saved
3488
-
3489
- if (empty($articleData['ID'])) $created++; else $updated++;
3490
 
3491
  if ( ! $is_cron and "default" == $this->options['import_processing'] ){
3492
  $processed_records = $created + $updated + $skipped;
3493
  $logger and call_user_func($logger, sprintf(__('<span class="processing_info"><span class="created_count">%s</span><span class="updated_count">%s</span><span class="percents_count">%s</span></span>', 'wp_all_import_plugin'), $created, $updated, ceil(($processed_records/$this->count) * 100)));
3494
  }
3495
-
3496
- }
3497
  $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_after_post_import', 'wp_all_import_plugin'));
3498
  do_action('pmxi_after_post_import', $this->id);
3499
 
@@ -3502,23 +3502,23 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3502
  //restore_error_handler();
3503
  }
3504
 
3505
- $this->set(array(
3506
- 'imported' => $created + $updated,
3507
  'created' => $created,
3508
  'updated' => $updated,
3509
  'skipped' => $skipped,
3510
- 'last_activity' => date('Y-m-d H:i:s')
3511
  ))->update();
3512
-
3513
  if ( ! $is_cron ){
3514
 
3515
- PMXI_Plugin::$session->save_data();
3516
 
3517
  $records_count = $this->created + $this->updated + $this->skipped;
3518
 
3519
  $records_to_import = (empty($specified_records)) ? $this->count : $specified_records[count($specified_records) -1];
3520
 
3521
- $is_import_complete = ($records_count == $records_to_import);
3522
 
3523
  // Set out of stock status for missing records [Woocommerce add-on option]
3524
  if ( $is_import_complete and (empty($this->options['is_delete_missing']) || $this->options['is_update_missing_cf'] || $this->options['set_missing_to_draft']) and $post_type[$i] == "product" and class_exists('PMWI_Plugin') and !empty($this->options['missing_records_stock_status']) and "manual" != $this->options['duplicate_matching']) {
@@ -3526,10 +3526,10 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3526
  $logger and call_user_func($logger, __('Update stock status previously imported posts which are no longer actual...', 'wp_all_import_plugin'));
3527
  $args = array('import_id' => $this->id, 'iteration !=' => $this->iteration);
3528
  if (!empty($this->options['is_import_specified'])) $args['specified'] = 1;
3529
- $postList = new PMXI_Post_List();
3530
  $missingPosts = $postList->getBy($args);
3531
  if ( ! $missingPosts->isEmpty() ){
3532
- foreach ($missingPosts as $missingPost) {
3533
  update_post_meta( $missingPost['post_id'], '_stock_status', 'outofstock' );
3534
  update_post_meta( $missingPost['post_id'], '_stock', 0 );
3535
 
@@ -3548,21 +3548,21 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3548
  unset($missingPostRecord);
3549
  }
3550
  }
3551
- }
3552
- }
3553
-
3554
  } catch (XmlImportException $e) {
3555
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'wp_all_import_plugin') . ': ' . $e->getMessage());
3556
- $logger and !$is_cron and PMXI_Plugin::$session->errors++;
3557
- }
3558
-
3559
  $logger and $is_import_complete and call_user_func($logger, __('Cleaning temporary data...', 'wp_all_import_plugin'));
3560
  foreach ($tmp_files as $file) { // remove all temporary files created
3561
  @unlink($file);
3562
- }
3563
-
3564
  remove_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // return any filtering rules back if they has been disabled for import procedure
3565
-
3566
  return $this;
3567
  }
3568
 
@@ -3670,16 +3670,16 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3670
 
3671
  public function delete_source($logger = false)
3672
  {
3673
- if ($this->options['is_delete_source'])
3674
  {
3675
  $uploads = wp_upload_dir();
3676
 
3677
- $logger and call_user_func($logger, __('Deleting source XML file...', 'wp_all_import_plugin'));
3678
 
3679
  // Delete chunks
3680
  foreach (PMXI_Helper::safe_glob($uploads['basedir'] . DIRECTORY_SEPARATOR . PMXI_Plugin::TEMP_DIRECTORY . DIRECTORY_SEPARATOR . 'pmxi_chunk_*', PMXI_Helper::GLOB_RECURSE | PMXI_Helper::GLOB_PATH) as $filePath) {
3681
  $logger and call_user_func($logger, __('Deleting chunks files...', 'wp_all_import_plugin'));
3682
- @file_exists($filePath) and wp_all_import_remove_source($filePath, false);
3683
  }
3684
 
3685
  if ($this->type != "ftp"){
@@ -3699,35 +3699,35 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3699
  }
3700
  }
3701
  }
3702
- }
3703
 
3704
  public function delete_missing_records($logger, $iteration)
3705
  {
3706
- if ( ! empty($this->options['is_delete_missing']) and $this->options['duplicate_matching'] == 'auto') {
3707
 
3708
  empty($this->deleted) and $logger and call_user_func($logger, __('Removing previously imported posts which are no longer actual...', 'wp_all_import_plugin'));
3709
- $postList = new PMXI_Post_List();
3710
 
3711
- $args = array('import_id' => $this->id, 'iteration !=' => $iteration);
3712
- if ( ! empty($this->options['is_import_specified']) ) $args['specified'] = 1;
3713
 
3714
  $missing_ids = array();
3715
  $missingPosts = $postList->getBy($args);
3716
 
3717
- if ( ! $missingPosts->isEmpty() ):
3718
-
3719
  foreach ($missingPosts as $missingPost) {
3720
-
3721
  $missing_ids[] = $missingPost;
3722
-
3723
  }
3724
 
3725
- endif;
3726
 
3727
  // Delete posts from database
3728
- if ( ! empty($missing_ids) && is_array($missing_ids) ){
3729
-
3730
- $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_delete_post', 'wp_all_import_plugin'));
3731
 
3732
  $logger and call_user_func($logger, __('Deleting posts from database', 'wp_all_import_plugin'));
3733
 
@@ -3740,9 +3740,9 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3740
  if ( ! empty($missingPostRecords) ) {
3741
 
3742
  foreach ( $missingPostRecords as $k => $missingPostRecord ) {
3743
-
3744
  $to_delete = true;
3745
-
3746
  // Instead of deletion, set Custom Field
3747
  if ($this->options['is_update_missing_cf']){
3748
  switch ($this->options['custom_type']){
@@ -3764,17 +3764,17 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3764
  $to_delete = false;
3765
  }
3766
 
3767
- // Instead of deletion, change post status to Draft
3768
  if ($this->options['set_missing_to_draft']){
3769
  if ($final_post_type = get_post_type($missingPostRecord['post_id']) and $final_post_type != 'product_variation' and 'draft' != get_post_status($missingPostRecord['post_id']))
3770
  {
3771
  $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $missingPostRecord['post_id']) );
3772
  $this->recount_terms($missingPostRecord['post_id'], $final_post_type);
3773
  $logger and call_user_func($logger, sprintf(__('Instead of deletion, change post with ID `%s` status to Draft', 'wp_all_import_plugin'), $missingPostRecord['post_id']));
3774
- }
3775
  $to_delete = false;
3776
  }
3777
-
3778
  $to_delete = apply_filters('wp_all_import_is_post_to_delete', $to_delete, $missingPostRecord['post_id'], $this);
3779
 
3780
  if ($to_delete) {
@@ -3787,7 +3787,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3787
  // Clear post's relationships
3788
  wp_delete_object_term_relationships($missingPostRecord['post_id'], get_object_taxonomies('' != $this->options['custom_type'] ? $this->options['custom_type'] : 'post'));
3789
  }
3790
- }
3791
  else {
3792
  $skipp_from_deletion[] = $missingPostRecord['post_id'];
3793
  $postRecord = new PMXI_Post_Record();
@@ -3810,7 +3810,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3810
 
3811
  do_action('pmxi_missing_post', $missingPostRecord['post_id']);
3812
 
3813
- unset($missingPostRecords[$k]);
3814
  }
3815
  }
3816
 
@@ -3848,18 +3848,18 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3848
  }
3849
  break;
3850
  }
3851
-
3852
  // Delete record form pmxi_posts
3853
  $sql = "DELETE FROM " . PMXI_Plugin::getInstance()->getTablePrefix() . "posts WHERE post_id IN (".implode(',', $ids).") AND import_id = %d";
3854
- $this->wpdb->query(
3855
  $this->wpdb->prepare($sql, $this->id)
3856
- );
3857
 
3858
- $this->set(array('deleted' => $this->deleted + count($ids)))->update();
3859
 
3860
  $logger and call_user_func($logger, sprintf(__('%d Posts deleted from database. IDs (%s)', 'wp_all_import_plugin'), $this->deleted, implode(",", $ids)));
3861
  }
3862
- }
3863
 
3864
  if ( PMXI_Plugin::is_ajax() ) break;
3865
  }
@@ -3875,39 +3875,39 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3875
 
3876
  protected function pushmeta($pid, $meta_key, $meta_value){
3877
 
3878
- if (empty($meta_key)) return;
3879
 
3880
  $this->post_meta_to_insert[] = array(
3881
  'meta_key' => $meta_key,
3882
  'meta_value' => $meta_value,
3883
  'pid' => $pid
3884
- );
3885
 
3886
  }
3887
 
3888
  protected function executeSQL(){
3889
-
3890
  $import_entry = ( in_array( $this->options['custom_type'], array('import_users', 'shop_customer') ) ) ? 'user' : 'post';
3891
 
3892
  // prepare bulk SQL query
3893
  $meta_table = _get_meta_table( $import_entry );
3894
-
3895
- if ( $this->post_meta_to_insert ){
3896
  $values = array();
3897
  $already_added = array();
3898
-
3899
  foreach (array_reverse($this->post_meta_to_insert) as $key => $value) {
3900
  if ( ! empty($value['meta_key']) and ! in_array($value['pid'] . '-' . $value['meta_key'], $already_added) ){
3901
- $already_added[] = $value['pid'] . '-' . $value['meta_key'];
3902
- $values[] = '(' . $value['pid'] . ',"' . $value['meta_key'] . '",\'' . maybe_serialize($value['meta_value']) .'\')';
3903
  }
3904
  }
3905
-
3906
  $this->wpdb->query("INSERT INTO $meta_table (`" . $import_entry . "_id`, `meta_key`, `meta_value`) VALUES " . implode(',', $values));
3907
  $this->post_meta_to_insert = array();
3908
- }
3909
  }
3910
-
3911
  public function _filter_has_cap_unfiltered_html($caps)
3912
  {
3913
  $caps['unfiltered_html'] = true;
@@ -3992,7 +3992,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
3992
  if ( ! $keepPosts) {
3993
  $missing_ids = array();
3994
  $sql = "SELECT post_id FROM " . PMXI_Plugin::getInstance()->getTablePrefix() . "posts WHERE import_id = %d";
3995
- $missingPosts = $this->wpdb->get_results(
3996
  $this->wpdb->prepare($sql, $this->id)
3997
  );
3998
  if ( ! empty($missingPosts) ):
@@ -4008,15 +4008,15 @@ class PMXI_Import_Record extends PMXI_Model_Record {
4008
  $this->deleteRecords($is_delete_attachments, $is_deleted_images, $ids);
4009
  // Delete record form pmxi_posts
4010
  $sql = "DELETE FROM " . PMXI_Plugin::getInstance()->getTablePrefix() . "posts WHERE post_id IN (".implode(',', $ids).") AND import_id = %d";
4011
- $this->wpdb->query(
4012
  $this->wpdb->prepare($sql, $this->id)
4013
  );
4014
- $this->set(array('deleted' => $this->deleted + count($ids)))->update();
4015
  }
4016
  break;
4017
  }
4018
  return (count($missing_ids_arr) > 1) ? false : true;
4019
- }
4020
  }
4021
  return true;
4022
  }
@@ -4028,15 +4028,15 @@ class PMXI_Import_Record extends PMXI_Model_Record {
4028
  * @chainable
4029
  */
4030
  public function deletePosts($keepPosts = TRUE, $is_deleted_images = 'auto', $is_delete_attachments = 'auto') {
4031
- $post = new PMXI_Post_List();
4032
- if ( ! $keepPosts) {
4033
  $ids = array();
4034
- foreach ($post->getBy('import_id', $this->id)->convertRecords() as $p) {
4035
  $ids[] = $p->post_id;
4036
  }
4037
  if ( ! empty($ids) ){
4038
  $this->deleteRecords($is_delete_attachments, $is_deleted_images, $ids);
4039
- }
4040
  }
4041
  $this->wpdb->query($this->wpdb->prepare('DELETE FROM ' . $post->getTable() . ' WHERE import_id = %s', $this->id));
4042
  return $this;
@@ -4099,7 +4099,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
4099
  */
4100
  public function deleteFiles() {
4101
  $fileList = new PMXI_File_List();
4102
- foreach($fileList->getBy('import_id', $this->id)->convertRecords() as $f) {
4103
  $f->delete();
4104
  }
4105
  return $this;
@@ -4109,9 +4109,9 @@ class PMXI_Import_Record extends PMXI_Model_Record {
4109
  * @return PMXI_Import_Record
4110
  * @chainable
4111
  */
4112
- public function deleteHistories(){
4113
  $historyList = new PMXI_History_List();
4114
- foreach ($historyList->getBy('import_id', $this->id)->convertRecords() as $h) {
4115
  $h->delete();
4116
  }
4117
  return $this;
@@ -4127,7 +4127,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
4127
  $i->delete($keepPosts);
4128
  }
4129
  return $this;
4130
- }
4131
  /**
4132
  * @see parent::delete()
4133
  * @param bool[optional] $keepPosts When set to false associated wordpress posts will be deleted as well
@@ -4137,7 +4137,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
4137
  if ($is_delete_import)
4138
  {
4139
  $this->deleteFiles()->deleteHistories()->deleteChildren($keepPosts);
4140
- }
4141
  $expired_sessions = array();
4142
  $expired_sessions[] = "_wpallimport_session_expires_" . $this->id . "_";
4143
  $expired_sessions[] = "_wpallimport_session_" . $this->id . "_";
@@ -4152,5 +4152,5 @@ class PMXI_Import_Record extends PMXI_Model_Record {
4152
  {
4153
  return in_array($this->type, array('url', 'ftp', 'file'));
4154
  }
4155
-
4156
  }
4
 
5
  public static $cdata = array();
6
 
7
+ protected $errors;
8
+
9
  /**
10
  * Some pre-processing logic, such as removing control characters from xml to prevent parsing errors
11
  * @param string $xml
12
  */
13
  public static function preprocessXml( &$xml ) {
14
+
15
+ if ( empty(PMXI_Plugin::$session->is_csv) and empty(PMXI_Plugin::$is_csv)){
16
+
17
+ self::$cdata = array();
18
 
19
  $is_preprocess_enabled = apply_filters('is_xml_preprocess_enabled', true);
20
 
29
  $xml = str_replace('{{CPLACE_' . ($key + 1) . '}}', $val, $xml);
30
  }
31
  }
32
+ }
33
+ }
34
  }
35
 
36
  /**
43
  if (FALSE === $xml or '' == $xml) {
44
  $errors and $errors->add('form-validation', __('WP All Import can\'t read your file.<br/><br/>Probably, you are trying to import an invalid XML feed. Try opening the XML feed in a web browser (Google Chrome is recommended for opening XML files) to see if there is an error message.<br/>Alternatively, run the feed through a validator: http://validator.w3.org/<br/>99% of the time, the reason for this error is because your XML feed isn\'t valid.<br/>If you are 100% sure you are importing a valid XML feed, please contact WP All Import support.', 'wp_all_import_plugin'));
45
  } else {
46
+
47
+ PMXI_Import_Record::preprocessXml($xml);
48
 
49
  if ( function_exists('simplexml_load_string')){
50
  libxml_use_internal_errors(true);
51
  libxml_clear_errors();
52
  $_x = @simplexml_load_string($xml);
53
+ $xml_errors = libxml_get_errors();
54
  libxml_clear_errors();
55
+ if ($xml_errors) {
56
  $error_msg = '<strong>' . __('Invalid XML', 'wp_all_import_plugin') . '</strong><ul>';
57
  foreach($xml_errors as $error) {
58
  $error_msg .= '<li>';
63
  $error_msg .= '</li>';
64
  }
65
  $error_msg .= '</ul>';
66
+ $errors and $errors->add('form-validation', $error_msg);
67
  } else {
68
  return true;
69
  }
70
  }
71
  else{
72
+ $errors and $errors->add('form-validation', __('Required PHP components are missing.', 'wp_all_import_plugin'));
73
+ $errors and $errors->add('form-validation', __('WP All Import requires the SimpleXML PHP module to be installed. This is a standard feature of PHP, and is necessary for WP All Import to read the files you are trying to import.<br/>Please contact your web hosting provider and ask them to install and activate the SimpleXML PHP module.', 'wp_all_import_plugin'));
74
  }
75
  }
76
  return false;
673
 
674
  return $result;
675
  }
676
+
677
  public $post_meta_to_insert = array();
678
 
679
  public function is_parsing_required( $option ){
694
  $cxpath = $xpath_prefix . $this->xpath;
695
 
696
  $this->options += PMXI_Plugin::get_default_import_options(); // make sure all options are defined
697
+
698
  $avoid_pingbacks = PMXI_Plugin::getInstance()->getOption('pingbacks');
699
 
700
  $cron_sleep = (int) PMXI_Plugin::getInstance()->getOption('cron_sleep');
701
+
702
  if ( $avoid_pingbacks and ! defined( 'WP_IMPORTING' ) ) define( 'WP_IMPORTING', true );
703
 
704
+ $postRecord = new PMXI_Post_Record();
705
+
706
  $tmp_files = array();
707
  // compose records to import
708
  $records = array();
725
 
726
  $chunk == 1 and $logger and call_user_func($logger, __('Composing titles...', 'wp_all_import_plugin'));
727
  if ( ! empty($this->options['title'])){
728
+ $titles = XmlImportParser::factory($xml, $cxpath, $this->options['title'], $file)->parse($records); $tmp_files[] = $file;
729
  }
730
  else{
731
  $loop and $titles = array_fill(0, $loop, '');
771
  }
772
 
773
  if ( "xpath" == $this->options['status'] ){
774
+ $chunk == 1 and $logger and call_user_func($logger, __('Composing statuses...', 'wp_all_import_plugin'));
775
  $post_status = array();
776
  if ( ! empty($this->options['status_xpath']) && $this->is_parsing_required('is_update_status') ){
777
+ $post_status = XmlImportParser::factory($xml, $cxpath, $this->options['status_xpath'], $file)->parse($records); $tmp_files[] = $file;
778
  }
779
  else{
780
  count($titles) and $post_status = array_fill(0, count($titles), 'publish');
781
  }
782
  }
783
+
784
  if ( "xpath" == $this->options['comment_status'] ){
785
+ $chunk == 1 and $logger and call_user_func($logger, __('Composing comment statuses...', 'wp_all_import_plugin'));
786
  $comment_status = array();
787
  if (!empty($this->options['comment_status_xpath']) && $this->is_parsing_required('is_update_comment_status') ){
788
  $comment_status = XmlImportParser::factory($xml, $cxpath, $this->options['comment_status_xpath'], $file)->parse($records); $tmp_files[] = $file;
793
  }
794
 
795
  if ( "xpath" == $this->options['ping_status'] ){
796
+ $chunk == 1 and $logger and call_user_func($logger, __('Composing ping statuses...', 'wp_all_import_plugin'));
797
  $ping_status = array();
798
  if (!empty($this->options['ping_status_xpath'])){
799
  $ping_status = XmlImportParser::factory($xml, $cxpath, $this->options['ping_status_xpath'], $file)->parse($records); $tmp_files[] = $file;
804
  }
805
 
806
  if ( "xpath" == $this->options['post_format'] ){
807
+ $chunk == 1 and $logger and call_user_func($logger, __('Composing post formats...', 'wp_all_import_plugin'));
808
  $post_format = array();
809
  if (!empty($this->options['post_format_xpath'])){
810
  $post_format = XmlImportParser::factory($xml, $cxpath, $this->options['post_format_xpath'], $file)->parse($records); $tmp_files[] = $file;
827
  }
828
 
829
  if ( "no" == $this->options['is_multiple_page_template'] ){
830
+ $chunk == 1 and $logger and call_user_func($logger, __('Composing page templates...', 'wp_all_import_plugin'));
831
  $page_template = array();
832
  if (!empty($this->options['single_page_template'])){
833
  $page_template = XmlImportParser::factory($xml, $cxpath, $this->options['single_page_template'], $file)->parse($records); $tmp_files[] = $file;
835
  else{
836
  count($titles) and $page_template = array_fill(0, count($titles), 'default');
837
  }
838
+ }
839
 
840
  if ( $this->options['is_override_post_type'] and ! empty($this->options['post_type_xpath']) ){
841
  $chunk == 1 and $logger and call_user_func($logger, __('Composing post types...', 'wp_all_import_plugin'));
852
  }
853
 
854
  if ( "no" == $this->options['is_multiple_page_parent'] ){
855
+ $chunk == 1 and $logger and call_user_func($logger, __('Composing page parent...', 'wp_all_import_plugin'));
856
  $page_parent = array();
857
  if ( ! empty($this->options['single_page_parent']) && $this->is_parsing_required('is_update_parent') ){
858
  $page_parent = XmlImportParser::factory($xml, $cxpath, $this->options['single_page_parent'], $file)->parse($records); $tmp_files[] = $file;
903
  count($titles) and $post_author = array_fill(0, count($titles), $current_user->ID);
904
  }
905
 
906
+ $chunk == 1 and $logger and call_user_func($logger, __('Composing slugs...', 'wp_all_import_plugin'));
907
  $post_slug = array();
908
  if (!empty($this->options['post_slug']) && $this->is_parsing_required('is_update_slug') ){
909
  $post_slug = XmlImportParser::factory($xml, $cxpath, $this->options['post_slug'], $file)->parse($records); $tmp_files[] = $file;
920
  count($titles) and $is_image_featured = array_fill(0, count($titles), '');
921
  }
922
 
923
+ $chunk == 1 and $logger and call_user_func($logger, __('Composing menu order...', 'wp_all_import_plugin'));
924
  $menu_order = array();
925
  if (!empty($this->options['order']) && $this->is_parsing_required('is_update_menu_order')){
926
  $menu_order = XmlImportParser::factory($xml, $cxpath, $this->options['order'], $file)->parse($records); $tmp_files[] = $file;
929
  count($titles) and $menu_order = array_fill(0, count($titles), '');
930
  }
931
 
932
+ $chunk == 1 and $logger and call_user_func($logger, __('Composing contents...', 'wp_all_import_plugin'));
933
  if (!empty($this->options['content']) && $this->is_parsing_required('is_update_content') ){
934
  $contents = XmlImportParser::factory(
935
  ((!empty($this->options['is_keep_linebreaks']) and intval($this->options['is_keep_linebreaks'])) ? $xml : preg_replace('%\r\n?|\n%', ' ', $xml)),
936
  $cxpath,
937
  $this->options['content'],
938
  $file)->parse($records
939
+ ); $tmp_files[] = $file;
940
  }
941
  else{
942
  count($titles) and $contents = array_fill(0, count($titles), '');
943
  }
944
+
945
  $chunk == 1 and $logger and call_user_func($logger, __('Composing dates...', 'wp_all_import_plugin'));
946
  if ( $this->is_parsing_required('is_update_dates') ){
947
  if ('specific' == $this->options['date_type']) {
981
  else{
982
  count($titles) and $dates = array_fill(0, count($titles), date('Y-m-d H:i:s', strtotime(current_time('mysql'))));
983
  }
984
+
985
  // [custom taxonomies]
986
  require_once(ABSPATH . 'wp-admin/includes/taxonomy.php');
987
 
988
+ $taxonomies = array();
989
  $exclude_taxonomies = apply_filters('pmxi_exclude_taxonomies', (class_exists('PMWI_Plugin')) ? array('post_format', 'product_type', 'product_shipping_class', 'product_visibility') : array('post_format'));
990
  $post_taxonomies = array_diff_key(get_taxonomies_by_object_type(array($this->options['custom_type']), 'object'), array_flip($exclude_taxonomies));
991
  if ( $this->is_parsing_required('is_update_categories') && ! empty($post_taxonomies) && ! in_array($this->options['custom_type'], array('import_users', 'taxonomies', 'shop_customer', 'comments', 'woo_reviews')) ):
998
  switch ($this->options['tax_logic'][$tx_name]){
999
  case 'single':
1000
  if ( isset($this->options['tax_single_xpath'][$tx_name]) && $this->options['tax_single_xpath'][$tx_name] !== "" ){
1001
+ $txes = XmlImportParser::factory($xml, $cxpath, $this->options['tax_single_xpath'][$tx_name], $file)->parse($records); $tmp_files[] = $file;
1002
  foreach ($txes as $i => $tx) {
1003
  $taxonomies[$tx_name][$i][] = wp_all_import_ctx_mapping(array(
1004
  'name' => $tx,
1008
  'hierarchy_level' => 1,
1009
  'max_hierarchy_level' => 1
1010
  ), $mapping_rules, $tx_name);
1011
+ }
1012
  }
1013
  break;
1014
  case 'multiple':
1015
  if ( ! empty($this->options['tax_multiple_xpath'][$tx_name]) ){
1016
+ $txes = XmlImportParser::factory($xml, $cxpath, $this->options['tax_multiple_xpath'][$tx_name], $file)->parse($records); $tmp_files[] = $file;
1017
  foreach ($txes as $i => $tx) {
1018
  $_tx = $tx;
1019
  // apply mapping rules before splitting via separator symbol
1020
+ if ( ! empty($this->options['tax_enable_mapping'][$tx_name]) and ! empty($this->options['tax_logic_mapping'][$tx_name]) ){
1021
+ if ( ! empty( $mapping_rules) ){
1022
  foreach ($mapping_rules as $rule) {
1023
+ if ( ! empty($rule[trim($_tx)])){
1024
  $_tx = trim($rule[trim($_tx)]);
1025
  break;
1026
  }
1027
  }
1028
  }
1029
+ }
1030
+ $delimeted_taxonomies = explode( ! empty($this->options['tax_multiple_delim'][$tx_name]) ? $this->options['tax_multiple_delim'][$tx_name] : ',', $_tx);
1031
  if ( ! empty($delimeted_taxonomies) ){
1032
+ foreach ($delimeted_taxonomies as $cc) {
1033
  $taxonomies[$tx_name][$i][] = wp_all_import_ctx_mapping(array(
1034
  'name' => $cc,
1035
  'parent' => false,
1039
  'max_hierarchy_level' => 1
1040
  ), $mapping_rules, $tx_name);
1041
  }
1042
+ }
1043
  }
1044
  }
1045
  break;
1046
  case 'hierarchical':
1047
+ if ( ! empty($this->options['tax_hierarchical_logic_entire'][$tx_name])){
1048
  if (! empty($this->options['tax_hierarchical_xpath'][$tx_name]) and is_array($this->options['tax_hierarchical_xpath'][$tx_name])){
1049
  count($titles) and $iterator = array_fill(0, count($titles), 0);
1050
  $taxonomies_hierarchy_groups = array_fill(0, count($titles), array());
1051
+
1052
  // separate hierarchy groups via symbol
1053
  if ( ! empty($this->options['is_tax_hierarchical_group_delim'][$tx_name]) and ! empty($this->options['tax_hierarchical_group_delim'][$tx_name])){
1054
+ foreach ($this->options['tax_hierarchical_xpath'][$tx_name] as $k => $tx_xpath) {
1055
  if (empty($tx_xpath)) continue;
1056
+ $txes = XmlImportParser::factory($xml, $cxpath, $tx_xpath, $file)->parse($records); $tmp_files[] = $file;
1057
  foreach ($txes as $i => $tx) {
1058
  $_tx = $tx;
1059
  // apply mapping rules before splitting via separator symbol
1060
+ if ( ! empty($this->options['tax_enable_mapping'][$tx_name]) and ! empty($this->options['tax_logic_mapping'][$tx_name]) ){
1061
+ if ( ! empty( $mapping_rules) ){
1062
  foreach ($mapping_rules as $rule) {
1063
+ if ( ! empty($rule[trim($_tx)])){
1064
  $_tx = trim($rule[trim($_tx)]);
1065
  break;
1066
  }
1073
  if ( ! empty($group) ) array_push($taxonomies_hierarchy_groups[$i], $group);
1074
  }
1075
  }
1076
+ }
1077
  }
1078
  }
1079
  else{
1080
  foreach ($this->options['tax_hierarchical_xpath'][$tx_name] as $k => $tx_xpath) {
1081
  if (empty($tx_xpath)) continue;
1082
+ $txes = XmlImportParser::factory($xml, $cxpath, $tx_xpath, $file)->parse($records); $tmp_files[] = $file;
1083
+ foreach ($txes as $i => $tx) {
1084
  array_push($taxonomies_hierarchy_groups[$i], $tx);
1085
  }
1086
  }
1087
  }
1088
+
1089
  foreach ($taxonomies_hierarchy_groups as $i => $groups) { if (empty($groups)) continue;
1090
+ foreach ($groups as $kk => $tx) {
1091
  $_tx = $tx;
1092
  // apply mapping rules before splitting via separator symbol
1093
+ if ( ! empty($this->options['tax_enable_mapping'][$tx_name]) and ! empty($this->options['tax_logic_mapping'][$tx_name]) ){
1094
+ if ( ! empty( $mapping_rules) ){
1095
+ foreach ($mapping_rules as $rule) {
1096
+ if ( ! empty($rule[trim($_tx)])){
1097
  $_tx = trim($rule[trim($_tx)]);
1098
  break;
1099
  }
1101
  }
1102
  }
1103
  $delimeted_taxonomies = array_filter(array_filter(explode( ! empty($this->options['tax_hierarchical_delim'][$tx_name]) ? $this->options['tax_hierarchical_delim'][$tx_name] : ',', $_tx)));
1104
+ if ( ! empty($delimeted_taxonomies) ){
1105
+ foreach ($delimeted_taxonomies as $j => $cc) {
1106
  $is_assign_term = true;
1107
  if ( ! empty($this->options['tax_hierarchical_last_level_assign'][$tx_name]) ){
1108
  $is_assign_term = (count($delimeted_taxonomies) == $j + 1) ? 1 : 0;
1115
  'hierarchy_level' => $j + 1,
1116
  'max_hierarchy_level' => count($delimeted_taxonomies)
1117
  ), $mapping_rules, $tx_name);
1118
+ $iterator[$i]++;
1119
  }
1120
+ }
1121
  }
1122
+ }
1123
  }
1124
  }
1125
+ if ( ! empty($this->options['tax_hierarchical_logic_manual'][$tx_name])){
1126
  if ( ! empty($this->options['post_taxonomies'][$tx_name]) ){
1127
  $taxonomies_hierarchy = json_decode($this->options['post_taxonomies'][$tx_name], true);
1128
+
1129
+ foreach ($taxonomies_hierarchy as $k => $taxonomy){ if ("" == $taxonomy['xpath']) continue;
1130
+ $txes_raw = XmlImportParser::factory($xml, $cxpath, $taxonomy['xpath'], $file)->parse($records); $tmp_files[] = $file;
1131
  $warned = array();
1132
+
1133
  foreach ($txes_raw as $i => $cc) {
1134
 
1135
  $_tx = $cc;
1136
  // apply mapping rules before splitting via separator symbol
1137
+ if ( ! empty($this->options['tax_enable_mapping'][$tx_name]) and ! empty($this->options['tax_logic_mapping'][$tx_name]) ){
1138
+ if ( ! empty( $mapping_rules) ){
1139
  foreach ($mapping_rules as $rule) {
1140
+ if ( ! empty($rule[trim($_tx)])){
1141
  $_tx = trim($rule[trim($_tx)]);
1142
  break;
1143
  }
1144
  }
1145
  }
1146
  }
1147
+
1148
  if ( ! empty($this->options['tax_manualhierarchy_delim'][$tx_name])){
1149
  $delimeted_taxonomies = explode($this->options['tax_manualhierarchy_delim'][$tx_name], $_tx);
1150
  }
1151
+
1152
  if ( empty($delimeted_taxonomies) ) continue;
1153
 
1154
  if (empty($taxonomies_hierarchy[$k]['txn_names'][$i])) $taxonomies_hierarchy[$k]['txn_names'][$i] = array();
1155
  if (empty($taxonomies[$tx_name][$i])) $taxonomies[$tx_name][$i] = array();
1156
+ $count_cats = count($taxonomies[$tx_name][$i]);
1157
+
1158
  foreach ($delimeted_taxonomies as $j => $dc) {
1159
+
1160
+ if (!empty($taxonomy['parent_id'])) {
1161
  foreach ($taxonomies_hierarchy as $key => $value){
1162
+ if ($value['item_id'] == $taxonomy['parent_id'] and !empty($value['txn_names'][$i])){
1163
+ foreach ($value['txn_names'][$i] as $parent) {
1164
  $taxonomies[$tx_name][$i][] = wp_all_import_ctx_mapping(array(
1165
  'name' => trim($dc),
1166
  'parent' => $parent,
1171
  ), $mapping_rules, $tx_name);
1172
 
1173
  $taxonomies_hierarchy[$k]['txn_names'][$i][] = $taxonomies[$tx_name][$i][count($taxonomies[$tx_name][$i]) - 1];
1174
+ }
1175
  }
1176
+ }
1177
  }
1178
+ else {
1179
  $taxonomies[$tx_name][$i][] = wp_all_import_ctx_mapping(array(
1180
  'name' => trim($dc),
1181
  'parent' => false,
1187
 
1188
  $taxonomies_hierarchy[$k]['txn_names'][$i][] = $taxonomies[$tx_name][$i][count($taxonomies[$tx_name][$i]) - 1];
1189
  }
1190
+ }
1191
  }
1192
  }
1193
  }
1194
+ }
1195
  break;
1196
 
1197
  default:
1198
+
1199
  break;
1200
  }
1201
  }
1202
  endforeach;
1203
+ endif;
1204
  // [/custom taxonomies]
1205
 
1206
  // Composing featured images
1207
+ $image_sections = apply_filters('wp_all_import_image_sections', array(
1208
  array(
1209
  'slug' => '',
1210
  'title' => __('Images', 'wp_all_import_plugin'),
1211
  'type' => 'images'
1212
  )
1213
+ ));
1214
 
1215
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
1216
  $logger and call_user_func($logger, __('<b>WARNING</b>', 'wp_all_import_plugin') . ': ' . $uploads['error']);
1217
+ $logger and call_user_func($logger, __('<b>WARNING</b>: No featured images will be created. Uploads folder is not found.', 'wp_all_import_plugin'));
1218
+ $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1219
  } else {
1220
  $images_bundle = array();
1221
  $auto_rename_images_bundle = array();
1331
 
1332
  // Composing attachments
1333
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
1334
+ $logger and call_user_func($logger, __('<b>WARNING</b>', 'wp_all_import_plugin') . ': ' . $uploads['error']);
1335
+ $logger and call_user_func($logger, __('<b>WARNING</b>: No attachments will be created', 'wp_all_import_plugin'));
1336
  $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1337
  } else {
1338
  $chunk == 1 and $logger and call_user_func($logger, __('Composing URLs for attachments files...', 'wp_all_import_plugin'));
1346
  foreach($atchs as $atch) if (!preg_match("/{.*}/", trim($atch))) $parse_multiple = false;
1347
  if ($parse_multiple) {
1348
  foreach($atchs as $atch) {
1349
+ $posts_attachments = XmlImportParser::factory($xml, $cxpath, trim($atch), $file)->parse($records); $tmp_files[] = $file;
1350
+ foreach($posts_attachments as $i => $val) $attachments[$i][] = $val;
1351
  }
1352
  }
1353
  else {
1354
+ $attachments = XmlImportParser::factory($xml, $cxpath, $this->options['attachments'], $file)->parse($records); $tmp_files[] = $file;
1355
  }
1356
  }
1357
  } else {
1367
  count($titles) and $unique_keys = array_fill(0, count($titles), '');
1368
  }
1369
 
1370
+ $chunk == 1 and $logger and call_user_func($logger, __('Processing posts...', 'wp_all_import_plugin'));
1371
 
1372
  $addons = array();
1373
  $addons_data = array();
1380
  'xml' => $xml,
1381
  'logger' => $logger,
1382
  'chunk' => $chunk,
1383
+ 'xpath_prefix' => $xpath_prefix
1384
  );
1385
  $parse_functions = apply_filters('wp_all_import_addon_parse', array());
1386
+ foreach (PMXI_Admin_Addons::get_active_addons() as $class) {
1387
+ $model_class = str_replace("_Plugin", "_Import_Record", $class);
1388
+ if (class_exists($model_class)){
1389
  $addons[$class] = new $model_class();
1390
+ $addons_data[$class] = ( method_exists($addons[$class], 'parse') ) ? $addons[$class]->parse($parsingData) : false;
1391
  } else {
1392
  if ( ! empty($parse_functions[$class]) ){
1393
  if ( is_array($parse_functions[$class]) and is_callable($parse_functions[$class]) or ! is_array($parse_functions[$class]) and function_exists($parse_functions[$class]) ){
1394
+ $addons_data[$class] = call_user_func($parse_functions[$class], $parsingData);
1395
  }
1396
  }
1397
  }
1398
  }
1399
 
1400
+ // save current import state to variables before import
1401
  $created = $this->created;
1402
  $updated = $this->updated;
1403
+ $skipped = $this->skipped;
1404
+
1405
  $specified_records = array();
1406
 
1407
  $simpleXml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
1408
+
1409
  $rootNodes = $simpleXml->xpath($cxpath);
1410
 
1411
  if ($this->options['is_import_specified']) {
1436
  break;
1437
  }
1438
 
1439
+ if ($is_cron and $cron_sleep) sleep($cron_sleep);
1440
 
1441
  $logger and call_user_func($logger, __('---', 'wp_all_import_plugin'));
1442
  $logger and call_user_func($logger, sprintf(__('Record #%s', 'wp_all_import_plugin'), $this->imported + $this->skipped + $i + 1));
1443
 
1444
+ if ( "manual" == $this->options['duplicate_matching']
1445
+ and ! empty($specified_records)
1446
  and ! in_array($created + $updated + $skipped + 1, $specified_records) )
1447
  {
1448
+ $skipped++;
1449
  $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'wp_all_import_plugin'));
1450
+ $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1451
  $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1452
+ $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1453
+ continue;
1454
  }
1455
 
1456
  $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_before_post_import ...', 'wp_all_import_plugin'));
1468
  $logger and call_user_func($logger, __('<b>WARNING</b>: title is empty.', 'wp_all_import_plugin'));
1469
  $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1470
  }
1471
+ }
1472
 
1473
  switch ($this->options['custom_type']){
1474
  case 'import_users':
1578
  // }
1579
  break;
1580
  }
1581
+
1582
  // Re-import Records Matching
1583
  $post_to_update = false; $post_to_update_id = false;
1584
 
1585
  // An array representation of current XML node
1586
+ $current_xml_node = wp_all_import_xml2array($rootNodes[$i]);
1587
 
1588
  $check_for_duplicates = apply_filters('wp_all_import_is_check_duplicates', true, $this->id);
1589
 
1590
  if ( $check_for_duplicates ) {
1591
  // if Auto Matching re-import option selected
1592
  if ( "manual" != $this->options['duplicate_matching'] ) {
1593
+ // find corresponding article among previously imported
1594
  $logger and call_user_func($logger, sprintf(__('Find corresponding article among previously imported for post `%s`...', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1595
  $postList = new PMXI_Post_List();
1596
  $args = array(
1622
  if (empty($post_to_update)) {
1623
  $logger and call_user_func($logger, sprintf(__('Duplicate post wasn\'t found with unique key `%s`...', 'wp_all_import_plugin'), wp_all_import_clear_xss($unique_keys[$i])));
1624
  }
1625
+
1626
  // if Manual Matching re-import option seleted
1627
  } else {
1628
+
1629
  if ('custom field' == $this->options['duplicate_indicator']) {
1630
  $custom_duplicate_value = XmlImportParser::factory($xml, $cxpath, $this->options['custom_duplicate_value'], $file)->parse($records); $tmp_files[] = $file;
1631
  $custom_duplicate_name = XmlImportParser::factory($xml, $cxpath, $this->options['custom_duplicate_name'], $file)->parse($records); $tmp_files[] = $file;
1632
  } else {
1633
  count($titles) and $custom_duplicate_name = $custom_duplicate_value = array_fill(0, count($titles), '');
1634
  }
1635
+
1636
  $logger and call_user_func($logger, sprintf(__('Find corresponding article among database for post `%s`...', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1637
 
1638
  $duplicates = array();
1676
  $logger and call_user_func($logger, sprintf(__('Duplicate post wasn\'t found for post `%s`...', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1677
  }
1678
  }
1679
+ }
1680
 
1681
  $is_post_to_skip = apply_filters('wp_all_import_is_post_to_skip', false, $this->id, $current_xml_node, $i, $post_to_update_id, $simpleXml);
1682
 
1685
  $postRecord->set(array('iteration' => $this->iteration))->update();
1686
  }
1687
  $skipped++;
1688
+ $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1689
  $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1690
+ $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1691
+ continue;
1692
+ }
1693
 
1694
  if ( ! empty($specified_records) ) {
1695
  if ( ! in_array($created + $updated + $skipped + 1, $specified_records) ) {
1696
  if ( ! $postRecord->isEmpty() ) {
1697
  $postRecord->set(array('iteration' => $this->iteration))->update();
1698
  }
1699
+ $skipped++;
1700
  $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'wp_all_import_plugin'));
1701
+ $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1702
  $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1703
+ $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1704
  continue;
1705
+ }
1706
+ }
1707
 
1708
  $missing_images = array();
1709
  // Duplicate record is found
1715
 
1716
  if ( ! $continue_import ){
1717
 
1718
+ if ( ! $postRecord->isEmpty() ) $postRecord->set(array('iteration' => $this->iteration))->update();
1719
 
1720
  $skipped++;
1721
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: By filter wp_all_import_is_post_to_update `%s`', 'wp_all_import_plugin'), $articleData['post_title']));
1722
+ $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1723
+ $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1724
+ $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1725
  do_action('wp_all_import_post_skipped', $post_to_update_id, $this->id, $current_xml_node);
1726
  continue;
1727
  }
1729
  //$logger and call_user_func($logger, sprintf(__('Duplicate record is found for `%s`', 'wp_all_import_plugin'), $articleData['post_title']));
1730
 
1731
  // Do not update already existing records option selected
1732
+ if ("yes" == $this->options['is_keep_former_posts']) {
1733
 
1734
+ if ( ! $postRecord->isEmpty() ) $postRecord->set(array('iteration' => $this->iteration))->update();
1735
 
1736
  do_action('pmxi_do_not_update_existing', $post_to_update_id, $this->id, $this->iteration, $xml, $i);
1737
 
1738
  $skipped++;
1739
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: Previously imported record found for `%s`', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1740
+ $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1741
+ $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1742
+ $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1743
  do_action('wp_all_import_post_skipped', $post_to_update_id, $this->id, $current_xml_node);
1744
  continue;
1745
  }
1963
  }
1964
  }
1965
  elseif ( ! $postRecord->isEmpty() ){
1966
+
1967
  // existing post not found though it's track was found... clear the leftover, plugin will continue to treat record as new
1968
  $postRecord->clear();
1969
+
1970
+ }
1971
 
1972
  $logger and call_user_func($logger, sprintf(__('Applying filter `pmxi_article_data` for `%s`', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
1973
  $articleData = apply_filters('pmxi_article_data', $articleData, $this, $post_to_update, $current_xml_node);
1974
+
1975
  // no new records are created. it will only update posts it finds matching duplicates for
1976
+ if ( ! $this->options['create_new_records'] and empty($articleData['ID']) ){
1977
+
1978
  if ( ! $postRecord->isEmpty() ) $postRecord->set(array('iteration' => $this->iteration))->update();
1979
 
1980
  $logger and call_user_func($logger, __('<b>SKIPPED</b>: The option \'Create new posts from records newly present in your file\' is disabled in your import settings.', 'wp_all_import_plugin'));
1981
+ $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
1982
  $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
1983
+ $skipped++;
1984
+ $logger and !$is_cron and PMXI_Plugin::$session->save_data();
1985
  do_action('wp_all_import_post_skipped', 0, $this->id, $current_xml_node);
1986
  continue;
1987
  }
1988
+
1989
  // cloak urls with `WP Wizard Cloak` if corresponding option is set
1990
  if ( ! empty($this->options['is_cloak']) and class_exists('PMLC_Plugin')) {
1991
  if (preg_match_all('%<a\s[^>]*href=(?(?=")"([^"]*)"|(?(?=\')\'([^\']*)\'|([^\s>]*)))%is', $articleData['post_content'], $matches, PREG_PATTERN_ORDER)) {
2061
  }
2062
  }
2063
  }
2064
+ }
2065
 
2066
+ // insert article being imported
2067
  if ($this->options['is_fast_mode']){
2068
  foreach (array('transition_post_status', 'save_post', 'pre_post_update', 'add_attachment', 'edit_attachment', 'edit_post', 'post_updated', 'wp_insert_post', 'save_post_' . $post_type[$i]) as $act) {
2069
  remove_all_actions($act);
2075
  $continue_import = true;
2076
  $continue_import = apply_filters('wp_all_import_is_post_to_create', $continue_import, $current_xml_node, $this->id);
2077
 
2078
+ if ( ! $continue_import ){
2079
  $skipped++;
2080
  $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: By filter wp_all_import_is_post_to_create `%s`', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
2081
+ $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
2082
+ $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
2083
+ $logger and !$is_cron and PMXI_Plugin::$session->save_data();
2084
  do_action('wp_all_import_post_skipped', 0, $this->id, $current_xml_node);
2085
  continue;
2086
  }
2205
  $pid = (empty($articleData['ID'])) ? wp_insert_post($articleData, true) : wp_update_post($articleData, true);
2206
  break;
2207
  }
2208
+
2209
  if (empty($pid)) {
2210
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'wp_all_import_plugin') . ': something wrong, ID = 0 was generated.');
2211
  $logger and !$is_cron and PMXI_Plugin::$session->errors++;
2227
  $is_images_to_update = apply_filters('pmxi_is_images_to_update', true, $articleData, $current_xml_node, $pid);
2228
 
2229
  if ("manual" != $this->options['duplicate_matching'] or empty($articleData['ID'])){
2230
+ // associate post with import
2231
  $product_key = (($post_type[$i] == "product" and PMXI_Admin_Addons::get_addon('PMWI_Plugin')) ? $addons_data['PMWI_Plugin']['single_product_ID'][$i] : '');
2232
  if ($post_type[$i] == "taxonomies"){
2233
  $product_key = 'taxonomy_term';
2313
  // Deligate import operation to addons.
2314
  foreach (PMXI_Admin_Addons::get_active_addons() as $class) {
2315
  if (class_exists($class)) {
2316
+ if ( method_exists($addons[$class], 'import') ) $addons[$class]->import($importData);
2317
  } else {
2318
  if (!empty($import_functions[$class])) {
2319
  if (is_array($import_functions[$class]) and is_callable($import_functions[$class]) or ! is_array($import_functions[$class]) and function_exists($import_functions[$class]) ) {
2320
+ call_user_func($import_functions[$class], $importData, $addons_data[$class]);
2321
+ }
2322
  }
2323
  }
2324
  }
2330
  if ( ! empty($articleData['post_type']) && !in_array($articleData['post_type'], array('taxonomies', 'comments', 'woo_reviews')) && ('page' == $articleData['post_type'] || version_compare($wp_version, '4.7.0', '>=')) && wp_all_import_is_update_cf('_wp_page_template', $this->options) && ( !empty($this->options['page_template']) || "no" == $this->options['is_multiple_page_template']) ){
2331
  update_post_meta($pid, '_wp_page_template', ("no" == $this->options['is_multiple_page_template']) ? $page_template[$i] : $this->options['page_template']);
2332
  }
2333
+
2334
  // [featured image]
2335
 
2336
  $featuredImage = false;
2441
  }
2442
  }
2443
 
2444
+ if (empty($image) || !preg_match('%\W(jpg|jpeg|png|gif|webp|svg)$%i', trim(basename($image)))) continue;
2445
 
2446
  $attid = false;
2447
 
2580
  if ( $is_images_to_update and ! empty($images_uploads) and false === $images_uploads['error'] and ( ! empty($articleData['post_type']) and in_array($articleData['post_type'], ["product", "product_variation"]) and class_exists('PMWI_Plugin') or $is_allow_import_images) and (empty($articleData['ID']) or $this->options['update_all_data'] == "yes" or ( $this->options['update_all_data'] == "no" and $this->options['is_update_images'])) ) {
2581
 
2582
  if ( ! empty($images_bundle) ){
2583
+
2584
+ require_once(ABSPATH . 'wp-admin/includes/image.php');
2585
 
2586
  $is_show_add_new_images = apply_filters('wp_all_import_is_show_add_new_images', true, $post_type[$i]);
2587
 
2590
  foreach ($images_bundle as $slug => $bundle_data) {
2591
 
2592
  if ( ! $is_images_section_enabled && $slug == 'pmxi_gallery_image' ) continue;
2593
+
2594
  $featured_images = $bundle_data['files'];
2595
 
2596
  $option_slug = ($slug == 'pmxi_gallery_image') ? '' : $slug;
2597
 
2598
+ $gallery_attachment_ids = array();
2599
 
2600
  if ( ! empty($featured_images[$i]) ){
2601
 
2605
  if ( ! @is_writable($targetDir) ){
2606
  $logger and call_user_func($logger, sprintf(__('<b>ERROR</b>: Target directory %s is not writable', 'wp_all_import_plugin'), $targetDir));
2607
  }
2608
+ else{
2609
+
2610
+ $success_images = false;
2611
+
2612
  $imgs = array();
2613
 
2614
  switch ($this->options[$option_slug . 'download_images']) {
2617
  break;
2618
  case 'gallery':
2619
  $featured_delim = $this->options[$option_slug . 'gallery_featured_delim'];
2620
+ break;
2621
  default: // yes
2622
  $featured_delim = $this->options[$option_slug . 'download_featured_delim'];
2623
  break;
2624
+ }
2625
 
2626
  $line_imgs = explode("\n", $featured_images[$i]);
2627
  if ( ! empty($line_imgs) )
2628
  foreach ($line_imgs as $line_img)
2629
+ $imgs = array_merge($imgs, ( ! empty($featured_delim) ) ? str_getcsv($line_img, $featured_delim) : array($line_img) );
2630
 
2631
  // keep existing and add newest images
2632
  if ( ! empty($articleData['ID']) and $this->options['is_update_images'] and $this->options['update_images_logic'] == "add_new" and $this->options['update_all_data'] == "no" and $is_show_add_new_images){
2633
+
2634
  $logger and call_user_func($logger, __('- Keep existing and add newest images ...', 'wp_all_import_plugin'));
2635
 
2636
+ $attachment_imgs = get_attached_media( 'image', $pid );
2637
 
2638
  if ( $post_type[$i] == "product" ){
2639
  $gallery_attachment_ids = array_filter(explode(",", get_post_meta($pid, '_product_image_gallery', true)));
2640
  }
2641
 
2642
+ if ( $attachment_imgs ) {
2643
+ foreach ( $attachment_imgs as $attachment_img ) {
2644
  $post_thumbnail_id = get_post_thumbnail_id( $pid );
2645
  if ( empty($post_thumbnail_id) and $this->options[$option_slug . 'is_featured'] ) {
2646
  set_post_thumbnail($pid, $attachment_img->ID);
2647
  }
2648
  elseif(!in_array($attachment_img->ID, $gallery_attachment_ids) and $post_thumbnail_id != $attachment_img->ID) {
2649
+ $gallery_attachment_ids[] = $attachment_img->ID;
2650
+ }
2651
+ }
2652
+ $success_images = true;
2653
+ }
2654
 
2655
  if ( ! empty($gallery_attachment_ids) ){
2656
  foreach ($gallery_attachment_ids as $aid){
2658
  }
2659
  }
2660
  }
2661
+
2662
  if ( ! empty($imgs) ) {
2663
 
2664
+ if ( $this->options[$option_slug . 'set_image_meta_title'] and !empty($image_meta_titles_bundle[$slug])){
2665
+ $img_titles = array();
2666
  $line_img_titles = explode("\n", $image_meta_titles_bundle[$slug][$i]);
2667
  if ( ! empty($line_img_titles) )
2668
  foreach ($line_img_titles as $line_img_title)
2669
  $img_titles = array_merge($img_titles, ( ! empty($this->options[$option_slug . 'image_meta_title_delim']) ) ? explode($this->options[$option_slug . 'image_meta_title_delim'], $line_img_title) : array($line_img_title) );
2670
+
2671
  }
2672
+ if ( $this->options[$option_slug . 'set_image_meta_caption'] and !empty($image_meta_captions_bundle[$slug])){
2673
+ $img_captions = array();
2674
  $line_img_captions = explode("\n", $image_meta_captions_bundle[$slug][$i]);
2675
  if ( ! empty($line_img_captions) )
2676
  foreach ($line_img_captions as $line_img_caption)
2677
  $img_captions = array_merge($img_captions, ( ! empty($this->options[$option_slug . 'image_meta_caption_delim']) ) ? explode($this->options[$option_slug . 'image_meta_caption_delim'], $line_img_caption) : array($line_img_caption) );
2678
 
2679
  }
2680
+ if ( $this->options[$option_slug . 'set_image_meta_alt'] and !empty($image_meta_alts_bundle[$slug])){
2681
+ $img_alts = array();
2682
  $line_img_alts = explode("\n", $image_meta_alts_bundle[$slug][$i]);
2683
  if ( ! empty($line_img_alts) )
2684
  foreach ($line_img_alts as $line_img_alt)
2685
  $img_alts = array_merge($img_alts, ( ! empty($this->options[$option_slug . 'image_meta_alt_delim']) ) ? explode($this->options[$option_slug . 'image_meta_alt_delim'], $line_img_alt) : array($line_img_alt) );
2686
 
2687
  }
2688
+ if ( $this->options[$option_slug . 'set_image_meta_description'] and !empty($image_meta_descriptions_bundle[$slug])){
2689
+ $img_descriptions = array();
2690
  $line_img_descriptions = ($this->options[$option_slug . 'image_meta_description_delim_logic'] == 'line' or empty($this->options[$option_slug . 'image_meta_description_delim'])) ? explode("\n", $image_meta_descriptions_bundle[$slug][$i]) : array($image_meta_descriptions_bundle[$slug][$i]);
2691
  if ( ! empty($line_img_descriptions) )
2692
  foreach ($line_img_descriptions as $line_img_description)
2693
  $img_descriptions = array_merge($img_descriptions, ($this->options[$option_slug . 'image_meta_description_delim_logic'] == 'separate' and ! empty($this->options[$option_slug . 'image_meta_description_delim']) ) ? explode($this->options[$option_slug . 'image_meta_description_delim'], $line_img_description) : array($line_img_description) );
2694
 
2695
+ }
2696
 
2697
+ $is_keep_existing_images = ( ! empty($articleData['ID']) and $this->options['is_update_images'] and $this->options['update_images_logic'] == "add_new" and $this->options['update_all_data'] == "no" and $is_show_add_new_images);
2698
 
2699
  foreach ($imgs as $k => $img_url) {
2700
 
2713
  continue;
2714
  }
2715
 
2716
+ $attid = false;
2717
 
2718
+ $attch = null;
2719
 
2720
  // remove encoded quotes from url (&#34; and &#39;)
2721
  $url = html_entity_decode(trim($img_url), ENT_QUOTES);
2722
 
2723
+ if (empty($url)) continue;
2724
 
2725
  $bn = wp_all_import_sanitize_filename(urldecode(wp_all_import_basename($url)));
2726
  $default_extension = pmxi_getExtension($bn);
2731
  else {
2732
  $img_ext = pmxi_getExtensionFromStr($url);
2733
 
2734
+ if ($img_ext == "") $img_ext = pmxi_get_remote_image_ext($url);
2735
  }
2736
 
2737
  $logger and call_user_func($logger, sprintf(__('- Importing image `%s` for `%s` ...', 'wp_all_import_plugin'), $img_url, $this->getRecordTitle($articleData)));
2740
  $image_name = urldecode(($this->options[$option_slug . 'auto_rename_images'] and !empty($auto_rename_images_bundle[$slug][$i])) ? sanitize_file_name(($img_ext) ? str_replace("." . $default_extension, "", $auto_rename_images_bundle[$slug][$i]) : $auto_rename_images_bundle[$slug][$i]) : (($img_ext) ? str_replace("." . $default_extension, "", $bn) : $bn)) . (("" != $img_ext) ? '.' . $img_ext : '');
2741
  $image_name = apply_filters("wp_all_import_image_filename", $image_name, empty($img_titles[$k]) ? '' : $img_titles[$k], empty($img_captions[$k]) ? '' : $img_captions[$k], empty($img_alts[$k]) ? '' : $img_alts[$k], $articleData, $this->id, $img_url);
2742
 
2743
+ // if wizard store image data to custom field
2744
  $create_image = false;
2745
  $download_image = true;
2746
  $wp_filetype = false;
2747
 
2748
+ $is_base64_images_allowed = apply_filters("wp_all_import_is_base64_images_allowed", true, $url, $this->id);
2749
 
2750
+ if ( $bundle_data['type'] == 'images' and wp_all_import_is_base64_encoded($url) and $is_base64_images_allowed ){
2751
  $image_name = empty($this->options[$option_slug . 'auto_rename_images']) ? md5($url) . '.jpg' : sanitize_file_name($auto_rename_images_bundle[$slug][$i]) . '.jpg';
2752
  $image_name = apply_filters("wp_all_import_image_filename", $image_name, empty($img_titles[$k]) ? '' : $img_titles[$k], empty($img_captions[$k]) ? '' : $img_captions[$k], empty($img_alts[$k]) ? '' : $img_alts[$k], $articleData, $this->id, $img_url);
2753
 
2788
  }
2789
  }
2790
  }
2791
+ }
2792
+
2793
+ if ( ! $create_image && empty($attch) ) {
2794
 
 
 
2795
  if ($this->options[$option_slug . 'auto_rename_images'] and !empty($auto_rename_images_bundle[$slug][$i])) {
2796
  if ($k) {
2797
  $image_name = str_replace('.' . pmxi_getExtension($image_name), '', $image_name) . '-' . $k . '.' . pmxi_getExtension($image_name);
2798
+ }
2799
  }
2800
+
2801
  $image_filename = wp_unique_filename($targetDir, $image_name);
2802
  $image_filepath = $targetDir . '/' . $image_filename;
2803
 
2804
  // search existing attachment
2805
  if ($this->options[$option_slug . 'search_existing_images'] or "gallery" == $this->options[$option_slug . 'download_images']){
2806
+
2807
  $image_filename = $image_name;
2808
 
2809
  // trying to find existing image in images table
2853
  if ($imageRecord->isEmpty()){
2854
  $imageRecord->set(array(
2855
  'attachment_id' => $attid,
2856
+ 'image_url' => (wp_all_import_is_base64_encoded($url) && $is_base64_images_allowed) ? '' : $url,
2857
  'image_filename' => $image_name
2858
  ))->insert();
2859
  }
2863
  // update image URL if it was not set
2864
  if (empty($imageRecord->image_url)){
2865
  $imageRecord->set(array(
2866
+ 'image_url' => (wp_all_import_is_base64_encoded($url) && $is_base64_images_allowed) ? '' : $url,
2867
  ))->update();
2868
  }
2869
  break;
2884
  if ($download_image && "gallery" != $this->options[$option_slug . 'download_images']){
2885
 
2886
  // do not download images
2887
+ if ( "no" == $this->options[$option_slug . 'download_images'] ){
2888
 
2889
  $image_filename = wp_unique_filename($targetDir, $image_name);
2890
+ $image_filepath = $targetDir . '/' . $image_filename;
2891
+
2892
  $wpai_uploads = $uploads['basedir'] . DIRECTORY_SEPARATOR . PMXI_Plugin::FILES_DIRECTORY . DIRECTORY_SEPARATOR;
2893
  $wpai_image_path = $wpai_uploads . str_replace('%20', ' ', $url);
2894
 
2895
  $logger and call_user_func($logger, sprintf(__('- Searching for existing image `%s`', 'wp_all_import_plugin'), $wpai_image_path));
2896
 
2897
  if ( @file_exists($wpai_image_path) and @copy( $wpai_image_path, $image_filepath )){
2898
+ $download_image = false;
2899
  // validate import attachments
2900
  if ($bundle_data['type'] == 'files'){
2901
  if( ! $wp_filetype = wp_check_filetype(wp_all_import_basename($image_filepath), null )) {
2904
  @unlink($image_filepath);
2905
  }
2906
  else {
2907
+ $create_image = true;
2908
  $logger and call_user_func($logger, sprintf(__('- File `%s` has been successfully found', 'wp_all_import_plugin'), $wpai_image_path));
2909
  }
2910
  }
2911
  // validate import images
2912
  elseif($bundle_data['type'] == 'images'){
2913
  if( preg_match('%\W(svg)$%i', wp_all_import_basename($image_filepath)) or $image_info = apply_filters('pmxi_getimagesize', @getimagesize($image_filepath), $image_filepath) and in_array($image_info[2], wp_all_import_supported_image_types())) {
2914
+ $create_image = true;
2915
  $logger and call_user_func($logger, sprintf(__('- Image `%s` has been successfully found', 'wp_all_import_plugin'), $wpai_image_path));
2916
  }
2917
  else
2919
  $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: File %s is not a valid image and cannot be set as featured one', 'wp_all_import_plugin'), $image_filepath));
2920
  $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
2921
  @unlink($image_filepath);
2922
+ }
2923
  }
2924
+ }
2925
+ }
2926
  else {
2927
  $image_info = $this->downloadFile($url, $image_filepath, $is_cron, $logger, $bundle_data['type']);
2928
  if ( ! $image_info ) {
2935
  }
2936
  }
2937
  $create_image = empty($image_info) ? false : true;
2938
+ }
2939
  }
2940
  }
2941
 
2949
  if ($bundle_data['type'] == 'images') {
2950
  if ( ! empty($image_info) && is_array($image_info) ) {
2951
  $file_mime_type = image_type_to_mime_type($image_info[2]);
2952
+ }
2953
  $file_mime_type = apply_filters('wp_all_import_image_mime_type', $file_mime_type, $image_filepath);
2954
  }
2955
  else {
2973
  if ($imageRecord->isEmpty()){
2974
  $imageRecord->set(array(
2975
  'attachment_id' => $attid,
2976
+ 'image_url' => (wp_all_import_is_base64_encoded($url) && $is_base64_images_allowed) ? '' : $url,
2977
  'image_filename' => $image_name
2978
  ))->insert();
2979
  }
2984
  // update image URL if it was not set
2985
  if (empty($imageRecord->image_url)){
2986
  $imageRecord->set(array(
2987
+ 'image_url' => (wp_all_import_is_base64_encoded($url) && $is_base64_images_allowed) ? '' : $url
2988
  ))->update();
2989
  }
2990
  break;
3006
  if ($attch != null && empty($attch->post_parent) && ! in_array($post_type[$i], array('taxonomies'))){
3007
  wp_update_post(
3008
  array(
3009
+ 'ID' => $attch->ID,
3010
  'post_parent' => $pid
3011
  )
3012
  );
3017
  if ( $this->options[$option_slug . 'set_image_meta_caption'] and ! empty($img_captions[$k]) ) $update_attachment_meta['post_excerpt'] = trim($img_captions[$k]);
3018
  if ( $this->options[$option_slug . 'set_image_meta_description'] and ! empty($img_descriptions[$k]) ) $update_attachment_meta['post_content'] = trim($img_descriptions[$k]);
3019
  if ( $this->options[$option_slug . 'set_image_meta_alt'] and ! empty($img_alts[$k]) ) update_post_meta($attid, '_wp_attachment_image_alt', trim($img_alts[$k]));
3020
+
3021
  if ( !empty($update_attachment_meta)) {
3022
  $update_attachment_meta['ID'] = $attid;
3023
  $gallery_post = wp_update_post( $update_attachment_meta, true );
3026
  }
3027
  }
3028
 
3029
+ $logger and call_user_func($logger, __('- <b>ACTION</b>: ' . $slug, 'wp_all_import_plugin'));
3030
+ do_action( $slug, $pid, $attid, ($handle_image) ? $handle_image['file'] : $image_filepath, $is_keep_existing_images ? 'add_images' : 'update_images');
3031
 
3032
  $success_images = true;
3033
 
3047
 
3048
  if ($attch != null and empty($attch->post_parent)) {
3049
  $logger and call_user_func($logger, sprintf(__('- Attachment with ID: `%s` has been successfully updated for image `%s`', 'wp_all_import_plugin'), $attid, ($handle_image) ? $handle_image['url'] : $targetUrl . '/' . $image_filename));
3050
+ }
3051
  elseif(empty($attch)) {
3052
  $logger and call_user_func($logger, sprintf(__('- Attachment with ID: `%s` has been successfully created for image `%s`', 'wp_all_import_plugin'), $attid, ($handle_image) ? $handle_image['url'] : $targetUrl . '/' . $image_filename));
3053
  }
3054
+ }
3055
+ }
3056
  }
3057
+
3058
  // Set product gallery images
3059
  if ( $post_type[$i] == "product" ){
3060
  update_post_meta($pid, '_product_image_gallery', (!empty($gallery_attachment_ids)) ? implode(',', $gallery_attachment_ids) : '');
3065
  if ( ! $success_images and "yes" == $this->options[$option_slug . 'create_draft'] and $final_post_type != 'product_variation' and ! in_array($post_type[$i], array('taxonomies', 'comments', 'woo_reviews'))) {
3066
  $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $pid) );
3067
  $logger and call_user_func($logger, sprintf(__('- Post `%s` saved as Draft, because no images are downloaded successfully', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
3068
+ }
3069
  }
3070
  }
3071
+ else{
3072
  // Create entry as Draft if no images are downloaded successfully
3073
+ $final_post_type = get_post_type($pid);
3074
  if ( "yes" == $this->options[$option_slug . 'create_draft'] and $final_post_type != 'product_variation' and ! in_array($post_type[$i], array('taxonomies', 'comments', 'woo_reviews'))){
3075
  $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $pid) );
3076
  $logger and call_user_func($logger, sprintf(__('Post `%s` saved as Draft, because no images are downloaded successfully', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
3121
  {
3122
  $logger and call_user_func($logger, sprintf(__('Images import skipped for post `%s` according to \'pmxi_is_images_to_update\' filter...', 'wp_all_import_plugin'), $this->getRecordTitle($articleData)));
3123
  }
3124
+ // [/featured image]
3125
 
3126
  // [attachments]
3127
  $is_attachments_to_update = apply_filters('pmxi_is_attachments_to_update', true, $articleData, $current_xml_node);
3309
  // [custom taxonomies]
3310
  if ( ! empty($taxonomies) ){
3311
 
3312
+ $logger and call_user_func($logger, __('<b>TAXONOMIES:</b>', 'wp_all_import_plugin'));
3313
 
3314
+ foreach ($taxonomies as $tx_name => $txes) {
3315
 
3316
  // Skip updating product attributes
3317
  if ( PMXI_Admin_Addons::get_addon('PMWI_Plugin') and strpos($tx_name, "pa_") === 0 ) continue;
3318
 
3319
  if ( empty($articleData['ID']) or $this->options['update_all_data'] == "yes" or ( $this->options['update_all_data'] == "no" and $this->options['is_update_categories'] )) {
3320
+
3321
+ $logger and call_user_func($logger, sprintf(__('- Importing taxonomy `%s` ...', 'wp_all_import_plugin'), $tx_name));
3322
 
3323
  if ( ! empty($this->options['tax_logic'][$tx_name]) and $this->options['tax_logic'][$tx_name] == 'hierarchical' and ! empty($this->options['tax_hierarchical_logic'][$tx_name]) and $this->options['tax_hierarchical_logic'][$tx_name] == 'entire'){
3324
  $logger and call_user_func($logger, sprintf(__('- Auto-nest enabled with separator `%s` ...', 'wp_all_import_plugin'), ( ! empty($this->options['tax_hierarchical_delim'][$tx_name]) ? $this->options['tax_hierarchical_delim'][$tx_name] : ',')));
3325
  }
3326
 
3327
  if (!empty($articleData['ID'])){
3328
+ if ($this->options['update_all_data'] == "no" and $this->options['update_categories_logic'] == "all_except" and !empty($this->options['taxonomies_list'])
3329
+ and is_array($this->options['taxonomies_list']) and in_array($tx_name, $this->options['taxonomies_list'])){
3330
  $logger and call_user_func($logger, sprintf(__('- %s %s has been skipped attempted to `Leave these taxonomies alone, update all others`...', 'wp_all_import_plugin'), $custom_type_details->labels->singular_name, $tx_name));
3331
  continue;
3332
+ }
3333
+ if ($this->options['update_all_data'] == "no" and $this->options['update_categories_logic'] == "only" and ((!empty($this->options['taxonomies_list'])
3334
+ and is_array($this->options['taxonomies_list']) and ! in_array($tx_name, $this->options['taxonomies_list'])) or empty($this->options['taxonomies_list']))){
3335
  $logger and call_user_func($logger, sprintf(__('- %s %s has been skipped attempted to `Update only these taxonomies, leave the rest alone`...', 'wp_all_import_plugin'), $custom_type_details->labels->singular_name, $tx_name));
3336
  continue;
3337
  }
3338
+ }
3339
 
3340
  $assign_taxes = array();
3341
 
3342
  if ($this->options['update_categories_logic'] == "add_new" and !empty($existing_taxonomies[$tx_name][$i])){
3343
+ $assign_taxes = $existing_taxonomies[$tx_name][$i];
3344
  unset($existing_taxonomies[$tx_name][$i]);
3345
  }
3346
  elseif(!empty($existing_taxonomies[$tx_name][$i])){
3384
  }
3385
  }
3386
  }
3387
+ }
3388
+
3389
+ if ( is_wp_error($term) ){
3390
  $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: `%s`', 'wp_all_import_plugin'), $term->get_error_message()));
3391
  $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
3392
  }
3401
  if (!in_array($p, $assign_taxes)) $assign_taxes[] = $p;
3402
  }
3403
  }
3404
+ }
3405
+ if (!in_array($term->term_taxonomy_id, $assign_taxes)) $assign_taxes[] = $term->term_taxonomy_id;
3406
+ if (!$is_created_term){
3407
+ if ( empty($parent_id) ){
3408
+ $logger and call_user_func($logger, sprintf(__('- Attempted to create parent %s %s `%s`, duplicate detected. Importing %s to existing `%s` %s, ID %d, slug `%s` ...', 'wp_all_import_plugin'), $custom_type_details->labels->singular_name, $tx_name, $single_tax['name'], $custom_type_details->labels->singular_name, $term->name, $tx_name, $term->term_id, $term->slug));
3409
+ }
3410
+ else{
3411
+ $logger and call_user_func($logger, sprintf(__('- Attempted to create child %s %s `%s`, duplicate detected. Importing %s to existing `%s` %s, ID %d, slug `%s` ...', 'wp_all_import_plugin'), $custom_type_details->labels->singular_name, $tx_name, $single_tax['name'], $custom_type_details->labels->singular_name, $term->name, $tx_name, $term->term_id, $term->slug));
3412
  }
 
 
 
3413
  }
3414
+ }
3415
+ }
3416
  }
3417
+ }
3418
  endif;
3419
  $assign_taxes = apply_filters('wp_all_import_set_post_terms', $assign_taxes, $tx_name, $pid, $this->id);
3420
+ // associate taxes with post
3421
  $this->associate_terms($pid, ( empty($assign_taxes) ? false : $assign_taxes ), $tx_name, $logger, $is_cron, $articleData['post_status']);
3422
  }
3423
  else {
3425
  }
3426
  }
3427
  if ( $this->options['update_all_data'] == "no" and ( ($this->options['is_update_categories'] and $this->options['update_categories_logic'] != 'full_update') or ( ! $this->options['is_update_categories'] and ( is_object_in_taxonomy( $post_type[$i], 'category' ) or is_object_in_taxonomy( $post_type[$i], 'post_tag' ) ) ) ) ) {
3428
+
3429
  if ( ! empty($existing_taxonomies) ){
3430
  foreach ($existing_taxonomies as $tx_name => $txes) {
3431
  // Skip updating product attributes
3432
  if ( PMXI_Admin_Addons::get_addon('PMWI_Plugin') and strpos($tx_name, "pa_") === 0 ) continue;
3433
 
3434
+ if (!empty($txes[$i]))
3435
  $this->associate_terms($pid, $txes[$i], $tx_name, $logger, $is_cron, $articleData['post_status']);
3436
  }
3437
  }
3438
  }
3439
+ }
3440
+ // [/custom taxonomies]
3441
 
3442
+ if (empty($articleData['ID'])) {
3443
  $logger and call_user_func($logger, sprintf(__('<b>CREATED</b> `%s` `%s` (ID: %s)', 'wp_all_import_plugin'), $this->getRecordTitle($articleData), $custom_type_details->labels->singular_name, $pid));
3444
+ } else {
3445
  $logger and call_user_func($logger, sprintf(__('<b>UPDATED</b> `%s` `%s` (ID: %s)', 'wp_all_import_plugin'), $this->getRecordTitle($articleData), $custom_type_details->labels->singular_name, $pid));
3446
  }
3447
 
3461
 
3462
  // prepare data for import
3463
  $importData = array(
3464
+ 'pid' => $pid,
3465
+ 'import' => $this,
3466
  'logger' => $logger,
3467
+ 'is_update' => $is_update
3468
  );
3469
 
3470
  $saved_functions = apply_filters('wp_all_import_addon_saved_post', array());
3471
 
3472
  // deligate operation to addons
3473
+ foreach (PMXI_Admin_Addons::get_active_addons() as $class){
3474
  if (class_exists($class)){
3475
+ if ( method_exists($addons[$class], 'saved_post') ) $addons[$class]->saved_post($importData);
3476
  } else {
3477
  if ( ! empty($saved_functions[$class]) ){
3478
  if ( is_array($saved_functions[$class]) and is_callable($saved_functions[$class]) or ! is_array($saved_functions[$class]) and function_exists($saved_functions[$class]) ){
3479
+ call_user_func($saved_functions[$class], $importData);
3480
+ }
3481
+ }
3482
  }
3483
  }
3484
+
3485
+ // [/addons import]
3486
  $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_saved_post', 'wp_all_import_plugin'));
3487
  do_action( 'pmxi_saved_post', $pid, $rootNodes[$i], $is_update ); // hook that was triggered immediately after post saved
3488
+
3489
+ if (empty($articleData['ID'])) $created++; else $updated++;
3490
 
3491
  if ( ! $is_cron and "default" == $this->options['import_processing'] ){
3492
  $processed_records = $created + $updated + $skipped;
3493
  $logger and call_user_func($logger, sprintf(__('<span class="processing_info"><span class="created_count">%s</span><span class="updated_count">%s</span><span class="percents_count">%s</span></span>', 'wp_all_import_plugin'), $created, $updated, ceil(($processed_records/$this->count) * 100)));
3494
  }
3495
+
3496
+ }
3497
  $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_after_post_import', 'wp_all_import_plugin'));
3498
  do_action('pmxi_after_post_import', $this->id);
3499
 
3502
  //restore_error_handler();
3503
  }
3504
 
3505
+ $this->set(array(
3506
+ 'imported' => $created + $updated,
3507
  'created' => $created,
3508
  'updated' => $updated,
3509
  'skipped' => $skipped,
3510
+ 'last_activity' => date('Y-m-d H:i:s')
3511
  ))->update();
3512
+
3513
  if ( ! $is_cron ){
3514
 
3515
+ PMXI_Plugin::$session->save_data();
3516
 
3517
  $records_count = $this->created + $this->updated + $this->skipped;
3518
 
3519
  $records_to_import = (empty($specified_records)) ? $this->count : $specified_records[count($specified_records) -1];
3520
 
3521
+ $is_import_complete = ($records_count == $records_to_import);
3522
 
3523
  // Set out of stock status for missing records [Woocommerce add-on option]
3524
  if ( $is_import_complete and (empty($this->options['is_delete_missing']) || $this->options['is_update_missing_cf'] || $this->options['set_missing_to_draft']) and $post_type[$i] == "product" and class_exists('PMWI_Plugin') and !empty($this->options['missing_records_stock_status']) and "manual" != $this->options['duplicate_matching']) {
3526
  $logger and call_user_func($logger, __('Update stock status previously imported posts which are no longer actual...', 'wp_all_import_plugin'));
3527
  $args = array('import_id' => $this->id, 'iteration !=' => $this->iteration);
3528
  if (!empty($this->options['is_import_specified'])) $args['specified'] = 1;
3529
+ $postList = new PMXI_Post_List();
3530
  $missingPosts = $postList->getBy($args);
3531
  if ( ! $missingPosts->isEmpty() ){
3532
+ foreach ($missingPosts as $missingPost) {
3533
  update_post_meta( $missingPost['post_id'], '_stock_status', 'outofstock' );
3534
  update_post_meta( $missingPost['post_id'], '_stock', 0 );
3535
 
3548
  unset($missingPostRecord);
3549
  }
3550
  }
3551
+ }
3552
+ }
3553
+
3554
  } catch (XmlImportException $e) {
3555
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'wp_all_import_plugin') . ': ' . $e->getMessage());
3556
+ $logger and !$is_cron and PMXI_Plugin::$session->errors++;
3557
+ }
3558
+
3559
  $logger and $is_import_complete and call_user_func($logger, __('Cleaning temporary data...', 'wp_all_import_plugin'));
3560
  foreach ($tmp_files as $file) { // remove all temporary files created
3561
  @unlink($file);
3562
+ }
3563
+
3564
  remove_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // return any filtering rules back if they has been disabled for import procedure
3565
+
3566
  return $this;
3567
  }
3568
 
3670
 
3671
  public function delete_source($logger = false)
3672
  {
3673
+ if ($this->options['is_delete_source'])
3674
  {
3675
  $uploads = wp_upload_dir();
3676
 
3677
+ $logger and call_user_func($logger, __('Deleting source XML file...', 'wp_all_import_plugin'));
3678
 
3679
  // Delete chunks
3680
  foreach (PMXI_Helper::safe_glob($uploads['basedir'] . DIRECTORY_SEPARATOR . PMXI_Plugin::TEMP_DIRECTORY . DIRECTORY_SEPARATOR . 'pmxi_chunk_*', PMXI_Helper::GLOB_RECURSE | PMXI_Helper::GLOB_PATH) as $filePath) {
3681
  $logger and call_user_func($logger, __('Deleting chunks files...', 'wp_all_import_plugin'));
3682
+ @file_exists($filePath) and wp_all_import_remove_source($filePath, false);
3683
  }
3684
 
3685
  if ($this->type != "ftp"){
3699
  }
3700
  }
3701
  }
3702
+ }
3703
 
3704
  public function delete_missing_records($logger, $iteration)
3705
  {
3706
+ if ( ! empty($this->options['is_delete_missing']) and $this->options['duplicate_matching'] == 'auto') {
3707
 
3708
  empty($this->deleted) and $logger and call_user_func($logger, __('Removing previously imported posts which are no longer actual...', 'wp_all_import_plugin'));
3709
+ $postList = new PMXI_Post_List();
3710
 
3711
+ $args = array('import_id' => $this->id, 'iteration !=' => $iteration);
3712
+ if ( ! empty($this->options['is_import_specified']) ) $args['specified'] = 1;
3713
 
3714
  $missing_ids = array();
3715
  $missingPosts = $postList->getBy($args);
3716
 
3717
+ if ( ! $missingPosts->isEmpty() ):
3718
+
3719
  foreach ($missingPosts as $missingPost) {
3720
+
3721
  $missing_ids[] = $missingPost;
3722
+
3723
  }
3724
 
3725
+ endif;
3726
 
3727
  // Delete posts from database
3728
+ if ( ! empty($missing_ids) && is_array($missing_ids) ){
3729
+
3730
+ $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_delete_post', 'wp_all_import_plugin'));
3731
 
3732
  $logger and call_user_func($logger, __('Deleting posts from database', 'wp_all_import_plugin'));
3733
 
3740
  if ( ! empty($missingPostRecords) ) {
3741
 
3742
  foreach ( $missingPostRecords as $k => $missingPostRecord ) {
3743
+
3744
  $to_delete = true;
3745
+
3746
  // Instead of deletion, set Custom Field
3747
  if ($this->options['is_update_missing_cf']){
3748
  switch ($this->options['custom_type']){
3764
  $to_delete = false;
3765
  }
3766
 
3767
+ // Instead of deletion, change post status to Draft
3768
  if ($this->options['set_missing_to_draft']){
3769
  if ($final_post_type = get_post_type($missingPostRecord['post_id']) and $final_post_type != 'product_variation' and 'draft' != get_post_status($missingPostRecord['post_id']))
3770
  {
3771
  $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $missingPostRecord['post_id']) );
3772
  $this->recount_terms($missingPostRecord['post_id'], $final_post_type);
3773
  $logger and call_user_func($logger, sprintf(__('Instead of deletion, change post with ID `%s` status to Draft', 'wp_all_import_plugin'), $missingPostRecord['post_id']));
3774
+ }
3775
  $to_delete = false;
3776
  }
3777
+
3778
  $to_delete = apply_filters('wp_all_import_is_post_to_delete', $to_delete, $missingPostRecord['post_id'], $this);
3779
 
3780
  if ($to_delete) {
3787
  // Clear post's relationships
3788
  wp_delete_object_term_relationships($missingPostRecord['post_id'], get_object_taxonomies('' != $this->options['custom_type'] ? $this->options['custom_type'] : 'post'));
3789
  }
3790
+ }
3791
  else {
3792
  $skipp_from_deletion[] = $missingPostRecord['post_id'];
3793
  $postRecord = new PMXI_Post_Record();
3810
 
3811
  do_action('pmxi_missing_post', $missingPostRecord['post_id']);
3812
 
3813
+ unset($missingPostRecords[$k]);
3814
  }
3815
  }
3816
 
3848
  }
3849
  break;
3850
  }
3851
+
3852
  // Delete record form pmxi_posts
3853
  $sql = "DELETE FROM " . PMXI_Plugin::getInstance()->getTablePrefix() . "posts WHERE post_id IN (".implode(',', $ids).") AND import_id = %d";
3854
+ $this->wpdb->query(
3855
  $this->wpdb->prepare($sql, $this->id)
3856
+ );
3857
 
3858
+ $this->set(array('deleted' => $this->deleted + count($ids)))->update();
3859
 
3860
  $logger and call_user_func($logger, sprintf(__('%d Posts deleted from database. IDs (%s)', 'wp_all_import_plugin'), $this->deleted, implode(",", $ids)));
3861
  }
3862
+ }
3863
 
3864
  if ( PMXI_Plugin::is_ajax() ) break;
3865
  }
3875
 
3876
  protected function pushmeta($pid, $meta_key, $meta_value){
3877
 
3878
+ if (empty($meta_key)) return;
3879
 
3880
  $this->post_meta_to_insert[] = array(
3881
  'meta_key' => $meta_key,
3882
  'meta_value' => $meta_value,
3883
  'pid' => $pid
3884
+ );
3885
 
3886
  }
3887
 
3888
  protected function executeSQL(){
3889
+
3890
  $import_entry = ( in_array( $this->options['custom_type'], array('import_users', 'shop_customer') ) ) ? 'user' : 'post';
3891
 
3892
  // prepare bulk SQL query
3893
  $meta_table = _get_meta_table( $import_entry );
3894
+
3895
+ if ( $this->post_meta_to_insert ){
3896
  $values = array();
3897
  $already_added = array();
3898
+
3899
  foreach (array_reverse($this->post_meta_to_insert) as $key => $value) {
3900
  if ( ! empty($value['meta_key']) and ! in_array($value['pid'] . '-' . $value['meta_key'], $already_added) ){
3901
+ $already_added[] = $value['pid'] . '-' . $value['meta_key'];
3902
+ $values[] = '(' . $value['pid'] . ',"' . $value['meta_key'] . '",\'' . maybe_serialize($value['meta_value']) .'\')';
3903
  }
3904
  }
3905
+
3906
  $this->wpdb->query("INSERT INTO $meta_table (`" . $import_entry . "_id`, `meta_key`, `meta_value`) VALUES " . implode(',', $values));
3907
  $this->post_meta_to_insert = array();
3908
+ }
3909
  }
3910
+
3911
  public function _filter_has_cap_unfiltered_html($caps)
3912
  {
3913
  $caps['unfiltered_html'] = true;
3992
  if ( ! $keepPosts) {
3993
  $missing_ids = array();
3994
  $sql = "SELECT post_id FROM " . PMXI_Plugin::getInstance()->getTablePrefix() . "posts WHERE import_id = %d";
3995
+ $missingPosts = $this->wpdb->get_results(
3996
  $this->wpdb->prepare($sql, $this->id)
3997
  );
3998
  if ( ! empty($missingPosts) ):
4008
  $this->deleteRecords($is_delete_attachments, $is_deleted_images, $ids);
4009
  // Delete record form pmxi_posts
4010
  $sql = "DELETE FROM " . PMXI_Plugin::getInstance()->getTablePrefix() . "posts WHERE post_id IN (".implode(',', $ids).") AND import_id = %d";
4011
+ $this->wpdb->query(
4012
  $this->wpdb->prepare($sql, $this->id)
4013
  );
4014
+ $this->set(array('deleted' => $this->deleted + count($ids)))->update();
4015
  }
4016
  break;
4017
  }
4018
  return (count($missing_ids_arr) > 1) ? false : true;
4019
+ }
4020
  }
4021
  return true;
4022
  }
4028
  * @chainable
4029
  */
4030
  public function deletePosts($keepPosts = TRUE, $is_deleted_images = 'auto', $is_delete_attachments = 'auto') {
4031
+ $post = new PMXI_Post_List();
4032
+ if ( ! $keepPosts) {
4033
  $ids = array();
4034
+ foreach ($post->getBy('import_id', $this->id)->convertRecords() as $p) {
4035
  $ids[] = $p->post_id;
4036
  }
4037
  if ( ! empty($ids) ){
4038
  $this->deleteRecords($is_delete_attachments, $is_deleted_images, $ids);
4039
+ }
4040
  }
4041
  $this->wpdb->query($this->wpdb->prepare('DELETE FROM ' . $post->getTable() . ' WHERE import_id = %s', $this->id));
4042
  return $this;
4099
  */
4100
  public function deleteFiles() {
4101
  $fileList = new PMXI_File_List();
4102
+ foreach($fileList->getBy('import_id', $this->id)->convertRecords() as $f) {
4103
  $f->delete();
4104
  }
4105
  return $this;
4109
  * @return PMXI_Import_Record
4110
  * @chainable
4111
  */
4112
+ public function deleteHistories(){
4113
  $historyList = new PMXI_History_List();
4114
+ foreach ($historyList->getBy('import_id', $this->id)->convertRecords() as $h) {
4115
  $h->delete();
4116
  }
4117
  return $this;
4127
  $i->delete($keepPosts);
4128
  }
4129
  return $this;
4130
+ }
4131
  /**
4132
  * @see parent::delete()
4133
  * @param bool[optional] $keepPosts When set to false associated wordpress posts will be deleted as well
4137
  if ($is_delete_import)
4138
  {
4139
  $this->deleteFiles()->deleteHistories()->deleteChildren($keepPosts);
4140
+ }
4141
  $expired_sessions = array();
4142
  $expired_sessions[] = "_wpallimport_session_expires_" . $this->id . "_";
4143
  $expired_sessions[] = "_wpallimport_session_" . $this->id . "_";
4152
  {
4153
  return in_array($this->type, array('url', 'ftp', 'file'));
4154
  }
4155
+
4156
  }
plugin.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: WP All Import
4
  Plugin URI: http://www.wpallimport.com/wordpress-xml-csv-import/?utm_source=import-plugin-free&utm_medium=wp-plugins-page&utm_campaign=upgrade-to-pro
5
  Description: The most powerful solution for importing XML and CSV files to WordPress. Create Posts and Pages with content from any XML or CSV file. A paid upgrade to WP All Import Pro is available for support and additional features.
6
- Version: 3.6.5
7
  Author: Soflyy
8
  */
9
 
@@ -25,7 +25,7 @@ define('WP_ALL_IMPORT_ROOT_URL', rtrim(plugin_dir_url(__FILE__), '/'));
25
  */
26
  define('WP_ALL_IMPORT_PREFIX', 'pmxi_');
27
 
28
- define('PMXI_VERSION', '3.6.5');
29
 
30
  define('PMXI_EDITION', 'free');
31
 
3
  Plugin Name: WP All Import
4
  Plugin URI: http://www.wpallimport.com/wordpress-xml-csv-import/?utm_source=import-plugin-free&utm_medium=wp-plugins-page&utm_campaign=upgrade-to-pro
5
  Description: The most powerful solution for importing XML and CSV files to WordPress. Create Posts and Pages with content from any XML or CSV file. A paid upgrade to WP All Import Pro is available for support and additional features.
6
+ Version: 3.6.6
7
  Author: Soflyy
8
  */
9
 
25
  */
26
  define('WP_ALL_IMPORT_PREFIX', 'pmxi_');
27
 
28
+ define('PMXI_VERSION', '3.6.6');
29
 
30
  define('PMXI_EDITION', 'free');
31
 
readme.txt CHANGED
@@ -1,8 +1,8 @@
1
  === Import any XML or CSV File to WordPress ===
2
  Contributors: soflyy, wpallimport
3
  Requires at least: 4.1
4
- Tested up to: 5.8
5
- Stable tag: 3.6.5
6
  Tags: wordpress csv import, wordpress xml import, xml, csv, datafeed, import, migrate, import csv to wordpress, import xml to wordpress, advanced xml import, advanced csv import, bulk csv import, bulk xml import, bulk data import, xml to custom post type, csv to custom post type, woocommerce csv import, woocommerce xml import, csv import, import csv, xml import, import xml, csv importer
7
 
8
  WP All Import is an extremely powerful importer that makes it easy to import any XML or CSV file to WordPress.
@@ -105,6 +105,9 @@ Does it work with special character encoding like Hebrew, Arabic, Chinese, etc?
105
 
106
  == Changelog ==
107
 
 
 
 
108
  = 3.6.5 =
109
  * improvement: better sanitization and escaping of data in WP All Import interface
110
 
1
  === Import any XML or CSV File to WordPress ===
2
  Contributors: soflyy, wpallimport
3
  Requires at least: 4.1
4
+ Tested up to: 5.9
5
+ Stable tag: 3.6.6
6
  Tags: wordpress csv import, wordpress xml import, xml, csv, datafeed, import, migrate, import csv to wordpress, import xml to wordpress, advanced xml import, advanced csv import, bulk csv import, bulk xml import, bulk data import, xml to custom post type, csv to custom post type, woocommerce csv import, woocommerce xml import, csv import, import csv, xml import, import xml, csv importer
7
 
8
  WP All Import is an extremely powerful importer that makes it easy to import any XML or CSV file to WordPress.
105
 
106
  == Changelog ==
107
 
108
+ = 3.6.6 =
109
+ * bug fix: jQuery nestedSortable compatibility with WordPress 5.9
110
+
111
  = 3.6.5 =
112
  * improvement: better sanitization and escaping of data in WP All Import interface
113
 
static/js/jquery/jquery.mjs.nestedSortable.js CHANGED
@@ -86,6 +86,11 @@
86
  $.ui.ddmanager.prepareOffsets(this, event);
87
  }
88
 
 
 
 
 
 
89
  //Regenerate the absolute position used for position checks
90
  this.positionAbs = this._convertPositionTo("absolute");
91
 
@@ -165,7 +170,7 @@
165
  var newList = document.createElement(o.listType);
166
 
167
  this.beyondMaxLevels = 0;
168
-
169
  // If the item is moved to the left, send it to its parent's level unless there are siblings below it.
170
  if (parentItem != null && nextItem == null &&
171
  (o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
@@ -332,7 +337,7 @@
332
  depth --;
333
  }
334
 
335
- id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
336
 
337
  if (depth === sDepth + 1) {
338
  pid = o.rootID;
@@ -343,7 +348,7 @@
343
  .match(o.expression || (/(.+)[-=_](.+)/));
344
  pid = parentItem[2];
345
  }
346
-
347
  if (id) {
348
  var pmxi_is_assign = $(item).find('input.assign_term:first').is(':checked');
349
  ret.push({"item_id": id[2], "left": left, "right": right, "parent_id": pid, "xpath":$(item).find('input.xpath_field').val(), "assign" : pmxi_is_assign });
@@ -370,7 +375,7 @@
370
 
371
  if (this.options.listType) {
372
  var list = item.closest(this.options.listType);
373
- while (list && list.length > 0 &&
374
  !list.is('.ui-sortable')) {
375
  level++;
376
  list = list.parent().closest(this.options.listType);
@@ -424,4 +429,4 @@
424
  }));
425
 
426
  $.mjs.pmxi_nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.pmxi_nestedSortable.prototype.options);
427
- })(jQuery);
86
  $.ui.ddmanager.prepareOffsets(this, event);
87
  }
88
 
89
+ this.dragDirection = {
90
+ vertical: this._getDragVerticalDirection(),
91
+ horizontal: this._getDragHorizontalDirection()
92
+ };
93
+
94
  //Regenerate the absolute position used for position checks
95
  this.positionAbs = this._convertPositionTo("absolute");
96
 
170
  var newList = document.createElement(o.listType);
171
 
172
  this.beyondMaxLevels = 0;
173
+
174
  // If the item is moved to the left, send it to its parent's level unless there are siblings below it.
175
  if (parentItem != null && nextItem == null &&
176
  (o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
337
  depth --;
338
  }
339
 
340
+ id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
341
 
342
  if (depth === sDepth + 1) {
343
  pid = o.rootID;
348
  .match(o.expression || (/(.+)[-=_](.+)/));
349
  pid = parentItem[2];
350
  }
351
+
352
  if (id) {
353
  var pmxi_is_assign = $(item).find('input.assign_term:first').is(':checked');
354
  ret.push({"item_id": id[2], "left": left, "right": right, "parent_id": pid, "xpath":$(item).find('input.xpath_field').val(), "assign" : pmxi_is_assign });
375
 
376
  if (this.options.listType) {
377
  var list = item.closest(this.options.listType);
378
+ while (list && list.length > 0 &&
379
  !list.is('.ui-sortable')) {
380
  level++;
381
  list = list.parent().closest(this.options.listType);
429
  }));
430
 
431
  $.mjs.pmxi_nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.pmxi_nestedSortable.prototype.options);
432
+ })(jQuery);