PluginProbe
Import WP – CSV & XML Import Export for WordPress / 2.15.0
Import WP – CSV & XML Import Export for WordPress v2.15.0
2.15.1 2.15.0 2.14.24 2.14.23 2.7.0 2.7.1 2.7.10 2.7.11 2.7.12 2.7.13 2.7.14 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 2.9.1 All 144 releases
← All changes | class/Common/Importer/Template/PostTemplate.php +381 -106 2.7.7 → 2.15.0 View file →
@@ -17,12 +17,12 @@
17 17 protected $name = 'Post';
18 18 protected $mapper = 'post';
19 19 protected $field_map = [
20 20 'ID' => 'post.ID',
21 + 'post_name' => 'post.post_name',
21 22 'post_title' => 'post.post_title',
22 23 'post_content' => 'post.post_content',
23 24 'post_excerpt' => 'post.post_excerpt',
24 - 'post_name' => 'post.post_name',
25 25 'post_status' => 'post.post_status',
26 26 'menu_order' => 'post.menu_order',
27 27 'post_password' => 'post.post_password',
28 28 'post_date' => 'post.post_date',
@@ -61,8 +61,10 @@
61 61 $this->field_options = array_merge($this->field_options, [
62 62 'post._parent.parent' => [$this, 'get_post_parent_options'],
63 63 'taxonomies.*.tax' => [$this, 'get_taxonomy_options'],
64 64 ]);
65 +
66 + $this->default_enabled_fields[] = 'post.post_status';
65 67 }
66 68
67 69 /**
68 70 * @param string $message
@@ -80,9 +82,9 @@
80 82 }
81 83 }
82 84
83 85 if (!empty($this->_attachments)) {
84 - $message .= ', Attachments: (' . implode(', ', $this->_attachments) . ')';
86 + $message .= sprintf(__(', Attachments: (%s)', 'jc-importer'), implode(', ', $this->_attachments));
85 87 }
86 88
87 89 return $message;
88 90 }
@@ -91,98 +93,98 @@
91 93 {
92 94 $groups = [];
93 95
94 96 // Post
95 - $groups[] = $this->register_group('Post Fields', 'post', [
96 - $this->register_field('ID', 'ID', [
97 - 'tooltip' => __('ID is only used to reference existing records', 'importwp')
97 + $groups[] = $this->register_group(__('Post Fields', 'jc-importer'), 'post', [
98 + $this->register_field(__('ID', 'jc-importer'), 'ID', [
99 + 'tooltip' => __('ID is only used to reference existing records', 'jc-importer')
98 100 ]),
99 - $this->register_core_field('Title', 'post_title', [
100 - 'tooltip' => __('Title of the post.', 'importwp')
101 + $this->register_core_field(__('Title', 'jc-importer'), 'post_title', [
102 + 'tooltip' => __('Title of the post.', 'jc-importer')
101 103 ]),
102 - $this->register_core_field('Content', 'post_content', [
103 - 'tooltip' => __('Main WYSIWYG editor content of the post.', 'importwp')
104 + $this->register_core_field(__('Content', 'jc-importer'), 'post_content', [
105 + 'tooltip' => __('Main WYSIWYG editor content of the post.', 'jc-importer')
104 106 ]),
105 - $this->register_field('Excerpt', 'post_excerpt', [
106 - 'tooltip' => __('A custom short extract for the post.', 'importwp')
107 + $this->register_field(__('Excerpt', 'jc-importer'), 'post_excerpt', [
108 + 'tooltip' => __('A custom short extract for the post.', 'jc-importer')
107 109 ]),
108 - $this->register_field('Slug', 'post_name', [
109 - 'tooltip' => __('The slug is the user friendly and URL valid name of the post.', 'importwp')
110 + $this->register_field(__('Slug', 'jc-importer'), 'post_name', [
111 + 'tooltip' => __('The slug is the user friendly and URL valid name of the post.', 'jc-importer')
110 112 ]),
111 - $this->register_field('Status', 'post_status', [
113 + $this->register_field(__('Status', 'jc-importer'), 'post_status', [
112 114 'default' => 'publish',
113 115 'options' => [
114 - ['value' => 'draft', 'label' => 'Draft'],
115 - ['value' => 'publish', 'label' => 'Published'],
116 - ['value' => 'pending', 'label' => 'Pending'],
117 - ['value' => 'future', 'label' => 'Future'],
118 - ['value' => 'private', 'label' => 'Private'],
119 - ['value' => 'trash', 'label' => 'Trash']
116 + ['value' => 'draft', 'label' => __('Draft', 'jc-importer')],
117 + ['value' => 'publish', 'label' => __('Published', 'jc-importer')],
118 + ['value' => 'pending', 'label' => __('Pending', 'jc-importer')],
119 + ['value' => 'future', 'label' => __('Future', 'jc-importer')],
120 + ['value' => 'private', 'label' => __('Private', 'jc-importer')],
121 + ['value' => 'trash', 'label' => __('Trash', 'jc-importer')]
120 122 ],
121 - 'tooltip' => __('Whether the post can accept comments. Accepts open or closed', 'importwp')
123 + 'tooltip' => __('The status of a given post determines how WordPress handles that post', 'jc-importer')
122 124 ]),
123 - $this->register_group('Parent Settings', '_parent', [
124 - $this->register_field('Parent', 'parent', [
125 + $this->register_group(__('Parent Settings', 'jc-importer'), '_parent', [
126 + $this->register_field(__('Parent', 'jc-importer'), 'parent', [
125 127 'default' => '',
126 128 'options' => 'callback',
127 - 'tooltip' => __('Set this for the post it belongs to', 'importwp')
129 + 'tooltip' => __('Set this for the post it belongs to', 'jc-importer')
128 130 ]),
129 - $this->register_field('Parent Field Type', '_parent_type', [
131 + $this->register_field(__('Parent Field Type', 'jc-importer'), '_parent_type', [
130 132 'default' => 'id',
131 133 'options' => [
132 - ['value' => 'id', 'label' => 'ID'],
133 - ['value' => 'slug', 'label' => 'Slug'],
134 - ['value' => 'name', 'label' => 'Name'],
135 - ['value' => 'column', 'label' => 'Reference Column'],
134 + ['value' => 'id', 'label' => __('ID', 'jc-importer')],
135 + ['value' => 'slug', 'label' => __('Slug', 'jc-importer')],
136 + ['value' => 'name', 'label' => __('Name', 'jc-importer')],
137 + ['value' => 'column', 'label' => __('Reference Column', 'jc-importer')],
136 138 ],
137 139 'type' => 'select',
138 - 'tooltip' => __('Select how the parent field should be handled', 'importwp')
140 + 'tooltip' => __('Select how the parent field should be handled', 'jc-importer')
139 141 ]),
140 - $this->register_field('Parent Reference Column', '_parent_ref', [
142 + $this->register_field(__('Parent Reference Column', 'jc-importer'), '_parent_ref', [
141 143 'condition' => ['_parent_type', '==', 'column'],
142 - 'tooltip' => __('Select the column/node that the parent field is referencing', 'importwp')
144 + 'tooltip' => __('Select the column/node that the parent field is referencing', 'jc-importer')
143 145 ])
144 146 ]),
145 - $this->register_field('Order', 'menu_order', [
146 - 'tooltip' => __('The order the post should be displayed in', 'importwp')
147 + $this->register_field(__('Order', 'jc-importer'), 'menu_order', [
148 + 'tooltip' => __('The order the post should be displayed in', 'jc-importer')
147 149 ]),
148 - $this->register_group('Author Settings', '_author', [
149 - $this->register_field('Author', 'post_author', [
150 - 'tooltip' => __('The user of who added this post', 'importwp')
150 + $this->register_group(__('Author Settings', 'jc-importer'), '_author', [
151 + $this->register_field(__('Author', 'jc-importer'), 'post_author', [
152 + 'tooltip' => __('The user of who added this post', 'jc-importer')
151 153 ]),
152 - $this->register_field('Author Field Type', '_author_type', [
154 + $this->register_field(__('Author Field Type', 'jc-importer'), '_author_type', [
153 155 'default' => 'id',
154 156 'options' => [
155 - ['value' => 'id', 'label' => 'ID'],
156 - ['value' => 'login', 'label' => 'Login'],
157 - ['value' => 'email', 'label' => 'Email'],
157 + ['value' => 'id', 'label' => __('ID', 'jc-importer')],
158 + ['value' => 'login', 'label' => __('Login', 'jc-importer')],
159 + ['value' => 'email', 'label' => __('Email', 'jc-importer')],
158 160 ],
159 - 'tooltip' => __('Select how the author field should be handled', 'importwp')
161 + 'tooltip' => __('Select how the author field should be handled', 'jc-importer')
160 162 ])
161 163 ]),
162 - $this->register_field('Password', 'post_password', [
163 - 'tooltip' => __('The password to access the post', 'importwp')
164 + $this->register_field(__('Password', 'jc-importer'), 'post_password', [
165 + 'tooltip' => __('The password to access the post', 'jc-importer')
164 166 ]),
165 - $this->register_field('Date', 'post_date', [
166 - 'tooltip' => __('The date of the post , enter in the format "YYYY-MM-DD HH:ii:ss"', 'importwp')
167 + $this->register_field(__('Date', 'jc-importer'), 'post_date', [
168 + 'tooltip' => __('The date of the post , enter in the format "YYYY-MM-DD HH:ii:ss"', 'jc-importer')
167 169 ]),
168 - $this->register_field('Allow Comments', 'comment_status', [
170 + $this->register_field(__('Allow Comments', 'jc-importer'), 'comment_status', [
169 171 'options' => [
170 - ['value' => '0', 'label' => 'Disabled'],
171 - ['value' => '1', 'label' => 'Enabled']
172 + ['value' => '0', 'label' => __('Disabled', 'jc-importer')],
173 + ['value' => '1', 'label' => __('Enabled', 'jc-importer')]
172 174 ],
173 175 'default' => '0',
174 - 'tooltip' => __('Whether the post can accept comments', 'importwp')
176 + 'tooltip' => __('Whether the post can accept comments', 'jc-importer')
175 177 ]),
176 - $this->register_field('Allow Pingbacks', 'ping_status', [
178 + $this->register_field(__('Allow Pingbacks', 'jc-importer'), 'ping_status', [
177 179 'options' => [
178 - ['value' => 'closed', 'label' => 'Closed'],
179 - ['value' => 'open', 'label' => 'Open']
180 + ['value' => 'closed', 'label' => __('Closed', 'jc-importer')],
181 + ['value' => 'open', 'label' => __('Open', 'jc-importer')]
180 182 ],
181 183 'default' => 'closed',
182 - 'tooltip' => __('Whether the post can accept pings', 'importwp')
184 + 'tooltip' => __('Whether the post can accept pings', 'jc-importer')
183 185 ])
184 - ]);
186 + ], ['link' => 'https://www.importwp.com/docs/wordpress-page-importer-template/']);
185 187
186 188 // Taxonomies
187 189 $groups[] = $this->register_taxonomy_fields();
188 190
@@ -193,49 +195,72 @@
193 195 }
194 196
195 197 public function register_taxonomy_fields()
196 198 {
197 - return $this->register_group('Taxonomies', 'taxonomies', [
198 - $this->register_field('Taxonomy', 'tax', [
199 + return $this->register_group(__('Taxonomies', 'jc-importer'), 'taxonomies', [
200 + $this->register_field(__('Taxonomy', 'jc-importer'), 'tax', [
199 201 'default' => 'category',
200 202 'options' => 'callback',
201 - 'tooltip' => __('Select the type of taxonomy you are importing to.', 'importwp')
203 + 'tooltip' => __('Select the type of taxonomy you are importing to.', 'jc-importer')
202 204 ]),
203 - $this->register_field('Terms', 'term', [
204 - 'tooltip' => __('Name of the taxonomy term or terms (entered as a comma seperated list).', 'importwp')
205 + $this->register_field(__('Terms', 'jc-importer'), 'term', [
206 + 'tooltip' => __('Name of the taxonomy term or terms (entered as a comma seperated list).', 'jc-importer')
205 207 ]),
206 - $this->register_group('Settings', 'settings', [
207 - $this->register_field('Delimiter', '_delimiter', [
208 + $this->register_group(__('Settings', 'jc-importer'), 'settings', [
209 + $this->register_field(__('Delimiter', 'jc-importer'), '_delimiter', [
208 210 'type' => 'text',
209 - 'tooltip' => 'A single character used to seperate terms when listing multiple, Leave empty to use default: ,'
211 + 'tooltip' => sprintf(__('A single character used to seperate terms when listing multiple, Leave empty to use default: %s', 'jc-importer'), ',')
210 212 ]),
211 - $this->register_field('Enable Hierarchy', '_hierarchy', [
213 + $this->register_field(__('Term Type', 'jc-importer'), '_type', [
214 + 'tooltip' => __('Select what type the term values are (e.g. Name, Slug, or ID)', 'jc-importer'),
215 + 'default' => 'name',
216 + 'options' => [
217 + ['value' => 'name', 'label' => __('Name', 'jc-importer')],
218 + ['value' => 'slug', 'label' => __('Slug', 'jc-importer')],
219 + ['value' => 'term_id', 'label' => __('ID', 'jc-importer')],
220 + ['value' => 'custom_field', 'label' => __('Custom Field', 'jc-importer')],
221 + ],
222 + 'type' => 'select'
223 + ]),
224 + $this->register_field(__('Custom Field', 'jc-importer'), '_type_cf', [
225 + 'condition' => [
226 + ['_type', '==', 'custom_field']
227 + ]
228 + ]),
229 + $this->register_field(__('Enable Hierarchy', 'jc-importer'), '_hierarchy', [
212 230 'default' => 'no',
213 231 'options' => [
214 - ['value' => 'no', 'label' => 'No'],
215 - ['value' => 'yes', 'label' => 'Yes'],
232 + ['value' => 'no', 'label' => __('No', 'jc-importer')],
233 + ['value' => 'yes', 'label' => __('Yes', 'jc-importer')],
216 234 ],
217 235 'type' => 'select'
218 236 ]),
219 - $this->register_field('Hierarchy Character', '_hierarchy_character', [
237 + $this->register_field(__('Hierarchy Character', 'jc-importer'), '_hierarchy_character', [
220 238 'default' => '>',
221 239 'condition' => ['_hierarchy', '==', 'yes'],
222 240 ]),
223 - $this->register_field('Append Terms', '_append', [
241 + $this->register_field(__('Hierarchy Relationship', 'jc-importer'), '_hierarchy_relationship', [
242 + 'default' => 'all',
243 + 'options' => [
244 + ['value' => 'all', 'label' => __('Connect all terms', 'jc-importer')],
245 + ['value' => 'last', 'label' => __('Connect last term', 'jc-importer')],
246 + ],
247 + 'type' => 'select',
248 + 'condition' => ['_hierarchy', '==', 'yes'],
249 + ]),
250 + $this->register_field(__('Append Terms', 'jc-importer'), '_append', [
224 251 'default' => 'no',
225 252 'options' => [
226 - ['value' => 'no', 'label' => 'No'],
227 - ['value' => 'yes', 'label' => 'Yes'],
253 + ['value' => 'no', 'label' => __('No', 'jc-importer')],
254 + ['value' => 'yes', 'label' => __('Yes', 'jc-importer')],
228 255 ],
229 256 'type' => 'select'
230 257 ]),
231 258 ], ['type' => 'settings'])
232 - ], ['type' => 'repeatable', 'row_base' => true]);
259 + ], ['type' => 'repeatable', 'row_base' => true, 'row_summary' => ['tax', 'term'], 'link' => 'https://www.importwp.com/docs/how-to-import-wordpress-taxonomies-onto-a-post-type/']);
233 260 }
234 261
235 - public function register_settings()
236 - {
237 - }
262 + public function register_settings() {}
238 263
239 264 public function register_options()
240 265 {
241 266 return [];
@@ -349,9 +374,9 @@
349 374 // // set flag to say slug has been generated
350 375 // $data->add(['post_name' => 'yes'], '_generated');
351 376 // }
352 377
353 - if ($this->importer->isEnabledField('post._parent') && isset($post_field_map['post_parent'])) {
378 + if ($this->importer->isEnabledField('post._parent') && isset($post_field_map['post_parent']) && !empty($post_field_map['post_parent'])) {
354 379
355 380 $parent_id = 0;
356 381 $parent_field_type = $data->getValue('post._parent._parent_type');
357 382
@@ -411,9 +436,9 @@
411 436 'key' => '_iwp_ref_' . $field,
412 437 'value' => $value
413 438 )
414 439 ),
415 - 'post_status' => 'any'
440 + 'post_status' => 'any, trash, future'
416 441 ));
417 442 if ($query->have_posts()) {
418 443 return $query->posts[0];
419 444 }
@@ -445,9 +470,8 @@
445 470 * @var Attachment $attachment
446 471 */
447 472 $attachment = Container::getInstance()->get('attachment');
448 473
449 - $this->featured_set = false;
450 474 $this->process_taxonomies($post_id, $data);
451 475 $this->process_attachments($post_id, $data, $filesystem, $ftp, $attachment);
452 476
453 477 parent::post_process($post_id, $data);
@@ -475,8 +499,9 @@
475 499
476 500 $processed_taxonomies = [];
477 501 $term_hierarchy = [];
478 502 $term_hierarchy_enabled = [];
503 + $term_types = [];
479 504 $term_append = [];
480 505
481 506 // Pre-Process taxonomy data
482 507 for ($i = 0; $i < $total_rows; $i++) {
@@ -496,11 +521,16 @@
496 521 $term_append[$tax] = isset($row[$prefix . 'settings._append']) && $row[$prefix . 'settings._append'] == 'yes';
497 522
498 523 $delimiter = apply_filters('iwp/taxonomy=' . $tax . '/value_delimiter', $base_delimiter);
499 524
525 + $term_types[$tax] = isset($row[$prefix . 'settings._type']) && !empty($row[$prefix . 'settings._type']) ? $row[$prefix . 'settings._type'] : 'name';
526 + $term_types_cf[$tax] = isset($row[$prefix . 'settings._type_cf']) && !empty($row[$prefix . 'settings._type_cf']) ? $row[$prefix . 'settings._type_cf'] : '';
527 +
500 528 $hierarchy_enabled = isset($row[$prefix . 'settings._hierarchy']) && $row[$prefix . 'settings._hierarchy'] === 'yes' ? true : false;
501 529 $hierarchy_character = isset($row[$prefix . 'settings._hierarchy_character']) ? $row[$prefix . 'settings._hierarchy_character'] : null;
530 + $hierarchy_terms = isset($row[$prefix . 'settings._hierarchy_relationship']) ? $row[$prefix . 'settings._hierarchy_relationship'] : null;
502 531
532 +
503 533 $delimiter = isset($row[$prefix . 'settings._delimiter']) && strlen(trim($row[$prefix . 'settings._delimiter'])) === 1 ? trim($row[$prefix . 'settings._delimiter']) : $delimiter;
504 534
505 535 if (empty($hierarchy_character)) {
506 536 $hierarchy_enabled = false;
@@ -516,9 +546,9 @@
516 546 if ($data->permission()) {
517 547 $allowed = $data->permission()->validate([$permission_key => ''], $data->getMethod(), $group);
518 548 $is_allowed = isset($allowed[$permission_key]) ? true : false;
519 549
520 - if (!$is_allowed || empty($term)) {
550 + if (!$is_allowed || ($term_append[$tax] == true && empty($term))) {
521 551 continue;
522 552 }
523 553 }
524 554
@@ -552,58 +582,141 @@
552 582 // TODO: Process term hierarchy
553 583 foreach ($term_hierarchy as $processed_tax => $term_hierarchy_list) {
554 584
555 585 // clear existing taxonomies
556 - if (!isset($term_append[$processed_tax]) || !$term_append[$processed_tax]) {
557 - wp_set_object_terms($post_id, null, $processed_tax);
558 - }
586 + $clear_existing_terms = !isset($term_append[$processed_tax]) || !$term_append[$processed_tax];
559 587
560 588 if (empty($term_hierarchy_list)) {
561 589 continue;
562 590 }
563 591
592 + $new_terms = [];
593 +
564 594 foreach ($term_hierarchy_list as $hierarchy_list) {
565 595
566 596 $prev_term = isset($term_hierarchy_enabled[$processed_tax]) ? 0 : null;
597 + $type = $term_types[$processed_tax];
567 598
568 - foreach ($hierarchy_list as $term) {
599 + foreach ($hierarchy_list as $term_i => $term) {
569 600 if (!isset($this->_taxonomies[$processed_tax])) {
570 601 $this->_taxonomies[$processed_tax] = [];
571 602 }
572 603
573 - $term_result = $this->create_or_get_taxonomy_term($post_id, $processed_tax, $term, $prev_term);
604 + $connect_terms = true;
605 + if ($hierarchy_enabled && $hierarchy_terms === 'last') {
606 + $connect_terms = $term_i == count($hierarchy_list) - 1;
607 + }
608 +
609 + $search_term = $term;
610 + if ($type === 'custom_field') {
611 + $search_term = [
612 + $term_types_cf[$processed_tax],
613 + $term
614 + ];
615 + }
616 +
617 + $term_result = $this->create_or_get_taxonomy_term($post_id, $processed_tax, $search_term, $prev_term, $type, false);
574 618 if ($term_result) {
575 619 $prev_term = $term_result->term_id;
576 620 $this->_taxonomies[$processed_tax][] = $term_result->name;
577 621 }
622 +
623 + if ($connect_terms && $term_result) {
624 + $new_terms[] = $term_result->term_id;
625 + }
578 626 }
579 627 }
628 +
629 + // Connect all terms in one go.
630 + wp_set_object_terms($post_id, $new_terms, $processed_tax, !$clear_existing_terms);
580 631 }
581 632 }
582 633
583 - private function create_or_get_taxonomy_term($post_id, $tax, $term, $parent)
634 + public function create_or_get_taxonomy_term($post_id, $tax, $term, $parent, $term_type = 'name', $set = true)
584 635 {
636 + if (!in_array($term_type, ['slug', 'name', 'term_id', 'custom_field'])) {
637 + $term_type = 'name';
638 + }
585 639
586 640 if (is_null($parent)) {
587 641
588 642 // we do not care about parent, just fetch first
589 - $tmp_term = get_term_by('name', $term, $tax);
643 +
644 + if ($term_type === 'custom_field') {
645 +
646 + if (!isset($term[0], $term[1]) || empty($term[0]) || empty($term[1])) {
647 + return false;
648 + }
649 +
650 + $terms = get_terms([
651 + 'taxonomy' => $tax,
652 + 'meta_key' => $term[0],
653 + 'meta_value' => $term[1],
654 + 'hide_empty' => false
655 + ]);
656 + if (empty($terms)) {
657 + return false;
658 + }
659 +
660 + $tmp_term = $terms[0];
661 + } else {
662 + $tmp_term = get_term_by($term_type, $term, $tax);
663 + }
664 +
590 665 if ($tmp_term) {
591 - wp_set_object_terms($post_id, $tmp_term->term_id, $tax, true);
666 + $tmp_term = apply_filters('iwp/importer/template/post_term', $tmp_term, $tax);
667 + if ($set) {
668 + wp_set_object_terms($post_id, $tmp_term->term_id, $tax, true);
669 + }
592 670 return $tmp_term;
593 671 }
594 672 } else {
595 - $terms = get_terms([
596 - 'taxonomy' => $tax,
597 - 'name' => $term,
598 - 'hide_empty' => false
599 - ]);
673 +
674 + if ($term_type === 'slug') {
675 +
676 + $terms = get_terms([
677 + 'taxonomy' => $tax,
678 + 'slug' => $term,
679 + 'hide_empty' => false
680 + ]);
681 + } elseif ($term_type === 'term_id') {
682 +
683 + // ID will only return a single record
684 + $terms = [];
685 + $tmp_term = get_term_by($term_type, $term, $tax);
686 + if ($tmp_term) {
687 + $terms[] = $tmp_term;
688 + }
689 + } else if ($term_type === 'custom_field') {
690 +
691 + if (!isset($term[0], $term[1]) || empty($term[0]) || empty($term[1])) {
692 + return false;
693 + }
694 +
695 + $terms = get_terms([
696 + 'taxonomy' => $tax,
697 + 'meta_key' => $term[0],
698 + 'meta_value' => $term[1],
699 + 'hide_empty' => false
700 + ]);
701 + } else {
702 +
703 + $terms = get_terms([
704 + 'taxonomy' => $tax,
705 + 'name' => $term,
706 + 'hide_empty' => false
707 + ]);
708 + }
709 +
600 710 if (!empty($terms)) {
601 711 foreach ($terms as $tmp_term) {
602 712 if (intval($tmp_term->parent) === intval($parent)) {
603 713
604 714 // attach term to post
605 - wp_set_object_terms($post_id, $tmp_term->term_id, $tax, true);
715 + $tmp_term = apply_filters('iwp/importer/template/post_term', $tmp_term, $tax);
716 + if ($set) {
717 + wp_set_object_terms($post_id, $tmp_term->term_id, $tax, true);
718 + }
606 719 return $tmp_term;
607 720 }
608 721 }
609 722 }
@@ -608,12 +721,24 @@
608 721 }
609 722 }
610 723 }
611 724
725 + // should not create new term since we are using the term_id
726 + if ($term_type === 'term_id' || $term_type === 'custom_field') {
727 + return false;
728 + }
729 +
730 + // allow the option to disable the creation of terms
731 + if (false === apply_filters('iwp/importer/template/post_create_term', true)) {
732 + return false;
733 + }
734 +
612 735 // add term
613 736 $term_id = wp_insert_term($term, $tax, ['parent' => $parent]);
614 737 if (!is_wp_error($term_id)) {
615 - wp_set_object_terms($post_id, $term_id['term_id'], $tax, true);
738 + if ($set) {
739 + wp_set_object_terms($post_id, $term_id['term_id'], $tax, true);
740 + }
616 741 return get_term($term_id['term_id'], $tax);
617 742 }
618 743
619 744 return false;
@@ -662,8 +787,10 @@
662 787 $sub_rows = $data->getData($sub_group_id);
663 788 }
664 789
665 790 foreach ($sub_rows as $row) {
791 +
792 + $row = $this->process_attachment_meta_permissions($row, $data, $group, $permission_key, $row_prefix);
666 793 $ids = $this->process_attachment($post_id, $row, $row_prefix, $filesystem, $ftp, $attachment);
667 794 $attachment_ids = array_merge($attachment_ids, $ids);
668 795 }
669 796 }
@@ -764,9 +891,9 @@
764 891 'map' => []
765 892 ];
766 893 }
767 894
768 - $attachments['image']['map'][$matches[1]] = sprintf('{%d}', $index);
895 + $attachments['image']['map'][$matches[1]] = sprintf('{%s}', $index);
769 896 $attachments['image']['map']['featured'] = 'yes';
770 897 } elseif (preg_match('/^tax_([a-zA-Z0-9_]+)\.(.*?)$/', $field, $matches) === 1) {
771 898
772 899 // Capture Taxonomies.
@@ -778,9 +905,9 @@
778 905 'map' => []
779 906 ];
780 907 }
781 908
782 - $taxonomies[$taxonomy]['map'][$matches[2]] = sprintf('{%d}', $index);
909 + $taxonomies[$taxonomy]['map'][$matches[2]] = sprintf('{%s}', $index);
783 910 } elseif (preg_match('/^author\.(.*?)$/', $field, $matches) === 1) {
784 911
785 912 // Capture author.
786 913 // author.ID, author.user_login,author.user_nicename,author.user_email,author.user_url,author.display_name
@@ -787,9 +914,9 @@
787 914 if (!isset($author['map'])) {
788 915 $author['map'] = [];
789 916 }
790 917
791 - $author['map'][$matches[1]] = sprintf('{%d}', $index);
918 + $author['map'][$matches[1]] = sprintf('{%s}', $index);
792 919 } elseif (preg_match('/^parent\.(.*?)$/', $field, $matches) === 1) {
793 920
794 921 // Capture parent
795 922 // parent.id,parent.name,parent.slug
@@ -796,14 +923,14 @@
796 923 if (!isset($parent['map'])) {
797 924 $parent['map'] = [];
798 925 }
799 926
800 - $parent['map'][$matches[1]] = sprintf('{%d}', $index);
927 + $parent['map'][$matches[1]] = sprintf('{%s}', $index);
801 928 } elseif (isset($this->field_map[$field])) {
802 929
803 930 // Handle core fields
804 931 $field_key = $this->field_map[$field];
805 - $map[$field_key] = sprintf('{%d}', $index);
932 + $map[$field_key] = sprintf('{%s}', $index);
806 933
807 934 if (in_array($field, $this->optional_fields)) {
808 935 $enabled[] = $field_key;
809 936 }
@@ -829,23 +956,39 @@
829 956 'settings._append' => 'no',
830 957 'settings._delimiter' => '',
831 958 'settings._hierarchy' => 'no',
832 959 'settings._hierarchy_character' => '>',
960 + 'settings._type' => 'name',
833 961 ];
834 962
835 963 foreach ($taxonomies as $taxonomy => $taxonomy_data) {
964 + $term_map = isset($taxonomy_data['map']) && is_array($taxonomy_data['map']) ? $taxonomy_data['map'] : [];
836 965 $data = [];
837 966
838 - if (isset($taxonomy_data['map']['hierarchy::name'])) {
839 - $data['term'] = $taxonomy_data['map']['hierarchy::name'];
967 + // Prefer name/slug over hierarchy::* (those extra columns are always
968 + // present on a full CSV export). Always store term type so IDs are
969 + // not imported as names.
970 + if (isset($term_map['name'])) {
971 + $data['term'] = $term_map['name'];
972 + $data['settings._type'] = 'name';
973 + } elseif (isset($term_map['slug'])) {
974 + $data['term'] = $term_map['slug'];
975 + $data['settings._type'] = 'slug';
976 + } elseif (isset($term_map['hierarchy::name'])) {
977 + $data['term'] = $term_map['hierarchy::name'];
840 978 $data['settings._hierarchy'] = 'yes';
841 - } elseif (isset($taxonomy_data['map']['hierarchy::slug'])) {
842 - $data['term'] = $taxonomy_data['map']['hierarchy::slug'];
979 + $data['settings._type'] = 'name';
980 + } elseif (isset($term_map['hierarchy::slug'])) {
981 + $data['term'] = $term_map['hierarchy::slug'];
843 982 $data['settings._hierarchy'] = 'yes';
844 - } elseif (isset($taxonomy_data['map']['name'])) {
845 - $data['term'] = $taxonomy_data['map']['name'];
846 - } elseif (isset($taxonomy_data['map']['slug'])) {
847 - $data['term'] = $taxonomy_data['map']['slug'];
983 + $data['settings._type'] = 'slug';
984 + } elseif (isset($term_map['id'])) {
985 + $data['term'] = $term_map['id'];
986 + $data['settings._type'] = 'term_id';
987 + } elseif (isset($term_map['hierarchy::id'])) {
988 + $data['term'] = $term_map['hierarchy::id'];
989 + $data['settings._hierarchy'] = 'yes';
990 + $data['settings._type'] = 'term_id';
848 991 } else {
849 992 continue;
850 993 }
851 994
@@ -850,8 +993,14 @@
850 993 }
851 994
852 995 $data['tax'] = $taxonomy;
853 996
997 + $row_base = $this->find_exporter_loop_row_base($fields, 'tax_' . $taxonomy);
998 + if ($row_base !== '') {
999 + $data['row_base'] = $row_base;
1000 + $data['term'] = $this->relative_exporter_map($data['term'], $row_base);
1001 + }
1002 +
854 1003 $data = wp_parse_args($data, $defaults);
855 1004
856 1005 $map = array_merge($map, array_reduce(array_keys($data), function ($carry, $key) use ($data, $taxonomy_counter) {
857 1006 $carry[sprintf('taxonomies.%d.%s', $taxonomy_counter, $key)] = $data[$key];
@@ -983,6 +1132,132 @@
983 1132 return [
984 1133 'map' => $map,
985 1134 'enabled' => $enabled
986 1135 ];
1136 + }
1137 +
1138 + public function get_permission_fields($importer_model)
1139 + {
1140 + $permission_fields = parent::get_permission_fields($importer_model);
1141 +
1142 + $permission_fields['core'] = [
1143 + 'ID' => __('ID', 'jc-importer'),
1144 + 'post_title' => __('Title', 'jc-importer'),
1145 + 'post_content' => __('Content', 'jc-importer'),
1146 + 'post_excerpt' => __('Excerpt', 'jc-importer'),
1147 + 'post_name' => __('Slug', 'jc-importer'),
1148 + 'post_status' => __('Post Status', 'jc-importer'),
1149 + 'menu_order' => __('Menu order', 'jc-importer'),
1150 + 'post_password' => __('password', 'jc-importer'),
1151 + 'post_date' => __('Date', 'jc-importer'),
1152 + 'comment_status' => __('Comment Status', 'jc-importer'),
1153 + 'ping_status' => __('Ping Status', 'jc-importer'),
1154 + 'post_parent' => __('Parent', 'jc-importer'),
1155 + 'post_author' => __('Author', 'jc-importer'),
1156 + ];
1157 +
1158 + $permission_fields['taxonomies'] = [];
1159 + $taxonomies = $this->get_taxonomy_options($importer_model);
1160 + foreach ($taxonomies as $taxonomy) {
1161 + $permission_fields['taxonomies']['taxonomy.' . $taxonomy['value']] = $taxonomy['label'];
1162 + }
1163 +
1164 + $field_map = $importer_model->getMap();
1165 + if (isset($field_map['attachments._index']) && $field_map['attachments._index'] > 0) {
1166 + $permission_fields['attachments'] = [];
1167 + for ($i = 0; $i < $field_map['attachments._index']; $i++) {
1168 + $permission_fields['attachments']['attachments.' . $i] = 'Attachment Row ' . ($i + 1);
1169 +
1170 + // Meta fields
1171 + $permission_fields['attachments']['attachments.' . $i . '._alt'] = 'Attachment Row ' . ($i + 1) . ' - Alt Text';
1172 + $permission_fields['attachments']['attachments.' . $i . '._title'] = 'Attachment Row ' . ($i + 1) . ' - Title Text';
1173 + $permission_fields['attachments']['attachments.' . $i . '._caption'] = 'Attachment Row ' . ($i + 1) . ' - Caption Text';
1174 + $permission_fields['attachments']['attachments.' . $i . '._description'] = 'Attachment Row ' . ($i + 1) . ' - Description Text';
1175 + }
1176 + }
1177 +
1178 + return $permission_fields;
1179 + }
1180 +
1181 + public function get_unique_identifier_options($importer_model, $unique_fields = [])
1182 + {
1183 + $output = parent::get_unique_identifier_options($importer_model, $unique_fields);
1184 +
1185 + return array_merge(
1186 + $output,
1187 + $this->get_unique_identifier_options_from_map($importer_model, $unique_fields, $this->field_map, $this->optional_fields)
1188 + );
1189 + }
1190 +
1191 + /**
1192 + * XML/JSON from-exporter headings are path => selection; CSV is a numeric list.
1193 + *
1194 + * @param array $fields
1195 + * @return bool
1196 + */
1197 + protected function headings_are_paths($fields)
1198 + {
1199 + if (!is_array($fields) || empty($fields)) {
1200 + return false;
1201 + }
1202 +
1203 + foreach (array_keys($fields) as $key) {
1204 + if (is_string($key) && $key !== '' && !is_numeric($key) && strpos($key, '/') !== false) {
1205 + return true;
1206 + }
1207 + }
1208 +
1209 + return false;
1210 + }
1211 +
1212 + /**
1213 + * Loop node path used as row_base when creating an importer from an XML/JSON export.
1214 + *
1215 + * @param array $fields
1216 + * @param string $loop_selection
1217 + * @return string
1218 + */
1219 + protected function find_exporter_loop_row_base($fields, $loop_selection)
1220 + {
1221 + if ($loop_selection === '' || !$this->headings_are_paths($fields)) {
1222 + return '';
1223 + }
1224 +
1225 + foreach ($fields as $path => $selection) {
1226 + if ($selection === $loop_selection && is_string($path) && strpos($path, '/') !== false) {
1227 + return $path;
1228 + }
1229 + }
1230 +
1231 + return '';
1232 + }
1233 +
1234 + /**
1235 + * Rewrite a mapped path so it is relative to the exporter loop node.
1236 + *
1237 + * @param string $mapped
1238 + * @param string $row_base
1239 + * @return string
1240 + */
1241 + protected function relative_exporter_map($mapped, $row_base)
1242 + {
1243 + if ($row_base === '' || !is_string($mapped) || $mapped === '') {
1244 + return $mapped;
1245 + }
1246 +
1247 + if (preg_match('/^\{(.*)\}$/', $mapped, $matches) !== 1) {
1248 + return $mapped;
1249 + }
1250 +
1251 + $path = $matches[1];
1252 + if (strpos($path, $row_base) !== 0 || $path === $row_base) {
1253 + return $mapped;
1254 + }
1255 +
1256 + $relative = substr($path, strlen($row_base));
1257 + if ($relative !== '' && $relative[0] !== '/') {
1258 + $relative = '/' . $relative;
1259 + }
1260 +
1261 + return '{' . $relative . '}';
987 1262 }
988 1263 }