PluginProbe
Import WP – CSV & XML Import Export for WordPress / trunk
Import WP – CSV & XML Import Export for WordPress vtrunk
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 trunk 0.1.6 All 142 releases
jc-importer / class / Common / Model / ImporterModel.php

ImporterModel.php in Import WP – CSV & XML Import Export for WordPress trunk, at class/Common/Model/ImporterModel.php

738 lines 19.8 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\Model;
4
5 use ImportWP\Common\Filesystem\Filesystem;
6 use ImportWP\Common\Util\Logger;
7
8 class ImporterModel
9 {
10 /**
11 * @var int $id
12 */
13 protected $id;
14
15 /**
16 * @var int $user_id
17 */
18 protected $user_id;
19
20 /**
21 * @var string $name
22 */
23 protected $name;
24
25 /**
26 * @var string $template
27 */
28 protected $template;
29
30 /**
31 * @var string $template_type
32 */
33 protected $template_type;
34
35 /**
36 * @var string $parser
37 */
38 protected $parser;
39
40 /**
41 * @var string $mapper
42 */
43 protected $mapper;
44
45 /**
46 * @var string $datasource
47 */
48 protected $datasource;
49
50 /**
51 * @var array $datasource_settings
52 */
53 protected $datasource_settings;
54
55 /**
56 * @var string $file
57 */
58 protected $file;
59
60 /**
61 * @var int $file_id
62 */
63 protected $file_id;
64
65 /**
66 * @var array $file_settings
67 */
68 protected $file_settings;
69
70 /**
71 * @var array $map
72 */
73 protected $map;
74
75 /**
76 * @var array $enabled
77 */
78 protected $enabled;
79
80 /**
81 * @var array $permissions
82 */
83 protected $permissions;
84
85 /**
86 * @var int $max_row
87 */
88 protected $max_row;
89
90 /**
91 * @var int $start_row
92 */
93 protected $start_row;
94
95 /**
96 * Importer general settings
97 *
98 * @var array
99 */
100 protected $settings = [];
101
102 /**
103 * @var int
104 */
105 protected $version;
106 protected $version_latest = 2;
107
108 /**
109 * @var bool
110 */
111 protected $debug;
112
113 public function __construct($data = null, $debug = false)
114 {
115 $this->debug = $debug;
116 $this->setup_data($data);
117 }
118
119 private function setup_data($data)
120 {
121
122 if (is_array($data)) {
123
124 // fetch data from array
125 $this->id = isset($data['id']) && intval($data['id']) > 0 ? intval($data['id']) : null;
126 $this->name = $data['name'];
127 $this->template = isset($data['template']) ? $data['template'] : null;
128 $this->template_type = isset($data['template_type']) ? $data['template_type'] : null;
129 $this->parser = isset($data['parser']) ? $data['parser'] : null;
130 $this->mapper = isset($data['mapper']) ? $data['mapper'] : null;
131 $this->map = isset($data['map']) ? $data['map'] : null;
132 $this->enabled = isset($data['enabled']) ? $data['enabled'] : null;
133 $this->file_id = isset($data['file'], $data['file']['id']) ? $data['file']['id'] : null;
134 if ($this->file_id) {
135 $this->file = $this->get_attached_file($this->file_id);
136 }
137 $this->file_settings = array_merge($this->getDetaultFileSettings(), isset($data['file'], $data['file']['settings']) ? $data['file']['settings'] : array());
138 $this->datasource = isset($data['datasource'], $data['datasource']['type']) ? $data['datasource']['type'] : null;
139 $this->datasource_settings = isset($data['datasource'], $data['datasource']['settings']) ? $data['datasource']['settings'] : null;
140 $this->permissions = isset($data['permissions']) ? $data['permissions'] : null;
141 $this->start_row = isset($data['settings'], $data['settings']['start_row']) ? $data['settings']['start_row'] : null;
142 $this->max_row = isset($data['settings'], $data['settings']['max_row']) ? $data['settings']['max_row'] : null;
143 $this->settings = isset($data['settings']) ? $data['settings'] : [];
144 $this->version = isset($data['version']) ? $data['version'] : 0;
145 } elseif (!is_null($data)) {
146
147 $post = false;
148
149 if ($data instanceof \WP_Post) {
150
151 // fetch data from post
152 $post = $data;
153 } elseif (intval($data) > 0) {
154
155 // fetch data from id
156 $this->id = intval($data);
157 $post = get_post($this->id);
158 }
159
160 if ($post && $post->post_type === IWP_POST_TYPE) {
161
162 // Fix broken importer issue.
163 $json = maybe_unserialize($post->post_content, true);
164 if (!is_array($json)) {
165 $json = [];
166 }
167
168 $this->id = $post->ID;
169 $this->name = $post->post_title;
170 $this->user_id = $post->post_author;
171
172 $this->template = isset($json['template']) ? $json['template'] : null;
173 $this->template_type = isset($json['template_type']) ? $json['template_type'] : null;
174 $this->parser = isset($json['parser']) ? $json['parser'] : null;
175 $this->mapper = isset($json['mapper']) ? $json['mapper'] : null;
176 $this->map = isset($json['map']) ? $json['map'] : [];
177 $this->enabled = isset($json['enabled']) ? $json['enabled'] : [];
178 $this->file_id = isset($json['file'], $json['file']['id']) ? intval($json['file']['id']) : 0;
179 if ($this->file_id > 0) {
180 $this->file = $this->get_attached_file($this->file_id);
181 }
182
183 if (!isset($json['file']['settings']) || !is_array($json['file']['settings'])) {
184 $json['file']['settings'] = [];
185 }
186
187 $this->file_settings = array_merge($this->getDetaultFileSettings(), $json['file']['settings']);
188
189 $this->datasource = isset($json['datasource'], $json['datasource']['type']) ? $json['datasource']['type'] : null;
190 $this->datasource_settings = isset($json['datasource'], $json['datasource']['settings']) ? $json['datasource']['settings'] : [];
191
192 $this->permissions = isset($json['permissions']) ? $json['permissions'] : [];
193
194 $this->start_row = isset($json['settings'], $json['settings']['start_row']) ? $json['settings']['start_row'] : null;
195 $this->max_row = isset($json['settings'], $json['settings']['max_row']) ? $json['settings']['max_row'] : null;
196 $this->settings = isset($json['settings']) ? $json['settings'] : [];
197 $this->version = isset($json['version']) ? $json['version'] : 0;
198 }
199 }
200
201 Logger::setId($this->getId());
202 }
203
204 public function data($view = 'public')
205 {
206 $files = $this->getFiles();
207 $file = $this->getFile();
208 if ($view === 'public' && false === $this->debug) {
209
210 if ($file) {
211 $file = basename($file);
212 }
213
214 foreach ($files as &$tmp_file) {
215 $tmp_file = basename($tmp_file) . ' - (Added: ' . date(get_option('date_format') . ' \a\t ' . get_option('time_format'), filemtime($tmp_file)) . ')';
216 }
217 } else {
218 foreach ($files as &$tmp_file) {
219
220 $tmp_file .= ' - (Added: ' . date(get_option('date_format') . ' \a\t ' . get_option('time_format'), filemtime($tmp_file)) . ')';
221 }
222 }
223
224 $file_data = [
225 'id' => $this->getFileId(),
226 'src' => $file,
227 'settings' => $this->file_settings
228 ];
229
230 $datasource_data = [
231 'type' => $this->getDatasource(),
232 'settings' => (object) $this->getDatasourceSettings()
233 ];
234
235 $settings = array_merge($this->settings, [
236 'start_row' => $this->start_row,
237 'max_row' => $this->max_row,
238 ]);
239
240 $result = array(
241 'id' => $this->id,
242 'name' => $this->getName(),
243 'template' => $this->template,
244 'template_type' => $this->template_type,
245 'parser' => $this->getParser(),
246 'cron' => [],
247 'file' => $file_data,
248 'files' => (object) $files,
249 'datasource' => $datasource_data,
250 'map' => (object) $this->map,
251 'enabled' => (object) $this->enabled,
252 'permissions' => (object) $this->getPermissions(),
253 'settings' => (object) $settings,
254 'version' => $this->version,
255 );
256
257 if (true === $this->debug) {
258 global $wpdb;
259 $content = $wpdb->get_var($wpdb->prepare("SELECT post_content from {$wpdb->posts} WHERE post_type='%s' AND ID=%d", IWP_POST_TYPE, $this->getId()));
260 $result['debug'] = [
261 'settings' => base64_encode($content),
262 // 'log' => file_get_contents(Logger::getLogFile($this->getId()))
263 ];
264 }
265
266 return $result;
267 }
268
269 public function save()
270 {
271 // Match what happens in wp-rest.
272 remove_filter('content_save_pre', 'wp_filter_post_kses');
273
274 $settings = array_merge($this->settings, [
275 'start_row' => $this->start_row,
276 'max_row' => $this->max_row,
277 ]);
278
279 $post_content = array(
280 'template' => $this->template,
281 'template_type' => $this->template_type,
282 'file' => [
283 'id' => $this->file_id,
284 'settings' => $this->file_settings
285 ],
286 'datasource' => [
287 'type' => $this->datasource,
288 'settings' => $this->getDatasourceSettings()
289 ],
290 'parser' => $this->parser,
291 'map' => $this->map,
292 'enabled' => $this->enabled,
293 'permissions' => $this->permissions,
294 'settings' => $settings,
295 'version' => $this->version
296 );
297
298 if (is_null($this->id)) {
299
300 if ($this->template === 'jet-engine-cct') {
301
302 // do not force the new permissions interface.
303
304 } else {
305
306 // set defaults on new importers
307 $post_content['version'] = $this->version_latest;
308 $post_content['settings']['unique_identifier_type'] = 'field';
309 }
310 }
311
312 $postarr = array(
313 'post_title' => $this->name,
314 'post_content' => wp_slash(serialize($post_content)),
315 );
316
317 if (is_null($this->id)) {
318 $postarr['post_type'] = IWP_POST_TYPE;
319 $postarr['post_status'] = 'publish';
320
321 $result = wp_insert_post($postarr, true);
322 } else {
323 $postarr['ID'] = $this->id;
324 $result = wp_update_post($postarr, true);
325 }
326
327 // Match what happens in wp-rest.
328 add_filter('content_save_pre', 'wp_filter_post_kses');
329
330
331 if (!is_wp_error($result)) {
332 $this->setup_data($result);
333 }
334
335 return $result;
336 }
337
338 public function delete()
339 {
340 if (get_post_type($this->getId()) === IWP_POST_TYPE) {
341 wp_delete_post($this->getId(), true);
342 }
343 }
344
345 public function getAllowedFileTypes()
346 {
347
348 $parser = $this->getParser();
349 $allowed_file_types = apply_filters('iwp/importer/datasource/allowed_file_types', ['xml', 'csv'], $this);
350
351 if (!is_null($parser)) {
352 $allowed_file_types = [$parser];
353 }
354
355 return $allowed_file_types;
356 }
357
358 public function setDatasource($datasource)
359 {
360 $this->datasource = $datasource;
361 }
362
363 public function setDatasourceSetting($key, $value)
364 {
365 $this->datasource_settings[$key] = $value;
366 }
367
368 public function getSetting($key)
369 {
370 return isset($this->settings[$key]) ? $this->settings[$key] : null;
371 }
372
373 public function setSetting($key, $value)
374 {
375 $this->settings[$key] = $value;
376 }
377
378 public function setFileId($file_id)
379 {
380 $this->file_id = $file_id;
381 $this->file = $this->get_attached_file($this->file_id);
382
383 if (is_null($this->file_settings)) {
384 $this->file_settings = $this->getDetaultFileSettings();
385 }
386 }
387
388 public function getDetaultFileSettings()
389 {
390 switch ($this->getParser()) {
391 case 'xml':
392 return [
393 'base_path' => null,
394 'setup' => false
395 ];
396 break;
397 case 'csv':
398 return [
399 'enclosure' => '"',
400 'delimiter' => ',',
401 'escape' => '\\',
402 'show_headings' => true,
403 'setup' => false
404 ];
405 break;
406 }
407
408 return [];
409 }
410
411 public function setFile($file_id, $settings)
412 {
413 $this->file_id = $file_id;
414 $this->file = $this->get_attached_file($this->file_id);
415 $this->file_settings = array_merge($this->getDetaultFileSettings(), $settings);
416 }
417
418 public function setMaxRow($max)
419 {
420 $this->max_row = $max;
421 }
422
423 public function setStartRow($start)
424 {
425 $this->start_row = $start;
426 }
427
428 public function setName($name)
429 {
430 $this->name = $name;
431 }
432
433 public function setParser($parser)
434 {
435 $this->parser = $parser;
436 }
437
438 public function setTemplate($template, $template_type = '')
439 {
440 $this->template = $template;
441 $this->template_type = $template_type;
442 }
443
444 public function getDatasource()
445 {
446 return $this->datasource;
447 }
448
449 public function getDatasourceSettings()
450 {
451 return $this->datasource_settings;
452 }
453
454 public function getDatasourceSetting($key)
455 {
456 return isset($this->datasource_settings[$key]) ? $this->datasource_settings[$key] : null;
457 }
458
459 public function getFile()
460 {
461 return $this->file;
462 }
463
464 public function getFileId()
465 {
466 return $this->file_id;
467 }
468
469 public function getFiles()
470 {
471 $files = [];
472
473 if (!$this->getId()) {
474 return $files;
475 }
476
477 global $wpdb;
478 $query = "SELECT meta_key, meta_value
479 FROM {$wpdb->postmeta}
480 WHERE post_id={$this->getId()} AND meta_key
481 LIKE '\_importer\_file\_%'";
482
483 $results = $wpdb->get_results($query, ARRAY_A);
484
485 foreach ($results as $result) {
486 $key = $result['meta_key'];
487 $id = intval(str_replace('_importer_file_', '', $key));
488 $value = $result['meta_value'];
489 $resolved = Filesystem::resolve_importer_file_path($value);
490 if (!$resolved) {
491 continue;
492 }
493
494 $files[$id] = $resolved;
495
496 // Soft-migrate legacy absolute paths to uploads-relative storage.
497 $relative = Filesystem::to_uploads_relative_path($resolved);
498 if ($relative !== '' && $relative !== $value) {
499 update_post_meta($this->getId(), $key, $relative);
500 }
501 }
502
503 return $files;
504 }
505
506 public function get_attached_file($post_id)
507 {
508 $files = $this->getFiles();
509 return isset($files[$post_id]) ? $files[$post_id] : false;
510 }
511
512 /**
513 * Set the limit of importer files
514 *
515 * @param integer $limit The number of files to keep, 0 to keep all files.
516 * @return void
517 */
518 public function limit_importer_files($limit = 0)
519 {
520
521 $limit = intval($limit);
522 if ($limit <= -1) {
523 return;
524 }
525
526 $files = $this->getFiles();
527 if (empty($files) || count($files) <= $limit) {
528 return;
529 }
530
531 ksort($files);
532
533 $file_ids = array_keys($files);
534
535 for ($i = 0; $i < count($files) - $limit; $i++) {
536
537 $id = $file_ids[$i];
538 $path = $files[$id];
539
540 if ($id === $this->getFileId()) {
541 continue;
542 }
543
544 if (!file_exists($path) || unlink($path)) {
545 global $wpdb;
546 $query = "DELETE FROM {$wpdb->postmeta} WHERE post_id={$this->getId()} AND meta_key = '_importer_file_{$id}'";
547 $result = $wpdb->query($query);
548 }
549 }
550 }
551
552 public function getId()
553 {
554 return $this->id;
555 }
556
557 public function getMaxRow()
558 {
559 return $this->max_row;
560 }
561
562 public function getStartRow()
563 {
564 return $this->start_row;
565 }
566
567 public function getName()
568 {
569 return $this->name;
570 }
571
572 public function getParser()
573 {
574 return $this->parser;
575 }
576
577 public function getStatus()
578 {
579 clean_post_cache($this->id);
580 $post = get_post($this->id);
581 return (array) maybe_unserialize($post->post_excerpt);
582 }
583
584 public function getStatusId()
585 {
586 return get_post_meta($this->getId(), '_iwp_session', true);
587 }
588
589 public function getTemplate()
590 {
591 return $this->template;
592 }
593
594 public function getFileSettings()
595 {
596 return $this->file_settings;
597 }
598
599 public function getFileSetting($key, $default = null)
600 {
601 return isset($this->file_settings[$key]) ? $this->file_settings[$key] : $default;
602 }
603
604 public function setFileSetting($key, $value)
605 {
606 $this->file_settings[$key] = $value;
607 }
608
609 public function getMap()
610 {
611 return $this->map;
612 }
613
614 public function setMap($key, $value)
615 {
616 $this->map[$key] = $value;
617 }
618
619 /**
620 * Replace the entire field map (skips null values from deleted repeater rows).
621 *
622 * @param array $map
623 */
624 public function replaceMap($map)
625 {
626 $this->map = [];
627 if (!is_array($map)) {
628 return;
629 }
630
631 foreach ($map as $key => $value) {
632 if ($value === null) {
633 continue;
634 }
635 $this->map[$key] = $value;
636 }
637 }
638
639 public function getEnabled()
640 {
641 return $this->enabled;
642 }
643
644 public function setEnabled($key, $value = true)
645 {
646 if ($value === true) {
647 $this->enabled[$key] = $value;
648 } elseif (isset($this->enabled[$key])) {
649 unset($this->enabled[$key]);
650 }
651 }
652
653 public function isEnabledField($key)
654 {
655 return isset($this->enabled[$key]) && $this->enabled[$key] === true ? true : false;
656 }
657
658 public function getPermission($key)
659 {
660 return isset($this->permissions[$key]) ? $this->permissions[$key] : false;
661 }
662
663 public function getPermissions()
664 {
665 return $this->permissions;
666 }
667
668 public function setPermission($key, $settings)
669 {
670 $this->permissions[$key] = $settings;
671 }
672
673 public function getFilters()
674 {
675 $output = [];
676 $filter_data = $this->getSetting('filters');
677 if (!is_array($filter_data)) {
678 return $output;
679 }
680
681 $max_groups = isset($filter_data['filters._index']) ? intval($filter_data['filters._index']) : 0;
682 if ($max_groups <= 0) {
683 return $output;
684 }
685
686 for ($i = 0; $i < $max_groups; $i++) {
687 $group_data = [];
688 $max_rows = isset($filter_data["filters.{$i}._index"]) ? intval($filter_data["filters.{$i}._index"]) : 0;
689 if ($max_groups <= 0) {
690 continue;
691 }
692
693 for ($j = 0; $j < $max_rows; $j++) {
694
695 $group_data[] = [
696 'left' => isset($filter_data["filters.{$i}.{$j}.left"]) ? $filter_data["filters.{$i}.{$j}.left"] : "",
697 'condition' => isset($filter_data["filters.{$i}.{$j}.condition"]) ? $filter_data["filters.{$i}.{$j}.condition"] : "equal",
698 'right' => isset($filter_data["filters.{$i}.{$j}.right"]) ? $filter_data["filters.{$i}.{$j}.right"] : "",
699 ];
700 }
701
702 $output[] = $group_data;
703 }
704
705 return $output;
706 }
707
708 public function getUserId()
709 {
710 return intval($this->user_id) > 0 ? intval($this->user_id) : false;
711 }
712
713 public function getVersion()
714 {
715 return $this->version;
716 }
717
718 public function get_iwp_reference_meta_key()
719 {
720 return '_iwp_ref_uid';
721 }
722
723 public function has_custom_unique_identifier()
724 {
725 return $this->getSetting('unique_identifier_type') === 'custom';
726 }
727
728 public function has_field_unique_identifier()
729 {
730 return $this->getSetting('unique_identifier_type') === 'field';
731 }
732
733 public function has_legacy_unique_identifier()
734 {
735 return !in_array($this->getSetting('unique_identifier_type'), ['custom', 'field']);
736 }
737 }
738