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 +657 -118 2.7.1 → 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',
@@ -30,8 +30,20 @@
30 30 'ping_status' => 'post.ping_status',
31 31 'post_parent' => 'post._parent.parent',
32 32 ];
33 33
34 + protected $optional_fields = [
35 + 'ID',
36 + 'post_excerpt',
37 + 'post_name',
38 + 'post_status',
39 + 'menu_order',
40 + 'post_password',
41 + 'post_date',
42 + 'comment_status',
43 + 'ping_status'
44 + ];
45 +
34 46 protected $_taxonomies = [];
35 47 protected $_attachments = [];
36 48
37 49 private $virtual_fields = [];
@@ -49,8 +61,10 @@
49 61 $this->field_options = array_merge($this->field_options, [
50 62 'post._parent.parent' => [$this, 'get_post_parent_options'],
51 63 'taxonomies.*.tax' => [$this, 'get_taxonomy_options'],
52 64 ]);
65 +
66 + $this->default_enabled_fields[] = 'post.post_status';
53 67 }
54 68
55 69 /**
56 70 * @param string $message
@@ -68,9 +82,9 @@
68 82 }
69 83 }
70 84
71 85 if (!empty($this->_attachments)) {
72 - $message .= ', Attachments: (' . implode(', ', $this->_attachments) . ')';
86 + $message .= sprintf(__(', Attachments: (%s)', 'jc-importer'), implode(', ', $this->_attachments));
73 87 }
74 88
75 89 return $message;
76 90 }
@@ -79,98 +93,98 @@
79 93 {
80 94 $groups = [];
81 95
82 96 // Post
83 - $groups[] = $this->register_group('Post Fields', 'post', [
84 - $this->register_field('ID', 'ID', [
85 - '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')
86 100 ]),
87 - $this->register_core_field('Title', 'post_title', [
88 - 'tooltip' => __('Title of the post.', 'importwp')
101 + $this->register_core_field(__('Title', 'jc-importer'), 'post_title', [
102 + 'tooltip' => __('Title of the post.', 'jc-importer')
89 103 ]),
90 - $this->register_core_field('Content', 'post_content', [
91 - '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')
92 106 ]),
93 - $this->register_field('Excerpt', 'post_excerpt', [
94 - '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')
95 109 ]),
96 - $this->register_field('Slug', 'post_name', [
97 - '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')
98 112 ]),
99 - $this->register_field('Status', 'post_status', [
113 + $this->register_field(__('Status', 'jc-importer'), 'post_status', [
100 114 'default' => 'publish',
101 115 'options' => [
102 - ['value' => 'draft', 'label' => 'Draft'],
103 - ['value' => 'publish', 'label' => 'Published'],
104 - ['value' => 'pending', 'label' => 'Pending'],
105 - ['value' => 'future', 'label' => 'Future'],
106 - ['value' => 'private', 'label' => 'Private'],
107 - ['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')]
108 122 ],
109 - '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')
110 124 ]),
111 - $this->register_group('Parent Settings', '_parent', [
112 - $this->register_field('Parent', 'parent', [
125 + $this->register_group(__('Parent Settings', 'jc-importer'), '_parent', [
126 + $this->register_field(__('Parent', 'jc-importer'), 'parent', [
113 127 'default' => '',
114 128 'options' => 'callback',
115 - 'tooltip' => __('Set this for the post it belongs to', 'importwp')
129 + 'tooltip' => __('Set this for the post it belongs to', 'jc-importer')
116 130 ]),
117 - $this->register_field('Parent Field Type', '_parent_type', [
131 + $this->register_field(__('Parent Field Type', 'jc-importer'), '_parent_type', [
118 132 'default' => 'id',
119 133 'options' => [
120 - ['value' => 'id', 'label' => 'ID'],
121 - ['value' => 'slug', 'label' => 'Slug'],
122 - ['value' => 'name', 'label' => 'Name'],
123 - ['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')],
124 138 ],
125 139 'type' => 'select',
126 - 'tooltip' => __('Select how the parent field should be handled', 'importwp')
140 + 'tooltip' => __('Select how the parent field should be handled', 'jc-importer')
127 141 ]),
128 - $this->register_field('Parent Reference Column', '_parent_ref', [
142 + $this->register_field(__('Parent Reference Column', 'jc-importer'), '_parent_ref', [
129 143 'condition' => ['_parent_type', '==', 'column'],
130 - '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')
131 145 ])
132 146 ]),
133 - $this->register_field('Order', 'menu_order', [
134 - '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')
135 149 ]),
136 - $this->register_group('Author Settings', '_author', [
137 - $this->register_field('Author', 'post_author', [
138 - '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')
139 153 ]),
140 - $this->register_field('Author Field Type', '_author_type', [
154 + $this->register_field(__('Author Field Type', 'jc-importer'), '_author_type', [
141 155 'default' => 'id',
142 156 'options' => [
143 - ['value' => 'id', 'label' => 'ID'],
144 - ['value' => 'login', 'label' => 'Login'],
145 - ['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')],
146 160 ],
147 - 'tooltip' => __('Select how the author field should be handled', 'importwp')
161 + 'tooltip' => __('Select how the author field should be handled', 'jc-importer')
148 162 ])
149 163 ]),
150 - $this->register_field('Password', 'post_password', [
151 - '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')
152 166 ]),
153 - $this->register_field('Date', 'post_date', [
154 - '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')
155 169 ]),
156 - $this->register_field('Allow Comments', 'comment_status', [
170 + $this->register_field(__('Allow Comments', 'jc-importer'), 'comment_status', [
157 171 'options' => [
158 - ['value' => '0', 'label' => 'Disabled'],
159 - ['value' => '1', 'label' => 'Enabled']
172 + ['value' => '0', 'label' => __('Disabled', 'jc-importer')],
173 + ['value' => '1', 'label' => __('Enabled', 'jc-importer')]
160 174 ],
161 175 'default' => '0',
162 - 'tooltip' => __('Whether the post can accept comments', 'importwp')
176 + 'tooltip' => __('Whether the post can accept comments', 'jc-importer')
163 177 ]),
164 - $this->register_field('Allow Pingbacks', 'ping_status', [
178 + $this->register_field(__('Allow Pingbacks', 'jc-importer'), 'ping_status', [
165 179 'options' => [
166 - ['value' => 'closed', 'label' => 'Closed'],
167 - ['value' => 'open', 'label' => 'Open']
180 + ['value' => 'closed', 'label' => __('Closed', 'jc-importer')],
181 + ['value' => 'open', 'label' => __('Open', 'jc-importer')]
168 182 ],
169 183 'default' => 'closed',
170 - 'tooltip' => __('Whether the post can accept pings', 'importwp')
184 + 'tooltip' => __('Whether the post can accept pings', 'jc-importer')
171 185 ])
172 - ]);
186 + ], ['link' => 'https://www.importwp.com/docs/wordpress-page-importer-template/']);
173 187
174 188 // Taxonomies
175 189 $groups[] = $this->register_taxonomy_fields();
176 190
@@ -181,43 +195,72 @@
181 195 }
182 196
183 197 public function register_taxonomy_fields()
184 198 {
185 - return $this->register_group('Taxonomies', 'taxonomies', [
186 - $this->register_field('Taxonomy', 'tax', [
199 + return $this->register_group(__('Taxonomies', 'jc-importer'), 'taxonomies', [
200 + $this->register_field(__('Taxonomy', 'jc-importer'), 'tax', [
187 201 'default' => 'category',
188 202 'options' => 'callback',
189 - 'tooltip' => __('Select the type of taxonomy you are importing to.', 'importwp')
203 + 'tooltip' => __('Select the type of taxonomy you are importing to.', 'jc-importer')
190 204 ]),
191 - $this->register_field('Terms', 'term', [
192 - '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')
193 207 ]),
194 - $this->register_field('Enable Hierarchy', '_hierarchy', [
195 - 'default' => 'no',
196 - 'options' => [
197 - ['value' => 'no', 'label' => 'No'],
198 - ['value' => 'yes', 'label' => 'Yes'],
199 - ],
200 - 'type' => 'select'
201 - ]),
202 - $this->register_field('Hierarchy Character', '_hierarchy_character', [
203 - 'default' => '>',
204 - 'condition' => ['_hierarchy', '==', 'yes'],
205 - ]),
206 - $this->register_field('Append Terms', '_append', [
207 - 'default' => 'no',
208 - 'options' => [
209 - ['value' => 'no', 'label' => 'No'],
210 - ['value' => 'yes', 'label' => 'Yes'],
211 - ],
212 - 'type' => 'select'
213 - ]),
214 - ], ['type' => 'repeatable', 'row_base' => true]);
208 + $this->register_group(__('Settings', 'jc-importer'), 'settings', [
209 + $this->register_field(__('Delimiter', 'jc-importer'), '_delimiter', [
210 + 'type' => 'text',
211 + 'tooltip' => sprintf(__('A single character used to seperate terms when listing multiple, Leave empty to use default: %s', 'jc-importer'), ',')
212 + ]),
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', [
230 + 'default' => 'no',
231 + 'options' => [
232 + ['value' => 'no', 'label' => __('No', 'jc-importer')],
233 + ['value' => 'yes', 'label' => __('Yes', 'jc-importer')],
234 + ],
235 + 'type' => 'select'
236 + ]),
237 + $this->register_field(__('Hierarchy Character', 'jc-importer'), '_hierarchy_character', [
238 + 'default' => '>',
239 + 'condition' => ['_hierarchy', '==', 'yes'],
240 + ]),
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', [
251 + 'default' => 'no',
252 + 'options' => [
253 + ['value' => 'no', 'label' => __('No', 'jc-importer')],
254 + ['value' => 'yes', 'label' => __('Yes', 'jc-importer')],
255 + ],
256 + 'type' => 'select'
257 + ]),
258 + ], ['type' => 'settings'])
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/']);
215 260 }
216 261
217 - public function register_settings()
218 - {
219 - }
262 + public function register_settings() {}
220 263
221 264 public function register_options()
222 265 {
223 266 return [];
@@ -263,25 +306,18 @@
263 306 continue;
264 307 }
265 308 }
266 309
267 - $optional_fields = [
268 - 'ID',
269 - 'post_excerpt',
270 - 'post_name',
271 - 'post_status',
272 - 'menu_order',
273 - 'post_password',
274 - 'post_date',
275 - 'comment_status',
276 - 'ping_status'
277 - ];
278 - foreach ($optional_fields as $optional_field) {
310 + foreach ($this->optional_fields as $optional_field) {
279 311 if (true !== $this->importer->isEnabledField('post.' . $optional_field)) {
280 312 unset($post_field_map[$optional_field]);
281 313 }
282 314 }
283 315
316 + if (isset($post_field_map['post_date'])) {
317 + $post_field_map['post_date_gmt'] = get_gmt_from_date($post_field_map['post_date']);
318 + }
319 +
284 320 if (true !== $this->importer->isEnabledField('post._parent')) {
285 321 unset($post_field_map['post_parent']);
286 322 }
287 323
@@ -338,9 +374,9 @@
338 374 // // set flag to say slug has been generated
339 375 // $data->add(['post_name' => 'yes'], '_generated');
340 376 // }
341 377
342 - 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'])) {
343 379
344 380 $parent_id = 0;
345 381 $parent_field_type = $data->getValue('post._parent._parent_type');
346 382
@@ -400,9 +436,9 @@
400 436 'key' => '_iwp_ref_' . $field,
401 437 'value' => $value
402 438 )
403 439 ),
404 - 'post_status' => 'any'
440 + 'post_status' => 'any, trash, future'
405 441 ));
406 442 if ($query->have_posts()) {
407 443 return $query->posts[0];
408 444 }
@@ -434,9 +470,8 @@
434 470 * @var Attachment $attachment
435 471 */
436 472 $attachment = Container::getInstance()->get('attachment');
437 473
438 - $this->featured_set = false;
439 474 $this->process_taxonomies($post_id, $data);
440 475 $this->process_attachments($post_id, $data, $filesystem, $ftp, $attachment);
441 476
442 477 parent::post_process($post_id, $data);
@@ -464,8 +499,9 @@
464 499
465 500 $processed_taxonomies = [];
466 501 $term_hierarchy = [];
467 502 $term_hierarchy_enabled = [];
503 + $term_types = [];
468 504 $term_append = [];
469 505
470 506 // Pre-Process taxonomy data
471 507 for ($i = 0; $i < $total_rows; $i++) {
@@ -481,15 +517,22 @@
481 517 foreach ($sub_rows as $row) {
482 518 $tax = isset($row[$prefix . 'tax']) ? $row[$prefix . 'tax'] : null;
483 519 $terms = isset($row[$prefix . 'term']) ? $row[$prefix . 'term'] : null;
484 520
485 - $term_append[$tax] = isset($row[$prefix . '_append']) && $row[$prefix . '_append'] == 'yes';
521 + $term_append[$tax] = isset($row[$prefix . 'settings._append']) && $row[$prefix . 'settings._append'] == 'yes';
486 522
487 523 $delimiter = apply_filters('iwp/taxonomy=' . $tax . '/value_delimiter', $base_delimiter);
488 524
489 - $hierarchy_enabled = isset($row[$prefix . '_hierarchy']) && $row[$prefix . '_hierarchy'] === 'yes' ? true : false;
490 - $hierarchy_character = isset($row[$prefix . '_hierarchy_character']) ? $row[$prefix . '_hierarchy_character'] : null;
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'] : '';
491 527
528 + $hierarchy_enabled = isset($row[$prefix . 'settings._hierarchy']) && $row[$prefix . 'settings._hierarchy'] === 'yes' ? true : false;
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;
531 +
532 +
533 + $delimiter = isset($row[$prefix . 'settings._delimiter']) && strlen(trim($row[$prefix . 'settings._delimiter'])) === 1 ? trim($row[$prefix . 'settings._delimiter']) : $delimiter;
534 +
492 535 if (empty($hierarchy_character)) {
493 536 $hierarchy_enabled = false;
494 537 }
495 538
@@ -503,9 +546,9 @@
503 546 if ($data->permission()) {
504 547 $allowed = $data->permission()->validate([$permission_key => ''], $data->getMethod(), $group);
505 548 $is_allowed = isset($allowed[$permission_key]) ? true : false;
506 549
507 - if (!$is_allowed || empty($term)) {
550 + if (!$is_allowed || ($term_append[$tax] == true && empty($term))) {
508 551 continue;
509 552 }
510 553 }
511 554
@@ -539,58 +582,141 @@
539 582 // TODO: Process term hierarchy
540 583 foreach ($term_hierarchy as $processed_tax => $term_hierarchy_list) {
541 584
542 585 // clear existing taxonomies
543 - if (!isset($term_append[$processed_tax]) || !$term_append[$processed_tax]) {
544 - wp_set_object_terms($post_id, null, $processed_tax);
545 - }
586 + $clear_existing_terms = !isset($term_append[$processed_tax]) || !$term_append[$processed_tax];
546 587
547 588 if (empty($term_hierarchy_list)) {
548 589 continue;
549 590 }
550 591
592 + $new_terms = [];
593 +
551 594 foreach ($term_hierarchy_list as $hierarchy_list) {
552 595
553 596 $prev_term = isset($term_hierarchy_enabled[$processed_tax]) ? 0 : null;
597 + $type = $term_types[$processed_tax];
554 598
555 - foreach ($hierarchy_list as $term) {
599 + foreach ($hierarchy_list as $term_i => $term) {
556 600 if (!isset($this->_taxonomies[$processed_tax])) {
557 601 $this->_taxonomies[$processed_tax] = [];
558 602 }
559 603
560 - $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);
561 618 if ($term_result) {
562 619 $prev_term = $term_result->term_id;
563 620 $this->_taxonomies[$processed_tax][] = $term_result->name;
564 621 }
622 +
623 + if ($connect_terms && $term_result) {
624 + $new_terms[] = $term_result->term_id;
625 + }
565 626 }
566 627 }
628 +
629 + // Connect all terms in one go.
630 + wp_set_object_terms($post_id, $new_terms, $processed_tax, !$clear_existing_terms);
567 631 }
568 632 }
569 633
570 - 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)
571 635 {
636 + if (!in_array($term_type, ['slug', 'name', 'term_id', 'custom_field'])) {
637 + $term_type = 'name';
638 + }
572 639
573 640 if (is_null($parent)) {
574 641
575 642 // we do not care about parent, just fetch first
576 - $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 +
577 665 if ($tmp_term) {
578 - 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 + }
579 670 return $tmp_term;
580 671 }
581 672 } else {
582 - $terms = get_terms([
583 - 'taxonomy' => $tax,
584 - 'name' => $term,
585 - 'hide_empty' => false
586 - ]);
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 +
587 710 if (!empty($terms)) {
588 711 foreach ($terms as $tmp_term) {
589 712 if (intval($tmp_term->parent) === intval($parent)) {
590 713
591 714 // attach term to post
592 - 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 + }
593 719 return $tmp_term;
594 720 }
595 721 }
596 722 }
@@ -595,12 +721,24 @@
595 721 }
596 722 }
597 723 }
598 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 +
599 735 // add term
600 736 $term_id = wp_insert_term($term, $tax, ['parent' => $parent]);
601 737 if (!is_wp_error($term_id)) {
602 - 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 + }
603 741 return get_term($term_id['term_id'], $tax);
604 742 }
605 743
606 744 return false;
@@ -649,8 +787,10 @@
649 787 $sub_rows = $data->getData($sub_group_id);
650 788 }
651 789
652 790 foreach ($sub_rows as $row) {
791 +
792 + $row = $this->process_attachment_meta_permissions($row, $data, $group, $permission_key, $row_prefix);
653 793 $ids = $this->process_attachment($post_id, $row, $row_prefix, $filesystem, $ftp, $attachment);
654 794 $attachment_ids = array_merge($attachment_ids, $ids);
655 795 }
656 796 }
@@ -719,6 +859,405 @@
719 859 ];
720 860 }
721 861
722 862 return $result;
863 + }
864 +
865 + /**
866 + * Convert fields/headings to data map
867 + *
868 + * @param mixed $fields
869 + * @param ImporterModel $importer
870 + * @return array
871 + */
872 + public function generate_field_map($fields, $importer)
873 + {
874 + $result = parent::generate_field_map($fields, $importer);
875 + $map = $result['map'];
876 + $enabled = $result['enabled'];
877 +
878 + $taxonomies = [];
879 + $attachments = [];
880 + $author = [];
881 + $parent = [];
882 +
883 + foreach ($fields as $index => $field) {
884 +
885 + if (preg_match('/^image\.(.*?)$/', $field, $matches) === 1) {
886 +
887 + // Capture featured image.
888 + // image.id,url, title, alt, caption, description
889 + if (!isset($attachments['image'])) {
890 + $attachments['image'] = [
891 + 'map' => []
892 + ];
893 + }
894 +
895 + $attachments['image']['map'][$matches[1]] = sprintf('{%s}', $index);
896 + $attachments['image']['map']['featured'] = 'yes';
897 + } elseif (preg_match('/^tax_([a-zA-Z0-9_]+)\.(.*?)$/', $field, $matches) === 1) {
898 +
899 + // Capture Taxonomies.
900 + // tax_{taxonomy}.name,slug,id,hierarchy::id,hierarchy::name,hierarchy::slug
901 +
902 + $taxonomy = $matches[1];
903 + if (!isset($taxonomies[$taxonomy])) {
904 + $taxonomies[$taxonomy] = [
905 + 'map' => []
906 + ];
907 + }
908 +
909 + $taxonomies[$taxonomy]['map'][$matches[2]] = sprintf('{%s}', $index);
910 + } elseif (preg_match('/^author\.(.*?)$/', $field, $matches) === 1) {
911 +
912 + // Capture author.
913 + // author.ID, author.user_login,author.user_nicename,author.user_email,author.user_url,author.display_name
914 + if (!isset($author['map'])) {
915 + $author['map'] = [];
916 + }
917 +
918 + $author['map'][$matches[1]] = sprintf('{%s}', $index);
919 + } elseif (preg_match('/^parent\.(.*?)$/', $field, $matches) === 1) {
920 +
921 + // Capture parent
922 + // parent.id,parent.name,parent.slug
923 + if (!isset($parent['map'])) {
924 + $parent['map'] = [];
925 + }
926 +
927 + $parent['map'][$matches[1]] = sprintf('{%s}', $index);
928 + } elseif (isset($this->field_map[$field])) {
929 +
930 + // Handle core fields
931 + $field_key = $this->field_map[$field];
932 + $map[$field_key] = sprintf('{%s}', $index);
933 +
934 + if (in_array($field, $this->optional_fields)) {
935 + $enabled[] = $field_key;
936 + }
937 +
938 + if (in_array($field, ['post_status', 'comment_status', 'ping_status'])) {
939 + $map[$field_key . '._enable_text'] = 'yes';
940 + }
941 + }
942 + }
943 +
944 + $taxonomies = apply_filters('iwp/importer/generate_field_map/taxonomies', $taxonomies, $fields, $importer);
945 + $attachments = apply_filters('iwp/importer/generate_field_map/attachments', $attachments, $fields, $importer);
946 + $author = apply_filters('iwp/importer/generate_field_map/author', $author, $fields, $importer);
947 + $parent = apply_filters('iwp/importer/generate_field_map/parent', $parent, $fields, $importer);
948 +
949 + if (!empty($taxonomies)) {
950 +
951 + $taxonomy_counter = 0;
952 + $defaults = [
953 + 'row_base' => '',
954 + 'tax' => '',
955 + 'term' => '',
956 + 'settings._append' => 'no',
957 + 'settings._delimiter' => '',
958 + 'settings._hierarchy' => 'no',
959 + 'settings._hierarchy_character' => '>',
960 + 'settings._type' => 'name',
961 + ];
962 +
963 + foreach ($taxonomies as $taxonomy => $taxonomy_data) {
964 + $term_map = isset($taxonomy_data['map']) && is_array($taxonomy_data['map']) ? $taxonomy_data['map'] : [];
965 + $data = [];
966 +
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'];
978 + $data['settings._hierarchy'] = 'yes';
979 + $data['settings._type'] = 'name';
980 + } elseif (isset($term_map['hierarchy::slug'])) {
981 + $data['term'] = $term_map['hierarchy::slug'];
982 + $data['settings._hierarchy'] = 'yes';
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';
991 + } else {
992 + continue;
993 + }
994 +
995 + $data['tax'] = $taxonomy;
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 +
1003 + $data = wp_parse_args($data, $defaults);
1004 +
1005 + $map = array_merge($map, array_reduce(array_keys($data), function ($carry, $key) use ($data, $taxonomy_counter) {
1006 + $carry[sprintf('taxonomies.%d.%s', $taxonomy_counter, $key)] = $data[$key];
1007 + return $carry;
1008 + }, []));
1009 +
1010 + $taxonomy_counter++;
1011 + }
1012 +
1013 + $map['taxonomies._index'] = $taxonomy_counter;
1014 + }
1015 +
1016 + if (!empty($attachments)) {
1017 +
1018 + $attachment_counter = 0;
1019 + $defaults = [
1020 + 'row_base' => '',
1021 + 'location' => '',
1022 + 'settings._delimiter' => '',
1023 + 'settings._download' => 'remote',
1024 + 'settings._enable_image_hash' => 'yes',
1025 + 'settings._featured' => 'no',
1026 + 'settings._ftp_host' => '',
1027 + 'settings._ftp_pass' => '',
1028 + 'settings._ftp_path' => '',
1029 + 'settings._ftp_user' => '',
1030 + 'settings._local_url' => '',
1031 + 'settings._meta._alt' => '',
1032 + 'settings._meta._caption' => '',
1033 + 'settings._meta._description' => '',
1034 + 'settings._meta._enabled' => 'no',
1035 + 'settings._meta._title' => '',
1036 + 'settings._remote_url' => '',
1037 + ];
1038 +
1039 + foreach ($attachments as $attachment_data) {
1040 +
1041 + $data = [];
1042 +
1043 + if (!isset($attachment_data['map']['url'])) {
1044 + continue;
1045 + }
1046 +
1047 + // location
1048 + $data['location'] = $attachment_data['map']['url'];
1049 +
1050 + if (isset($attachment_data['map']['featured'])) {
1051 + $data['settings._featured'] = $attachment_data['map']['featured'];
1052 + }
1053 +
1054 + // Meta
1055 + if (isset($attachment_data['map']['title'])) {
1056 + $data['settings._meta._title'] = $attachment_data['map']['title'];
1057 + $data['settings._meta._enabled'] = 'yes';
1058 + }
1059 + if (isset($attachment_data['map']['alt'])) {
1060 + $data['settings._meta._alt'] = $attachment_data['map']['alt'];
1061 + $data['settings._meta._enabled'] = 'yes';
1062 + }
1063 + if (isset($attachment_data['map']['description'])) {
1064 + $data['settings._meta._description'] = $attachment_data['map']['description'];
1065 + $data['settings._meta._enabled'] = 'yes';
1066 + }
1067 + if (isset($attachment_data['map']['caption'])) {
1068 + $data['settings._meta._caption'] = $attachment_data['map']['caption'];
1069 + $data['settings._meta._enabled'] = 'yes';
1070 + }
1071 +
1072 + $data = wp_parse_args($data, $defaults);
1073 +
1074 + $map = array_merge($map, array_reduce(array_keys($data), function ($carry, $key) use ($data, $attachment_counter) {
1075 + $carry[sprintf('attachments.%d.%s', $attachment_counter, $key)] = $data[$key];
1076 + return $carry;
1077 + }, []));
1078 +
1079 + $attachment_counter++;
1080 + }
1081 +
1082 + $map['attachments._index'] = $attachment_counter;
1083 + }
1084 +
1085 + if (!empty($author)) {
1086 +
1087 + // TODO: enable field? this is a seperate field list
1088 + $enabled_key = 'post._author';
1089 + if (isset($author['map']['user_email'])) {
1090 +
1091 + $enabled[] = $enabled_key;
1092 + $map['post._author.post_author'] = $author['map']['user_email'];
1093 + $map['post._author._author_type'] = 'email';
1094 + } elseif (isset($author['map']['user_login'])) {
1095 +
1096 + $enabled[] = $enabled_key;
1097 + $map['post._author.post_author'] = $author['map']['user_login'];
1098 + $map['post._author._author_type'] = 'login';
1099 + } elseif (isset($author['map']['ID'])) {
1100 +
1101 + $enabled[] = $enabled_key;
1102 + $map['post._author.post_author'] = $author['map']['ID'];
1103 + $map['post._author._author_type'] = 'id';
1104 + }
1105 + }
1106 +
1107 + if (!empty($parent)) {
1108 +
1109 + // parent.id,parent.name,parent.slug
1110 + $enabled_key = 'post._parent';
1111 + if (isset($parent['map']['name'])) {
1112 +
1113 + $enabled[] = $enabled_key;
1114 + $map['post._parent.parent'] = $parent['map']['name'];
1115 + $map['post._parent.parent._enable_text'] = 'yes';
1116 + $map['post._parent._parent_type'] = 'name';
1117 + } elseif (isset($parent['map']['slug'])) {
1118 +
1119 + $enabled[] = $enabled_key;
1120 + $map['post._parent.parent'] = $parent['map']['slug'];
1121 + $map['post._parent.parent._enable_text'] = 'yes';
1122 + $map['post._parent._parent_type'] = 'slug';
1123 + } elseif (isset($parent['map']['id'])) {
1124 +
1125 + $enabled[] = $enabled_key;
1126 + $map['post._parent.parent'] = $parent['map']['name'];
1127 + $map['post._parent.parent._enable_text'] = 'yes';
1128 + $map['post._parent._parent_type'] = 'id';
1129 + }
1130 + }
1131 +
1132 + return [
1133 + 'map' => $map,
1134 + 'enabled' => $enabled
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 . '}';
723 1262 }
724 1263 }