PluginProbe
Import WP – CSV & XML Import Export for WordPress / 2.8.0
Import WP – CSV & XML Import Export for WordPress v2.8.0
2.15.1 2.15.0 2.14.24 2.14.23 2.7.0 2.7.1 2.7.10 2.7.11 2.7.12 2.7.13 2.7.14 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 2.9.1 All 144 releases
jc-importer / class / Common / Rest / RestManager.php

RestManager.php in Import WP – CSV & XML Import Export for WordPress 2.8.0, at class/Common/Rest/RestManager.php

1,516 lines 53.6 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\Rest;
4
5 use ImportWP\Common\Exporter\ExporterManager;
6 use ImportWP\Common\Exporter\State\ExporterState;
7 use ImportWP\Common\Filesystem\Filesystem;
8 use ImportWP\Common\Filesystem\ZipArchive;
9 use ImportWP\Common\Http\Http;
10 use ImportWP\Common\Importer\ImporterManager;
11 use ImportWP\Common\Importer\Preview\CSVPreview;
12 use ImportWP\Common\Importer\Preview\XMLPreview;
13 use ImportWP\Common\Importer\State\ImporterState;
14 use ImportWP\Common\Importer\Template\Template;
15 use ImportWP\Common\Importer\Template\TemplateManager;
16 use ImportWP\Common\Migration\Migrations;
17 use ImportWP\Common\Model\ExporterModel;
18 use ImportWP\Common\Model\ImporterModel;
19 use ImportWP\Common\Properties\Properties;
20 use ImportWP\Common\Util\Logger;
21 use ImportWP\Common\Util\Util;
22 use ImportWP\Container;
23 use ImportWP\EventHandler;
24
25 class RestManager extends \WP_REST_Controller
26 {
27 /**
28 * @var Properties
29 */
30 protected $properties;
31
32 /**
33 * @var Http
34 */
35 protected $http;
36
37 /**
38 * @var Filesystem
39 */
40 protected $filesystem;
41
42 /**
43 * @var ImporterManager
44 */
45 protected $importer_manager;
46
47 /**
48 * @var ExporterManager
49 */
50 protected $exporter_manager;
51
52 /**
53 * @var TemplateManager $template_manager
54 */
55 protected $template_manager;
56
57 /**
58 * @var EventHandler
59 */
60 protected $event_handler;
61
62 public function __construct(ImporterManager $importer_manager, ExporterManager $exporter_manager, Properties $properties, Http $http, Filesystem $filesystem, TemplateManager $template_manager, $event_handler)
63 {
64 $this->importer_manager = $importer_manager;
65 $this->exporter_manager = $exporter_manager;
66 $this->properties = $properties;
67 $this->http = $http;
68 $this->filesystem = $filesystem;
69 $this->template_manager = $template_manager;
70 $this->event_handler = $event_handler;
71 }
72
73 public function register()
74 {
75 add_action('rest_api_init', array($this, 'register_routes'));
76 }
77
78 public function register_routes()
79 {
80 $namespace = $this->properties->rest_namespace . '/' . $this->properties->rest_version;
81
82 register_rest_route($namespace, '/system/check', array(
83 array(
84 'methods' => \WP_REST_Server::READABLE,
85 'callback' => array($this, 'check_rest_status'),
86 'permission_callback' => array($this, 'get_permission')
87 )
88 ));
89 register_rest_route($namespace, '/system/migrate', array(
90 array(
91 'methods' => \WP_REST_Server::READABLE,
92 'callback' => array($this, 'migrate'),
93 'permission_callback' => array($this, 'get_permission')
94 )
95 ));
96
97 register_rest_route($namespace, '/importer', array(
98 array(
99 'methods' => \WP_REST_Server::CREATABLE,
100 'callback' => array($this, 'save_importer'),
101 'permission_callback' => array($this, 'get_permission')
102 )
103 ));
104
105 register_rest_route($namespace, '/importers', array(
106 array(
107 'methods' => \WP_REST_Server::READABLE,
108 'callback' => array($this, 'get_importers'),
109 'permission_callback' => array($this, 'get_permission')
110 ),
111 ));
112
113 register_rest_route($namespace, '/status', array(
114 array(
115 'methods' => \WP_REST_Server::READABLE,
116 'callback' => array($this, 'get_status'),
117 'permission_callback' => array($this, 'get_permission')
118 ),
119 ));
120
121 register_rest_route($namespace, '/importer/(?P<id>\d+)', array(
122 array(
123 'methods' => \WP_REST_Server::READABLE,
124 'callback' => array($this, 'get_importer'),
125 'permission_callback' => array($this, 'get_permission')
126 ),
127 array(
128 'methods' => \WP_REST_Server::EDITABLE,
129 'callback' => array($this, 'save_importer'),
130 'permission_callback' => array($this, 'get_permission')
131 ),
132 array(
133 'methods' => \WP_REST_Server::DELETABLE,
134 'callback' => array($this, 'delete_importer'),
135 'permission_callback' => array($this, 'get_permission')
136 ),
137 ));
138
139 register_rest_route($namespace, '/importer/(?P<id>\d+)/upload', array(
140 array(
141 'methods' => \WP_REST_Server::EDITABLE,
142 'callback' => array($this, 'attach_file'),
143 'permission_callback' => array($this, 'get_permission')
144 )
145 ));
146
147 register_rest_route($namespace, '/importer/(?P<id>\d+)/file-process', array(
148 array(
149 'methods' => \WP_REST_Server::CREATABLE,
150 'callback' => array($this, 'get_file_process'),
151 'permission_callback' => array($this, 'get_permission')
152 )
153 ));
154
155 register_rest_route($namespace, '/importer/(?P<id>\d+)/file-preview', array(
156 array(
157 'methods' => \WP_REST_Server::CREATABLE,
158 'callback' => array($this, 'get_file_preview'),
159 'permission_callback' => array($this, 'get_permission')
160 )
161 ));
162
163 register_rest_route($namespace, '/importer/(?P<id>\d+)/preview', array(
164 array(
165 'methods' => \WP_REST_Server::CREATABLE,
166 'callback' => array($this, 'get_preview'),
167 'permission_callback' => array($this, 'get_permission')
168 )
169 ));
170
171 register_rest_route($namespace, '/importer/(?P<id>\d+)/init', array(
172 array(
173 'methods' => \WP_REST_Server::READABLE,
174 'callback' => array($this, 'init_import'),
175 'permission_callback' => array($this, 'get_permission')
176 )
177 ));
178
179 register_rest_route($namespace, '/importer/(?P<id>\d+)/run', array(
180 array(
181 'methods' => \WP_REST_Server::CREATABLE,
182 'callback' => array($this, 'run_import'),
183 'permission_callback' => array($this, 'get_permission')
184 )
185 ));
186
187 register_rest_route($namespace, '/importer/(?P<id>\d+)/pause', array(
188 array(
189 'methods' => \WP_REST_Server::CREATABLE,
190 'callback' => array($this, 'pause_import'),
191 'permission_callback' => array($this, 'get_permission')
192 )
193 ));
194
195 register_rest_route($namespace, '/importer/(?P<id>\d+)/stop', array(
196 array(
197 'methods' => \WP_REST_Server::CREATABLE,
198 'callback' => array($this, 'stop_import'),
199 'permission_callback' => array($this, 'get_permission')
200 )
201 ));
202
203 register_rest_route($namespace, '/importer/(?P<id>\d+)/field', array(
204 array(
205 'methods' => \WP_REST_Server::CREATABLE,
206 'callback' => array($this, 'get_template_field_options'),
207 'permission_callback' => array($this, 'get_permission')
208 )
209 ));
210
211 register_rest_route($namespace, '/importer/(?P<id>\d+)/logs/(?P<session>\S+)', array(
212 array(
213 'methods' => \WP_REST_Server::READABLE,
214 'callback' => array($this, 'get_log'),
215 'permission_callback' => array($this, 'get_permission')
216 )
217 ));
218
219 register_rest_route($namespace, '/importer/(?P<id>\d+)/logs', array(
220 array(
221 'methods' => \WP_REST_Server::READABLE,
222 'callback' => array($this, 'get_logs'),
223 'permission_callback' => array($this, 'get_permission')
224 )
225 ));
226
227 register_rest_route($namespace, '/settings', array(
228 array(
229 'methods' => \WP_REST_Server::CREATABLE,
230 'callback' => array($this, 'save_settings'),
231 'permission_callback' => array($this, 'get_permission')
232 ),
233 array(
234 'methods' => \WP_REST_Server::READABLE,
235 'callback' => array($this, 'get_settings'),
236 'permission_callback' => array($this, 'get_permission')
237 ),
238 ));
239
240 register_rest_route($namespace, '/import-export', array(
241 array(
242 'methods' => \WP_REST_Server::CREATABLE,
243 'callback' => array($this, 'import_exporters'),
244 'permission_callback' => array($this, 'get_permission')
245 ),
246 array(
247 'methods' => \WP_REST_Server::READABLE,
248 'callback' => array($this, 'export_importers'),
249 'permission_callback' => array($this, 'get_permission')
250 ),
251 ));
252
253 register_rest_route($namespace, '/importer/(?P<id>\d+)/debug_log', array(
254 array(
255 'methods' => \WP_REST_Server::READABLE,
256 'callback' => array($this, 'get_debug_log'),
257 'permission_callback' => array($this, 'get_permission')
258 )
259 ));
260
261 register_rest_route($namespace, '/importer/(?P<id>\d+)/template', array(
262 array(
263 'methods' => \WP_REST_Server::READABLE,
264 'callback' => array($this, 'get_template'),
265 'permission_callback' => array($this, 'get_permission')
266 )
267 ));
268
269 // Exporter
270
271 register_rest_route($namespace, '/exporter', array(
272 array(
273 'methods' => \WP_REST_Server::CREATABLE,
274 'callback' => array($this, 'save_exporter'),
275 'permission_callback' => array($this, 'get_permission')
276 )
277 ));
278
279 register_rest_route($namespace, '/exporters', array(
280 array(
281 'methods' => \WP_REST_Server::READABLE,
282 'callback' => array($this, 'get_exporters'),
283 'permission_callback' => array($this, 'get_permission')
284 ),
285 ));
286
287 register_rest_route($namespace, '/exporter/(?P<id>\d+)', array(
288 array(
289 'methods' => \WP_REST_Server::READABLE,
290 'callback' => array($this, 'get_exporter'),
291 'permission_callback' => array($this, 'get_permission')
292 ),
293 array(
294 'methods' => \WP_REST_Server::EDITABLE,
295 'callback' => array($this, 'save_exporter'),
296 'permission_callback' => array($this, 'get_permission')
297 ),
298 array(
299 'methods' => \WP_REST_Server::DELETABLE,
300 'callback' => array($this, 'delete_exporter'),
301 'permission_callback' => array($this, 'get_permission')
302 ),
303 ));
304
305 register_rest_route($namespace, '/exporter/(?P<id>\d+)/init', array(
306 array(
307 'methods' => \WP_REST_Server::READABLE,
308 'callback' => array($this, 'init_export'),
309 'permission_callback' => array($this, 'get_permission')
310 )
311 ));
312
313 register_rest_route($namespace, '/exporter/(?P<id>\d+)/run', array(
314 array(
315 'methods' => \WP_REST_Server::CREATABLE,
316 'callback' => array($this, 'run_exporter'),
317 'permission_callback' => array($this, 'get_permission')
318 ),
319 ));
320
321 register_rest_route($namespace, '/exporter/status', array(
322 array(
323 'methods' => \WP_REST_Server::READABLE,
324 'callback' => array($this, 'get_exporter_status'),
325 'permission_callback' => array($this, 'get_permission')
326 ),
327 ));
328 }
329
330 public function get_permission()
331 {
332
333 if (!current_user_can('manage_options')) {
334 return new \WP_Error('rest_forbidden', esc_html__('You do not have permissions.', $this->properties->plugin_domain), array('status' => 401));
335 }
336
337 return true;
338 }
339
340 public function sanitize($data, $name = null, $path = [])
341 {
342 $path[] = $name;
343
344 if (is_array($data)) {
345 foreach ($data as $k => $v) {
346 $data[$k] = $this->sanitize($v, $k, $path);
347 }
348
349 return $data;
350 }
351
352 $full_path = implode('.', array_filter($path));
353 if (!is_null($full_path)) {
354
355 if (preg_match('/^map\.\S+/', $full_path) !== false) {
356 return $data;
357 }
358 }
359
360 if (!is_null($name)) {
361 switch ($name) {
362 case 'id':
363 return intval($data);
364 }
365 }
366
367 return sanitize_text_field($data);
368 }
369
370 public function check_rest_status(\WP_REST_Request $request)
371 {
372 $result = [];
373 // find required php ext: https://github.com/llaville/php-compat-info
374
375 $tmp_writable = wp_is_writable($this->filesystem->get_temp_directory());
376
377
378 $result = [
379 'tmp_writable' => [
380 'status' => $tmp_writable ? 'yes' : 'no',
381 'message' => $tmp_writable ? '' : 'WordPress is unable to write to directory: ' . $this->filesystem->get_temp_directory() . ', make sure this directory is writable.',
382 ],
383 'rest_enabled' => [
384 'status' => 'yes',
385 'message' => '',
386 ],
387 'ext_simplexml' => [
388 'status' => extension_loaded('SimpleXML') ? 'yes' : 'no',
389 'message' => '',
390 ],
391 'ext_mbstring' => [
392 'status' => extension_loaded('mbstring') ? 'yes' : 'no',
393 'message' => '',
394 ],
395 'ext_xmlreader' => [
396 'status' => extension_loaded('xmlreader') ? 'yes' : 'no',
397 'message' => '',
398 ],
399 'php_version' => [
400 'status' => version_compare(phpversion(), '5.5.0') ? 'yes' : 'no',
401 'message' => '',
402 ],
403 'zip_archive' => [
404 'status' => ZipArchive::has_requirements_met() ? 'yes' : 'no'
405 ]
406 ];
407 return $this->http->end_rest_success($result);
408 }
409
410 public function migrate(\WP_REST_Request $request)
411 {
412 $migration = new Migrations();
413 $result = $migration->migrate();
414
415 return $this->http->end_rest_success("Migration Complete.");
416 }
417
418 public function get_importers(\WP_REST_Request $request)
419 {
420 $importers = $this->importer_manager->get_importers();
421 $result = [];
422
423 foreach ($importers as $importer) {
424 $result[] = $importer->data();
425 }
426
427 return $this->http->end_rest_success($result);
428 }
429
430 public function get_importer(\WP_REST_Request $request)
431 {
432 Logger::setRequestType('get_importer');
433
434 $id = intval($request->get_param('id'));
435 $importer_data = $this->importer_manager->get_importer($id);
436 $response = $importer_data->data('public');
437 return $this->http->end_rest_success($response);
438 }
439
440 public function save_importer(\WP_REST_Request $request)
441 {
442 Logger::setRequestType('save_importer');
443
444 $post_data = $request->get_body_params();
445 $id = isset($post_data['id']) ? intval($post_data['id']) : null;
446
447 $temp_post_data = [
448 'create' => [],
449 'update' => []
450 ];
451
452 if (isset($post_data['permissions'])) {
453 // TODO: update sanitize method to keep track of hierarchy
454 $temp_post_data['create'] = explode("\n", $post_data['permissions']['create']['fields']);
455 $temp_post_data['update'] = explode("\n", $post_data['permissions']['update']['fields']);
456 }
457
458 $post_data = $this->sanitize($post_data);
459
460 if (isset($post_data['permissions'])) {
461 // TODO: Method to bypass sanitization not needed once sanitize method has been upgraded
462 foreach (['create', 'update'] as $permission_method) {
463 $permission_fields = $temp_post_data[$permission_method];
464 if (!empty($permission_fields)) {
465 $post_data['permissions'][$permission_method]['fields'] = array_values(array_filter(array_map([$this, 'sanitize'], $permission_fields, array_fill(0, count($permission_fields), 'permission_' . $permission_method . '_fields'))));
466 } else {
467 $post_data['permissions'][$permission_method]['fields'] = [];
468 }
469 }
470 }
471
472
473
474 $importer = new ImporterModel($id, $this->importer_manager->is_debug());
475
476 if (isset($post_data['datasource'])) {
477 $importer->setDatasource($post_data['datasource']);
478 }
479
480 if (isset($post_data['remote_url'])) {
481 $importer->setDatasourceSetting('remote_url', $post_data['remote_url']);
482 }
483
484 if (isset($post_data['local_url'])) {
485 $importer->setDatasourceSetting('local_url', wp_normalize_path($post_data['local_url']));
486 }
487
488 if (isset($post_data['existing_id'])) {
489 $importer->setFileId(intval($post_data['existing_id']));
490 }
491
492 if (isset($post_data['template'], $post_data['template_type'])) {
493 $importer->setTemplate($post_data['template'], $post_data['template_type']);
494
495 // Get default template options
496 $template_class = $this->importer_manager->get_template($post_data['template']);
497
498 /**
499 * @var Template $template
500 */
501 $template = $this->template_manager->load_template($template_class);
502 $template_options = $template->get_default_template_options();
503
504 if (isset($post_data['template_options'])) {
505 $template_options = array_merge($template_options, $post_data['template_options']);
506 }
507
508 foreach ($template_options as $key => $val) {
509 $importer->setSetting($key, $val);
510 }
511 }
512
513 if (isset($post_data['name'])) {
514 $importer->setName($post_data['name']);
515 }
516
517 if (isset($post_data['setting_start_row'])) {
518 $importer->setStartRow($post_data['setting_start_row']);
519 }
520
521 if (isset($post_data['setting_max_row'])) {
522 $importer->setMaxRow($post_data['setting_max_row']);
523 }
524
525 // save settings
526 foreach ($post_data as $key => $value) {
527 if (1 === preg_match('/^setting_(?<key>.*)/', $key, $matches)) {
528
529 $value = $this->sanitize_setting($value);
530 $importer->setSetting($matches['key'], $value);
531 }
532 }
533
534 $parser = $importer->getParser();
535
536 if (isset($post_data['file_settings_encoding'])) {
537 $importer->setFileSetting('file_encoding', $post_data['file_settings_encoding']);
538 }
539
540 if ($parser === 'csv') {
541
542 $clear_config = false;
543 if (isset($post_data['file_settings_delimiter'])) {
544
545 $old_delimiter = $importer->getFileSetting('delimiter');
546 if ($old_delimiter !== $post_data['file_settings_delimiter']) {
547 $clear_config = true;
548 }
549 $importer->setFileSetting('delimiter', $post_data['file_settings_delimiter']);
550 }
551 if (isset($post_data['file_settings_enclosure'])) {
552 $old_enclosure = $importer->getFileSetting('enclosure');
553 if ($old_enclosure !== $post_data['file_settings_enclosure']) {
554 $clear_config = true;
555 }
556 $importer->setFileSetting('enclosure', $post_data['file_settings_enclosure']);
557 }
558 if (isset($post_data['file_settings_show_headings'])) {
559 $importer->setFileSetting('show_headings', $post_data['file_settings_show_headings'] === 'true' || $post_data['file_settings_show_headings'] === true ? true : false);
560 }
561
562 if ($clear_config) {
563 $this->importer_manager->clear_config_files($importer->getId(), true);
564 }
565 } elseif ($parser === 'xml') {
566 if (isset($post_data['file_settings_base_path'])) {
567 $importer->setFileSetting('base_path', $post_data['file_settings_base_path']);
568 }
569 }
570
571 if (isset($post_data['file_settings_setup'])) {
572 $importer->setFileSetting('setup', $post_data['file_settings_setup'] === 'true' ? true : false);
573 }
574
575 if (isset($post_data['map']) && is_array($post_data['map'])) {
576 foreach ($post_data['map'] as $key => $value) {
577
578 if (1 === preg_match('/\._index$/', $key)) {
579 $value = intval($value);
580 }
581
582 $importer->setMap($key, $value);
583 }
584 }
585
586 if (isset($post_data['enabled']) && is_array($post_data['enabled'])) {
587 foreach ($post_data['enabled'] as $key => $value) {
588 if ($value === 'true') {
589 $importer->setEnabled($key);
590 } else {
591 $importer->setEnabled($key, false);
592 }
593 }
594 }
595
596 if (isset($post_data['permissions']) && is_array($post_data['permissions'])) {
597
598 // create
599 if (isset($post_data['permissions']['create'])) {
600 $create = $post_data['permissions']['create'];
601 $importer->setPermission('create', [
602 'enabled' => isset($create['enabled']) && $create['enabled'] === 'true' ? true : false,
603 'type' => isset($create['type']) && in_array($create['type'], ['include', 'exclude'], true) ? $create['type'] : null,
604 'fields' => isset($create['fields']) ? $create['fields'] : [],
605 ]);
606 }
607
608 // update
609 if (isset($post_data['permissions']['update'])) {
610 $update = $post_data['permissions']['update'];
611 $importer->setPermission('update', [
612 'enabled' => isset($update['enabled']) && $update['enabled'] === 'true' ? true : false,
613 'type' => isset($update['type']) && in_array($update['type'], ['include', 'exclude'], true) ? $update['type'] : null,
614 'fields' => isset($update['fields']) ? $update['fields'] : [],
615 ]);
616 }
617
618 // remove
619 if (isset($post_data['permissions']['remove'])) {
620 $importer->setPermission('remove', [
621 'enabled' => $post_data['permissions']['remove']['enabled'] === 'true',
622 'trash' => $post_data['permissions']['remove']['trash'] === 'true',
623 ]);
624 }
625 }
626
627 $result = $importer->save();
628 if (is_wp_error($result)) {
629 return $this->http->end_rest_error($result->get_error_message());
630 }
631 return $this->http->end_rest_success($importer->data());
632 }
633
634 private function sanitize_setting($value)
635 {
636 if (is_array($value)) {
637 foreach ($value as &$tmp) {
638 $tmp = $this->sanitize_setting($tmp);
639 }
640 return $value;
641 } else {
642 if (in_array($value, ['true', 'false'], true)) {
643 if ($value === 'true') {
644 $value = true;
645 } else {
646 $value = false;
647 }
648 }
649 }
650
651 return $value;
652 }
653
654 public function get_status(\WP_REST_Request $request)
655 {
656 $this->http->set_stream_headers();
657
658 Logger::disable();
659
660 $importer_ids = $request->get_param('ids');
661
662 $result = [];
663
664 $query_data = array(
665 'post_type' => IWP_POST_TYPE,
666 'posts_per_page' => -1,
667 'fields' => 'ids'
668 );
669 if (!empty($importer_ids)) {
670 $query_data['post__in'] = $importer_ids;
671 }
672
673 $query = new \WP_Query($query_data);
674
675 foreach ($query->posts as $importer_id) {
676
677 $importer_model = $this->importer_manager->get_importer($importer_id);
678 $config = $this->importer_manager->get_config($importer_model);
679
680 $output = ImporterState::get_state($importer_id);
681 $output['version'] = 2;
682 $output['message'] = $this->generate_status_message($output);
683 $output['importer'] = $importer_id;
684 $output['process'] = intval($config->get('process'));
685
686 $result[] = $this->event_handler->run('iwp/importer/status/output', [$output, $importer_model]);
687 }
688
689 echo json_encode($result) . "\n";
690 die();
691 }
692
693 /**
694 * @param array $data
695 * @return string
696 */
697 protected function generate_status_message($data)
698 {
699 $output = '';
700
701 if (!$data || !isset($data['status']) || is_null($data['status']) || empty($data['status'])) {
702 return '';
703 }
704
705 if (isset($data['status'])) {
706 switch ($data['status']) {
707 case 'cancelled':
708 $output .= 'Import cancelled';
709 break;
710 case 'complete':
711 $output .= 'Import complete';
712 break;
713 case 'error':
714 $output = $data['message'];
715 return $output;
716 break;
717 }
718 }
719
720 if (isset($data['status']) && $data['status'] === 'running' && isset($data['section'])) {
721 switch ($data['section']) {
722 case 'import':
723 case 'delete':
724 $output = $data['section'] === 'import' ? 'Importing: ' : 'Deleting: ';
725 $output .= $data['progress'][$data['section']]['current_row'] . ' / ' . ($data['progress'][$data['section']]['end'] - $data['progress'][$data['section']]['start']);
726
727 break;
728 }
729 }
730
731 if (isset($data['stats'])) {
732 if ($data['stats']['inserts'] > 0) {
733 $output .= sprintf(', Inserts: %d', $data['stats']['inserts']);
734 }
735 if ($data['stats']['updates'] > 0) {
736 $output .= sprintf(', Updates: %d', $data['stats']['updates']);
737 }
738 if ($data['stats']['deletes'] > 0) {
739 $output .= sprintf(', Deletes: %d', $data['stats']['deletes']);
740 }
741 if ($data['stats']['skips'] > 0) {
742 $output .= sprintf(', Skips: %d', $data['stats']['skips']);
743 }
744 if ($data['stats']['errors'] > 0) {
745 $output .= sprintf(', Errors: %d', $data['stats']['errors']);
746 }
747 }
748
749 if (isset($data['timestamp'], $data['updated'])) {
750 /**
751 * @var Util $util
752 */
753 $util = Container::getInstance()->get('util');
754 $output .= ', Run Time: ' . $util->format_time($data['updated'] - $data['timestamp']);
755 } elseif (isset($data['duration'])) {
756 /**
757 * @var Util $util
758 */
759 $util = Container::getInstance()->get('util');
760 $output .= ', Run Time: ' . $util->format_time($data['duration']);
761 }
762
763 return $output;
764 }
765
766 public function delete_importer(\WP_REST_Request $request)
767 {
768 Logger::setRequestType('delete_importer');
769
770 $id = intval($request->get_param('id'));
771 $this->importer_manager->delete_importer($id);
772 return $this->http->end_rest_success(true);
773 }
774
775 public function attach_file(\WP_REST_Request $request)
776 {
777 $id = intval($request->get_param('id'));
778 $post_data = $this->sanitize($request->get_body_params());
779
780 $action = $post_data['action'];
781
782 $importer = $this->importer_manager->get_importer($id);
783
784 // TODO: Remove duplicate code, found in cron manager
785
786 switch ($action) {
787 case 'file_upload':
788 $attachment_id = $this->importer_manager->upload_file($importer, $_FILES['file']);
789 break;
790 case 'file_remote':
791 $raw_source = $post_data['remote_url'];
792 $source = apply_filters('iwp/importer/datasource', $raw_source, $raw_source, $importer);
793 $source = apply_filters('iwp/importer/datasource/remote', $source, $raw_source, $importer);
794
795 $filetype = $importer->getParser();
796 if (is_null($filetype)) {
797 $filetype = $post_data['filetype'];
798 }
799
800 $attachment_id = $this->importer_manager->remote_file($importer, $source, $filetype, null, $importer->getId() . '-');
801 break;
802 case 'file_local':
803 $raw_source = $post_data['local_url'];
804 $source = apply_filters('iwp/importer/datasource', $raw_source, $raw_source, $importer);
805 $source = apply_filters('iwp/importer/datasource/local', $source, $raw_source, $importer);
806 $attachment_id = $this->importer_manager->local_file($importer, $source);
807 break;
808 default:
809 $attachment_id = new \WP_Error('IWP_RM_1', 'Invalid form action');
810 break;
811 }
812
813 if (is_wp_error($attachment_id)) {
814 return $this->http->end_rest_error($attachment_id->get_error_message());
815 }
816
817 return $this->http->end_rest_success($importer->data());
818 }
819
820 public function get_file_process(\WP_REST_Request $request)
821 {
822 try {
823 $id = intval($request->get_param('id'));
824 $post_data = $this->sanitize($request->get_body_params());
825
826 $importer = $this->importer_manager->get_importer($id);
827 if (!$importer) {
828 return $this->http->end_rest_error('Invalid importer');
829 }
830
831 $this->importer_manager->clear_config_files($id, true);
832 $parser = $importer->getParser();
833
834 if ('xml' === $parser) {
835
836 $nodes = $this->importer_manager->process_xml_file($id, true);
837 $importer->setFileSetting('nodes', $nodes);
838 } elseif ('csv' === $parser) {
839
840 $delimiter = isset($post_data['delimiter']) ? $post_data['delimiter'] : null;
841 if (is_null($delimiter)) {
842 $delimiter = ',';
843 }
844
845 $enclosure = isset($post_data['enclosure']) ? $post_data['enclosure'] : null;
846 if (is_null($enclosure)) {
847 $enclosure = '"';
848 }
849
850 $count = $this->importer_manager->process_csv_file($id, $delimiter, $enclosure, true);
851
852 // Need fresh importer, due to process_csv_file importer modifications might get overwritten.
853 $importer = $this->importer_manager->get_importer($id);
854 $importer->setFileSetting('count', $count);
855 } else {
856
857 do_action('iwp/file-process/' . $parser, $importer, $post_data);
858 }
859
860 $importer->setFileSetting('processed', true);
861 $importer->save();
862
863 return $this->http->end_rest_success($importer->data());
864 } catch (\Exception $e) {
865 return $this->http->end_rest_error($e->getMessage());
866 }
867 }
868
869 public function get_file_preview(\WP_REST_Request $request)
870 {
871 try {
872 $id = intval($request->get_param('id'));
873 $post_data = $this->sanitize($request->get_body_params());
874 $importer = $this->importer_manager->get_importer($id);
875
876 $import_file_exists = $this->filesystem->file_exists($importer->getFile());
877 if (is_wp_error($import_file_exists)) {
878 throw new \Exception("Unable to load preview, " . $import_file_exists->get_error_message());
879 }
880
881 $record_index = isset($post_data['record']) ? $post_data['record'] : null;
882 if (is_null($record_index)) {
883 $record_index = 0;
884 }
885
886 // Temp set file_encoding
887 if (isset($post_data['file_encoding'])) {
888 $importer->setFileSetting('file_encoding', $post_data['file_encoding']);
889 }
890
891 if ($importer->getParser() === 'xml') {
892
893 $config = $this->importer_manager->get_config($importer, true);
894 $file = $this->importer_manager->get_xml_file($importer, $config);
895
896 $base_path = $post_data['base_path'];
897 if (!is_null($base_path)) {
898 $file->setRecordPath($base_path);
899 }
900
901 $preview = new XMLPreview($file, $base_path);
902 $result = $preview->data();
903 if (is_wp_error($result)) {
904 return $this->http->end_rest_error($result);
905 }
906
907 return $this->http->end_rest_success($result[0]);
908 } elseif ($importer->getParser() === 'csv') {
909
910 $config = $this->importer_manager->get_config($importer, true);
911 $file = $this->importer_manager->get_csv_file($importer, $config);
912
913 $clear_config = false;
914 if (!is_null($post_data['delimiter']) && $post_data['delimiter'] !== $file->getDelimiter()) {
915 $clear_config = true;
916 } elseif (!is_null($post_data['enclosure']) && $post_data['enclosure'] !== $file->getEnclosure()) {
917 $clear_config = true;
918 }
919
920 if ($clear_config) {
921 $this->importer_manager->clear_config_files($importer->getId(), true);
922 $config = $this->importer_manager->get_config($importer, true);
923 $file = $this->importer_manager->get_csv_file($importer, $config);
924 }
925
926 $delimiter = $post_data['delimiter'];
927 if (!is_null($delimiter)) {
928 $file->setDelimiter($delimiter);
929 }
930
931 $enclosure = $post_data['enclosure'];
932 if (!is_null($enclosure)) {
933 $file->setEnclosure($enclosure);
934 }
935
936 // parse bool param from string
937 $show_headings = $post_data['show_headings'];
938 if (in_array($show_headings, ['true', 'false'])) {
939 $show_headings = $show_headings === 'true' ? true : false;
940 }
941
942 if (is_null($show_headings)) {
943 $show_headings = $importer->getFileSetting('show_headings');
944 }
945
946 $preview = new CSVPreview($file);
947 $result = $preview->data($record_index, $show_headings);
948 if (is_wp_error($result)) {
949 return $this->http->end_rest_error($result);
950 }
951
952 return $this->http->end_rest_success($result);
953 } else {
954
955 $result = apply_filters('iwp/file-preview/' . $importer->getParser(), null, $importer);
956 if (is_wp_error($result)) {
957 return $this->http->end_rest_error($result);
958 }
959
960 return $this->http->end_rest_success($result);
961 }
962 } catch (\Exception $error) {
963 return $this->http->end_rest_error($error->getMessage());
964 }
965 }
966
967 public function get_preview(\WP_REST_Request $request)
968 {
969 // if no fields have been posted send all previews
970 try {
971 $id = intval($request->get_param('id'));
972 $importer = $this->importer_manager->get_importer($id);
973 $import_file_exists = $this->filesystem->file_exists($importer->getFile());
974 if (is_wp_error($import_file_exists)) {
975 throw new \Exception("Unable to load preview, " . $import_file_exists->get_error_message());
976 }
977
978 $parser = $importer->getParser();
979
980 $fields = $this->sanitize($request->get_body_params());
981 if (is_null($fields) || empty($fields)) {
982 $fields = $importer->getMap();
983 }
984
985 if ('xml' === $parser) {
986 $result = $this->importer_manager->preview_xml_file($importer, $fields);
987 } elseif ('csv' === $parser) {
988 $row = 0;
989 if ($importer->getFileSetting('show_headings') === true) {
990 $row = 1;
991 }
992 $result = $this->importer_manager->preview_csv_file($importer, $fields, $row);
993 } else {
994
995 $result = apply_filters('iwp/record-preview/' . $parser, [], $importer, $fields);
996 if (is_wp_error($result)) {
997 return $this->http->end_rest_error($result);
998 }
999
1000 return $this->http->end_rest_success($result);
1001 }
1002
1003 return $this->http->end_rest_success($result);
1004 } catch (\Exception $error) {
1005 return $this->http->end_rest_error($error->getMessage());
1006 }
1007 }
1008
1009 /**
1010 * Trigger a new import.
1011 *
1012 * @param \WP_REST_Request $request
1013 * @return array
1014 */
1015 public function init_import(\WP_REST_Request $request)
1016 {
1017 $id = intval($request->get_param('id'));
1018
1019 Logger::setRequestType('rest::init_import');
1020
1021 Logger::write('init_import -start', $id);
1022
1023 $importer_data = $this->importer_manager->get_importer($id);
1024
1025 // clear existing
1026 ImporterState::clear_options($importer_data->getId());
1027
1028 // This is used for storing version on imported records
1029 $session_id = md5($importer_data->getId() . time());
1030 update_post_meta($importer_data->getId(), '_iwp_session', $session_id);
1031
1032 Logger::clearRequestType();
1033
1034 return $this->http->end_rest_success([
1035 'session' => $session_id
1036 ]);
1037 }
1038
1039 public function run_import(\WP_REST_Request $request)
1040 {
1041 $this->http->set_stream_headers();
1042
1043 Logger::setRequestType('rest::run_import');
1044
1045 $session = $request->get_param('session');
1046 $user = uniqid('iwp', true);
1047 $id = intval($request->get_param('id'));
1048 Logger::write('run_import -session=' . $session, $id);
1049
1050 $importer_data = $this->importer_manager->get_importer($id);
1051 Logger::write('run_import -import=start', $id);
1052
1053 $state = $this->importer_manager->import($importer_data->getId(), $user, $session);
1054 $state['message'] = $this->generate_status_message($state);
1055
1056 Logger::clearRequestType();
1057
1058 return $this->http->end_rest_success($state);
1059 }
1060
1061 public function pause_import(\WP_REST_Request $request)
1062 {
1063 $id = intval($request->get_param('id'));
1064 $paused = $this->sanitize($request->get_param('paused'), 'paused');
1065
1066 $importer_data = $this->importer_manager->get_importer($id);
1067 $user = uniqid('iwp', true);
1068
1069 $state = ImporterState::wait_for_lock($importer_data->getId(), $user, function () use ($importer_data, $paused) {
1070 $state = ImporterState::get_state($importer_data->getId());
1071
1072
1073 if ($paused === 'no') {
1074 $state['status'] = 'running';
1075 } else {
1076 $state['status'] = 'paused';
1077 }
1078
1079 ImporterState::set_state($importer_data->getId(), $state);
1080 return $state;
1081 });
1082
1083 return $this->http->end_rest_success($state);
1084 }
1085
1086 public function stop_import(\WP_REST_Request $request)
1087 {
1088 $id = intval($request->get_param('id'));
1089
1090 $importer_data = $this->importer_manager->get_importer($id);
1091
1092 $user = uniqid('iwp');
1093
1094 $state = ImporterState::wait_for_lock($importer_data->getId(), $user, function () use ($importer_data) {
1095 $state = ImporterState::get_state($importer_data->getId());
1096 $state['status'] = 'cancelled';
1097 ImporterState::set_state($importer_data->getId(), $state);
1098 return $state;
1099 });
1100
1101 return $this->http->end_rest_success($state);
1102 }
1103
1104 /**
1105 * Get field options for current template
1106 *
1107 * @param \WP_REST_Request $request
1108 * @return void
1109 */
1110 public function get_template_field_options(\WP_REST_Request $request)
1111 {
1112 $id = intval($request->get_param('id'));
1113 $field = $this->sanitize($request->get_param('field'), 'field');
1114
1115 $importer_data = $this->importer_manager->get_importer($id);
1116 $template = $this->importer_manager->get_importer_template($id);
1117
1118 return $this->http->end_rest_success($template->get_field_options($field, $importer_data));
1119 }
1120
1121 public function get_logs(\WP_REST_Request $request)
1122 {
1123 $id = intval($request->get_param('id'));
1124 $importer_data = $this->importer_manager->get_importer($id);
1125 $logs = $this->importer_manager->get_importer_logs($importer_data);
1126 return $this->http->end_rest_success(array_reverse($logs));
1127 }
1128
1129 public function get_log(\WP_REST_Request $request)
1130 {
1131 $id = intval($request->get_param('id'));
1132 $session = $this->sanitize($request->get_param('session'), 'session');
1133 $page = intval($request->get_param('page'));
1134 if ($page < 1) {
1135 $page = 1;
1136 }
1137 $importer_data = $this->importer_manager->get_importer($id);
1138 $log = $this->importer_manager->get_importer_log($importer_data, $session, $page, 500);
1139 $status = $this->importer_manager->get_importer_status_report($importer_data, $session);
1140 return $this->http->end_rest_success(['logs' => $log, 'status' => $status]);
1141 }
1142
1143 public function get_debug_log(\WP_REST_Request $request)
1144 {
1145 $id = intval($request->get_param('id'));
1146 $page = intval($request->get_param('page'));
1147 if ($page < 1) {
1148 $page = 1;
1149 }
1150 $importer_data = $this->importer_manager->get_importer($id);
1151 $log = $this->importer_manager->get_importer_debug_log($importer_data, $page, 100);
1152
1153 $download = Logger::getLogFile($importer_data->getId(), true);
1154 return $this->http->end_rest_success(['log' => $log, 'download' => $download]);
1155 }
1156
1157 public function save_settings(\WP_REST_Request $request)
1158 {
1159 $post_data = $request->get_body_params();
1160 $post_data = $this->sanitize($post_data);
1161
1162 $defaults = $this->properties->_default_settings();
1163
1164 $output = [];
1165
1166 foreach ($defaults as $setting => $default) {
1167 if (isset($post_data[$setting])) {
1168 if ('bool' === $default['type']) {
1169 // Handle Boolean
1170 if (is_bool($post_data[$setting])) {
1171 $output[$setting] = $post_data[$setting];
1172 } elseif (in_array($post_data[$setting], ['true', 'false'])) {
1173 $output[$setting] = $post_data[$setting] === 'true' ? true : false;
1174 } else {
1175 $output[$setting] = boolval($post_data[$setting]);
1176 }
1177 } elseif ('number' === $default['type']) {
1178 $output[$setting] = intval($post_data[$setting]);
1179 } else {
1180 $output[$setting] = $post_data[$setting];
1181 }
1182 } else {
1183 $output[$setting] = $default['value'];
1184 }
1185 }
1186
1187 update_site_option('iwp_settings', $output);
1188
1189 return $this->http->end_rest_success($this->properties->get_settings());
1190 }
1191
1192 public function get_settings(\WP_REST_Request $request = null)
1193 {
1194 $output = $this->properties->get_settings();
1195 return $this->http->end_rest_success($output);
1196 }
1197
1198 public function get_template(\WP_REST_Request $request = null)
1199 {
1200 Logger::setRequestType('get_template');
1201
1202 $importer_id = $request->get_param('id');
1203 $importer_model = $this->importer_manager->get_importer($importer_id);
1204 $importer_template = $importer_model->getTemplate();
1205
1206 $templates = $this->importer_manager->get_templates();
1207
1208 if (!isset($templates[$importer_template])) {
1209 return $this->http->end_rest_error("Invalid template \"" . $importer_template . "\"");
1210 }
1211
1212 $template_id = $templates[$importer_template];
1213 $template_class = $this->template_manager->load_template($template_id);
1214
1215 $output = [
1216 'id' => $template_id,
1217 'label' => $template_class->get_name(),
1218 'map' => $template_class->get_fields($importer_model),
1219 'settings' => $template_class->register_settings(),
1220 'options' => $template_class->register_options(),
1221 ];
1222 return $this->http->end_rest_success($output);
1223 }
1224
1225 public function export_importers(\WP_REST_Request $request = null)
1226 {
1227 Logger::setRequestType('export_importers');
1228
1229 $importer_ids = $request->get_param('ids');
1230
1231 $sql_ids = array_map(function ($v) {
1232 return "'" . esc_sql($v) . "'";
1233 }, $importer_ids);
1234 $sql_ids = implode(',', $sql_ids);
1235
1236 $output = [];
1237
1238 /**
1239 * @var \WPDB $wpdb
1240 */
1241 global $wpdb;
1242 $results = $wpdb->get_results("SELECT post_title, post_content from {$wpdb->posts} WHERE post_type='" . IWP_POST_TYPE . "' AND ID IN (" . $sql_ids . ")", ARRAY_A);
1243 foreach ($results as $result) {
1244
1245 $data = unserialize($result['post_content']);
1246
1247 unset($data['file']['id']);
1248 unset($data['file']['settings']['count']);
1249 unset($data['file']['settings']['processed']);
1250
1251
1252 $row = [
1253 'name' => $result['post_title'],
1254 'data' => $data
1255 ];
1256
1257 if ($this->importer_manager->is_debug()) {
1258 $row['raw'] = base64_encode($result['post_content']);
1259 }
1260
1261 $output[] = $row;
1262 }
1263
1264 $json = json_encode($output);
1265
1266 header('Content-disposition: attachment; filename="ImportWP-export-' . date('Y-m-d') . '.json"');
1267 header('Content-type: "application/json"; charset="utf8"');
1268 header('Expires: 0');
1269 header('Cache-Control: must-revalidate');
1270 header('Pragma: public');
1271 header('Content-Length: ' . strlen($json));
1272
1273 echo $json;
1274 die();
1275 }
1276
1277 public function import_exporters(\WP_REST_Request $request = null)
1278 {
1279 Logger::setRequestType('import_exporters');
1280
1281 $upload = $this->filesystem->upload_file($_FILES['file']);
1282 if (is_wp_error($upload)) {
1283 return $this->http->end_rest_error($upload->get_error_message());
1284 }
1285
1286 $json_contents = file_get_contents($upload['dest']);
1287 @unlink($upload['dest']);
1288
1289 $contents = json_decode($json_contents, true);
1290 $counter = 0;
1291 $errors = [];
1292 if (!empty($contents)) {
1293 foreach ($contents as $importer) {
1294
1295 $result = wp_insert_post([
1296 'post_type' => IWP_POST_TYPE,
1297 'post_title' => $importer['name'],
1298 'post_status' => 'publish',
1299 'post_author' => get_current_user_id(),
1300 'post_content' => serialize($importer['data'])
1301 ], true);
1302
1303 if (is_wp_error($result)) {
1304 $errors[] = $result->get_error_message();
1305 continue;
1306 }
1307
1308 $counter++;
1309 }
1310 }
1311
1312 if (empty($counter)) {
1313 return $this->http->end_rest_error('No Importers found.');
1314 }
1315
1316 return $this->http->end_rest_success("Import Complete, {$counter} Importer" . ($counter > 1 ? 's' : '') . '.');
1317 }
1318
1319 public function save_exporter(\WP_REST_Request $request = null)
1320 {
1321 Logger::setRequestType('save_exporter');
1322
1323 $post_data = $request->get_body_params();
1324 $id = isset($post_data['id']) ? intval($post_data['id']) : null;
1325
1326
1327 $exporter = new ExporterModel($id, $this->importer_manager->is_debug());
1328
1329 if (isset($post_data['name'])) {
1330 $exporter->setName($post_data['name']);
1331 }
1332
1333 if (isset($post_data['type'])) {
1334 $exporter->setType($post_data['type']);
1335 }
1336
1337 if (isset($post_data['file_type'])) {
1338 $exporter->setFileType($post_data['file_type']);
1339 }
1340
1341 if (isset($post_data['fields']) || $id > 0) {
1342 $exporter->setFields(isset($post_data['fields']) ? $post_data['fields'] : []);
1343 }
1344
1345 if (isset($post_data['filters']) || $id > 0) {
1346 $exporter->setFilters(isset($post_data['filters']) ? $post_data['filters'] : []);
1347 }
1348
1349 if (isset($post_data['unique_identifier'])) {
1350 $exporter->setUniqueIdentifier($post_data['unique_identifier']);
1351 }
1352
1353 if (isset($post_data['export_method'])) {
1354 $exporter->setExportMethod($post_data['export_method']);
1355 }
1356
1357 if (isset($post_data['cron'])) {
1358
1359 // TODO: Save cron settings
1360
1361 $cron = $this->sanitize_setting($post_data['cron']);
1362 $exporter->setCron($cron);
1363 }
1364
1365 $result = $exporter->save();
1366 if (is_wp_error($result)) {
1367 return $this->http->end_rest_error($result->get_error_message());
1368 }
1369 return $this->http->end_rest_success($exporter->data());
1370 }
1371
1372 public function get_exporters(\WP_REST_Request $request = null)
1373 {
1374 Logger::setRequestType('get_exporters');
1375
1376 $exporters = $this->exporter_manager->get_exporters();
1377 $result = [];
1378
1379 foreach ($exporters as $exporter) {
1380 $result[] = $exporter->data();
1381 }
1382
1383 return $this->http->end_rest_success($result);
1384 }
1385
1386 public function get_exporter(\WP_REST_Request $request = null)
1387 {
1388 Logger::setRequestType('get_exporter');
1389
1390 $id = intval($request->get_param('id'));
1391 $exporter_data = $this->exporter_manager->get_exporter($id);
1392 $response = $exporter_data->data('public');
1393 return $this->http->end_rest_success($response);
1394 }
1395
1396 public function delete_exporter(\WP_REST_Request $request = null)
1397 {
1398 Logger::setRequestType('delete_exporter');
1399
1400 $id = intval($request->get_param('id'));
1401 $this->exporter_manager->delete_exporter($id);
1402 return $this->http->end_rest_success(true);
1403 }
1404
1405 /**
1406 * Trigger a new export.
1407 *
1408 * @param \WP_REST_Request $request
1409 * @return array
1410 */
1411 public function init_export(\WP_REST_Request $request)
1412 {
1413 $id = intval($request->get_param('id'));
1414
1415 Logger::setRequestType('rest::init_export');
1416
1417 Logger::write('init_import -start', $id);
1418
1419 $exporter_data = $this->exporter_manager->get_exporter($id);
1420
1421 // clear existing
1422 ExporterState::clear_options($exporter_data->getId());
1423
1424 // This is used for storing version on imported records
1425 $session_id = md5($exporter_data->getId() . time());
1426 update_post_meta($exporter_data->getId(), '_iwp_session', $session_id);
1427
1428 Logger::clearRequestType();
1429
1430 return $this->http->end_rest_success([
1431 'session' => $session_id
1432 ]);
1433 }
1434
1435 public function run_exporter(\WP_REST_Request $request)
1436 {
1437 Logger::setRequestType('run_exporter');
1438
1439 $this->http->set_stream_headers();
1440
1441 $id = intval($request->get_param('id'));
1442 $session = $request->get_param('session');
1443 $user = uniqid('iwp', true);
1444
1445 $exporter_data = $this->exporter_manager->get_exporter($id);
1446
1447 $status = $this->exporter_manager->export($exporter_data, $user, $session);
1448 echo json_encode($status);
1449 // Logger::write(__CLASS__ . '::run_import -import=end -status=' . $status->get_status(), $id);
1450
1451 // if (!empty($this->output_cache)) {
1452 // echo $this->output_cache;
1453 // $this->output_cache = '';
1454 // }
1455
1456 // $output = $status->output();
1457 // $output['message'] = $this->generate_exporter_status_message($status);
1458 // echo json_encode($output) . "\n";
1459 die();
1460 }
1461
1462 public function get_exporter_status(\WP_REST_Request $request)
1463 {
1464 Logger::setRequestType('get_exporter_status');
1465
1466 $exporter_ids = $request->get_param('ids');
1467 $result = array();
1468 $query_data = array(
1469 'post_type' => EWP_POST_TYPE,
1470 'posts_per_page' => -1,
1471 'fields' => 'ids'
1472 );
1473
1474 if (!empty($exporter_ids)) {
1475 $query_data['post__in'] = $exporter_ids;
1476 }
1477
1478 $query = new \WP_Query($query_data);
1479
1480 if (!empty($query->posts)) {
1481 foreach ($query->posts as $post_id) {
1482
1483 $exporter = $this->exporter_manager->get_exporter($post_id);
1484 $status = ExporterState::get_state($post_id);
1485 $status['exporter'] = $post_id;
1486 $status['version'] = 2;
1487
1488 $current = $status['progress']['export']['current_row'];
1489 $end = $status['progress']['export']['end'] - $status['progress']['export']['start'];
1490 $status['progress'] = $end > 0 ? ($current / $end) * 100 : 0;
1491
1492 $output = '';
1493
1494 switch ($status['status']) {
1495 case 'cancelled':
1496 $output .= 'Export cancelled';
1497 break;
1498 case 'complete':
1499 $output .= 'Export complete';
1500 break;
1501 case 'running':
1502 $output .= 'Exporting: ' . $current . '/' . $end;
1503 break;
1504 }
1505
1506 $status['message'] = $output;
1507
1508 $result[] = $this->event_handler->run('iwp/exporter/status/output', [$status, $exporter]);
1509 }
1510 }
1511
1512 echo json_encode($result) . "\n";
1513 die();
1514 }
1515 }
1516