PluginProbe
Import WP – CSV & XML Import Export for WordPress / 2.14.24
Import WP – CSV & XML Import Export for WordPress v2.14.24
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 / Template.php

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

1,213 lines 44.3 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\File\XMLFile;
9 use ImportWP\Common\Importer\Mapper\AbstractMapper;
10 use ImportWP\Common\Importer\ParsedData;
11 use ImportWP\Common\Model\ImporterModel;
12 use ImportWP\Common\Util\Logger;
13 use ImportWP\Container;
14 use ImportWP\EventHandler;
15
16 class Template extends AbstractTemplate
17 {
18 /**
19 * Template name
20 *
21 * @var string
22 */
23 protected $name;
24 /**
25 * Mapper name
26 *
27 * @var string
28 */
29 protected $mapper;
30 /**
31 * @var ImporterModel
32 */
33 protected $importer;
34
35 /**
36 * Registered data groups
37 *
38 * @var string[]
39 */
40 protected $groups;
41
42 /**
43 * List of field option callbacks
44 *
45 * @var array
46 */
47 protected $field_options = [];
48
49 protected $default_template_options = [];
50
51 /**
52 *
53 * List of optional fields that are enabled by default
54 * @var string[]
55 */
56 protected $default_enabled_fields = [];
57
58 /**
59 * @var \WP_Error[] $errors
60 */
61 protected $errors = [];
62
63 /**
64 * @var EventHandler $event_handler
65 */
66 private $event_handler;
67
68 /**
69 * @var boolean
70 */
71 private $featured_set = false;
72
73 public function __construct(EventHandler $event_handler)
74 {
75 $this->event_handler = $event_handler;
76 $this->event_handler->run('template.init', [$this]);
77
78 $this->groups = $this->event_handler->run('template.data_groups', [$this->groups, $this]);
79
80 // Register field options callbacks
81 $this->field_options = [
82 '*.row_base' => [$this, 'get_row_base']
83 ];
84 $this->field_options = $this->event_handler->run('template.field_option_callbacks', [$this->field_options, $this]);
85 }
86
87 /**
88 * Get xml record base
89 *
90 * @param ImporterModel $importer_model
91 * @return array
92 */
93 public function get_row_base($importer_model)
94 {
95 /**
96 * @var ImporterManager $importer_manager
97 */
98 $importer_manager = Container::getInstance()->get('importer_manager');
99 $tmp = false;
100 $results = [];
101
102 if ($importer_model->getParser() !== 'xml') {
103 return $results;
104 }
105
106 $base_path = $importer_model->getFileSetting('base_path');
107 $nodes = $importer_model->getFileSetting('nodes');
108
109 $config = $importer_manager->get_config($importer_model->getId(), $tmp);
110
111 $filePath = $importer_model->getFile();
112 $file = new XMLFile($filePath, $config);
113 $file->setRecordPath($base_path);
114 $nodes = $file->get_node_list();
115
116 foreach ($nodes as $node) {
117 if (strpos($node, $base_path) !== 0) {
118 continue;
119 }
120
121 $sub_node = substr($node, strlen($base_path));
122
123 $results[] = [
124 'value' => $sub_node,
125 'label' => $sub_node
126 ];
127 }
128
129 return $results;
130 }
131
132 public function get_name()
133 {
134 return $this->name;
135 }
136
137 public function get_mapper()
138 {
139 return $this->mapper;
140 }
141
142 public function get_importer()
143 {
144 return $this->importer;
145 }
146
147 public function get_fields(ImporterModel $importer = null)
148 {
149 $fields = $this->register();
150 $fields = $this->event_handler->run('template.fields', [$fields, $this, $importer]);
151 return $fields;
152 }
153
154 public function register()
155 {
156 return [];
157 }
158
159 public function register_hooks(ImporterModel $importer)
160 {
161 $this->importer = $importer;
162
163 add_filter('iwp/importer/before_mapper', array($this, 'pre_process'));
164 add_filter('iwp/status/record_inserted', [$this, 'display_record_info'], 10, 3);
165 add_filter('iwp/status/record_updated', [$this, 'display_record_info'], 10, 3);
166 }
167
168 public function unregister_hooks()
169 {
170 remove_filter('iwp/importer/before_mapper', array($this, 'pre_process'));
171 remove_filter('iwp/status/record_inserted', [$this, 'display_record_info'], 10, 3);
172 remove_filter('iwp/status/record_updated', [$this, 'display_record_info'], 10, 3);
173 }
174
175 /**
176 * @param string $message
177 * @param int $id
178 * @param ParsedData $data
179 * @return $string
180 */
181 public function display_record_info($message, $id, $data)
182 {
183
184 $fields = $data->getData();
185 if (!empty($fields)) {
186 $message .= ' (' . implode(', ', array_keys($fields)) . ')';
187 }
188
189 if (!empty($this->errors)) {
190 $errors = [];
191 foreach ($this->errors as $error) {
192 $errors[] = $error->get_error_message();
193 }
194
195 $message .= ', Errors: (' . implode(', ', $errors) . ')';
196 }
197
198 $this->errors = [];
199
200 return $message;
201 }
202
203 public function register_group($label, $key, $fields, $args = [])
204 {
205 if (isset($args['row_base']) && true === $args['row_base']) {
206
207 $fields = array_merge(
208 [$this->register_field(__('Repeater Node', 'jc-importer'), 'row_base', [
209 'type' => 'text',
210 'options' => 'callback',
211 'tooltip' => __('Select the path to the parent node containing values for this record, The preview when selecting data for each record should show a single record. Please note changing this will require updating references in this record.', 'jc-importer')
212 ])],
213 $fields
214 );
215 }
216
217 $tmp = [
218 'id' => $key,
219 'heading' => $label,
220 'type' => isset($args['type']) ? $args['type'] : 'group',
221 'fields' => $fields,
222 ];
223
224 if (isset($args['link']) && !empty($args['link'])) {
225 $tmp['link'] = $args['link'];
226 }
227
228 if (isset($args['condition']) && !empty($args['condition'])) {
229 $tmp['condition'] = $args['condition'];
230 }
231
232 // Allow for setting fields to be registered for the group
233 // currently only supporting toggle fields.
234 if (isset($args['settings']) && !empty($args['settings'])) {
235 $tmp['settings'] = $args['settings'];
236 }
237
238 return $tmp;
239 }
240
241 public function register_core_field($label, $key, $args = [])
242 {
243 $args['core'] = true;
244 return $this->register_field($label, $key, $args);
245 }
246
247 public function register_field($label, $key, $args = [])
248 {
249 $data = [
250 'id' => $key,
251 'label' => $label,
252 'type' => isset($args['type']) ? $args['type'] : 'field',
253 'core' => isset($args['core']) ? $args['core'] : false,
254 'tooltip' => isset($args['tooltip']) ? $args['tooltip'] : false
255 ];
256
257 if (isset($args['options'])) {
258 $data['options'] = $args['options'];
259 }
260
261 if (isset($args['default'])) {
262 $data['default'] = $args['default'];
263 }
264
265 if (isset($args['condition'])) {
266 $data['condition'] = $args['condition'];
267 }
268
269 return $data;
270 }
271
272 public function _register_attachment_setting_fields($display_conditions = [], $extra_fields = [], $disabled_fields = [])
273 {
274
275 $fields = [];
276
277 if (!in_array('_featured', $disabled_fields)) {
278 $fields[] = $this->register_field(__('Is Featured?', 'jc-importer'), '_featured', [
279 'default' => 'no',
280 'options' => [
281 ['value' => 'no', 'label' => __('No', 'jc-importer')],
282 ['value' => 'yes', 'label' => __('Yes', 'jc-importer')],
283 ],
284 'tooltip' => __('Is the attachment the featured image for the current post.', 'jc-importer')
285 ]);
286 }
287
288 $fields = array_merge($fields, [
289 $this->register_field(__('Download', 'jc-importer'), '_download', [
290 'default' => 'remote',
291 'options' => [
292 ['value' => 'remote', 'label' => __('Remote URL', 'jc-importer')],
293 ['value' => 'ftp', 'label' => __('FTP', 'jc-importer')],
294 ['value' => 'local', 'label' => __('Local Filesystem', 'jc-importer')],
295 ['value' => 'media', 'label' => __('Media Library', 'jc-importer')],
296 ],
297 'tooltip' => __('Select how the attachment is being downloaded.', 'jc-importer')
298 ]),
299 $this->register_field(__('Host', 'jc-importer'), '_ftp_host', [
300 'condition' => ['_download', '==', 'ftp'],
301 'tooltip' => __('Enter the FTP hostname', 'jc-importer')
302 ]),
303 $this->register_field(__('Username', 'jc-importer'), '_ftp_user', [
304 'condition' => ['_download', '==', 'ftp'],
305 'tooltip' => __('Enter the FTP username', 'jc-importer')
306 ]),
307 $this->register_field(__('Password', 'jc-importer'), '_ftp_pass', [
308 'condition' => ['_download', '==', 'ftp'],
309 'tooltip' => __('Enter the FTP password', 'jc-importer')
310 ]),
311 $this->register_field(__('Path', 'jc-importer'), '_ftp_path', [
312 'condition' => ['_download', '==', 'ftp'],
313 'tooltip' => __('Enter the FTP base path, this is prefixed onto the Location field, leave empty to be ignore', 'jc-importer')
314 ]),
315 $this->register_field(__('Base URL', 'jc-importer'), '_remote_url', [
316 'condition' => ['_download', '==', 'remote'],
317 'tooltip' => __('Enter the base url, this is prefixed onto the Location field, leave empty to be ignore', 'jc-importer')
318 ]),
319 $this->register_field(__('Base URL', 'jc-importer'), '_local_url', [
320 'condition' => ['_download', '==', 'local'],
321 'tooltip' => __('Enter the base path from this servers root file system, this is prefixed onto the Location field, leave empty to be ignore', 'jc-importer')
322 ]),
323
324 $this->register_field(__('Permissions', 'jc-importer'), '_enable_image_hash', [
325 'condition' => ['_download', '!=', 'media'],
326 'default' => 'yes',
327 'options' => [
328 ['value' => 'no', 'label' => __('Always download new files', 'jc-importer')],
329 ['value' => 'yes', 'label' => __('Search media library before downloading new files', 'jc-importer')],
330 ],
331 'tooltip' => __('Enable to stop duplicate images by searching the media library before downloading new files.', 'jc-importer')
332 ]),
333 $this->register_field(__('Delimiter', 'jc-importer'), '_delimiter', [
334 'type' => 'text',
335 'tooltip' => sprintf(__('A single character used to seperate attachments when listing multiple, Leave empty to use the default: %s', 'jc-importer'), ',')
336 ]),
337
338 ]);
339
340 if (!in_array('_meta', $disabled_fields)) {
341 $fields[] = $this->register_group(__('Attachment Meta', 'jc-importer'), '_meta', [
342 $this->register_field(__('Enable Meta', 'jc-importer'), '_enabled', [
343 'default' => 'no',
344 'options' => [
345 ['value' => 'no', 'label' => __('No', 'jc-importer')],
346 ['value' => 'yes', 'label' => __('Yes', 'jc-importer')],
347 ],
348 'type' => 'select',
349 'tooltip' => __('Enable/Disable the fields to import attachment meta data.', 'jc-importer')
350 ]),
351 $this->register_field(__('Alt Text', 'jc-importer'), '_alt', [
352 'condition' => ['_enabled', '==', 'yes'],
353 'tooltip' => __('Image attachment alt text.', 'jc-importer'),
354 ]),
355 $this->register_field(__('Title Text', 'jc-importer'), '_title', [
356 'condition' => ['_enabled', '==', 'yes'],
357 'tooltip' => __('Attachments title text.', 'jc-importer')
358 ]),
359 $this->register_field(__('Caption Text', 'jc-importer'), '_caption', [
360 'condition' => ['_enabled', '==', 'yes'],
361 'tooltip' => __('Image attachments caption text.', 'jc-importer')
362 ]),
363 $this->register_field(__('Description Text', 'jc-importer'), '_description', [
364 'condition' => ['_enabled', '==', 'yes'],
365 'tooltip' => __('Attachments description text.', 'jc-importer')
366 ])
367 ]);
368 }
369
370 return $this->register_group(__('Settings', 'jc-importer'), 'settings', array_merge($extra_fields, $fields), ['type' => 'settings', 'condition' => $display_conditions]);
371 }
372
373 public function register_attachment_fields($label = 'Images & Attachments', $name = 'attachments', $field_label = 'Location', $group_args = null, $attachment_args = [])
374 {
375 if (is_null($group_args)) {
376 $group_args = ['type' => 'repeatable', 'row_base' => true, 'link' => 'https://www.importwp.com/docs/how-to-import-wordpress-attachments-onto-a-post-type/'];
377 }
378
379 $display_conditions = isset($attachment_args['conditions']) ? $attachment_args['conditions'] : [];
380 $extra_fields = isset($attachment_args['extra_fields']) ? $attachment_args['extra_fields'] : [];
381 $disabled_fields = isset($attachment_args['disabled_fields']) ? $attachment_args['disabled_fields'] : [];
382
383 return $this->register_group($label, $name, [
384 $this->register_field($field_label, 'location', [
385 'tooltip' => __('The source location of the file being attached.', 'jc-importer')
386 ]),
387 $this->_register_attachment_setting_fields($display_conditions, $extra_fields, $disabled_fields)
388 ], $group_args);
389 }
390
391 public function get_field_options($field_name, $id)
392 {
393 $callback = false;
394 foreach ($this->field_options as $callback_field_name => $temp_callback) {
395 if (strpos($callback_field_name, '*') !== false) {
396
397 $callback_field_name = str_replace('.', '\.', $callback_field_name);
398
399 $pattern = str_replace('*', '[\S]+', $callback_field_name);
400 if (1 !== preg_match("/^{$pattern}/i", $field_name)) {
401 continue;
402 }
403
404 $callback = $temp_callback;
405 break;
406 }
407
408 if ($field_name !== $callback_field_name) {
409 continue;
410 }
411
412 $callback = $temp_callback;
413 break;
414 }
415
416 if (!$callback) {
417 return false;
418 }
419
420 if (!method_exists($callback[0], $callback[1])) {
421 return false;
422 }
423
424 if (!is_callable($callback)) {
425 return false;
426 }
427
428 return call_user_func_array($callback, [$id]);
429 }
430
431 public function get_default_template_options()
432 {
433 return $this->default_template_options;
434 }
435
436 /**
437 * Alter fields before they are parsed
438 *
439 * @param array $fields
440 * @return array
441 */
442 public function field_map($fields)
443 {
444 return $fields;
445 }
446
447 public function config_field_map($field_map)
448 {
449 $template_fields = $this->field_map($field_map);
450
451 $field_groups = [
452 'default' => [
453 'id' => 'default',
454 'fields' => []
455 ]
456 ];
457
458 foreach ($template_fields as $key => $value) {
459
460 if (empty($value) || preg_match('/\.row_base$/', $key) !== 1) {
461 continue;
462 }
463
464 $group_id = substr($key, 0, strlen($key) - strlen('.row_base'));
465
466 $field_groups[$group_id] = [
467 'id' => $group_id,
468 'base' => $value,
469 'fields' => []
470 ];
471 }
472
473 foreach ($template_fields as $field_id => $field_value) {
474
475 $found = false;
476
477 foreach ($field_groups as $group_prefix => $group_settings) {
478 if (false === strpos($field_id, $group_prefix) || preg_match('/\.row_base$/', $field_id) === 1) {
479 continue;
480 }
481
482 $field_groups[$group_prefix]['fields'][$field_id] = $field_value;
483 $found = true;
484 }
485
486 if (false === $found) {
487 $field_groups['default']['fields'][$field_id] = $field_value;
488 }
489 }
490
491 if ($this->importer->has_custom_unique_identifier()) {
492
493 $ref = $this->importer->getSetting('unique_identifier_ref');
494
495 $field_groups['iwp'] = [
496 'id' => 'iwp',
497 'fields' => [
498 $this->importer->get_iwp_reference_meta_key() => (!is_null($ref) ? $ref : '')
499 ]
500 ];
501 }
502
503 return $field_groups;
504 }
505
506 /**
507 * Process data before record is importer.
508 *
509 * Alter data that is passed to the mapper.
510 *
511 * @param ParsedData $data
512 * @return ParsedData
513 */
514 public function pre_process(ParsedData $data)
515 {
516 $data = $this->pre_process_groups($data);
517 $this->event_handler->run('template.pre_process', [$data, $this->importer, $this]);
518 return $data;
519 }
520
521 public function process($post_id, ParsedData $data, ImporterModel $importer_model)
522 {
523 $this->featured_set = false;
524 $this->event_handler->run('template.process', [$post_id, $data, $importer_model, $this]);
525 }
526
527 /**
528 * Process data after record is importer.
529 *
530 * Use data that is returned from the mapper.
531 *
532 * @param int $post_id
533 * @param ParsedData $data
534 * @return void
535 */
536 public function post_process($post_id, ParsedData $data)
537 {
538 $this->event_handler->run('template.post_process', [$post_id, $data, $this]);
539 }
540
541 public function pre_process_groups(ParsedData $data)
542 {
543 // Allows virtual groups to be registered
544 $this->groups = $this->event_handler->run('template.pre_process_groups', [$this->groups, $data, $this]);
545
546 if (is_array($this->groups) && !empty($this->groups)) {
547 $map = $data->getData('default');
548 foreach ($this->groups as $group) {
549 $group_map = [];
550
551 foreach ($map as $field_key => $fields_map) {
552 if (preg_match('/^' . $group . '\.(.*?)$/', $field_key) === 1) {
553 $group_map[$field_key] = $fields_map;
554 }
555 }
556
557 $data->replace($group_map, $group);
558 }
559 }
560
561 return $data;
562 }
563
564 /**
565 * Process attachment fields
566 *
567 * @param int $post_id
568 * @param array $row
569 * @param string $row_prefix
570 * @param Filesystem $filesystem
571 * @param Ftp $ftp
572 * @param Attachment $attachment
573 */
574 public function process_attachment($post_id, $row, $row_prefix, $filesystem, $ftp, $attachment)
575 {
576 $delimiter = apply_filters('iwp/value_delimiter', ',');
577 $delimiter = apply_filters('iwp/attachment/value_delimiter', $delimiter);
578
579 if (isset($row[$row_prefix . 'settings._delimiter'])) {
580
581 if (strlen(trim($row[$row_prefix . 'settings._delimiter'])) === 1) {
582 $delimiter = trim($row[$row_prefix . 'settings._delimiter']);
583 }
584 } elseif (isset($row[$row_prefix . '_delimiter'])) {
585
586 if (strlen(trim($row[$row_prefix . '_delimiter'])) === 1) {
587 $delimiter = trim($row[$row_prefix . '_delimiter']);
588 }
589 }
590
591 $meta_delimiter = apply_filters('iwp/attachment/meta_delimiter', $delimiter);
592
593 $locations = isset($row[$row_prefix . 'location']) ? $row[$row_prefix . 'location'] : null;
594 $location_parts = explode($delimiter, $locations);
595 $location_parts = array_filter(array_map('trim', $location_parts));
596
597 if (isset($row[$row_prefix . 'settings._meta._title'])) {
598 $attachment_titles = explode($meta_delimiter, $row[$row_prefix . 'settings._meta._title']);
599 } elseif ($row[$row_prefix . '_meta._title']) {
600 $attachment_titles = explode($meta_delimiter, $row[$row_prefix . '_meta._title']);
601 } else {
602 $attachment_titles = null;
603 }
604
605 if (isset($row[$row_prefix . 'settings._meta._alt'])) {
606 $attachment_alts = explode($meta_delimiter, $row[$row_prefix . 'settings._meta._alt']);
607 } elseif (isset($row[$row_prefix . '_meta._alt'])) {
608 $attachment_alts = explode($meta_delimiter, $row[$row_prefix . '_meta._alt']);
609 } else {
610 $attachment_alts = null;
611 }
612
613 if (isset($row[$row_prefix . 'settings._meta._caption'])) {
614 $attachment_captions = explode($meta_delimiter, $row[$row_prefix . 'settings._meta._caption']);
615 } elseif (isset($row[$row_prefix . '_meta._caption'])) {
616 $attachment_captions = explode($meta_delimiter, $row[$row_prefix . '_meta._caption']);
617 } else {
618 $attachment_captions = null;
619 }
620
621 if (isset($row[$row_prefix . 'settings._meta._description'])) {
622 $attachment_descriptions = explode($meta_delimiter, $row[$row_prefix . 'settings._meta._description']);
623 } elseif (isset($row[$row_prefix . '_meta._description'])) {
624 $attachment_descriptions = explode($meta_delimiter, $row[$row_prefix . '_meta._description']);
625 } else {
626 $attachment_descriptions = null;
627 }
628
629 if (isset($row[$row_prefix . 'settings._enable_image_hash'])) {
630 $attachment_enable_image_hash = $row[$row_prefix . 'settings._enable_image_hash'];
631 } elseif (isset($row[$row_prefix . '_enable_image_hash'])) {
632 $attachment_enable_image_hash = $row[$row_prefix . '_enable_image_hash'];
633 } else {
634 $attachment_enable_image_hash = 'yes';
635 }
636
637 $attachment_ids = [];
638 $location_counter = 0;
639 foreach ($location_parts as $location) {
640
641 if (empty($location)) {
642 continue;
643 }
644
645 if (isset($row[$row_prefix . 'settings._download'])) {
646 $download = $row[$row_prefix . 'settings._download'];
647 } elseif (isset($row[$row_prefix . '_download'])) {
648 $download = $row[$row_prefix . '_download'];
649 } else {
650 $download = null;
651 }
652
653 if (isset($row[$row_prefix . 'settings._featured'])) {
654 $featured = $row[$row_prefix . 'settings._featured'];
655 } elseif (isset($row[$row_prefix . '_featured'])) {
656 $featured = $row[$row_prefix . '_featured'];
657 } else {
658 $featured = null;
659 }
660
661
662 $source = null;
663 $result = false;
664 $attachment_id = null;
665 $attachment_salt = '';
666
667 $location = trim($location);
668
669 switch ($download) {
670 case 'remote':
671
672 if (isset($row[$row_prefix . 'settings._remote_url'])) {
673 $base_url = $row[$row_prefix . 'settings._remote_url'];
674 } elseif (isset($row[$row_prefix . '_remote_url'])) {
675 $base_url = $row[$row_prefix . '_remote_url'];
676 } else {
677 $base_url = null;
678 }
679
680 // check if file hash is already stored
681 $source = $base_url . $location;
682 if (empty($source)) {
683 continue 2;
684 }
685
686
687 $attachment_salt = file_exists($source) ? md5_file($source) : '';
688 $attachment_id = 0;
689 if ($attachment_enable_image_hash == 'yes') {
690 $attachment_id = $attachment->get_attachment_by_hash($source);
691 }
692
693 // check to see if remote url matches file existing in media library
694 if ($attachment_id <= 0) {
695 $dir = wp_get_upload_dir();
696 if (str_starts_with($source, $dir['baseurl'] . '/')) {
697 $attachment_id = attachment_url_to_postid($source);
698 }
699 }
700
701 if ($attachment_id <= 0) {
702
703 $main_zip_file = false;
704 if ($base_url === 'iwp_zip') {
705 $main_zip = get_post_meta($this->importer->getId(), '_iwp_zip', true);
706 if ($main_zip && file_exists($main_zip)) {
707 $base_url .= '://' . $main_zip;
708 $main_zip_file = $main_zip;
709 }
710 }
711
712 $zip = $this->get_zip_source($base_url, $filesystem);
713 if ($zip !== false) {
714
715 if (!$main_zip_file && isset($zip['src'])) {
716
717 /**
718 * @var \ImportWP\Common\Http\Http $http
719 */
720 $http = Container::getInstance()->get('http');
721 $result = $http->download_file($zip['src'], $zip['name']);
722 if (is_wp_error($result)) {
723 break;
724 }
725
726 if (!$result) {
727 $result = new \WP_Error('IWP_HTTP_2', __('Error downloading zip file', 'jc-importer'));
728 break;
729 }
730 }
731
732 $result = $this->get_file_from_zip($main_zip_file ? $main_zip_file : $zip['name'], $location, $filesystem);
733 if (!$result) {
734 continue 2;
735 }
736
737 break;
738 }
739 }
740
741 if (apply_filters('iwp/template/process_attachment/enable_file_size_hash', false) === true) {
742
743 // check to see if the remote url image is the same size as the one on disk.
744 if ($attachment_id > 0 && $attachment_enable_image_hash == 'yes') {
745
746 $existing_file = get_attached_file($attachment_id, true);
747
748 // Remove -scaled from the file name if it exists
749 if ($existing_file && file_exists($existing_file)) {
750 $existing_file = str_replace('-scaled.', '.', $existing_file);
751 }
752
753 if ($existing_file && file_exists($existing_file)) {
754 $head = wp_remote_head($source);
755 if (!is_wp_error($head)) {
756
757 // get file size from the header
758 $header_key = apply_filters('iwp/template/process_attachment/remote_file_size_header_key', 'content-length');
759 $size = wp_remote_retrieve_header($head, $header_key);
760 $existing_file_size = filesize($existing_file);
761
762 if ($size != $existing_file_size) {
763
764 // append the size to the attachment salt
765 $attachment_salt .= $size;
766 $attachment_id = $attachment->get_attachment_by_hash($source, $attachment_salt);
767 }
768 }
769 }
770 }
771 }
772
773 $custom_filename = apply_filters('iwp/attachment/filename', null, $source);
774 if ($attachment_id <= 0) {
775 Logger::write(__CLASS__ . '::process__attachments -remote=' . $source . ' -filename=' . $custom_filename);
776 $result = $filesystem->download_file($source, null, null, $custom_filename);
777 }
778 break;
779 case 'ftp':
780
781 if (isset($row[$row_prefix . 'settings._ftp_user'])) {
782 $ftp_user = $row[$row_prefix . 'settings._ftp_user'];
783 } elseif (isset($row[$row_prefix . '_ftp_user'])) {
784 $ftp_user = $row[$row_prefix . '_ftp_user'];
785 } else {
786 $ftp_user = null;
787 }
788
789 if (isset($row[$row_prefix . 'settings._ftp_host'])) {
790 $ftp_host = $row[$row_prefix . 'settings._ftp_host'];
791 } elseif (isset($row[$row_prefix . '_ftp_host'])) {
792 $ftp_host = $row[$row_prefix . '_ftp_host'];
793 } else {
794 $ftp_host = null;
795 }
796
797 if (isset($row[$row_prefix . 'settings._ftp_pass'])) {
798 $ftp_pass = $row[$row_prefix . 'settings._ftp_pass'];
799 } elseif (isset($row[$row_prefix . '_ftp_pass'])) {
800 $ftp_pass = $row[$row_prefix . '_ftp_pass'];
801 } else {
802 $ftp_pass = null;
803 }
804
805 if (isset($row[$row_prefix . 'settings._ftp_path'])) {
806 $base_url = $row[$row_prefix . 'settings._ftp_path'];
807 } elseif (isset($row[$row_prefix . '_ftp_path'])) {
808 $base_url = $row[$row_prefix . '_ftp_path'];
809 } else {
810 $base_url = null;
811 }
812
813 // check if file hash is already stored
814 $source = $base_url . $location;
815 if (empty($source)) {
816 continue 2;
817 }
818
819 $attachment_salt = file_exists($source) ? md5_file($source) : '';
820 $attachment_id = 0;
821 if ($attachment_enable_image_hash == 'yes') {
822 $attachment_id = $attachment->get_attachment_by_hash($source, $attachment_salt);
823 }
824
825 if ($attachment_id <= 0) {
826
827 $main_zip_file = false;
828 if ($base_url === 'iwp_zip') {
829 $main_zip = get_post_meta($this->importer->getId(), '_iwp_zip', true);
830 if ($main_zip && file_exists($main_zip)) {
831 $base_url .= '://' . $main_zip;
832 $main_zip_file = $main_zip;
833 }
834 }
835
836 $zip = $this->get_zip_source($base_url, $filesystem);
837 if ($zip !== false) {
838
839 if (!$main_zip_file && isset($zip['src'])) {
840 $result = $ftp->download_file($zip['src'], $ftp_host, $ftp_user, $ftp_pass, $zip['name']);
841 if (is_wp_error($result)) {
842 break;
843 }
844 }
845
846 $result = $this->get_file_from_zip($main_zip_file ? $main_zip_file : $zip['name'], $location, $filesystem);
847 if (!$result) {
848 continue 2;
849 }
850
851 break;
852 }
853 }
854
855 $custom_filename = apply_filters('iwp/attachment/filename', null, $source);
856 if ($attachment_id <= 0) {
857 Logger::write(__CLASS__ . '::process__attachments -ftp=' . $source . ' -filename=' . $custom_filename);
858 $result = $ftp->download_file($source, $ftp_host, $ftp_user, $ftp_pass, $custom_filename);
859 }
860 break;
861 case 'local':
862
863 if (isset($row[$row_prefix . 'settings._local_url'])) {
864 $base_url = $row[$row_prefix . 'settings._local_url'];
865 } elseif (isset($row[$row_prefix . '_local_url'])) {
866 $base_url = $row[$row_prefix . '_local_url'];
867 } else {
868 $base_url = null;
869 }
870
871 // check if file hash is already stored
872 $source = $base_url . $location;
873 if (empty($source)) {
874 continue 2;
875 }
876
877 $attachment_salt = file_exists($source) ? md5_file($source) : '';
878 $attachment_id = 0;
879 if ($attachment_enable_image_hash == 'yes') {
880 $attachment_id = $attachment->get_attachment_by_hash($source, $attachment_salt);
881 }
882
883 if ($attachment_id <= 0) {
884
885 $main_zip_file = false;
886 if ($base_url === 'iwp_zip') {
887 $main_zip = get_post_meta($this->importer->getId(), '_iwp_zip', true);
888 if ($main_zip && file_exists($main_zip)) {
889 $base_url .= '://' . $main_zip;
890 $main_zip_file = $main_zip;
891 }
892 }
893
894 $zip = $this->get_zip_source($base_url, $filesystem);
895 if ($zip !== false) {
896
897 if (!$main_zip_file && isset($zip['src'])) {
898 $result = $filesystem->copy($zip['src'], $zip['name']);
899 if (is_wp_error($result)) {
900 break;
901 }
902 }
903
904 $result = $this->get_file_from_zip($main_zip_file ? $main_zip_file : $zip['name'], $location, $filesystem);
905 if (!$result) {
906 continue 2;
907 }
908
909 break;
910 }
911 }
912
913 $custom_filename = apply_filters('iwp/attachment/filename', null, $source);
914 if ($attachment_id <= 0) {
915 Logger::write(__CLASS__ . '::process__attachments -local=' . $source . ' -filename=' . $custom_filename);
916 $result = $filesystem->copy_file($source, null, $custom_filename);
917 }
918 break;
919 case 'media':
920 $source = $location;
921 if (empty($source)) {
922 continue 2;
923 }
924
925 $attachment_id = $attachment->attachment_partial_url_to_postid($source);
926 Logger::write(__CLASS__ . '::process__attachments -media=' . $source);
927
928 break;
929 }
930
931 if (isset($row[$row_prefix . 'settings._meta._enabled'])) {
932 $meta_enabled = $row[$row_prefix . 'settings._meta._enabled'] === 'yes' ? true : false;
933 } elseif (isset($row[$row_prefix . '_meta._enabled'])) {
934 $meta_enabled = $row[$row_prefix . '_meta._enabled'] === 'yes' ? true : false;
935 } else {
936 $meta_enabled = false;
937 }
938
939 // insert attachment
940 if ($attachment_id <= 0) {
941
942 if (is_wp_error($result)) {
943 Logger::write(__CLASS__ . '::process__attachments -error=' . $result->get_error_message());
944 $this->errors[] = $result;
945 continue;
946 }
947
948 if (!$result) {
949 continue;
950 }
951
952 $attachment_args = [];
953 if ($meta_enabled) {
954 $attachment_args['title'] = isset($attachment_titles[$location_counter]) ? $attachment_titles[$location_counter] : null;
955 $attachment_args['alt'] = isset($attachment_alts[$location_counter]) ? $attachment_alts[$location_counter] : null;
956 $attachment_args['caption'] = isset($attachment_captions[$location_counter]) ? $attachment_captions[$location_counter] : null;
957 $attachment_args['description'] = isset($attachment_descriptions[$location_counter]) ? $attachment_descriptions[$location_counter] : null;;
958 }
959
960 // resize attachment
961 if ($crop_details = apply_filters('iwp/importer/template/process_attachment/resize', '__return_false')) {
962
963 if (is_array($crop_details) && count($crop_details) == 3 && file_exists($result['dest'])) {
964
965 list($max_w, $max_h, $crop) = $crop_details;
966
967 if (!is_null($max_w)) {
968 $max_w = absint($max_w);
969 }
970 if (!is_null($max_h)) {
971 $max_h = absint($max_h);
972 }
973
974 $editor = wp_get_image_editor($result['dest']);
975 if (!is_wp_error($editor)) {
976 $editor->resize($max_w, $max_h, (bool)$crop);
977 $editor->save($result['dest']);
978 } else {
979 Logger::write(__CLASS__ . '::process__attachments -resize -error=' . $editor->get_error_message());
980 }
981 }
982 }
983
984 $attachment_id = $attachment->insert_attachment($post_id, $result['dest'], $result['mime'], $attachment_args);
985 if (is_wp_error($attachment_id)) {
986 Logger::write(__CLASS__ . '::process__attachments -error=' . $attachment_id->get_error_message());
987 continue;
988 }
989
990 $attachment->generate_image_sizes($attachment_id, $result['dest']);
991 $attachment->store_attachment_hash($attachment_id, $source, $attachment_salt);
992 } else {
993 // Update existing attachment meta
994 if ($meta_enabled) {
995 $post_data = [];
996
997 if (isset($attachment_titles[$location_counter])) {
998 $post_data['post_title'] = $attachment_titles[$location_counter];
999 }
1000
1001 if (isset($attachment_descriptions[$location_counter])) {
1002 $post_data['post_content'] = $attachment_descriptions[$location_counter];
1003 }
1004
1005 if (isset($attachment_captions[$location_counter])) {
1006 $post_data['post_excerpt'] = $attachment_captions[$location_counter];
1007 }
1008
1009 if (!empty($post_data)) {
1010 $post_data['ID'] = $attachment_id;
1011 wp_update_post($post_data);
1012 }
1013
1014 if (isset($attachment_alts[$location_counter])) {
1015 update_post_meta($attachment_id, '_wp_attachment_image_alt', $attachment_alts[$location_counter]);
1016 }
1017 }
1018 }
1019
1020 $attachment_ids[] = $attachment_id;
1021 $attachment_url = wp_get_attachment_url($attachment_id);
1022 $this->_attachments[] = $attachment_url;
1023
1024 Logger::write(__CLASS__ . '::process__attachments -id=' . $attachment_id . ' -url=' . $attachment_url);
1025
1026 // set featured
1027 if ('yes' === $featured && false === $this->featured_set) {
1028 update_post_meta($post_id, '_thumbnail_id', $attachment_id);
1029 $this->featured_set = true;
1030 }
1031
1032 $location_counter++;
1033 }
1034
1035 return $attachment_ids;
1036 }
1037
1038 /**
1039 * Remove custom field meta fields from the provided array based on importer permissions.
1040 *
1041 * @param string[string] $custom_fields
1042 * @param ParsedData $data
1043 * @param string $group_name
1044 * @param string $permission_key
1045 * @param string $prefix
1046 * @return string[string]
1047 */
1048 public function process_attachment_meta_permissions($custom_fields, $data, $group_name, $permission_key, $prefix)
1049 {
1050 $allowed = $data->permission()->validate([
1051 $permission_key . '._alt' => '',
1052 $permission_key . '._title' => '',
1053 $permission_key . '._caption' => '',
1054 $permission_key . '._description' => ''
1055 ], $data->getMethod(), $group_name);
1056
1057 if (!isset($allowed[$permission_key . '._alt'])) {
1058 // remove alt
1059 unset($custom_fields[$prefix . 'settings._meta._alt']);
1060 }
1061 if (!isset($allowed[$permission_key . '._title'])) {
1062 // remove title
1063 unset($custom_fields[$prefix . 'settings._meta._title']);
1064 }
1065 if (!isset($allowed[$permission_key . '._caption'])) {
1066 // remove caption
1067 unset($custom_fields[$prefix . 'settings._meta._caption']);
1068 }
1069 if (!isset($allowed[$permission_key . '._description'])) {
1070 // remove description
1071 unset($custom_fields[$prefix . 'settings._meta._description']);
1072 }
1073
1074 return $custom_fields;
1075 }
1076
1077 /**
1078 * Add error message
1079 *
1080 * @param string|\WP_Error $error
1081 * @return void
1082 */
1083 public function add_error($error)
1084 {
1085 if (!is_wp_error($error)) {
1086 $error = new \WP_Error('IWP_TEMP_ERR', $error);
1087 }
1088
1089 $this->errors[] = $error;
1090 }
1091
1092 /**
1093 * Convert fields/headings to data map
1094 *
1095 * @param mixed $fields
1096 * @param ImporterModel $importer
1097 * @return array
1098 */
1099 public function generate_field_map($fields, $importer)
1100 {
1101 return ['enabled' => [], 'map' => []];
1102 }
1103
1104 public function get_zip_source($base_url, $filesystem)
1105 {
1106 $zip_parts = [];
1107 if (preg_match('/^iwp_zip:\/\/(.*?)$/', $base_url, $zip_parts) === 1) {
1108
1109 $iwp_tmp = $filesystem->get_temp_directory();
1110
1111 $iwp_tmp .= DIRECTORY_SEPARATOR . 'zip';
1112 if (!is_dir($iwp_tmp)) {
1113 mkdir($iwp_tmp);
1114 }
1115
1116 $hash = md5($base_url);
1117 $iwp_tmp .= DIRECTORY_SEPARATOR . $hash . '.zip';
1118 if (!file_exists($iwp_tmp)) {
1119 return ['src' => $zip_parts[1], 'name' => $iwp_tmp];
1120 }
1121
1122 return ['name' => $iwp_tmp];
1123 }
1124
1125 return false;
1126 }
1127
1128 public function get_file_from_zip($zip_path, $filename, $filesystem)
1129 {
1130 $zip = new \ZipArchive();
1131 if ($zip->open($zip_path) === true) {
1132 $output_data = $zip->getFromName($filename);
1133 if ($output_data === false) {
1134 return false;
1135 }
1136
1137 return $filesystem->string_to_file($output_data, $filename);
1138 }
1139
1140 return false;
1141 }
1142
1143 public function try_use_main_zip($base_url, $location)
1144 {
1145 if ($base_url === 'iwp_zip') {
1146
1147 $main_zip = get_post_meta($this->importer->getId(), '_iwp_zip', true);
1148 $source = $main_zip . $location;
1149 $base_url .= $main_zip;
1150 }
1151 }
1152
1153 public function get_permission_fields($importer_model)
1154 {
1155 return [];
1156 }
1157
1158 public function register_settings() {}
1159
1160 public function register_options()
1161 {
1162 return [];
1163 }
1164
1165 public function get_default_enabled_fields()
1166 {
1167 return $this->default_enabled_fields;
1168 }
1169
1170
1171 public function get_unique_identifier_options($importer_model, $unique_fields = [])
1172 {
1173 $output = [];
1174 return $output;
1175 }
1176
1177 public function get_unique_identifier_options_from_map($importer_model, $unique_fields, $field_map, $optional_fields)
1178 {
1179 $output = [];
1180 $mapped_data = $importer_model->getMap();
1181
1182 foreach ($field_map as $field_id => $field_map_key) {
1183
1184 if (isset($output[$field_id])) {
1185 continue;
1186 }
1187
1188 $output[$field_id] = [
1189 'value' => $field_id,
1190 'label' => $field_id,
1191 'uid' => false,
1192 'active' => false,
1193 ];
1194
1195 if (in_array($field_id, $unique_fields)) {
1196 $output[$field_id]['uid'] = true;
1197 }
1198
1199 if (!isset($mapped_data[$field_map_key]) || empty($mapped_data[$field_map_key])) {
1200 continue;
1201 }
1202
1203 if (in_array($field_id, $optional_fields) && true !== $importer_model->isEnabledField($field_map_key)) {
1204 continue;
1205 }
1206
1207 $output[$field_id]['active'] = true;
1208 }
1209
1210 return $output;
1211 }
1212 }
1213