PageRenderTime 60ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Template/src/parsers/ast_to_php/implementations/php_generator.php

https://github.com/Yannix/zetacomponents
PHP | 1176 lines | 675 code | 94 blank | 407 comment | 34 complexity | 6af82c2e95258ffb3c6cce8f13c007d3 MD5 | raw file
  1. <?php
  2. /**
  3. * File containing the ezcTemplateAstNodeGenerator class
  4. *
  5. * Licensed to the Apache Software Foundation (ASF) under one
  6. * or more contributor license agreements. See the NOTICE file
  7. * distributed with this work for additional information
  8. * regarding copyright ownership. The ASF licenses this file
  9. * to you under the Apache License, Version 2.0 (the
  10. * "License"); you may not use this file except in compliance
  11. * with the License. You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing,
  16. * software distributed under the License is distributed on an
  17. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18. * KIND, either express or implied. See the License for the
  19. * specific language governing permissions and limitations
  20. * under the License.
  21. *
  22. * @package Template
  23. * @version //autogen//
  24. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25. * @access private
  26. */
  27. /**
  28. * Generator of PHP code.
  29. *
  30. * Implements the ezcTemplateBasicAstNodeVisitor interface for visiting code elements
  31. * and generating code for them.
  32. *
  33. * @package Template
  34. * @version //autogen//
  35. * @access private
  36. */
  37. class ezcTemplateAstToPhpGenerator implements ezcTemplateAstNodeVisitor
  38. {
  39. /**
  40. * The default value to increase the indentation with.
  41. * Set it through the constructor.
  42. * @var int
  43. */
  44. private $indentation;
  45. /**
  46. * The current indentation value.
  47. * This starts at 0 and usually increases with value defined in self::$indentation.
  48. * @var int
  49. */
  50. private $currentIndentation;
  51. /**
  52. * Text which represents the current indentation.
  53. * This is automatically generated each time the indentation is changed.
  54. * @var string
  55. */
  56. private $indentationText;
  57. /**
  58. * Stack of old indentation values.
  59. * When the indentation changes it is pushed to the stack and later on restored.
  60. * @var array(int)
  61. */
  62. private $indentationStack;
  63. /**
  64. * File descriptor for the opened file which will contain the generated code.
  65. * @var resource
  66. */
  67. private $fd;
  68. /**
  69. * Flag for whether the footer has been written or.
  70. * This makes sure the destructor does not write it if it has been called earlier.
  71. * @var bool
  72. */
  73. private $hasWrittenFooter;
  74. /**
  75. * Flag for whether the output is currently at the beginning of a new line or not.
  76. * This is used to determine if the indentation text self::$indentationText
  77. * should be prepended to the current line or not.
  78. * @var bool
  79. */
  80. private $newline;
  81. /**
  82. * Escape the single quote in the output. Useful for the caching.
  83. * @var bool
  84. */
  85. private $escapeSingleQuote = false;
  86. /**
  87. * The character set defined in the template.
  88. * If set to false, it uses the $sourceCharset.
  89. * @var string|bool
  90. */
  91. private $charsetInTemplate = false;
  92. /**
  93. * The source character set.
  94. * @var string
  95. */
  96. private $sourceCharset;
  97. /**
  98. * Transform to the target character set.
  99. * @var string
  100. */
  101. private $targetCharset;
  102. /**
  103. * Constructs a new ezcTemplateAstToPhpGenerator
  104. *
  105. * @param string $path File path for the file which should be generated.
  106. * @param ezcTemplateConfiguration $configuration The template configuration.
  107. * @param int $indentation The default indentation to use when increasing it.
  108. */
  109. public function __construct( $path, $configuration, $indentation = 4 )
  110. {
  111. if ( file_exists( $path ) )
  112. {
  113. if ( !is_writable( $path ) )
  114. {
  115. throw new ezcTemplateFileNotWriteableException( $path, "generated PHP file" );
  116. }
  117. }
  118. $this->fd = @fopen( $path, "w" );
  119. if ( !$this->fd )
  120. {
  121. throw new ezcTemplateFileNotWriteableException( $path, "generated PHP file" );
  122. }
  123. $this->indentation = $indentation;
  124. $this->hasWrittenFooter = false;
  125. $this->currentIndentation = 0;
  126. $this->indentationText = '';
  127. $this->indentationStack = array();
  128. $this->newline = true;
  129. $this->sourceCharset = $configuration->sourceCharset;
  130. $this->targetCharset = $configuration->targetCharset;
  131. }
  132. /**
  133. * Writes the files footer and closes the file if it is open.
  134. */
  135. public function __destruct()
  136. {
  137. if ( $this->fd )
  138. {
  139. fclose( $this->fd );
  140. $this->fd = null;
  141. }
  142. }
  143. /**
  144. * Writes the opening tag and some comments for the PHP file.
  145. * @return void
  146. */
  147. protected function writeHeader()
  148. {
  149. fwrite( $this->fd,
  150. "<?php\n" );
  151. }
  152. /**
  153. * Writes the ending tag for the PHP file.
  154. * @return void
  155. */
  156. protected function writeFooter()
  157. {
  158. // Only write a newline if the current output is not properly ended with a newline.
  159. if ( !$this->newline )
  160. fwrite( $this->fd, "\n" );
  161. fwrite( $this->fd, "?>\n" );
  162. $this->hasWrittenFooter = true;
  163. }
  164. /**
  165. * Writes a text string to the currenly opened file.
  166. * The text string will be split up into lines and will have each line
  167. * indented according to current indentation rules.
  168. *
  169. * @param string $text The text string to write.
  170. * @param string $pre Text to place in front of each line (after indentation).
  171. * @param string $post Text to place after each line (before newline character).
  172. * @return void
  173. */
  174. protected function write( $text, $pre = null, $post = null )
  175. {
  176. $lines = preg_split( "#(\r\n|\r|\n)#", $text, -1, PREG_SPLIT_DELIM_CAPTURE );
  177. $count = count( $lines );
  178. for ( $i = 0; $i < $count; $i += 2 )
  179. {
  180. $line = $lines[$i];
  181. if ( $i + 1 < $count )
  182. {
  183. $str = $pre . $line . $post . $lines[$i + 1];
  184. if ( $this->newline )
  185. $str = $this->indentationText . $str;
  186. fwrite( $this->fd, $str );
  187. $this->newline = true;
  188. }
  189. else // The last line.
  190. {
  191. if ( strlen( $line ) > 0 )
  192. {
  193. $str = $pre . $line . $post;
  194. if ( $this->newline )
  195. $str = $this->indentationText . $str;
  196. fwrite( $this->fd, $str );
  197. $this->newline = false;
  198. }
  199. }
  200. }
  201. }
  202. /**
  203. * Increases the indentation with n characters.
  204. * The old indentation value is added to a stack which can be restored
  205. * with restoreIndentation().
  206. *
  207. * @param int $indentation The number of characters to increase the current indentation with.
  208. * @return void
  209. */
  210. public function increaseIndentation( $indentation )
  211. {
  212. $this->indentationStack[] = $this->currentIndentation;
  213. $this->currentIndentation += $indentation;
  214. if ( $this->currentIndentation > 0 )
  215. {
  216. $this->indentationText = str_repeat( " ", $this->currentIndentation );
  217. }
  218. else
  219. {
  220. $this->indentationText = "";
  221. }
  222. }
  223. /**
  224. * Restores the old indentation value from the stack.
  225. *
  226. * @throws Exception if the stack is empty.
  227. * @return void
  228. */
  229. public function restoreIndentation()
  230. {
  231. if ( count( $this->indentationStack ) == 0 )
  232. {
  233. throw new ezcTemplateInternalException( "Indentation stack is empty, cannot restore last indentation." );
  234. }
  235. $this->currentIndentation = array_pop( $this->indentationStack );
  236. if ( $this->currentIndentation > 0 )
  237. {
  238. $this->indentationText = str_repeat( " ", $this->currentIndentation );
  239. }
  240. else
  241. {
  242. $this->indentationText = "";
  243. }
  244. }
  245. /**
  246. * Generates code for control structures which takes a single parameter (optional).
  247. * The name of the control structure is sent in $name
  248. * @param ezcTemplateAstNode $control The control structure element to get parameter from.
  249. * @param string $name The name of the control structure, e.g. 'break'
  250. * @return void
  251. */
  252. protected function generateOptionalUnaryControl( ezcTemplateAstNode $control, $name )
  253. {
  254. $expression = $control->expression;
  255. if ( $expression === null )
  256. {
  257. $this->write( "{$name};\n" );
  258. }
  259. else
  260. {
  261. $this->write( "{$name} " );
  262. $expression->accept( $this );
  263. $this->write( ";\n" );
  264. }
  265. }
  266. /**
  267. * Generates code for control structures which takes a single parameter.
  268. * The name of the control structure is sent in $name
  269. * @param ezcTemplateAstNode $control The control structure element to get parameter from.
  270. * @param string $name The name of the control structure, e.g. 'break'
  271. * @return void
  272. */
  273. protected function generateUnaryControl( ezcTemplateAstNode $control, $name )
  274. {
  275. $this->write( "{$name} " );
  276. $control->expression->accept( $this );
  277. $this->write( ";\n" );
  278. }
  279. /**
  280. * Generates code for construct elements which looks like function calls.
  281. *
  282. * @param string $name The name of the construct to place in code.
  283. * @param ezcTemplateAstNode $construct The construct element.
  284. * @param array(ezcTemplateAstNode) $parameters
  285. * The parameters for the construct, will be written out with a comma
  286. * in between.
  287. * @return void
  288. */
  289. private function generateFunctionConstruct( $name, ezcTemplateAstNode $construct, Array $parameters )
  290. {
  291. $this->write( $name . "(" );
  292. foreach ( $parameters as $i => $parameter )
  293. {
  294. if ( $i > 0 )
  295. $this->write( "," );
  296. $parameter->accept( $this );
  297. }
  298. $this->write( ");\n" );
  299. }
  300. /**
  301. * Exports the constant type value.
  302. *
  303. * @param ezcTemplateLiteralAstNode $type The code element containing the constant value.
  304. * @return void
  305. */
  306. public function visitLiteralAstNode( ezcTemplateLiteralAstNode $type )
  307. {
  308. // Output type using var_export
  309. if ( is_string( $type->value ) )
  310. {
  311. $search = array( "\\",
  312. "\"",
  313. "\$",
  314. "\t",
  315. "\r",
  316. "\n" );
  317. $replace = array( "\\\\",
  318. "\\\"",
  319. "\\$",
  320. "\\t",
  321. "\\r",
  322. "\\n" );
  323. if ( $this->escapeSingleQuote )
  324. {
  325. $search[] = "'";
  326. $replace[] = "\\'";
  327. }
  328. $valueText = str_replace( $search, $replace, $type->value );
  329. $charset = $this->charsetInTemplate === false ? $this->sourceCharset : $this->charsetInTemplate;
  330. #echo "FROM", $charset;
  331. #echo "TO", $this->targetCharset;
  332. $valueText = iconv( $charset, $this->targetCharset, $valueText );
  333. $text = "\"$valueText\"";
  334. $this->write( $text );
  335. }
  336. elseif ( is_array( $type->value ) )
  337. {
  338. $this->write( "array(" );
  339. foreach ( $type->value as $val )
  340. {
  341. $val->accept( $this );
  342. $this->write( "," );
  343. }
  344. $this->write( ")" );
  345. // $this->write( var_export( $type->value, true ) );
  346. }
  347. else
  348. {
  349. $this->write( var_export( $type->value, true ) );
  350. }
  351. }
  352. /**
  353. * Writes an php array.
  354. *
  355. * @param ezcTemplateLiteralArrayAstNode $type
  356. * @return void
  357. */
  358. public function visitLiteralArrayAstNode( ezcTemplateLiteralArrayAstNode $type )
  359. {
  360. $first = true;
  361. $this->write( "array(" );
  362. foreach ( $type->value as $key => $val )
  363. {
  364. if ( !$first )
  365. {
  366. $this->write( "," );
  367. }
  368. if ( isset( $type->keys[$key] ) )
  369. {
  370. $type->keys[$key]->accept( $this );
  371. $this->write ( " => " );
  372. }
  373. $val->accept( $this );
  374. $first = false;
  375. }
  376. $this->write( ")" );
  377. }
  378. /**
  379. * Writes an output node.
  380. *
  381. * @param ezcTemplateOutputAstNode $type
  382. * @return void
  383. */
  384. public function visitOutputAstNode( ezcTemplateOutputAstNode $type )
  385. {
  386. $type->expression->accept( $this );
  387. }
  388. /**
  389. * Casts the value to the type.
  390. *
  391. * @param ezcTemplateTypeCastAstNode $node
  392. * @return void
  393. */
  394. public function visitTypeCastAstNode( ezcTemplateTypeCastAstNode $node )
  395. {
  396. $this->write( "(" . $node->type . ")" );
  397. $node->value->accept( $this );
  398. }
  399. /**
  400. * Writes the constant as-is.
  401. *
  402. * @param ezcTemplateConstantAstNode $type The code element containing the constant value.
  403. * @return void
  404. */
  405. public function visitConstantAstNode( ezcTemplateConstantAstNode $type )
  406. {
  407. $this->write( $type->value );
  408. }
  409. /**
  410. * Writes the EOL comment with correct start marker.
  411. *
  412. * @param ezcTemplateEolCommentAstNode $comment The code element containing the EOL comment.
  413. * @return void
  414. */
  415. public function visitEolCommentAstNode( ezcTemplateEolCommentAstNode $comment )
  416. {
  417. $marker = $comment->createMarkerText();
  418. if ( $comment->hasSeparator )
  419. {
  420. $marker .= ' ';
  421. }
  422. $this->write( $comment->text . "\n", $marker );
  423. }
  424. /**
  425. * Writes the block comment.
  426. *
  427. * @param ezcTemplateBlockCommentAstNode $comment The code element containing the block comment.
  428. * @return void
  429. */
  430. public function visitBlockCommentAstNode( ezcTemplateBlockCommentAstNode $comment )
  431. {
  432. // Comment output.
  433. // if ( $comment->hasSeparator )
  434. // {
  435. // $startMarker = '/* ';
  436. // $endMarker = ' */';
  437. // }
  438. // else
  439. // {
  440. // $startMarker = '/*';
  441. // $endMarker = '*/';
  442. // }
  443. // $this->write( $startMarker . $comment->text . $endMarker . "\n" );
  444. }
  445. /**
  446. * Writes a dollar sign and the name of the variable.
  447. *
  448. * @param ezcTemplateVariableAstNode $var The code element containing the variable value.
  449. * @return void
  450. */
  451. public function visitVariableAstNode( ezcTemplateVariableAstNode $var )
  452. {
  453. $this->write( '$' . $var->name );
  454. }
  455. /**
  456. * Writes a dollar sign and curly braces around the sub-expression.
  457. *
  458. * @param ezcTemplateDynamicVariableAstNode $var The code element containing the variable value.
  459. * @return void
  460. */
  461. public function visitDynamicVariableAstNode( ezcTemplateDynamicVariableAstNode $var )
  462. {
  463. $this->write( '${' );
  464. $var->nameExpression->accept( $this );
  465. $this->write( '}' );
  466. }
  467. /**
  468. * Visits a code element containing a dynamic string.
  469. *
  470. * @param ezcTemplateDynamicStringAstNode $dynamic The code element containing the dynamic string.
  471. * @return void
  472. */
  473. public function visitDynamicStringAstNode( ezcTemplateDynamicStringAstNode $dynamic )
  474. {
  475. $parameters = $dynamic->getParameters();
  476. $this->write( '"' );
  477. foreach ( $parameters as $parameter )
  478. {
  479. if ( $parameter instanceof ezcTemplateLiteralAstNode )
  480. {
  481. // Extract value as string and write it without the quotation marks.
  482. $value = (string)$parameter->value;
  483. $value = str_replace( array( "\\", "\"", "{" ),
  484. array( "\\\\", "\\\"", "\\{" ),
  485. $value );
  486. $this->write( $value );
  487. }
  488. else
  489. {
  490. $this->write( '{' );
  491. $parameter->accept( $this );
  492. $this->write( '}' );
  493. }
  494. }
  495. $this->write( '"' );
  496. }
  497. /**
  498. * Visits a code element containing an array fetch operator type.
  499. *
  500. * @param ezcTemplateArrayFetchOperatorAstNode $operator The code element containing the array fetch operator.
  501. * @return void
  502. */
  503. public function visitArrayFetchOperatorAstNode( ezcTemplateArrayFetchOperatorAstNode $operator )
  504. {
  505. $parameters = $operator->getParameters();
  506. $count = count( $parameters );
  507. if ( $count < $operator->minParameterCount )
  508. {
  509. throw new ezcTemplateInternalException( "The operator <" . get_class( $operator ) . " contains only " . count( $parameters ) . " parameters but should at least have {$operator->minParameterCount} parameters." );
  510. }
  511. // Generate code for first operand
  512. $parameters[0]->accept( $this );
  513. for ( $i = 1; $i < $count; ++$i )
  514. {
  515. // Generate the operator symbol before parameter.
  516. $this->write( "[" );
  517. // Generate code for operand
  518. $parameters[$i]->accept( $this );
  519. // and after parameter.
  520. $this->write( "]" );
  521. }
  522. }
  523. /**
  524. * Visits a code element containing a unary operator type.
  525. * Unary operators take one parameter and consist of a symbol.
  526. *
  527. * @param ezcTemplateOperatorAstNode $operator The code element containing the operator with parameter.
  528. * @return void
  529. */
  530. public function visitUnaryOperatorAstNode( ezcTemplateOperatorAstNode $operator )
  531. {
  532. $parameters = $operator->getParameters();
  533. if ( count( $parameters ) < $operator->minParameterCount )
  534. {
  535. throw new ezcTemplateInternalException( "The operator <" . get_class( $operator ) . " contains only " . count( $parameters ) . " parameters but should at least have {$operator->minParameterCount} parameters." );
  536. }
  537. if ( $operator->preOperator )
  538. {
  539. // Generate the operator symbol in between parameters.
  540. $this->write( " " . $operator->getOperatorPHPSymbol() );
  541. // Generate code for first operand
  542. $parameters[0]->accept( $this );
  543. }
  544. else
  545. {
  546. // Generate code for first operand
  547. $parameters[0]->accept( $this );
  548. // Generate the operator symbol in between parameters.
  549. $this->write( $operator->getOperatorPHPSymbol() . " " );
  550. }
  551. }
  552. /**
  553. * Visits a code element containing a binary operator type.
  554. * Binary operators take two parameters and consist of a symbol.
  555. *
  556. * @param ezcTemplateOperatorAstNode $operator The code element containing the operator with parameters.
  557. * @return void
  558. */
  559. public function visitBinaryOperatorAstNode( ezcTemplateOperatorAstNode $operator )
  560. {
  561. $parameters = $operator->getParameters();
  562. if ( count( $parameters ) < $operator->minParameterCount )
  563. {
  564. throw new ezcTemplateInternalException( "The operator <" . get_class( $operator ) . " contains only " . count( $parameters ) . " parameters but should at least have {$operator->minParameterCount} parameters." );
  565. }
  566. // Generate code for first operand
  567. $parameters[0]->accept( $this );
  568. // Generate the operator symbol in between parameters.
  569. if ( $operator instanceof ezcTemplateReferenceOperatorAstNode )
  570. {
  571. // No spaces around the '->'. PHP cannot handle: $myObj -> class
  572. $this->write( $operator->getOperatorPHPSymbol() );
  573. }
  574. else
  575. {
  576. $this->write( " " . $operator->getOperatorPHPSymbol() . " " );
  577. }
  578. // Generate code for second operand
  579. $parameters[1]->accept( $this );
  580. }
  581. /**
  582. * Visits a code element containing a function call.
  583. * Function call consist of a function name and arguments.
  584. *
  585. * @param ezcTemplateFunctionCallAstNode $fcall The code element containing the function call with arguments.
  586. * @return void
  587. */
  588. public function visitFunctionCallAstNode( ezcTemplateFunctionCallAstNode $fcall )
  589. {
  590. // Start arguments
  591. $this->write( $fcall->name . "(" );
  592. foreach ( $fcall->getParameters() as $i => $parameter )
  593. {
  594. if ( $i > 0 )
  595. $this->write( "," );
  596. $parameter->accept( $this );
  597. }
  598. $this->write( ")" );
  599. }
  600. /**
  601. * Visits a code element containing a body of statements.
  602. * A body consists of a series of statements in sequence.
  603. *
  604. * @param ezcTemplateBodyAstNode $body The code element containing the body.
  605. * @return void
  606. */
  607. public function visitBodyAstNode( ezcTemplateBodyAstNode $body )
  608. {
  609. foreach ( $body->statements as $statement )
  610. {
  611. $statement->accept( $this );
  612. }
  613. }
  614. /**
  615. * Visits a code element containing a body of statements.
  616. * A body consists of a series of statements in sequence.
  617. *
  618. * @param ezcTemplateRootAstNode $body The code element containing the body.
  619. * @return void
  620. */
  621. public function visitRootAstNode( ezcTemplateRootAstNode $body )
  622. {
  623. $this->charsetInTemplate = $body->charset;
  624. if ( $body->startProgram )
  625. {
  626. $this->writeHeader();
  627. }
  628. foreach ( $body->statements as $statement )
  629. {
  630. $statement->accept( $this );
  631. }
  632. if ( $body->startProgram )
  633. {
  634. $this->writeFooter();
  635. }
  636. }
  637. /**
  638. * Visits a code element containing a generic statement.
  639. * The expression is evaluated and and a semi-colon added to end the statement.
  640. * A generic statement contains a generic code expression but is terminated with a semi-colon.
  641. *
  642. * @param ezcTemplateGenericStatementAstNode $statement The code element containing the statement.
  643. * @return void
  644. */
  645. public function visitGenericStatementAstNode( ezcTemplateGenericStatementAstNode $statement )
  646. {
  647. $statement->expression->accept( $this );
  648. if ( $statement->terminateStatement )
  649. {
  650. $this->write( ";\n" );
  651. }
  652. }
  653. /**
  654. * Visits a code element containing if control structures.
  655. *
  656. * @param ezcTemplateIfAstNode $if The code element containing the if control structure.
  657. * @return void
  658. */
  659. public function visitIfAstNode( ezcTemplateIfAstNode $if )
  660. {
  661. foreach ( $if->conditions as $i => $conditionBody )
  662. {
  663. $condition = $conditionBody->condition;
  664. if ( $i == 0 )
  665. $this->write( "if (" );
  666. elseif ( $condition !== null )
  667. $this->write( "elseif (" );
  668. else
  669. $this->write( "else" );
  670. if ( $condition !== null )
  671. {
  672. $condition->accept( $this );
  673. $this->write( ")\n{\n" );
  674. }
  675. else
  676. {
  677. $this->write( "\n{\n" );
  678. }
  679. $this->increaseIndentation( $this->indentation );
  680. $conditionBody->body->accept( $this );
  681. $this->restoreIndentation();
  682. $this->write( "}\n" );
  683. }
  684. }
  685. /**
  686. * Pretends to write the dynamic block. The only thing it does is calling
  687. * the children with the escapeSingleQuote switched on.
  688. *
  689. * @param ezcTemplateDynamicBlockAstNode $statement
  690. * @return void
  691. */
  692. public function visitDynamicBlockAstNode( ezcTemplateDynamicBlockAstNode $statement )
  693. {
  694. $this->escapeSingleQuote = $statement->escapeSingleQuote;
  695. // Do not write anything, but call the children.
  696. $statement->body->accept( $this );
  697. $this->escapeSingleQuote = false;
  698. }
  699. /**
  700. * Visits a code element containing while control structures.
  701. *
  702. * @param ezcTemplateWhileAstNode $while The code element containing the while control structure.
  703. * @return void
  704. */
  705. public function visitWhileAstNode( ezcTemplateWhileAstNode $while )
  706. {
  707. $conditionBody = $while->conditionBody;
  708. $this->write( "while (" );
  709. $conditionBody->condition->accept( $this );
  710. $this->write( ")\n{\n" );
  711. $this->increaseIndentation( $this->indentation );
  712. $conditionBody->body->accept( $this );
  713. $this->restoreIndentation();
  714. $this->write( "}\n" );
  715. }
  716. /**
  717. * Visits a code element containing foreach control structures.
  718. *
  719. * @param ezcTemplateForeachAstNode $foreach The code element containing the foreach control structure.
  720. * @return void
  721. */
  722. public function visitForeachAstNode( ezcTemplateForeachAstNode $foreach )
  723. {
  724. $this->write( "foreach (" );
  725. $foreach->arrayExpression->accept( $this );
  726. $this->write( " as " );
  727. if ( $foreach->keyVariable !== null )
  728. {
  729. $foreach->keyVariable->accept( $this );
  730. $this->write( " => " );
  731. }
  732. $foreach->valueVariable->accept( $this );
  733. $this->write( ")\n{\n" );
  734. $this->increaseIndentation( $this->indentation );
  735. $foreach->body->accept( $this );
  736. $this->restoreIndentation();
  737. $this->write( "}\n" );
  738. }
  739. /**
  740. * Visits a code element containing break control structures.
  741. *
  742. * @param ezcTemplateBreakAstNode $break The code element containing the break control structure.
  743. * @return void
  744. */
  745. public function visitBreakAstNode( ezcTemplateBreakAstNode $break )
  746. {
  747. $this->generateOptionalUnaryControl( $break, "break" );
  748. }
  749. /**
  750. * Visits a code element containing continue control structures.
  751. *
  752. * @param ezcTemplateContinueAstNode $continue The code element containing the continue control structure.
  753. * @return void
  754. */
  755. public function visitContinueAstNode( ezcTemplateContinueAstNode $continue )
  756. {
  757. $this->generateOptionalUnaryControl( $continue, "continue" );
  758. }
  759. /**
  760. * Visits a code element containing return control structures.
  761. *
  762. * @param ezcTemplateReturnAstNode $return The code element containing the return control structure.
  763. * @return void
  764. */
  765. public function visitReturnAstNode( ezcTemplateReturnAstNode $return )
  766. {
  767. $this->generateOptionalUnaryControl( $return, "return" );
  768. }
  769. /**
  770. * Visits a code element containing require control structures.
  771. *
  772. * @param ezcTemplateRequireAstNode $require The code element containing the require control structure.
  773. * @return void
  774. */
  775. public function visitRequireAstNode( ezcTemplateRequireAstNode $require )
  776. {
  777. $this->generateUnaryControl( $require, "require" );
  778. }
  779. /**
  780. * Visits a code element containing require_once control structures.
  781. *
  782. * @param ezcTemplateRequireOnceAstNode $require The code element containing the require_once control structure.
  783. * @return void
  784. */
  785. public function visitRequireOnceAstNode( ezcTemplateRequireOnceAstNode $require )
  786. {
  787. $this->generateUnaryControl( $require, "require_once" );
  788. }
  789. /**
  790. * Visits a code element containing include control structures.
  791. *
  792. * @param ezcTemplateIncludeAstNode $include The code element containing the include control structure.
  793. * @return void
  794. */
  795. public function visitIncludeAstNode( ezcTemplateIncludeAstNode $include )
  796. {
  797. $this->generateUnaryControl( $include, "include" );
  798. }
  799. /**
  800. * Visits a code element containing include_once control structures.
  801. *
  802. * @param ezcTemplateIncludeOnceAstNode $include The code element containing the include_once control structure.
  803. * @return void
  804. */
  805. public function visitIncludeOnceAstNode( ezcTemplateIncludeOnceAstNode $include )
  806. {
  807. $this->generateUnaryControl( $include, "include_once" );
  808. }
  809. /**
  810. * Visits a code element containing switch control structures.
  811. *
  812. * @param ezcTemplateSwitchAstNode $switch The code element containing the switch control structure.
  813. * @return void
  814. */
  815. public function visitSwitchAstNode( ezcTemplateSwitchAstNode $switch )
  816. {
  817. $this->write( "switch (" );
  818. $switch->expression->accept( $this );
  819. $this->write( ")\n{\n" );
  820. $this->increaseIndentation( $this->indentation );
  821. foreach ( $switch->cases as $case )
  822. {
  823. $case->accept( $this );
  824. }
  825. $this->restoreIndentation();
  826. $this->write( "}\n" );
  827. }
  828. /**
  829. * Visits a code element containing case control structures.
  830. *
  831. * @param ezcTemplateCaseAstNode $case The code element containing the case control structure.
  832. * @return void
  833. */
  834. public function visitCaseAstNode( ezcTemplateCaseAstNode $case )
  835. {
  836. $this->write( "case " );
  837. $case->match->accept( $this );
  838. $this->write( ":\n" );
  839. $this->increaseIndentation( $this->indentation );
  840. $case->body->accept( $this );
  841. $this->restoreIndentation();
  842. }
  843. /**
  844. * Visits a code element containing default case control structures.
  845. *
  846. * @param ezcTemplateDefaultAstNode $default The code element containing the default case control structure.
  847. * @return void
  848. */
  849. public function visitDefaultAstNode( ezcTemplateDefaultAstNode $default )
  850. {
  851. $this->write( "default:\n" );
  852. $this->increaseIndentation( $this->indentation );
  853. $default->body->accept( $this );
  854. $this->restoreIndentation();
  855. }
  856. /**
  857. * Visits a code element containing conditions for if control structures.
  858. *
  859. * @param ezcTemplateConditionBodyAstNode $cond The code element containing the if condition.
  860. * @return void
  861. */
  862. public function visitConditionBodyAstNode( ezcTemplateConditionBodyAstNode $cond )
  863. {
  864. // Not used, data is extracted directly for if, while and do/while
  865. }
  866. /**
  867. * Visits a code element containing try control structures.
  868. *
  869. * @param ezcTemplateTryAstNode $try The code element containing the try control structure.
  870. * @return void
  871. */
  872. public function visitTryAstNode( ezcTemplateTryAstNode $try )
  873. {
  874. $this->write( "try\n{\n" );
  875. $this->increaseIndentation( $this->indentation );
  876. $try->body->accept( $this );
  877. $this->restoreIndentation();
  878. $this->write( "}\n" );
  879. foreach ( $try->catches as $catch )
  880. {
  881. $catch->accept( $this );
  882. }
  883. }
  884. /**
  885. * Visits a code element containing catch control structures.
  886. *
  887. * @param ezcTemplateCatchAstNode $catch The code element containing the catch control structure.
  888. * @return void
  889. */
  890. public function visitCatchAstNode( ezcTemplateCatchAstNode $catch )
  891. {
  892. $this->write( "catch (" . $catch->className . " " );
  893. $catch->variableExpression->accept( $this );
  894. $this->write( ")\n{\n" );
  895. $this->increaseIndentation( $this->indentation );
  896. $catch->body->accept( $this );
  897. $this->restoreIndentation();
  898. $this->write( "}\n" );
  899. }
  900. /**
  901. * Visits a code element containing echo construct.
  902. *
  903. * @param ezcTemplateEchoAstNode $echo The code element containing the echo construct.
  904. * @return void
  905. */
  906. public function visitEchoAstNode( ezcTemplateEchoAstNode $echo )
  907. {
  908. $outputList = $echo->getOutputList();
  909. $this->write( "echo " );
  910. foreach ( $outputList as $i => $output )
  911. {
  912. if ( $i > 0 )
  913. $this->write( "," );
  914. $output->accept( $this );
  915. }
  916. $this->write( ";\n" );
  917. }
  918. /**
  919. * Visits a code element containing print construct.
  920. *
  921. * @param ezcTemplatePrintAstNode $print The code element containing the print construct.
  922. * @return void
  923. */
  924. public function visitPrintAstNode( ezcTemplatePrintAstNode $print )
  925. {
  926. $this->write( "print " );
  927. $print->expression->accept( $this );
  928. $this->write( ";\n" );
  929. }
  930. /**
  931. * Visits a code element containing isset construct.
  932. *
  933. * @param ezcTemplateIssetAstNode $isset The code element containing the isset construct.
  934. * @return void
  935. */
  936. public function visitIssetAstNode( ezcTemplateIssetAstNode $isset )
  937. {
  938. $this->generateFunctionConstruct( 'isset', $isset, $isset->getExpressions() );
  939. }
  940. /**
  941. * Visits a code element containing unset construct.
  942. *
  943. * @param ezcTemplateUnsetAstNode $unset The code element containing the unset construct.
  944. * @return void
  945. */
  946. public function visitUnsetAstNode( ezcTemplateUnsetAstNode $unset )
  947. {
  948. $this->generateFunctionConstruct( 'unset', $unset, $unset->getExpressions() );
  949. }
  950. /**
  951. * Visits a code element containing empty construct.
  952. *
  953. * @param ezcTemplateEmptyAstNode $empty The code element containing the empty construct.
  954. * @return void
  955. */
  956. public function visitEmptyAstNode( ezcTemplateEmptyAstNode $empty )
  957. {
  958. $this->write( "empty(" );
  959. $empty->expression->accept( $this );
  960. $this->write( ");\n" );
  961. }
  962. /**
  963. * Writes parenthesis.
  964. *
  965. * @param ezcTemplateParenthesisAstNode $parenthesis
  966. * @return void
  967. */
  968. public function visitParenthesisAstNode( ezcTemplateParenthesisAstNode $parenthesis )
  969. {
  970. $this->write( "(" );
  971. $parenthesis->expression->accept( $this );
  972. $this->write( ")" );
  973. }
  974. /**
  975. * Writes curly braces.
  976. *
  977. * @param ezcTemplateCurlyBracesAstNode $curly
  978. * @return void
  979. */
  980. public function visitCurlyBracesAstNode( ezcTemplateCurlyBracesAstNode $curly )
  981. {
  982. $this->write( "{" );
  983. $curly->expression->accept( $this );
  984. $this->write( "}" );
  985. }
  986. /**
  987. * Writes a new class.
  988. *
  989. * @param ezcTemplateNewAstNode $new
  990. * @return void
  991. */
  992. public function visitNewAstNode( ezcTemplateNewAstNode $new )
  993. {
  994. $this->write( "new " );
  995. $this->write( $new->class . "(" );
  996. foreach ( $new->getParameters() as $i => $parameter )
  997. {
  998. if ( $i > 0 )
  999. $this->write( "," );
  1000. $parameter->accept( $this );
  1001. }
  1002. $this->write( ")" );
  1003. }
  1004. /**
  1005. * Writes the clone statement.
  1006. *
  1007. * @param ezcTemplateCloneAstNode $clone
  1008. * @return void
  1009. */
  1010. public function visitCloneAstNode( ezcTemplateCloneAstNode $clone )
  1011. {
  1012. $this->write( "clone " );
  1013. $this->write( $clone->object->accept($this) );
  1014. }
  1015. /**
  1016. * Writes raw PHP code.
  1017. *
  1018. * @param ezcTemplatePhpCodeAstNode $code
  1019. * @return void
  1020. */
  1021. public function visitPhpCodeAstNode( ezcTemplatePhpCodeAstNode $code )
  1022. {
  1023. $this->write( $code->code );
  1024. }
  1025. /**
  1026. * Writes a new runtime exception.
  1027. *
  1028. * @param ezcTemplateThrowExceptionAstNode $exception
  1029. * @return void
  1030. */
  1031. public function visitThrowExceptionAstNode( ezcTemplateThrowExceptionAstNode $exception )
  1032. {
  1033. $this->write( "throw new ezcTemplateRuntimeException( ");
  1034. $exception->message->accept( $this );
  1035. $this->write( ")" );
  1036. }
  1037. /**
  1038. * Writes an identifier.
  1039. *
  1040. * @param ezcTemplateIdentifierAstNode $node
  1041. * @return void
  1042. */
  1043. public function visitIdentifierAstNode( ezcTemplateIdentifierAstNode $node )
  1044. {
  1045. $this->write( $node->name );
  1046. }
  1047. /**
  1048. * Visits a node containing a nop node.
  1049. *
  1050. * @param ezcTemplateNopAstNode $node The node containing the nop node.
  1051. * @return void
  1052. */
  1053. public function visitNopAstNode( ezcTemplateNopAstNode $node )
  1054. {
  1055. // Nops don't create any output
  1056. }
  1057. }
  1058. ?>