PluginProbe
Import WP – CSV & XML Import Export for WordPress / 2.8.1
Import WP – CSV & XML Import Export for WordPress v2.8.1
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 / Exporter / ExporterManager.php

ExporterManager.php in Import WP – CSV & XML Import Export for WordPress 2.8.1, at class/Common/Exporter/ExporterManager.php

476 lines 14.0 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\Exporter;
4
5 use Exception;
6 use ImportWP\Common\Exporter\File\CSVFile;
7 use ImportWP\Common\Exporter\File\JSONFile;
8 use ImportWP\Common\Exporter\File\XMLFile;
9 use ImportWP\Common\Exporter\Mapper\CommentMapper;
10 use ImportWP\Common\Exporter\Mapper\MapperData;
11 use ImportWP\Common\Exporter\Mapper\PostMapper;
12 use ImportWP\Common\Exporter\Mapper\TaxMapper;
13 use ImportWP\Common\Exporter\Mapper\UserMapper;
14 use ImportWP\Common\Exporter\State\ExporterState;
15 use ImportWP\Common\Model\ExporterModel;
16 use ImportWP\Common\Runner\ExporterRunner;
17 use ImportWP\Common\Util\Logger;
18 use ImportWP\Container;
19
20 class ExporterManager
21 {
22 public function __construct()
23 {
24 add_action('admin_init', [$this, 'download_file']);
25 }
26
27 /**
28 * Download exporter file directly
29 *
30 * @return void
31 */
32 public function download_file()
33 {
34
35 if (!isset($_GET['page'], $_GET['exporter'], $_GET['download']) || $_GET['page'] !== 'importwp') {
36 return;
37 }
38
39 $exporter_data = $this->get_exporter(intval($_GET['exporter']));
40 $file = sanitize_key($_GET['download']);
41
42 $download_data = get_post_meta($exporter_data->getId(), '_ewp_file_' . $file, true);
43 if ($download_data) {
44
45 delete_post_meta($exporter_data->getId(), '_ewp_file_' . $file, $download_data);
46
47 header('Content-disposition: attachment; filename="' . basename($download_data['path']) . '"');
48 header('Content-type: "text/' . $download_data['type'] . '"; charset="utf8"');
49 readfile($download_data['path']);
50 die();
51 }
52 }
53
54 /**
55 * Get Exporters
56 *
57 * @return ExporterModel[]
58 */
59 public function get_exporters()
60 {
61
62 $result = array();
63 $query = new \WP_Query(array(
64 'post_type' => EWP_POST_TYPE,
65 'posts_per_page' => -1,
66 ));
67
68 foreach ($query->posts as $post) {
69 $result[] = $this->get_exporter($post);
70 }
71 return $result;
72 }
73
74 /**
75 * Get Exporter
76 *
77 * @param int $id
78 * @return ExporterModel
79 */
80 public function get_exporter($id)
81 {
82 if ($id instanceof ExporterModel) {
83 return $id;
84 }
85
86 if (EWP_POST_TYPE !== get_post_type($id)) {
87 return false;
88 }
89
90 return new ExporterModel($id, $this->is_debug());
91 }
92
93 public function is_debug()
94 {
95
96 if (defined('IWP_DEBUG') && true === IWP_DEBUG) {
97 return true;
98 }
99
100 $uninstall_enabled = get_option('iwp_settings');
101 if (isset($uninstall_enabled['debug']) && true === $uninstall_enabled['debug']) {
102 return true;
103 }
104
105 return false;
106 }
107
108 /**
109 * Delete Importer
110 *
111 * @param int $id
112 * @return void
113 */
114 public function delete_exporter($id)
115 {
116 $exporter = $this->get_exporter($id);
117 $exporter->delete();
118 }
119
120 public function export($id, $user = null, $session = null)
121 {
122 Logger::timer();
123
124 if (is_null($user)) {
125 $user = uniqid('iwp', true);
126 }
127
128 $exporter_data = $this->get_exporter($id);
129 $exporter_id = $exporter_data->getId();
130
131 $config_data = []; // get_site_option('iwp_exporter_config_' . $exporter_id, []);
132
133 $state = new ExporterState($exporter_id, $user);
134
135 try {
136
137
138 $state->init($session);
139
140 if ($exporter_data->getFileType() === 'csv') {
141 $file = new CSVFile($exporter_data);
142 } elseif ($exporter_data->getFileType() === 'xml') {
143 $file = new XMLFile($exporter_data);
144 } else {
145 $file = new JSONFile($exporter_data);
146 }
147
148 $type = $exporter_data->getType();
149 $matches = null;
150 if (preg_match('/^ewp_tax_(.*?)$/', $type, $matches) == 1) {
151 $taxonomy = $matches[1];
152 $mapper = new TaxMapper($taxonomy);
153 } elseif (preg_match('/^ewp_comment_(.*?)$/', $type, $matches) == 1) {
154 $post_type = $matches[1];
155 $mapper = new CommentMapper($post_type);
156 } elseif ($type === 'user') {
157 $mapper = new UserMapper();
158 } else {
159
160 $mapper = apply_filters('iwp/exporter/load_mapper', false, $type);
161 if (!$mapper) {
162 $mapper = new PostMapper($type);
163 }
164 }
165
166 /**
167 * @var MapperInterface $mapper
168 */
169 $mapper->set_filters($exporter_data->getFilters());
170
171 // Default to showing all fields, if none selected
172 if (empty($exporter_data->getFields(true))) {
173
174 $fields = $mapper->get_fields();
175
176 switch ($exporter_data->getFileType()) {
177 case 'csv':
178 $fields = $this->flattenFields($fields);
179 break;
180 default:
181 $fields = $this->nestedFields($fields);
182 break;
183 }
184
185
186 $exporter_data->setFields($fields);
187 }
188
189
190
191 if ($state->has_status('init')) {
192
193 if (!$mapper->have_records($exporter_id)) {
194 throw new \Exception(("No records found to export"));
195 }
196
197 // write
198 $config_data['id'] = $state->get_session();
199 $config_data['version'] = 1;
200 $config_data['records'] = $mapper->get_records();
201
202 // save
203 update_site_option('iwp_exporter_config_' . $exporter_id, $config_data);
204
205 $state->update(function ($state) use ($config_data) {
206 $state['id'] = $config_data['id'];
207 $state['status'] = 'running';
208 $state['progress']['export']['start'] = 0;
209 $state['progress']['export']['end'] = count($config_data['records']);
210 return $state;
211 });
212
213 $file->wipe();
214 $file->start();
215 } else {
216 $config_data = get_site_option('iwp_exporter_config_' . $exporter_id, []);
217 $mapper->set_records($config_data['records']);
218 }
219
220 /**
221 * @var Properties $properties
222 */
223 $properties = Container::getInstance()->get('properties');
224 $runner = new ExporterRunner($properties, $mapper, $file);
225 $runner->process($exporter_id, $user, $state);
226
227 // Lock the file to only write 1 end of file
228 if ($state->has_status('end')) {
229 $state->update(function ($state) use ($exporter_data, $file) {
230
231 if ($state['status'] !== 'end') {
232 return $state;
233 }
234
235 $file->end();
236
237 $key = md5(time());
238 add_post_meta($exporter_data->getId(), '_ewp_file_' . $key, array(
239 'url' => $file->get_file_url(),
240 'path' => $file->get_file_path(),
241 'type' => $exporter_data->getFileType()
242 ));
243 $state['file'] = $key;
244 $state['status'] = 'complete';
245 return $state;
246 });
247 }
248 } catch (\Exception $e) {
249
250 Logger::error('import -error=' . $e->getMessage(), $exporter_id);
251 return $state->error($e)->get_raw();
252 }
253
254
255 return $state->update(function ($data) {
256 $data['duration'] = floatval($data['duration']) + Logger::timer();
257 return $data;
258 })->get_raw();
259 }
260
261 public function export_old($id)
262 {
263 $exporter_data = $this->get_exporter($id);
264 $previous_time = microtime(true);
265
266 if ($exporter_data->getFileType() === 'csv') {
267 $file = new CSVFile($exporter_data);
268 } elseif ($exporter_data->getFileType() === 'xml') {
269 $file = new XMLFile($exporter_data);
270 } else {
271 $file = new JSONFile($exporter_data);
272 }
273
274 $type = $exporter_data->getType();
275 $matches = null;
276 if (preg_match('/^ewp_tax_(.*?)$/', $type, $matches) == 1) {
277 $taxonomy = $matches[1];
278 $mapper = new TaxMapper($taxonomy);
279 } elseif (preg_match('/^ewp_comment_(.*?)$/', $type, $matches) == 1) {
280 $post_type = $matches[1];
281 $mapper = new CommentMapper($post_type);
282 } elseif ($type === 'user') {
283 $mapper = new UserMapper();
284 } else {
285
286 $mapper = apply_filters('iwp/exporter/load_mapper', false, $type);
287 if (!$mapper) {
288 $mapper = new PostMapper($type);
289 }
290 }
291
292 $mapper->set_filters($exporter_data->getFilters());
293
294 // Default to showing all fields, if none selected
295 if (empty($exporter_data->getFields(true))) {
296
297 $fields = $mapper->get_fields();
298
299 switch ($exporter_data->getFileType()) {
300 case 'csv':
301 $fields = $this->flattenFields($fields);
302 break;
303 default:
304 $fields = $this->nestedFields($fields);
305 break;
306 }
307
308
309 $exporter_data->setFields($fields);
310 }
311
312 $file->start();
313
314 $columns = $exporter_data->getFields();
315
316 $total = 0;
317 $i = 0;
318
319 if ($mapper->have_records($exporter_data->getId())) {
320
321 $total = $mapper->found_records();
322
323 for ($i = 0; $i < $total; $i++) {
324
325 $mapper_data = new MapperData($mapper, $i);
326 if (!$mapper_data->skip()) {
327 $file->add($mapper_data);
328 }
329
330 $current_time = microtime(true);
331 $delta_time = $current_time - $previous_time;
332
333 if ($delta_time > 0.1) {
334 $exporter_data->set_status('running', $i, $total);
335 $previous_time = $current_time;
336 }
337 }
338 }
339
340 $file->end();
341
342 $key = md5(time());
343 add_post_meta($exporter_data->getId(), '_ewp_file_' . $key, array(
344 'url' => $file->get_file_url(),
345 'path' => $file->get_file_path(),
346 'type' => $exporter_data->getFileType()
347 ));
348
349 $status = $exporter_data->set_status('complete', $i, $total);
350 $status['file'] = $key;
351 return $status;
352 // echo json_encode($status) . "\n";
353
354 // flush();
355 // ob_flush();
356 // die();
357 }
358
359 public function flattenFields($fields, $prefix = '')
360 {
361 $output = [];
362
363 $output = array_merge($output, array_reduce($fields['fields'], function ($carry, $item) use ($prefix) {
364
365 $carry[] = [
366 'parent' => 0,
367 'id' => count($carry) + 1,
368 'selection' => $prefix . $item,
369 'loop' => false,
370 'custom' => false
371 ];
372
373 return $carry;
374 }, []));
375
376 if (!empty($fields['children'])) {
377 foreach ($fields['children'] as $child) {
378 $output = array_merge($output, $this->flattenFields($child, $child['key'] . '.'));
379 }
380 }
381
382 return $output;
383 }
384
385 private $nested_field_counter = 0;
386
387 public function nestedFields($fields, $prefix = '', $parent = 0)
388 {
389 $output = [];
390
391 if ($parent == 0) {
392
393 $this->nested_field_counter = 1;
394 $output[] = [
395 'parent' => 0,
396 'id' => 1,
397 'selection' => '',
398 'label' => 'records',
399 'loop' => false,
400 ];
401
402 $this->nested_field_counter++;
403 $output[] = [
404 'parent' => 1,
405 'id' => 2,
406 'selection' => 'main',
407 'label' => 'record',
408 'loop' => true,
409 ];
410
411 $parent = 2;
412 } elseif ($fields['loop'] == true) {
413 $this->nested_field_counter++;
414 $output[] = [
415 'parent' => $parent,
416 'id' => $this->nested_field_counter,
417 'selection' => '',
418 'label' => $fields['key'] . '_wrapper',
419 'loop' => false,
420 ];
421 $parent = $this->nested_field_counter;
422
423 $this->nested_field_counter++;
424 $output[] = [
425 'parent' => $parent,
426 'id' => $this->nested_field_counter,
427 'selection' => $fields['key'],
428 'label' => $fields['key'],
429 'loop' => true,
430 ];
431
432 $parent = $this->nested_field_counter;
433 }
434
435 if (isset($fields['loop_fields']) && !empty($fields['loop_fields'])) {
436
437 $output = array_merge($output, array_reduce($fields['loop_fields'], function ($carry, $item) use ($parent) {
438
439 $this->nested_field_counter++;
440 $carry[] = [
441 'parent' => $parent,
442 'id' => $this->nested_field_counter,
443 'selection' => $item,
444 'loop' => false,
445 'custom' => false
446 ];
447
448 return $carry;
449 }, []));
450 } else {
451
452 $output = array_merge($output, array_reduce($fields['fields'], function ($carry, $item) use ($prefix, $parent) {
453
454 $this->nested_field_counter++;
455 $carry[] = [
456 'parent' => $parent,
457 'id' => $this->nested_field_counter,
458 'selection' => $prefix . $item,
459 'loop' => false,
460 'custom' => false
461 ];
462
463 return $carry;
464 }, []));
465 }
466
467 if (!empty($fields['children'])) {
468 foreach ($fields['children'] as $child) {
469 $output = array_merge($output, $this->nestedFields($child, $child['key'] . '.', $parent));
470 }
471 }
472
473 return $output;
474 }
475 }
476