PluginProbe
Import WP – CSV & XML Import Export for WordPress / 2.7.5
Import WP – CSV & XML Import Export for WordPress v2.7.5
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 / File / XMLFile.php

XMLFile.php in Import WP – CSV & XML Import Export for WordPress 2.7.5, at class/Common/Exporter/File/XMLFile.php

311 lines 10.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\Exporter\File;
4
5 use ImportWP\Common\Exporter\Mapper\MapperData;
6
7 class XMLFile extends File
8 {
9 private $template;
10 private $template_loops;
11 private $template_sections = [];
12 private $template_data = [];
13 private $i = -1;
14
15 public function start()
16 {
17 // Generating a template, allows at a later date for custom templates to be added via user.
18 $this->template = $this->generateTemplate();
19
20 // Parse Template <!-- ewp:loop {"loop": "post"} -->
21 preg_match_all('/<!--\s*(\/?)ewp:loop\s*(\{.*?\})?\s*-->/', $this->template, $this->template_loops, PREG_OFFSET_CAPTURE);
22
23 // generate template loop data from matches
24 $last = $this->template_loops[0][count($this->template_loops[0]) - 1];
25 $this->template_sections['start'] = substr($this->template, 0, $this->template_loops[0][0][1]); // + strlen($this->template_loops[0][0][0]));
26 $this->template_sections['end'] = substr($this->template, $last[1] + strlen($last[0]));
27
28 fputs($this->fh, $this->template_sections['start'] . PHP_EOL);
29
30 $data = $this->buildTemplateDataStructure([]);
31 $this->template_data = $data[0];
32 }
33
34
35 public function buildTemplateDataStructure($data)
36 {
37 $this->i++;
38
39 if (count($this->template_loops[0]) < $this->i + 1) {
40 return $data;
41 }
42
43 $is_opener = $this->template_loops[1][$this->i][0] !== '/';
44 if ($is_opener) {
45
46 $row = [];
47 $row['id'] = $this->template_loops[0][$this->i][0];
48 $row['args'] = json_decode($this->template_loops[2][$this->i][0], true);
49 $row['start'] = $this->template_loops[0][$this->i][1];
50 $row['children'] = $this->buildTemplateDataStructure([]);
51 $row['end'] = $this->template_loops[0][$this->i][1];
52
53 $start_with_offset = $row['start'] + strlen($row['id']);
54
55 $row['template'] = [];
56
57 if (!empty($row['children'])) {
58
59 // start
60 $row['template']['open'] = trim(substr($this->template, $start_with_offset, $row['children'][0]['start'] - $start_with_offset));
61
62 // inbetween parts
63 if (count($row['children']) > 1) {
64
65 $tmp = [];
66 $tmp[] = $row['children'][0];
67
68 for ($i = 1; $i < count($row['children']); $i++) {
69 $prev = $row['children'][$i - 1];
70 $current = $row['children'][$i];
71 $end_with_offset = $prev['end'] + strlen($this->template_loops[0][$this->i][0]);
72 $tmp[] = trim(substr($this->template, $end_with_offset, $current['start'] - $end_with_offset));
73 $tmp[] = $row['children'][$i];
74 }
75
76 $row['children'] = $tmp;
77 }
78
79 // end
80
81 $prev_index = $this->i - 1;
82
83 $end_start = $this->template_loops[0][$prev_index][1] + strlen($this->template_loops[0][$prev_index][0]);
84 $end_end = $this->template_loops[0][$this->i][1];
85
86 $row['template']['close'] = trim(substr($this->template, $end_start, $end_end - $end_start));
87
88 // $next_index = $this->i + 1 == count($this->template_loops[0]) ? -1 : $this->i + 1;
89 // $end_with_offset = $row['end'] + strlen($this->template_loops[0][$this->i][0]);
90 // if ($next_index == -1) {
91 // $row['template'][] = trim(substr($this->template, $end_with_offset));
92 // } else {
93 // $row['template'][] = trim(substr($this->template, $end_with_offset, $this->template_loops[0][$next_index][1] - $end_with_offset));
94 // }
95 } else {
96 $row['template']['main'] = trim(substr($this->template, $start_with_offset, $row['end'] - $start_with_offset));
97 }
98
99 $data[] = $row;
100
101 return $this->buildTemplateDataStructure($data);
102 }
103
104 return $data;
105 }
106
107 public function generateTemplate()
108 {
109 $fields = $this->exporter->getFields();
110 $template = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
111 $template .= $this->recursivelyGenerateXML($fields);
112 return $template;
113 }
114
115 public function recursivelyGenerateXML($fields, $parent = 0, $schema = '', $loop = null)
116 {
117 $current_items = array_filter($fields, function ($item) use ($parent) {
118 return intval($item['parent']) == $parent;
119 });
120
121 // move attributes to top
122 usort($current_items, function ($a, $b) {
123
124 $found_a = isset($a['label']) && strpos($a['label'], '@') === 0;
125 $found_b = isset($b['label']) && strpos($b['label'], '@') === 0;
126
127 if ($found_a && !$found_b) {
128 return -1;
129 } elseif (!$found_a && $found_b) {
130 return 1;
131 }
132
133 return 0;
134 });
135
136
137
138 if (!empty($current_items)) {
139 foreach ($current_items as $current_item) {
140
141 $label = $this->getFieldLabel($current_item);
142
143 $is_attr = strpos($label, '@') === 0;
144
145 if ($is_attr) {
146
147 $label = $this->esc_attr($label);
148
149 // we are an attribute
150 if (isset($current_item['selection']) && !empty($current_item['selection'])) {
151
152 $selection = $current_item['selection'];
153 if (!isset($current_item['custom']) || $current_item['custom'] !== 'true') {
154 $selection = '{' . $selection . ' | ' . wp_json_encode(["escape" => true]) . '}';
155 }
156
157 $schema .= ' ' . $label . '="' . $selection . '"';
158 }
159 continue;
160 }
161
162 if (!$this->hasClosingTag($schema)) {
163 $schema = $this->checkForClosingTag($schema);
164 $schema .= "\n";
165 }
166
167 $label = $this->esc_label($label);
168
169 if (isset($current_item['loop']) && ($current_item['loop'] === 'true' || $current_item['loop'] === true)) {
170
171 $schema .= '<!-- ewp:loop ' . wp_json_encode(['loop' => $current_item['selection']]) . ' -->' . "\n";
172
173 $schema .= '<' . $label;
174 $schema = $this->recursivelyGenerateXML($fields, $current_item['id'], $schema, $current_item['selection']);
175 $schema = $this->checkForClosingTag($schema) . "\n";
176
177 $schema .= '</' . $label . '>' . "\n";
178
179 $schema .= '<!-- /ewp:loop -->' . "\n";
180 } else {
181
182 //TODO: if data is array, repeat
183 $schema .= '<' . $label;
184
185 $schema = $this->recursivelyGenerateXML($fields, $current_item['id'], $schema, $loop);
186
187 $schema = $this->checkForClosingTag($schema);
188
189 if (isset($current_item['selection']) && !empty($current_item['selection'])) {
190
191 $selection = $current_item['selection'];
192 if (!isset($current_item['custom']) || $current_item['custom'] !== 'true') {
193 $selection = '<![CDATA[{' . $selection . '}]]>';
194 }
195
196 $schema .= $selection;
197 }
198
199 $schema .= '</' . $label . '>' . "\n";
200 }
201 }
202 }
203
204 return $schema;
205 }
206
207 public function esc_label($label)
208 {
209
210 $label = str_replace(' ', '_', $label);
211 return $label;
212 }
213
214 public function esc_attr($attr)
215 {
216
217 // remove @ from start
218 $attr = substr($attr, 1);
219 $attr = str_replace(' ', '_', $attr);
220 return $attr;
221 }
222
223 /**
224 * @param MapperData $mapper
225 * @return void
226 */
227 public function add($mapper)
228 {
229 $output = $this->processLoop($this->template_data, $mapper);
230 fputs($this->fh, $output);
231 }
232
233 /**
234 * @param array $template_data
235 * @param MapperData $mapper
236 */
237 public function processLoop($template_data, $mapper, $loop_args = [], $depth = 0)
238 {
239 $output = '';
240
241 if (isset($template_data['args']) && $depth > 0) {
242 $loop_args = $template_data['args'];
243 }
244
245 $output .= PHP_EOL . '<!-- processLoop ' . wp_json_encode($loop_args) . ' -->' . PHP_EOL;
246
247 // TODO: get loop data and replace template variables
248 $loop_data = $mapper->data($loop_args);
249 foreach ($loop_data as $data) {
250
251 if (isset($template_data['template']['open'])) {
252 $output .= $mapper->template($template_data['template']['open'], $data);
253 }
254
255 if (!empty($template_data['children'])) {
256 foreach ($template_data['children'] as $child) {
257 if (is_array($child)) {
258 $output .= $this->processLoop($child, $mapper, $loop_args, $depth + 1);
259 } else {
260 $output .= $mapper->template($child, $data);
261 }
262 }
263 } elseif (isset($template_data['template']['main'])) {
264 $output .= $mapper->template($template_data['template']['main'], $data);
265 }
266
267 if (isset($template_data['template']['close'])) {
268 $output .= $mapper->template($template_data['template']['close'], $data);
269 }
270 }
271
272 $output .= PHP_EOL . '<!-- /processLoop -->' . PHP_EOL;
273
274 return $output;
275 }
276
277 public function checkForClosingTag($output)
278 {
279 $tmp = trim($output);
280 if (strlen($tmp) > 1 && substr($tmp, -1) !== '>') {
281 $output .= '>';
282 }
283 return $output;
284 }
285
286 public function hasClosingTag($output)
287 {
288 $tmp = trim($output);
289 if (strlen($tmp) > 1 && substr($tmp, -1) !== '>') {
290 return false;
291 }
292 return true;
293 }
294
295 public function indent($depth)
296 {
297 return str_repeat("\t", $depth + 1);
298 }
299
300 public function end()
301 {
302 fputs($this->fh, $this->template_sections['end'] . PHP_EOL);
303 fclose($this->fh);
304 }
305
306 public function get_file_name()
307 {
308 return $this->exporter->getId() . '.xml';
309 }
310 }
311