PluginProbe ʕ •ᴥ•ʔ
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets / 4.1.1
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets v4.1.1
4.1.1 3.9.5 3.9.6 4.0.0 4.0.1 4.1.0 trunk 2.12 2.13 2.14 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9 3.7.0 3.7.1 3.7.2 3.7.3 3.7.3-beta-1.0 3.7.4 3.7.4-beta-1.0 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4
wp-all-import / libraries / XmlImportTemplateCodeGenerator.php
wp-all-import / libraries Last commit date
ast 1 month ago XmlImportConfig.php 1 month ago XmlImportCsvParse.php 1 month ago XmlImportException.php 1 month ago XmlImportParser.php 1 month ago XmlImportReaderInterface.php 1 month ago XmlImportSQLParse.php 1 month ago XmlImportStringReader.php 1 month ago XmlImportTemplate.php 1 month ago XmlImportTemplateCodeGenerator.php 1 month ago XmlImportTemplateParser.php 1 month ago XmlImportTemplateScanner.php 3 days ago XmlImportToken.php 1 month ago XmlImportXLSParse.php 1 month ago wpaipclzip.lib.php 1 month ago
XmlImportTemplateCodeGenerator.php
428 lines
1 <?php
2 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_is_writable, WordPress.NamingConventions.PrefixAllGlobals
3 if ( ! defined( 'ABSPATH' ) ) exit;
4 /**
5 * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
6 * @package General
7 */
8
9 require_once dirname(__FILE__) . '/XmlImportConfig.php';
10 require_once dirname(__FILE__) . '/ast/XmlImportAstSequence.php';
11 require_once dirname(__FILE__) . '/ast/XmlImportAstText.php';
12 require_once dirname(__FILE__) . '/ast/XmlImportAstPrint.php';
13 require_once dirname(__FILE__) . '/ast/XmlImportAstInteger.php';
14 require_once dirname(__FILE__) . '/ast/XmlImportAstFloat.php';
15 require_once dirname(__FILE__) . '/ast/XmlImportAstString.php';
16 require_once dirname(__FILE__) . '/ast/XmlImportAstXPath.php';
17 require_once dirname(__FILE__) . '/ast/XmlImportAstFunction.php';
18 require_once dirname(__FILE__) . '/ast/XmlImportAstWith.php';
19 require_once dirname(__FILE__) . '/ast/XmlImportAstForeach.php';
20 require_once dirname(__FILE__) . '/ast/XmlImportAstIf.php';
21 require_once dirname(__FILE__) . '/ast/XmlImportAstMath.php';
22 require_once dirname(__FILE__) . '/ast/XmlImportAstSpintax.php';
23
24 /**
25 * Is used to generate a PHP code from AST (Abstract Syntax Tree)
26 */
27 class XmlImportTemplateCodeGenerator
28 {
29
30 /**
31 * Top level statement sequence
32 *
33 * @var XmlImportAstSequence
34 */
35 private $sequence;
36
37 /**
38 * statement sequence stack
39 *
40 * @var array
41 */
42 private $sequenceStack = array();
43
44 /**
45 * SimpleXmlElement variable number
46 *
47 * @var int
48 */
49 private $xmlVariableNumber = 0;
50
51 /**
52 * Previous statement
53 *
54 * @var XmlImportAstStatement
55 */
56 private $previousStatement = null;
57
58 /**
59 * Stack of SimpleXmlElement instances
60 *
61 * @var array
62 */
63 private $xmlStack = array();
64
65 /**
66 * Whether PHP tag is open
67 *
68 * @var bool
69 */
70 private $isPhpTagOpen = false;
71
72 /**
73 * Creates new instance
74 *
75 * @param XmlImportAstSequence $sequence
76 */
77 public function __construct(XmlImportAstSequence $sequence)
78 {
79 $this->sequence = $sequence;
80 }
81
82 /**
83 * Generates the code and returns the filename under which it was stored in
84 * cache directory. If $filename is null then it is generated automatically
85 *
86 * @param string $filename
87 * @return string
88 */
89 public function generate($filename = null)
90 {
91 $result = '';
92 if (count($this->sequence->getVariables()))
93 {
94 $var = '$x' . $this->xmlVariableNumber++;
95 array_push($this->xmlStack, $var);
96 $result .= $this->openPhpTag() . $var . ' = $this->xml;' ;
97 }
98 $result .= $this->generateForSequence($this->sequence);
99
100 if (count($this->sequence->getVariables()))
101 {
102 array_pop($this->xmlStack);
103 }
104 // grab import ID for manual and cron import runs
105 $input = new PMXI_Input();
106 $import_id = $input->get('id');
107 if (empty($import_id)){
108 $import_id = $input->get('import_id');
109 }
110 if ( ! $filename or ! @is_writable($filename)) {
111 $filename = @tempnam(XmlImportConfig::getInstance()->getCacheDirectory(), 'xim_id_'. $import_id);
112 }
113 if ( ! $filename or ! @is_writable($filename) ){
114 $uploads = wp_upload_dir();
115 $targetDir = $uploads['basedir'] . DIRECTORY_SEPARATOR . PMXI_Plugin::TEMP_DIRECTORY;
116 $filename = $targetDir . DIRECTORY_SEPARATOR . wp_unique_filename($targetDir, 'tmpfile_id_'. $import_id);
117 }
118
119 file_put_contents($filename, $result);
120 $sleep = apply_filters( 'wp_all_import_shard_delay', 0 );
121 usleep($sleep);
122
123 //@chmod($filename, 0666);
124 return $filename;
125 }
126
127 /**
128 * Generates code for a statement sequence
129 *
130 * @param XmlImportAstSequence $sequence
131 * @return string
132 */
133 private function generateForSequence(XmlImportAstSequence $sequence)
134 {
135 array_push($this->sequenceStack, $sequence);
136 $result = '';
137
138 if (count($sequence->getVariableDefinitions()) > 0)
139 {
140 $result .= $this->openPhpTag();
141 foreach ($sequence->getVariableDefinitions() as $xpath)
142 {
143 $result .= PHP_EOL . str_replace('{{XML}}', $this->xmlStack[count($this->xmlStack) - 1], $xpath);
144 }
145 $result .= PHP_EOL;
146 }
147 foreach ($sequence->getStatements() as $statement)
148 {
149 $result .= $this->generateForStatement($statement);
150 }
151 array_pop($this->sequenceStack);
152
153 return $result;
154 }
155
156 /**
157 * Generates code for a statement
158 *
159 * @param XmlImportAstStatement $statement
160 * @return string
161 */
162 private function generateForStatement(XmlImportAstStatement $statement)
163 {
164 $result = '';
165 if ($statement instanceof XmlImportAstText)
166 {
167 $result .= $this->closePhpTag();
168 $text = preg_replace('%<\?|\?>%', '<?php echo "$0"; ?>', $statement->getValue()); // escape php tags
169 if ($this->previousStatement instanceof XmlImportAstPrint && (strpos($text, "\n") === 0 || strpos($text, "\r\n") === 0))
170 {
171 $result .= PHP_EOL;
172 }
173 $result .= $text;
174 }
175 else
176 {
177 $result .= $this->openPhpTag();
178 if ($statement instanceof XmlImportAstPrint)
179 {
180 $result .= 'echo ';
181 $result .= $this->generateForExpression($statement->getValue(), true) . ';';
182 }
183 elseif ($statement instanceof XmlImportAstWith)
184 {
185 $var = '$x' . $this->xmlVariableNumber++;
186 $result .= PHP_EOL . $var . ' = ' ;
187 $result .= $this->generateForExpression($statement->getXpath()) . ';' . PHP_EOL;
188
189 array_push($this->xmlStack, $var);
190 $result .= 'if (' . $var . ' !== false && count(' . $var . ') > 0) :' . PHP_EOL . $var .
191 ' = ' . $var . '[0];' . PHP_EOL;
192 $result .= $this->generateForSequence($statement->getBody());
193 array_pop($this->xmlStack);
194 $result .= $this->openPhpTag() . PHP_EOL . 'endif;' . PHP_EOL;
195 }
196 elseif ($statement instanceof XmlImportAstForeach)
197 {
198 $var = '$x' . $this->xmlVariableNumber++;
199 $result .= PHP_EOL . 'foreach (' . $this->generateForExpression($statement->getXPath(), false) .
200 ' as ' . $var . ') :' . PHP_EOL;
201 array_push($this->xmlStack, $var);
202 $result .= $this->generateForSequence($statement->getBody());
203 $result .= $this->openPhpTag() . PHP_EOL . 'endforeach;' . PHP_EOL;
204 array_pop($this->xmlStack);
205 }
206 elseif ($statement instanceof XmlImportAstIf)
207 {
208 $result .= PHP_EOL . 'if (' . $this->generateForExpression($statement->getCondition()) . ') :' . PHP_EOL;
209 $result .= $this->generateForSequence($statement->getIfBody());
210
211 foreach ($statement->getElseIfs() as $elseif)
212 {
213 $result .= $this->openPhpTag() . PHP_EOL . 'elseif (' . $this->generateForExpression($elseif->getCondition()) . ') :' . PHP_EOL;
214 $result .= $this->generateForSequence($elseif->getBody());
215 }
216 if (!is_null($body = $statement->getElseBody()))
217 {
218 $result .= $this->openPhpTag() . PHP_EOL . 'else :' . PHP_EOL;
219 $result .= $this->generateForSequence($body);
220 }
221 $result .= $this->openPhpTag() . PHP_EOL . 'endif;' . PHP_EOL;
222 }
223
224 }
225 $this->previousStatement = $statement;
226 return $result;
227 }
228
229 /**
230 * Generates code for expression
231 *
232 * @param XmlImportAstExpression $expression
233 * @param bool $inPrint whether in print or in clause or function argument
234 * @return string
235 */
236 private function generateForExpression(XmlImportAstExpression $expression, $inPrint = false)
237 {
238
239 switch (get_class($expression))
240 {
241 case 'XmlImportAstString':
242 $result = '"' . $this->getEscapedValue($expression->getValue()) . '"';
243 break;
244
245 case 'XmlImportAstInteger':
246 case 'XmlImportAstFloat':
247 $result = $expression->getValue();
248 break;
249
250 case 'XmlImportAstXPath':
251 if ($inPrint)
252 {
253 $variables = $this->sequenceStack[count($this->sequenceStack) - 1]->getVariables();
254 $result = '$this->getValue(' . $variables[$expression->getValue()] . ')';
255 }
256 else
257 {
258 $variables = $this->sequenceStack[count($this->sequenceStack) - 1]->getVariables();
259 $result = $variables[$expression->getValue()];
260 }
261 break;
262
263 case 'XmlImportAstFunction':
264 $result = $this->generateForFunction($expression);
265 break;
266
267 case 'XmlImportAstMath':
268 $result = $this->generateForMath($expression);
269 break;
270
271 case 'XmlImportAstSpintax':
272 $result = $this->generateForSpintax($expression);
273 break;
274 }
275 return $result;
276 }
277
278 /**
279 * Generates code for a function
280 *
281 * @param XmlImportAstFunction $function
282 * @return string
283 */
284 private function generateForFunction(XmlImportAstFunction $function)
285 {
286 $result = $function->getName() . '(';
287 $arguments = $function->getArguments();
288
289 for($i = 0; $i < count($arguments); $i++)
290 {
291 $result .= $this->generateForExpression($arguments[$i], true);
292 if ($i < (count($arguments) - 1))
293 $result .= ', ';
294 }
295 $result .= ')';
296
297 return $result;
298 }
299
300 /**
301 * Generates code for a function
302 *
303 * @param XmlImportAstFunction $function
304 * @return string
305 */
306 private function generateForMath(XmlImportAstMath $math)
307 {
308 $result = '';
309 $arguments = $math->getArguments();
310 for($i = 0; $i < count($arguments); $i++)
311 {
312 $result .= $this->generateForExpression($arguments[$i], true);
313 }
314
315 return 'number_format('.str_replace("\"", "", $result).',2)';
316 }
317
318 /**
319 * Generates code for a function
320 *
321 * @param XmlImportAstSpintax $expression
322 * @return string
323 */
324 private function generateForSpintax(XmlImportAstSpintax $spintax)
325 {
326 $result = '';
327 $arguments = $spintax->getArguments();
328 $elements = array();
329 $buf = array();
330
331 for($i = 0; $i < count($arguments); $i++)
332 {
333
334 if ($arguments[$i]->getValue() != '|') array_push($buf, $this->generateForExpression($arguments[$i], true)); else { array_push($elements, $buf); $buf = array();}
335
336 }
337
338 array_push($elements, $buf);
339
340 if (!empty($elements) and is_array($elements)){
341
342 $spintax_arr = $this->generateVariation($elements);
343
344 foreach ($spintax_arr as $key => $value) {
345 $result .= "\"<p>\".".implode(".", $value).".\"</p>\""; if ($key != count($spintax_arr) - 1) $result .= ".";
346 }
347
348 }
349
350 return $result;
351 }
352
353 function generateVariation($A, $i = 0)
354 {
355 $result = array();
356
357 if ($i < count($A))
358 {
359 $variations = $this->generateVariation($A, $i + 1);
360
361 for ($j = 0; $j < count($A[$i]); $j++)
362 {
363 if ($variations)
364 {
365 foreach ($variations as $variation)
366 {
367 $result[] = array_merge(array($A[$i][$j]), $variation);
368 }
369 }
370 else
371 {
372 $result[] = array($A[$i][$j]);
373 }
374 }
375 }
376
377 return $result;
378 }
379 /**
380 * Add PHP open tag if needed
381 *
382 * @return string
383 */
384 private function openPhpTag()
385 {
386 $result = '';
387 if (!$this->isPhpTagOpen)
388 {
389 $this->isPhpTagOpen = true;
390 $result = '<?php ';
391 }
392 return $result;
393 }
394
395 /**
396 * Adds PHP close tag if needed
397 *
398 * @return string
399 */
400 private function closePhpTag()
401 {
402 $result = '';
403 if ($this->isPhpTagOpen)
404 {
405 $this->isPhpTagOpen = false;
406 $result = '?>';
407 }
408 return $result;
409 }
410
411 /**
412 * Gets escaped value
413 *
414 * @return string
415 */
416 private function getEscapedValue($value)
417 {
418 $escapedValue = strtr($value, array(
419 "\n" => "\\n",
420 "\t" => "\\t",
421 "\r" => "\\r",
422 "$" => "\\$",
423 "\"" => "\\\"",
424 "\\" => "\\\\",
425 ));
426 return $escapedValue;
427 }
428 }