PluginProbe ʕ •ᴥ•ʔ
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets / 3.0
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets v3.0
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 13 years ago cache 13 years ago XmlImportConfig.php 13 years ago XmlImportCsvParse.php 13 years ago XmlImportException.php 13 years ago XmlImportParser.php 13 years ago XmlImportReaderInterface.php 13 years ago XmlImportStringReader.php 13 years ago XmlImportTemplate.php 13 years ago XmlImportTemplateCodeGenerator.php 13 years ago XmlImportTemplateParser.php 13 years ago XmlImportTemplateScanner.php 13 years ago XmlImportToken.php 13 years ago pclzip.lib.php 13 years ago
XmlImportTemplateCodeGenerator.php
383 lines
1 <?php
2 /**
3 * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4 * @package General
5 */
6
7 require_once dirname(__FILE__) . '/XmlImportConfig.php';
8 require_once dirname(__FILE__) . '/ast/XmlImportAstSequence.php';
9 require_once dirname(__FILE__) . '/ast/XmlImportAstText.php';
10 require_once dirname(__FILE__) . '/ast/XmlImportAstPrint.php';
11 require_once dirname(__FILE__) . '/ast/XmlImportAstInteger.php';
12 require_once dirname(__FILE__) . '/ast/XmlImportAstFloat.php';
13 require_once dirname(__FILE__) . '/ast/XmlImportAstString.php';
14 require_once dirname(__FILE__) . '/ast/XmlImportAstXPath.php';
15 require_once dirname(__FILE__) . '/ast/XmlImportAstWith.php';
16 require_once dirname(__FILE__) . '/ast/XmlImportAstForeach.php';
17 require_once dirname(__FILE__) . '/ast/XmlImportAstIf.php';
18 require_once dirname(__FILE__) . '/ast/XmlImportAstMath.php';
19 require_once dirname(__FILE__) . '/ast/XmlImportAstSpintax.php';
20
21 /**
22 * Is used to generate a PHP code from AST (Abstract Syntax Tree)
23 */
24 class XmlImportTemplateCodeGenerator
25 {
26
27 /**
28 * Top level statement sequence
29 *
30 * @var XmlImportAstSequence
31 */
32 private $sequence;
33
34 /**
35 * statement sequence stack
36 *
37 * @var array
38 */
39 private $sequenceStack = array();
40
41 /**
42 * SimpleXmlElement variable number
43 *
44 * @var int
45 */
46 private $xmlVariableNumber = 0;
47
48 /**
49 * Previous statement
50 *
51 * @var XmlImportAstStatement
52 */
53 private $previousStatement = null;
54
55 /**
56 * Stack of SimpleXmlElement instances
57 *
58 * @var array
59 */
60 private $xmlStack = array();
61
62 /**
63 * Whether PHP tag is open
64 *
65 * @var bool
66 */
67 private $isPhpTagOpen = false;
68
69 /**
70 * Creates new instance
71 *
72 * @param XmlImportAstSequence $sequence
73 */
74 public function __construct(XmlImportAstSequence $sequence)
75 {
76 $this->sequence = $sequence;
77 }
78
79 /**
80 * Generates the code and returns the filename under which it was stored in
81 * cache directory. If $filename is null then it is generated automatically
82 *
83 * @param string $filename
84 * @return string
85 */
86 public function generate($filename = null)
87 {
88 $result = '';
89 if (count($this->sequence->getVariables()))
90 {
91 $var = '$x' . $this->xmlVariableNumber++;
92 array_push($this->xmlStack, $var);
93 $result .= $this->openPhpTag() . $var . ' = $this->xml;' ;
94 }
95 $result .= $this->generateForSequence($this->sequence);
96
97 if (count($this->sequence->getVariables()))
98 {
99 array_pop($this->xmlStack);
100 }
101 if (is_null($filename))
102 {
103 $filename = tempnam(XmlImportConfig::getInstance()->getCacheDirectory(), 'xim');
104 }
105
106 file_put_contents($filename, $result);
107 return $filename;
108 }
109
110 /**
111 * Generates code for a statement sequence
112 *
113 * @param XmlImportAstSequence $sequence
114 * @return string
115 */
116 private function generateForSequence(XmlImportAstSequence $sequence)
117 {
118 array_push($this->sequenceStack, $sequence);
119 $result = '';
120 if (count($sequence->getVariableDefinitions()) > 0)
121 {
122 $result .= $this->openPhpTag();
123 foreach ($sequence->getVariableDefinitions() as $xpath)
124 {
125 $result .= PHP_EOL . str_replace('{{XML}}', $this->xmlStack[count($this->xmlStack) - 1], $xpath);
126 }
127 $result .= PHP_EOL;
128 }
129 foreach ($sequence->getStatements() as $statement)
130 {
131 $result .= $this->generateForStatement($statement);
132 }
133 array_pop($this->sequenceStack);
134
135 return $result;
136 }
137
138 /**
139 * Generates code for a statement
140 *
141 * @param XmlImportAstStatement $statement
142 * @return string
143 */
144 private function generateForStatement(XmlImportAstStatement $statement)
145 {
146 $result = '';
147 if ($statement instanceof XmlImportAstText)
148 {
149 $result .= $this->closePhpTag();
150 $text = preg_replace('%<\?|\?>%', '<?php echo "$0"; ?>', $statement->getValue()); // escape php tags
151 if ($this->previousStatement instanceof XmlImportAstPrint && (strpos($text, "\n") === 0 || strpos($text, "\r\n") === 0))
152 {
153 $result .= PHP_EOL;
154 }
155 $result .= $text;
156 }
157 else
158 {
159 $result .= $this->openPhpTag();
160 if ($statement instanceof XmlImportAstPrint)
161 {
162 $result .= 'echo ';
163 $result .= $this->generateForExpression($statement->getValue(), true) . ';';
164 }
165 elseif ($statement instanceof XmlImportAstWith)
166 {
167 $var = '$x' . $this->xmlVariableNumber++;
168 $result .= PHP_EOL . $var . ' = ' ;
169 $result .= $this->generateForExpression($statement->getXpath()) . ';' . PHP_EOL;
170
171 array_push($this->xmlStack, $var);
172 $result .= 'if (' . $var . ' !== false && count(' . $var . ') > 0) :' . PHP_EOL . $var .
173 ' = ' . $var . '[0];' . PHP_EOL;
174 $result .= $this->generateForSequence($statement->getBody());
175 array_pop($this->xmlStack);
176 $result .= $this->openPhpTag() . PHP_EOL . 'endif;' . PHP_EOL;
177 }
178 elseif ($statement instanceof XmlImportAstForeach)
179 {
180 $var = '$x' . $this->xmlVariableNumber++;
181 $result .= PHP_EOL . 'foreach (' . $this->generateForExpression($statement->getXPath()) .
182 ' as ' . $var . ') :' . PHP_EOL;
183 array_push($this->xmlStack, $var);
184 $result .= $this->generateForSequence($statement->getBody());
185 $result .= $this->openPhpTag() . PHP_EOL . 'endforeach;' . PHP_EOL;
186 array_pop($this->xmlStack);
187 }
188 elseif ($statement instanceof XmlImportAstIf)
189 {
190 $result .= PHP_EOL . 'if (' . $this->generateForExpression($statement->getCondition()) . ') :' . PHP_EOL;
191 $result .= $this->generateForSequence($statement->getIfBody());
192 foreach ($statement->getElseIfs() as $elseif)
193 {
194 $result .= $this->openPhpTag() . PHP_EOL . 'elseif (' . $this->generateForExpression($elseif->getCondition()) . ') :' . PHP_EOL;
195 $result .= $this->generateForSequence($elseif->getBody());
196 }
197 if (!is_null($body = $statement->getElseBody()))
198 {
199 $result .= $this->openPhpTag() . PHP_EOL . 'else :' . PHP_EOL;
200 $result .= $this->generateForSequence($body);
201 }
202 $result .= $this->openPhpTag() . PHP_EOL . 'endif;' . PHP_EOL;
203 }
204
205 }
206 $this->previousStatement = $statement;
207 return $result;
208 }
209
210 /**
211 * Generates code for expression
212 *
213 * @param XmlImportAstExpression $expression
214 * @param bool $inPrint whether in print or in clause or function argument
215 * @return string
216 */
217 private function generateForExpression(XmlImportAstExpression $expression, $inPrint = false)
218 {
219
220 switch (get_class($expression))
221 {
222 case 'XmlImportAstString':
223 $result = '"' . $this->getEscapedValue($expression->getValue()) . '"';
224 break;
225
226 case 'XmlImportAstInteger':
227 case 'XmlImportAstFloat':
228 $result = $expression->getValue();
229 break;
230
231 case 'XmlImportAstXPath':
232 if ($inPrint)
233 {
234 $variables = $this->sequenceStack[count($this->sequenceStack) - 1]->getVariables();
235 $result = '$this->getValue(' . $variables[$expression->getValue()] . ')';
236 }
237 else
238 {
239 $variables = $this->sequenceStack[count($this->sequenceStack) - 1]->getVariables();
240 $result = $variables[$expression->getValue()];
241 }
242 break;
243
244 case 'XmlImportAstMath':
245 $result = $this->generateForMath($expression);
246 break;
247
248 case 'XmlImportAstSpintax':
249 $result = $this->generateForSpintax($expression);
250 break;
251 }
252 return $result;
253 }
254
255 /**
256 * Generates code for a function
257 *
258 * @param XmlImportAstFunction $function
259 * @return string
260 */
261 private function generateForMath(XmlImportAstMath $math)
262 {
263 $result = '';
264 $arguments = $math->getArguments();
265 for($i = 0; $i < count($arguments); $i++)
266 {
267 $result .= $this->generateForExpression($arguments[$i], true);
268 }
269
270 return 'number_format('.str_replace("\"", "", $result).',2)';
271 }
272
273 /**
274 * Generates code for a function
275 *
276 * @param XmlImportAstSpintax $expression
277 * @return string
278 */
279 private function generateForSpintax(XmlImportAstSpintax $spintax)
280 {
281 $result = '';
282 $arguments = $spintax->getArguments();
283 $elements = array();
284 $buf = array();
285
286 for($i = 0; $i < count($arguments); $i++)
287 {
288
289 if ($arguments[$i]->getValue() != '|') array_push($buf, $this->generateForExpression($arguments[$i], true)); else { array_push($elements, $buf); $buf = array();}
290
291 }
292
293 array_push($elements, $buf);
294
295 if (!empty($elements) and is_array($elements)){
296
297 $spintax_arr = $this->generateVariation($elements);
298
299 foreach ($spintax_arr as $key => $value) {
300 $result .= "\"<p>\".".implode(".", $value).".\"</p>\""; if ($key != count($spintax_arr) - 1) $result .= ".";
301 }
302
303 }
304
305 return $result;
306 }
307
308 function generateVariation($A, $i = 0)
309 {
310 $result = array();
311
312 if ($i < count($A))
313 {
314 $variations = $this->generateVariation($A, $i + 1);
315
316 for ($j = 0; $j < count($A[$i]); $j++)
317 {
318 if ($variations)
319 {
320 foreach ($variations as $variation)
321 {
322 $result[] = array_merge(array($A[$i][$j]), $variation);
323 }
324 }
325 else
326 {
327 $result[] = array($A[$i][$j]);
328 }
329 }
330 }
331
332 return $result;
333 }
334 /**
335 * Add PHP open tag if needed
336 *
337 * @return string
338 */
339 private function openPhpTag()
340 {
341 $result = '';
342 if (!$this->isPhpTagOpen)
343 {
344 $this->isPhpTagOpen = true;
345 $result = '<?php ';
346 }
347 return $result;
348 }
349
350 /**
351 * Adds PHP close tag if needed
352 *
353 * @return string
354 */
355 private function closePhpTag()
356 {
357 $result = '';
358 if ($this->isPhpTagOpen)
359 {
360 $this->isPhpTagOpen = false;
361 $result = '?>';
362 }
363 return $result;
364 }
365
366 /**
367 * Gets escaped value
368 *
369 * @return string
370 */
371 private function getEscapedValue($value)
372 {
373 $escapedValue = strtr($value, array(
374 "\n" => "\\n",
375 "\t" => "\\t",
376 "\r" => "\\r",
377 "$" => "\\$",
378 "\"" => "\\\"",
379 "\\" => "\\\\",
380 ));
381 return $escapedValue;
382 }
383 }