PluginProbe
Import WP – CSV & XML Import Export for WordPress / 2.14.23
Import WP – CSV & XML Import Export for WordPress v2.14.23
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
jc-importer / class / Common / Importer / Template / PostTemplate.php

PostTemplate.php in Import WP – CSV & XML Import Export for WordPress 2.14.23, at class/Common/Importer/Template/PostTemplate.php

1,169 lines 44.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ImportWP\Common\Importer\Template;
4
5 use ImportWP\Common\Attachment\Attachment;
6 use ImportWP\Common\Filesystem\Filesystem;
7 use ImportWP\Common\Ftp\Ftp;
8 use ImportWP\Common\Importer\ParsedData;
9 use ImportWP\Common\Importer\TemplateInterface;
10 use ImportWP\Common\Model\ImporterModel;
11 use ImportWP\Common\Util\Logger;
12 use ImportWP\Container;
13 use ImportWP\EventHandler;
14
15 class PostTemplate extends Template implements TemplateInterface
16 {
17 protected $name = 'Post';
18 protected $mapper = 'post';
19 protected $field_map = [
20 'ID' => 'post.ID',
21 'post_name' => 'post.post_name',
22 'post_title' => 'post.post_title',
23 'post_content' => 'post.post_content',
24 'post_excerpt' => 'post.post_excerpt',
25 'post_status' => 'post.post_status',
26 'menu_order' => 'post.menu_order',
27 'post_password' => 'post.post_password',
28 'post_date' => 'post.post_date',
29 'comment_status' => 'post.comment_status',
30 'ping_status' => 'post.ping_status',
31 'post_parent' => 'post._parent.parent',
32 ];
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
46 protected $_taxonomies = [];
47 protected $_attachments = [];
48
49 private $virtual_fields = [];
50
51 public function __construct(EventHandler $event_handler)
52 {
53 parent::__construct($event_handler);
54
55 $this->groups[] = 'post';
56 $this->groups[] = 'taxonomies';
57 $this->groups[] = 'attachments';
58
59 $this->default_template_options['post_type'] = 'post';
60
61 $this->field_options = array_merge($this->field_options, [
62 'post._parent.parent' => [$this, 'get_post_parent_options'],
63 'taxonomies.*.tax' => [$this, 'get_taxonomy_options'],
64 ]);
65
66 $this->default_enabled_fields[] = 'post.post_status';
67 }
68
69 /**
70 * @param string $message
71 * @param int $id
72 * @param ParsedData $data
73 * @return $string
74 */
75 public function display_record_info($message, $id, $data)
76 {
77 $message = parent::display_record_info($message, $id, $data);
78
79 if (!empty($this->_taxonomies)) {
80 foreach ($this->_taxonomies as $tax => $terms) {
81 $message .= ', ' . $tax . ': (' . implode(', ', $terms) . ')';
82 }
83 }
84
85 if (!empty($this->_attachments)) {
86 $message .= sprintf(__(', Attachments: (%s)', 'jc-importer'), implode(', ', $this->_attachments));
87 }
88
89 return $message;
90 }
91
92 public function register()
93 {
94 $groups = [];
95
96 // Post
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')
100 ]),
101 $this->register_core_field(__('Title', 'jc-importer'), 'post_title', [
102 'tooltip' => __('Title of the post.', 'jc-importer')
103 ]),
104 $this->register_core_field(__('Content', 'jc-importer'), 'post_content', [
105 'tooltip' => __('Main WYSIWYG editor content of the post.', 'jc-importer')
106 ]),
107 $this->register_field(__('Excerpt', 'jc-importer'), 'post_excerpt', [
108 'tooltip' => __('A custom short extract for the post.', 'jc-importer')
109 ]),
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')
112 ]),
113 $this->register_field(__('Status', 'jc-importer'), 'post_status', [
114 'default' => 'publish',
115 'options' => [
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')]
122 ],
123 'tooltip' => __('The status of a given post determines how WordPress handles that post', 'jc-importer')
124 ]),
125 $this->register_group(__('Parent Settings', 'jc-importer'), '_parent', [
126 $this->register_field(__('Parent', 'jc-importer'), 'parent', [
127 'default' => '',
128 'options' => 'callback',
129 'tooltip' => __('Set this for the post it belongs to', 'jc-importer')
130 ]),
131 $this->register_field(__('Parent Field Type', 'jc-importer'), '_parent_type', [
132 'default' => 'id',
133 'options' => [
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')],
138 ],
139 'type' => 'select',
140 'tooltip' => __('Select how the parent field should be handled', 'jc-importer')
141 ]),
142 $this->register_field(__('Parent Reference Column', 'jc-importer'), '_parent_ref', [
143 'condition' => ['_parent_type', '==', 'column'],
144 'tooltip' => __('Select the column/node that the parent field is referencing', 'jc-importer')
145 ])
146 ]),
147 $this->register_field(__('Order', 'jc-importer'), 'menu_order', [
148 'tooltip' => __('The order the post should be displayed in', 'jc-importer')
149 ]),
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')
153 ]),
154 $this->register_field(__('Author Field Type', 'jc-importer'), '_author_type', [
155 'default' => 'id',
156 'options' => [
157 ['value' => 'id', 'label' => __('ID', 'jc-importer')],
158 ['value' => 'login', 'label' => __('Login', 'jc-importer')],
159 ['value' => 'email', 'label' => __('Email', 'jc-importer')],
160 ],
161 'tooltip' => __('Select how the author field should be handled', 'jc-importer')
162 ])
163 ]),
164 $this->register_field(__('Password', 'jc-importer'), 'post_password', [
165 'tooltip' => __('The password to access the post', 'jc-importer')
166 ]),
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')
169 ]),
170 $this->register_field(__('Allow Comments', 'jc-importer'), 'comment_status', [
171 'options' => [
172 ['value' => '0', 'label' => __('Disabled', 'jc-importer')],
173 ['value' => '1', 'label' => __('Enabled', 'jc-importer')]
174 ],
175 'default' => '0',
176 'tooltip' => __('Whether the post can accept comments', 'jc-importer')
177 ]),
178 $this->register_field(__('Allow Pingbacks', 'jc-importer'), 'ping_status', [
179 'options' => [
180 ['value' => 'closed', 'label' => __('Closed', 'jc-importer')],
181 ['value' => 'open', 'label' => __('Open', 'jc-importer')]
182 ],
183 'default' => 'closed',
184 'tooltip' => __('Whether the post can accept pings', 'jc-importer')
185 ])
186 ], ['link' => 'https://www.importwp.com/docs/wordpress-page-importer-template/']);
187
188 // Taxonomies
189 $groups[] = $this->register_taxonomy_fields();
190
191 // Attachments
192 $groups[] = $this->register_attachment_fields();
193
194 return $groups;
195 }
196
197 public function register_taxonomy_fields()
198 {
199 return $this->register_group(__('Taxonomies', 'jc-importer'), 'taxonomies', [
200 $this->register_field(__('Taxonomy', 'jc-importer'), 'tax', [
201 'default' => 'category',
202 'options' => 'callback',
203 'tooltip' => __('Select the type of taxonomy you are importing to.', 'jc-importer')
204 ]),
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')
207 ]),
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, 'link' => 'https://www.importwp.com/docs/how-to-import-wordpress-taxonomies-onto-a-post-type/']);
260 }
261
262 public function register_settings() {}
263
264 public function register_options()
265 {
266 return [];
267 }
268
269 /**
270 * Alter fields before they are parsed
271 *
272 * @param array $fields
273 * @return array
274 */
275 public function field_map($fields)
276 {
277 if ($this->importer->isEnabledField('post._parent') && $fields['post._parent._parent_type'] === 'column' && !empty($fields["post._parent._parent_ref"])) {
278 $fields['_iwp_ref_post_parent'] = $fields["post._parent._parent_ref"];
279 $this->virtual_fields[] = '_iwp_ref_post_parent';
280 }
281 return $fields;
282 }
283
284 /**
285 * Process data before record is importer.
286 *
287 * Alter data that is passed to the mapper.
288 *
289 * @param ParsedData $data
290 * @return ParsedData
291 */
292 public function pre_process(ParsedData $data)
293 {
294 $data = parent::pre_process($data);
295
296 $post_field_map = [];
297 foreach ($this->field_map as $field_id => $field_map_key) {
298 $post_field_map[$field_id] = $data->getValue($field_map_key);
299 }
300
301 // remove fields that have not been set
302 foreach ($post_field_map as $field_key => $field_map) {
303
304 if ($field_map === false) {
305 unset($post_field_map[$field_key]);
306 continue;
307 }
308 }
309
310 foreach ($this->optional_fields as $optional_field) {
311 if (true !== $this->importer->isEnabledField('post.' . $optional_field)) {
312 unset($post_field_map[$optional_field]);
313 }
314 }
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
320 if (true !== $this->importer->isEnabledField('post._parent')) {
321 unset($post_field_map['post_parent']);
322 }
323
324 if (true !== $this->importer->isEnabledField('post._author')) {
325 unset($post_field_map['post_author']);
326 }
327
328 if (!empty($this->virtual_fields)) {
329 foreach ($this->virtual_fields as $virtual_field) {
330 $value = $data->getValue($virtual_field);
331 if (false !== $value) {
332 $post_field_map[$virtual_field] = $value;
333 }
334 }
335 }
336
337 if ($this->importer->isEnabledField('post._author')) {
338 $post_author = $data->getValue('post._author.post_author');
339 $post_author_type = $data->getValue('post._author._author_type');
340
341 $user_id = 0;
342
343 if ($post_author_type === 'id') {
344
345 $user = get_user_by('ID', $post_author);
346 if ($user) {
347 $user_id = intval($user->ID);
348 }
349 } elseif ($post_author_type === 'login') {
350
351 $user = get_user_by('login', $post_author);
352 if ($user) {
353 $user_id = intval($user->ID);
354 }
355 } elseif ($post_author_type === 'email') {
356
357 $user = get_user_by('email', $post_author);
358 if ($user) {
359 $user_id = intval($user->ID);
360 }
361 }
362
363 if ($user_id > 0) {
364 $post_field_map['post_author'] = $user_id;
365 } else {
366 $post_field_map['post_author'] = '';
367 }
368 }
369
370 // post_name is a unique field, so generate slug from title if no slug present
371 // if (!isset($post_field_map['post_name']) || empty($post_field_map['post_name'])) {
372 // $post_field_map['post_name'] = sanitize_title($post_field_map['post_title']);
373
374 // // set flag to say slug has been generated
375 // $data->add(['post_name' => 'yes'], '_generated');
376 // }
377
378 if ($this->importer->isEnabledField('post._parent') && isset($post_field_map['post_parent']) && !empty($post_field_map['post_parent'])) {
379
380 $parent_id = 0;
381 $parent_field_type = $data->getValue('post._parent._parent_type');
382
383 if ($parent_field_type === 'name' || $parent_field_type === 'slug') {
384
385 // name or slug
386 $page = get_posts(array('name' => sanitize_title($post_field_map['post_parent']), 'post_type' => $this->importer->getSetting('post_type')));
387 if ($page) {
388 $parent_id = intval($page[0]->ID);
389 }
390 } elseif ($parent_field_type === 'id') {
391
392 // ID
393 $parent_id = intval($post_field_map['post_parent']);
394 } elseif ($parent_field_type === 'column') {
395
396 // reference column
397 $temp_id = $this->get_post_by_cf('post_parent', $post_field_map['post_parent']);
398 if (intval($temp_id > 0)) {
399 $parent_id = intval($temp_id);
400 }
401 }
402
403 if ($parent_id > 0) {
404 $post_field_map['post_parent'] = $parent_id;
405 }
406 }
407
408 foreach ($post_field_map as $key => $value) {
409 $post_field_map[$key] = apply_filters('iwp/template/process_field', $value, $key, $this->importer);
410 }
411
412 $data->replace($post_field_map, 'default');
413
414 return $data;
415 }
416
417 /**
418 * Find existing post/page/custom by reference field
419 *
420 * @param string $field Reference Field Name
421 * @param string $value Value to check against reference
422 *
423 * @return bool
424 */
425 public function get_post_by_cf($field, $value)
426 {
427
428 $query = new \WP_Query(array(
429 'post_type' => $this->importer->getSetting('post_type'),
430 'posts_per_page' => 1,
431 'fields' => 'ids',
432 'cache_results' => false,
433 'update_post_meta_cache' => false,
434 'meta_query' => array(
435 array(
436 'key' => '_iwp_ref_' . $field,
437 'value' => $value
438 )
439 ),
440 'post_status' => 'any, trash, future'
441 ));
442 if ($query->have_posts()) {
443 return $query->posts[0];
444 }
445 return false;
446 }
447
448 /**
449 * Process data after record is importer.
450 *
451 * Use data that is returned from the mapper.
452 *
453 * @param int $post_id
454 * @param ParsedData $data
455 * @return void
456 */
457 public function post_process($post_id, ParsedData $data)
458 {
459 /**
460 * @var Filesystem $filesystem
461 */
462 $filesystem = Container::getInstance()->get('filesystem');
463
464 /**
465 * @var Ftp $ftp
466 */
467 $ftp = Container::getInstance()->get('ftp');
468
469 /**
470 * @var Attachment $attachment
471 */
472 $attachment = Container::getInstance()->get('attachment');
473
474 $this->process_taxonomies($post_id, $data);
475 $this->process_attachments($post_id, $data, $filesystem, $ftp, $attachment);
476
477 parent::post_process($post_id, $data);
478 }
479
480 /**
481 * Process taxonomy group
482 *
483 * TODO: Possibly move this into parser?
484 *
485 * @param int $post_id
486 * @param ParsedData $data
487 * @return void
488 */
489 public function process_taxonomies($post_id, $data)
490 {
491 // reset list of taxonomies
492 $this->_taxonomies = [];
493
494 $group = 'taxonomies';
495 $taxonomes_data = $data->getData($group);
496 $total_rows = isset($taxonomes_data[$group . '._index']) ? intval($taxonomes_data[$group . '._index']) : 0;
497 $base_delimiter = apply_filters('iwp/value_delimiter', ',');
498 $base_delimiter = apply_filters('iwp/taxonomy/value_delimiter', $base_delimiter);
499
500 $processed_taxonomies = [];
501 $term_hierarchy = [];
502 $term_hierarchy_enabled = [];
503 $term_types = [];
504 $term_append = [];
505
506 // Pre-Process taxonomy data
507 for ($i = 0; $i < $total_rows; $i++) {
508
509 $prefix = $group . '.' . $i . '.';
510
511 $sub_rows = [$taxonomes_data];
512 if (isset($taxonomes_data[$prefix . 'row_base']) && !empty($taxonomes_data[$prefix . 'row_base'])) {
513 $sub_group_id = $group . '.' . $i;
514 $sub_rows = $data->getData($sub_group_id);
515 }
516
517 foreach ($sub_rows as $row) {
518 $tax = isset($row[$prefix . 'tax']) ? $row[$prefix . 'tax'] : null;
519 $terms = isset($row[$prefix . 'term']) ? $row[$prefix . 'term'] : null;
520
521 $term_append[$tax] = isset($row[$prefix . 'settings._append']) && $row[$prefix . 'settings._append'] == 'yes';
522
523 $delimiter = apply_filters('iwp/taxonomy=' . $tax . '/value_delimiter', $base_delimiter);
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
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
535 if (empty($hierarchy_character)) {
536 $hierarchy_enabled = false;
537 }
538
539 if (!is_null($tax) && !is_null($terms)) {
540 $terms = explode($delimiter, $terms);
541 foreach ($terms as $term) {
542
543 $term = trim($term);
544 $permission_key = 'taxonomy.' . $tax; //taxonomy.category | taxonomy.post_tag
545
546 if ($data->permission()) {
547 $allowed = $data->permission()->validate([$permission_key => ''], $data->getMethod(), $group);
548 $is_allowed = isset($allowed[$permission_key]) ? true : false;
549
550 if (!$is_allowed || ($term_append[$tax] == true && empty($term))) {
551 continue;
552 }
553 }
554
555 // handle taxonomies
556 if (!isset($processed_taxonomies[$tax])) {
557 $processed_taxonomies[$tax] = [];
558 }
559
560 $processed_taxonomies[$tax][] = $term;
561
562 // Handle hierarchy
563 if (!isset($term_hierarchy[$tax])) {
564 $term_hierarchy[$tax] = [];
565 }
566
567 if ($hierarchy_enabled) {
568 $hierarchy_parts = explode($hierarchy_character, $term);
569 if (count($hierarchy_parts) > 0) {
570 $hierarchy_parts = array_filter(array_map('trim', $hierarchy_parts));
571 $term_hierarchy[$tax][] = $hierarchy_parts;
572 $term_hierarchy_enabled[$tax] = true;
573 }
574 } else {
575 $term_hierarchy[$tax][] = [$term];
576 }
577 }
578 }
579 }
580 }
581
582 // TODO: Process term hierarchy
583 foreach ($term_hierarchy as $processed_tax => $term_hierarchy_list) {
584
585 // clear existing taxonomies
586 $clear_existing_terms = !isset($term_append[$processed_tax]) || !$term_append[$processed_tax];
587
588 if (empty($term_hierarchy_list)) {
589 continue;
590 }
591
592 $new_terms = [];
593
594 foreach ($term_hierarchy_list as $hierarchy_list) {
595
596 $prev_term = isset($term_hierarchy_enabled[$processed_tax]) ? 0 : null;
597 $type = $term_types[$processed_tax];
598
599 foreach ($hierarchy_list as $term_i => $term) {
600 if (!isset($this->_taxonomies[$processed_tax])) {
601 $this->_taxonomies[$processed_tax] = [];
602 }
603
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);
618 if ($term_result) {
619 $prev_term = $term_result->term_id;
620 $this->_taxonomies[$processed_tax][] = $term_result->name;
621 }
622
623 if ($connect_terms && $term_result) {
624 $new_terms[] = $term_result->term_id;
625 }
626 }
627 }
628
629 // Connect all terms in one go.
630 wp_set_object_terms($post_id, $new_terms, $processed_tax, !$clear_existing_terms);
631 }
632 }
633
634 public function create_or_get_taxonomy_term($post_id, $tax, $term, $parent, $term_type = 'name', $set = true)
635 {
636 if (!in_array($term_type, ['slug', 'name', 'term_id', 'custom_field'])) {
637 $term_type = 'name';
638 }
639
640 if (is_null($parent)) {
641
642 // we do not care about parent, just fetch first
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
665 if ($tmp_term) {
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 }
670 return $tmp_term;
671 }
672 } else {
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
710 if (!empty($terms)) {
711 foreach ($terms as $tmp_term) {
712 if (intval($tmp_term->parent) === intval($parent)) {
713
714 // attach term to post
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 }
719 return $tmp_term;
720 }
721 }
722 }
723 }
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
735 // add term
736 $term_id = wp_insert_term($term, $tax, ['parent' => $parent]);
737 if (!is_wp_error($term_id)) {
738 if ($set) {
739 wp_set_object_terms($post_id, $term_id['term_id'], $tax, true);
740 }
741 return get_term($term_id['term_id'], $tax);
742 }
743
744 return false;
745 }
746
747 /**
748 * Process attachments group
749 *
750 * TODO: Possibly move this into parser?
751 *
752 * @param int $post_id
753 * @param ParsedData $data
754 * @param Filesystem $filesystem
755 * @param FTP $ftp
756 * @param Attachment $attachment
757 * @return void
758 */
759 public function process_attachments($post_id, $data, $filesystem, $ftp, $attachment, $group = 'attachments')
760 {
761 // reset list of attachments
762 $this->_attachments = [];
763 $attachment_ids = [];
764
765 $attachment_data = $data->getData($group);
766 $total_rows = isset($attachment_data[$group . '._index']) ? intval($attachment_data[$group . '._index']) : 0;
767 $skipped = 0;
768
769 for ($i = 0; $i < $total_rows; $i++) {
770
771 $permission_key = $group . '.' . $i; //attachment.0 | attachment.1
772 if ($data->permission()) {
773 $allowed = $data->permission()->validate([$permission_key => ''], $data->getMethod(), $group);
774 $is_allowed = isset($allowed[$permission_key]) ? true : false;
775 if (!$is_allowed) {
776 $skipped++;
777 continue;
778 }
779 }
780
781 // Process Attachments
782 $row_prefix = $group . '.' . $i . '.';
783
784 $sub_rows = [$attachment_data];
785 if (isset($attachment_data[$row_prefix . 'row_base']) && !empty($attachment_data[$row_prefix . 'row_base'])) {
786 $sub_group_id = $group . '.' . $i;
787 $sub_rows = $data->getData($sub_group_id);
788 }
789
790 foreach ($sub_rows as $row) {
791
792 $row = $this->process_attachment_meta_permissions($row, $data, $group, $permission_key, $row_prefix);
793 $ids = $this->process_attachment($post_id, $row, $row_prefix, $filesystem, $ftp, $attachment);
794 $attachment_ids = array_merge($attachment_ids, $ids);
795 }
796 }
797
798 if ($skipped == $total_rows) {
799 return false;
800 }
801
802 return $attachment_ids;
803 }
804
805 /**
806 * Get list of posts
807 *
808 * @param ImporterModel $importer_model
809 *
810 * @return array
811 */
812 public function get_post_parent_options($importer_model)
813 {
814 $query = new \WP_Query(array(
815 'post_type' => $importer_model->getSetting('post_type'),
816 'posts_per_page' => -1,
817 'cache_results' => false,
818 'update_post_meta_cache' => false,
819 ));
820
821 if (is_wp_error($query)) {
822 return $query;
823 }
824
825 $result = [];
826 foreach ($query->posts as $post) {
827 $result[] = [
828 'value' => '' . $post->ID,
829 'label' => $post->post_title
830 ];
831 }
832
833 return $result;
834 }
835
836 /**
837 * Get list taxonomies
838 *
839 * @param ImporterModel $importer_model
840 *
841 * @return array
842 */
843 public function get_taxonomy_options($importer_model)
844 {
845 $taxonomies = get_object_taxonomies($importer_model->getSetting('post_type'), 'objects');
846
847 if (empty($taxonomies)) {
848 return [];
849 }
850
851 $result = [];
852 /**
853 * @var \WP_Taxonomy[] $taxonomies
854 */
855 foreach ($taxonomies as $key => $taxonomy) {
856 $result[] = [
857 'value' => '' . $key,
858 'label' => $taxonomy->label
859 ];
860 }
861
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 ];
961
962 foreach ($taxonomies as $taxonomy => $taxonomy_data) {
963 $data = [];
964
965 if (isset($taxonomy_data['map']['hierarchy::name'])) {
966 $data['term'] = $taxonomy_data['map']['hierarchy::name'];
967 $data['settings._hierarchy'] = 'yes';
968 } elseif (isset($taxonomy_data['map']['hierarchy::slug'])) {
969 $data['term'] = $taxonomy_data['map']['hierarchy::slug'];
970 $data['settings._hierarchy'] = 'yes';
971 } elseif (isset($taxonomy_data['map']['name'])) {
972 $data['term'] = $taxonomy_data['map']['name'];
973 } elseif (isset($taxonomy_data['map']['slug'])) {
974 $data['term'] = $taxonomy_data['map']['slug'];
975 } else {
976 continue;
977 }
978
979 $data['tax'] = $taxonomy;
980
981 $data = wp_parse_args($data, $defaults);
982
983 $map = array_merge($map, array_reduce(array_keys($data), function ($carry, $key) use ($data, $taxonomy_counter) {
984 $carry[sprintf('taxonomies.%d.%s', $taxonomy_counter, $key)] = $data[$key];
985 return $carry;
986 }, []));
987
988 $taxonomy_counter++;
989 }
990
991 $map['taxonomies._index'] = $taxonomy_counter;
992 }
993
994 if (!empty($attachments)) {
995
996 $attachment_counter = 0;
997 $defaults = [
998 'row_base' => '',
999 'location' => '',
1000 'settings._delimiter' => '',
1001 'settings._download' => 'remote',
1002 'settings._enable_image_hash' => 'yes',
1003 'settings._featured' => 'no',
1004 'settings._ftp_host' => '',
1005 'settings._ftp_pass' => '',
1006 'settings._ftp_path' => '',
1007 'settings._ftp_user' => '',
1008 'settings._local_url' => '',
1009 'settings._meta._alt' => '',
1010 'settings._meta._caption' => '',
1011 'settings._meta._description' => '',
1012 'settings._meta._enabled' => 'no',
1013 'settings._meta._title' => '',
1014 'settings._remote_url' => '',
1015 ];
1016
1017 foreach ($attachments as $attachment_data) {
1018
1019 $data = [];
1020
1021 if (!isset($attachment_data['map']['url'])) {
1022 continue;
1023 }
1024
1025 // location
1026 $data['location'] = $attachment_data['map']['url'];
1027
1028 if (isset($attachment_data['map']['featured'])) {
1029 $data['settings._featured'] = $attachment_data['map']['featured'];
1030 }
1031
1032 // Meta
1033 if (isset($attachment_data['map']['title'])) {
1034 $data['settings._meta._title'] = $attachment_data['map']['title'];
1035 $data['settings._meta._enabled'] = 'yes';
1036 }
1037 if (isset($attachment_data['map']['alt'])) {
1038 $data['settings._meta._alt'] = $attachment_data['map']['alt'];
1039 $data['settings._meta._enabled'] = 'yes';
1040 }
1041 if (isset($attachment_data['map']['description'])) {
1042 $data['settings._meta._description'] = $attachment_data['map']['description'];
1043 $data['settings._meta._enabled'] = 'yes';
1044 }
1045 if (isset($attachment_data['map']['caption'])) {
1046 $data['settings._meta._caption'] = $attachment_data['map']['caption'];
1047 $data['settings._meta._enabled'] = 'yes';
1048 }
1049
1050 $data = wp_parse_args($data, $defaults);
1051
1052 $map = array_merge($map, array_reduce(array_keys($data), function ($carry, $key) use ($data, $attachment_counter) {
1053 $carry[sprintf('attachments.%d.%s', $attachment_counter, $key)] = $data[$key];
1054 return $carry;
1055 }, []));
1056
1057 $attachment_counter++;
1058 }
1059
1060 $map['attachments._index'] = $attachment_counter;
1061 }
1062
1063 if (!empty($author)) {
1064
1065 // TODO: enable field? this is a seperate field list
1066 $enabled_key = 'post._author';
1067 if (isset($author['map']['user_email'])) {
1068
1069 $enabled[] = $enabled_key;
1070 $map['post._author.post_author'] = $author['map']['user_email'];
1071 $map['post._author._author_type'] = 'email';
1072 } elseif (isset($author['map']['user_login'])) {
1073
1074 $enabled[] = $enabled_key;
1075 $map['post._author.post_author'] = $author['map']['user_login'];
1076 $map['post._author._author_type'] = 'login';
1077 } elseif (isset($author['map']['ID'])) {
1078
1079 $enabled[] = $enabled_key;
1080 $map['post._author.post_author'] = $author['map']['ID'];
1081 $map['post._author._author_type'] = 'id';
1082 }
1083 }
1084
1085 if (!empty($parent)) {
1086
1087 // parent.id,parent.name,parent.slug
1088 $enabled_key = 'post._parent';
1089 if (isset($parent['map']['name'])) {
1090
1091 $enabled[] = $enabled_key;
1092 $map['post._parent.parent'] = $parent['map']['name'];
1093 $map['post._parent.parent._enable_text'] = 'yes';
1094 $map['post._parent._parent_type'] = 'name';
1095 } elseif (isset($parent['map']['slug'])) {
1096
1097 $enabled[] = $enabled_key;
1098 $map['post._parent.parent'] = $parent['map']['slug'];
1099 $map['post._parent.parent._enable_text'] = 'yes';
1100 $map['post._parent._parent_type'] = 'slug';
1101 } elseif (isset($parent['map']['id'])) {
1102
1103 $enabled[] = $enabled_key;
1104 $map['post._parent.parent'] = $parent['map']['name'];
1105 $map['post._parent.parent._enable_text'] = 'yes';
1106 $map['post._parent._parent_type'] = 'id';
1107 }
1108 }
1109
1110 return [
1111 'map' => $map,
1112 'enabled' => $enabled
1113 ];
1114 }
1115
1116 public function get_permission_fields($importer_model)
1117 {
1118 $permission_fields = parent::get_permission_fields($importer_model);
1119
1120 $permission_fields['core'] = [
1121 'ID' => __('ID', 'jc-importer'),
1122 'post_title' => __('Title', 'jc-importer'),
1123 'post_content' => __('Content', 'jc-importer'),
1124 'post_excerpt' => __('Excerpt', 'jc-importer'),
1125 'post_name' => __('Slug', 'jc-importer'),
1126 'post_status' => __('Post Status', 'jc-importer'),
1127 'menu_order' => __('Menu order', 'jc-importer'),
1128 'post_password' => __('password', 'jc-importer'),
1129 'post_date' => __('Date', 'jc-importer'),
1130 'comment_status' => __('Comment Status', 'jc-importer'),
1131 'ping_status' => __('Ping Status', 'jc-importer'),
1132 'post_parent' => __('Parent', 'jc-importer'),
1133 'post_author' => __('Author', 'jc-importer'),
1134 ];
1135
1136 $permission_fields['taxonomies'] = [];
1137 $taxonomies = $this->get_taxonomy_options($importer_model);
1138 foreach ($taxonomies as $taxonomy) {
1139 $permission_fields['taxonomies']['taxonomy.' . $taxonomy['value']] = $taxonomy['label'];
1140 }
1141
1142 $field_map = $importer_model->getMap();
1143 if (isset($field_map['attachments._index']) && $field_map['attachments._index'] > 0) {
1144 $permission_fields['attachments'] = [];
1145 for ($i = 0; $i < $field_map['attachments._index']; $i++) {
1146 $permission_fields['attachments']['attachments.' . $i] = 'Attachment Row ' . ($i + 1);
1147
1148 // Meta fields
1149 $permission_fields['attachments']['attachments.' . $i . '._alt'] = 'Attachment Row ' . ($i + 1) . ' - Alt Text';
1150 $permission_fields['attachments']['attachments.' . $i . '._title'] = 'Attachment Row ' . ($i + 1) . ' - Title Text';
1151 $permission_fields['attachments']['attachments.' . $i . '._caption'] = 'Attachment Row ' . ($i + 1) . ' - Caption Text';
1152 $permission_fields['attachments']['attachments.' . $i . '._description'] = 'Attachment Row ' . ($i + 1) . ' - Description Text';
1153 }
1154 }
1155
1156 return $permission_fields;
1157 }
1158
1159 public function get_unique_identifier_options($importer_model, $unique_fields = [])
1160 {
1161 $output = parent::get_unique_identifier_options($importer_model, $unique_fields);
1162
1163 return array_merge(
1164 $output,
1165 $this->get_unique_identifier_options_from_map($importer_model, $unique_fields, $this->field_map, $this->optional_fields)
1166 );
1167 }
1168 }
1169