PluginProbe ʕ •ᴥ•ʔ
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel / trunk
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel vtrunk
trunk 0.9.0 0.9.1 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0 1.2.1 1.2.10 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.14 1.4.15 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0
wp-all-export / classes / XMLWriter.php
wp-all-export / classes Last commit date
partner-discount-sdk 3 weeks ago CdataStrategy.php 3 weeks ago CdataStrategyAlways.php 3 weeks ago CdataStrategyFactory.php 3 weeks ago CdataStrategyIllegalCharacters.php 3 weeks ago CdataStrategyIllegalCharactersHtmlEntities.php 3 weeks ago CdataStrategyNever.php 3 weeks ago XMLWriter.php 3 weeks ago chunk.php 3 weeks ago config.php 3 years ago download.php 3 weeks ago handler.php 3 weeks ago helper.php 3 weeks ago input.php 3 weeks ago installer.php 3 weeks ago session.php 10 years ago wpallimport.php 3 weeks ago zip.php 4 years ago
XMLWriter.php
422 lines
1 <?php
2
3 // phpcs:ignoreFile WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound,WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound,WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- legitimate plugin prefixes (pmxe/PMXE/wpae/Wpae/wp_all_export/wpallexport/XmlExport/CdataStrategy/VariableProductTitle/Soflyy/GF_Export); Plugin Check does not honor phpcs.xml prefix declaration
4 // Handle eval errors that cause the script to finish
5 $wpaeErrorHandler = new WpaePhpInterpreterErrorHandler();
6 register_shutdown_function(array($wpaeErrorHandler, 'handle'));
7
8 /**
9 * Class PMXE_XMLWriter
10 */
11 class PMXE_XMLWriter extends XMLWriter
12 {
13 /**
14 * @var array
15 */
16 public $articles = array();
17
18
19 /**
20 * @param array $articles
21 */
22 public function writeArticle($articles = array())
23 {
24
25 $article = array_shift($articles);
26
27 if (!empty($articles)) {
28
29 $keys = array();
30 foreach ($articles as $a) {
31
32 foreach ($a as $key => $value) {
33
34 if (!isset($article[$key])) {
35 $article[$key] = array($value);
36 } else {
37 if (is_array($article[$key])){
38 array_push($article[$key], $value);
39 }
40 else{
41 $article[$key] = array($article[$key], $value);
42 }
43 }
44
45 if (!in_array($key, $keys)) $keys[] = $key;
46 }
47 }
48 }
49
50 if (!empty($article)) {
51 foreach ($article as $key => $value) {
52 if (!is_array($value) && strpos($value, '#delimiter#') !== FALSE) {
53 $article[$key] = explode('#delimiter#', $value);
54 }
55 }
56 }
57
58 $this->articles[] = $article;
59 }
60
61 /**
62 * @param $ns
63 * @param $element
64 * @param $uri
65 * @param $value
66 * @return bool
67 */
68 public function putElement($ns, $element, $uri, $value)
69 {
70 if (in_array(XmlExportEngine::$exportOptions['xml_template_type'], array('custom', 'XmlGoogleMerchants'))) return true;
71
72 if (empty($ns)) {
73 return $this->writeElement($element, $value);
74 } else {
75 return $this->writeElementNS($ns, $element, $uri, $value);
76 }
77 }
78
79 /**
80 * @param $ns
81 * @param $element
82 * @param $uri
83 * @return bool
84 */
85 public function beginElement($ns, $element, $uri)
86 {
87 if (in_array(XmlExportEngine::$exportOptions['xml_template_type'], array('custom', 'XmlGoogleMerchants'))) return true;
88
89 if (empty($ns)) {
90 return $this->startElement($element);
91 } else {
92 return $this->startElementNS($ns, $element, $uri);
93 }
94 }
95
96 /**
97 * @return bool
98 */
99 public function closeElement()
100 {
101
102 if (in_array(XmlExportEngine::$exportOptions['xml_template_type'], array('custom', 'XmlGoogleMerchants'))) return true;
103
104 return $this->endElement();
105 }
106
107 /**
108 * @param $value
109 * @param $element_name
110 *
111 * @return bool
112 */
113 public function writeData($value, $element_name)
114 {
115 if (in_array(XmlExportEngine::$exportOptions['xml_template_type'], array('custom', 'XmlGoogleMerchants'))) return true;
116
117 $cdataStrategyFactory = new CdataStrategyFactory();
118
119 if (!isset(XmlExportEngine::$exportOptions['custom_xml_cdata_logic'])) {
120 XmlExportEngine::$exportOptions['custom_xml_cdata_logic'] = 'auto';
121 }
122 $cdataStrategy = $cdataStrategyFactory->create_strategy(XmlExportEngine::$exportOptions['custom_xml_cdata_logic']);
123 $is_wrap_into_cdata = $cdataStrategy->should_cdata_be_applied($value);
124
125 $wrap_value_into_cdata = apply_filters('wp_all_export_is_wrap_value_into_cdata', $is_wrap_into_cdata, $value, $element_name);
126
127 if ($wrap_value_into_cdata === false) {
128 $value && $this->writeRaw($value);
129 } else {
130 if (XmlExportEngine::$is_preview && XmlExportEngine::$exportOptions['show_cdata_in_preview']) {
131 $this->text('CDATABEGIN' . $value . 'CDATACLOSE');
132 } else if (XmlExportEngine::$is_preview && !XmlExportEngine::$exportOptions['show_cdata_in_preview']) {
133 return $this->text($value);
134 } else {
135 $this->writeCdata($value);
136 }
137 }
138 }
139
140 /**
141 * @return mixed|string
142 */
143 public function wpae_flush()
144 {
145 if (!in_array(XmlExportEngine::$exportOptions['xml_template_type'], array('custom', 'XmlGoogleMerchants'))) return $this->flush(true);
146
147 $xml = '';
148 foreach ($this->articles as $article) {
149
150 $founded_values = array_keys($article);
151 $node_tpl = XmlExportEngine::$exportOptions['custom_xml_template_loop'];
152
153 // clean up XPaths for not found values
154 preg_match_all("%(\{[^\}\{]*\})%", $node_tpl, $matches);
155 $xpaths = array_unique($matches[0]);
156
157 if (!empty($xpaths)) {
158 foreach ($xpaths as $xpath) {
159 if (!in_array(preg_replace("%[\{\}]%", "", $xpath), $founded_values)) {
160 $node_tpl = str_replace($xpath, "", $node_tpl);
161 }
162 }
163 }
164
165 foreach ($article as $key => $value) {
166 switch ($key) {
167 case 'id':
168 $node_tpl = str_replace('{'.$key.'}', '{' . $value . '}', $node_tpl);
169 break;
170 default:
171 // replace [ and ]
172 $v = str_replace(']', 'CLOSEBRAKET', str_replace('[', 'OPENBRAKET', $value));
173 // replace { and }
174 $v = str_replace('}', 'CLOSECURVE', str_replace('{', 'OPENCURVE', $v));
175 // replace ( and )
176 $v = str_replace(')', 'CLOSECIRCLE', str_replace('(', 'OPENCIRCLE', $v));
177
178 $originalValue = $v;
179
180 if (is_array($v)) {
181 foreach($v as &$val) {
182 $val = str_replace("\"","**DOUBLEQUOT**",$val);
183 $val = str_replace("'","**SINGLEQUOT**",$val);
184 }
185
186 $delimiter = uniqid();
187 $node_tpl = preg_replace('%\[(.*)\{'.$key.'\}([^\[]*)\]%', "[$1explode('" . $delimiter . "', '" . implode($delimiter, $v) . "')$2]", $node_tpl);
188 $v = "[explode('" . $delimiter . "', '" . implode($delimiter, $v) . "')]";
189 $v = str_replace('<','**LT**', $v);
190 $v = str_replace('>','**GT**', $v);
191 } else {
192 $v = '{' . $v . '}';
193 }
194
195 $arrayTypes = array(
196 'Product Tags', 'Tags', 'Product Categories', 'Categories', 'Image URL', 'Image Filename', 'Image Path', 'Image ID', 'Image Title', 'Image Caption', 'Image Description', 'Image Alt Text', 'Product Type', 'Categories'
197 );
198
199 // We have an empty array, which is transformed into {}
200 if(in_array($key, $arrayTypes) && $v == "{}") {
201 $delimiter = uniqid();
202 $node_tpl = preg_replace('%\[(.*)\{'.$key.'\}([^\[]*)\]%', "[$1explode('" . $delimiter . "', '" . implode($delimiter, array()) . "')$2]", $node_tpl);
203 $v = "[explode('" . $delimiter . "', '" . implode($delimiter, array()) . "')]";
204 }
205
206 // We have an array with just one value (Which is transformed into a string)
207 if(in_array($key, $arrayTypes) && count($originalValue) == 1) {
208 $delimiter = uniqid();
209 $node_tpl = preg_replace('%\[(.*)\{'.$key.'\}([^\[]*)\]%', "[$1explode('" . $delimiter . "', '" . implode($delimiter, array($originalValue)) . "')$2]", $node_tpl);
210 $v = "[explode('" . $delimiter . "', '" . implode($delimiter, array($originalValue)) . "')]";
211 }
212
213 $node_tpl = str_replace('{' . $key . '}', $v, $node_tpl);
214
215 break;
216 }
217 }
218
219 $xml .= $node_tpl;
220
221 }
222
223 $this->articles = array();
224 $wpaeString = new WpaeString();
225 $xmlPrepreocesor = new WpaeXmlProcessor($wpaeString);
226 return $xmlPrepreocesor->process($xml);
227 }
228
229 public static function getIndentationCount($content, $str)
230 {
231 $lines = explode("\r", $content);
232 foreach ($lines as $lineNumber => $line) {
233 if (strpos($line, $str) !== false) {
234 return substr_count($line, "\t");
235 }
236 }
237
238 return -1;
239 }
240
241 public static function indentTag($tag, $indentationCount, $index)
242 {
243 if($index == 0) {
244 $indentationString = "";
245 } else {
246 $indentationString = str_repeat("\t", $indentationCount);
247 }
248
249 return $indentationString . $tag;
250 }
251
252 /**
253 * @param string $xml
254 * @return mixed|string
255 *
256 * @throws WpaeInvalidStringException
257 * @throws WpaeMethodNotFoundException
258 */
259 public static function preprocess_xml($xml = '')
260 {
261 $xml = str_replace('<![CDATA[', 'DOMCdataSection', $xml);
262
263 preg_match_all("%(\[[^\]\[]*\])%", $xml, $matches);
264 $snipets = empty($matches) ? array() : array_unique($matches[0]);
265 $simple_snipets = array();
266 preg_match_all("%(\{[^\}\{]*\})%", $xml, $matches);
267 $xpaths = array_unique($matches[0]);
268
269 if (!empty($xpaths)) {
270 foreach ($xpaths as $xpath) {
271 if (!in_array($xpath, $snipets)) $simple_snipets[] = $xpath;
272 }
273 }
274
275 if (!empty($snipets)) {
276 foreach ($snipets as $snipet) {
277 // if function is found
278 if (preg_match("%\w+\(.*\)%", $snipet)) {
279
280 $filtered = trim(trim(trim($snipet, "]"), "["));
281 $filtered = preg_replace("%[\{\}]%", "\"", $filtered);
282 $filtered = str_replace('CLOSEBRAKET', ']', str_replace('OPENBRAKET', '[', $filtered));
283 $filtered = str_replace('CLOSECURVE', '}', str_replace('OPENCURVE', '{', $filtered));
284 $filtered = str_replace('CLOSECIRCLE', ')', str_replace('OPENCIRCLE', '(', $filtered));
285
286 $functionName = self::sanitizeFunctionName($filtered);
287
288 $numberOfSingleQuotes = substr_count($filtered, "'");
289 $numberOfDoubleQuotes = substr_count($filtered, "\"");
290
291 if ($numberOfSingleQuotes % 2 || $numberOfDoubleQuotes % 2) {
292 throw new WpaeInvalidStringException( esc_html( $functionName ) );
293 }
294
295 if (!function_exists($functionName)) {
296 throw new WpaeMethodNotFoundException( esc_html( $functionName ) );
297 }
298
299 // phpcs:ignore Generic.PHP.ForbiddenFunctions.Found -- intentional: evaluates saved field-filter function-call expression
300 $values = eval("return " . $filtered . ";");
301
302 $v = '';
303 if (is_array($values)) {
304 $tag = false;
305
306 preg_match_all("%(<[\w]+[\s|>]{1})" . preg_quote($snipet) . "%", $xml, $matches);
307
308 if (!empty($matches[1])) {
309 $tag = array_shift($matches[1]);
310 }
311 if (empty($tag)) $tag = "<item>";
312
313 $indentationCount = self::getIndentationCount($xml, $tag);
314
315 $i = 0;
316 foreach ($values as $number => $value) {
317 $v .= self::indentTag($tag . self::maybe_cdata($value) . str_replace("<", "</", $tag) . "\n", $indentationCount, $i);
318 $i++;
319 }
320
321 $xml = str_replace($tag . $snipet . str_replace("<", "</", $tag), $v, $xml);
322 } else {
323 $xml = str_replace($snipet, self::maybe_cdata($values), $xml);
324 }
325 }
326 }
327 }
328
329 if (!empty($simple_snipets)) {
330 foreach ($simple_snipets as $snipet) {
331 $filtered = preg_replace("%[\{\}]%", "", $snipet);
332
333 $is_attribute = false;
334
335 //Encode data in attributes
336 if (strpos($xml, "\"$snipet\"") !== false || strpos($xml, "'$snipet'") !== false) {
337 $is_attribute = true;
338 $filtered = str_replace('&amp;', '&', $filtered);
339 $filtered = str_replace('&', '&amp;', $filtered);
340 $filtered = str_replace('\'', '&#x27;', $filtered);
341 $filtered = str_replace('"', '&quot;', $filtered);
342 $filtered = str_replace('<', '&lt;', $filtered);
343 $filtered = str_replace('>', '&gt;', $filtered);
344 }
345
346 $filtered = str_replace('CLOSEBRAKET', ']', str_replace('OPENBRAKET', '[', $filtered));
347 $filtered = str_replace('CLOSECURVE', '}', str_replace('OPENCURVE', '{', $filtered));
348 $filtered = str_replace('CLOSECIRCLE', ')', str_replace('OPENCIRCLE', '(', $filtered));
349
350 if ($is_attribute) {
351 $xml = str_replace($snipet, $filtered, $xml);
352 } else {
353 $xml = str_replace($snipet, self::maybe_cdata($filtered), $xml);
354 }
355 }
356 }
357
358 $xml = str_replace('DOMCdataSection', '<![CDATA[', $xml);
359
360 return $xml;
361 }
362
363 /**
364 * @param $v
365 * @return string
366 */
367 public static function maybe_cdata($v)
368 {
369
370 if (XmlExportEngine::$is_preview) {
371 $v = str_replace('&amp;', '&', (string) $v);
372 $v = htmlspecialchars($v);
373 }
374
375 if (XmlExportEngine::$is_preview && !XmlExportEngine::$exportOptions['show_cdata_in_preview']) {
376 return $v;
377 }
378
379 $cdataStrategyFactory = new CdataStrategyFactory();
380
381 if (!isset(XmlExportEngine::$exportOptions['custom_xml_cdata_logic'])) {
382 XmlExportEngine::$exportOptions['custom_xml_cdata_logic'] = 'auto';
383 }
384
385 $cdataStrategy = $cdataStrategyFactory->create_strategy(XmlExportEngine::$exportOptions['custom_xml_cdata_logic']);
386 $is_wrap_into_cdata = $cdataStrategy->should_cdata_be_applied($v);
387
388 if ($is_wrap_into_cdata === false) {
389 return $v;
390 } else {
391 if (XmlExportEngine::$is_preview && XmlExportEngine::$exportOptions['show_cdata_in_preview']) {
392 return 'CDATABEGIN' . $v . 'CDATACLOSE';
393 } else {
394 return "<![CDATA[" . $v . "]]>";
395 }
396 }
397 }
398
399 /**
400 * @param $filtered
401 * @return mixed
402 */
403 private static function sanitizeFunctionName($filtered)
404 {
405 $functionName = preg_replace('/"[^"]+"/', '', $filtered);
406 $functionName = preg_replace('/\'[^\']+\'/', '', $functionName);
407
408 $firstSingleQuote = strpos($functionName, '\'');
409 $firstDoubleQuote = strpos($functionName, '"');
410
411 if ($firstDoubleQuote < $firstSingleQuote && $firstDoubleQuote != 0) {
412 $functionName = explode('"', $functionName);
413 $functionName = $functionName[0];
414 } else if ($firstSingleQuote != 0) {
415 $functionName = explode('\'', $functionName);
416 $functionName = $functionName[0];
417 }
418 $functionName = str_replace(array('(', ')', ',', ' ', '\'', '"'), '', $functionName);
419
420 return $functionName;
421 }
422 }