/Template/src/parsers/source_to_tst/implementations/custom_block.php

https://github.com/xc/zetacomponents · PHP · 231 lines · 134 code · 37 blank · 60 comment · 26 complexity · 4dc1133361c0efe3106df6023d663ba1 MD5 · raw file

  1. <?php
  2. /**
  3. * File containing the ezcTemplateCustomBlockSourceToTstParser 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. * Parser for custom template blocks following a generic syntax.
  29. *
  30. * @package Template
  31. * @version //autogen//
  32. * @access private
  33. */
  34. class ezcTemplateCustomBlockSourceToTstParser extends ezcTemplateSourceToTstParser
  35. {
  36. /**
  37. * Passes control to parent.
  38. *
  39. * @param ezcTemplateParser $parser
  40. * @param ezcTemplateSourceToTstParser $parentParser
  41. * @param ezcTemplateCursor $startCursor
  42. */
  43. function __construct( ezcTemplateParser $parser, /*ezcTemplateSourceToTstParser*/ $parentParser, /*ezcTemplateCursor*/ $startCursor )
  44. {
  45. parent::__construct( $parser, $parentParser, $startCursor );
  46. $this->block = null;
  47. }
  48. /**
  49. * Returns the custom block definition.
  50. *
  51. * @param string $name
  52. * @return ezcTemplateCustomBlockDefinition
  53. */
  54. function getCustomBlockDefinition( $name )
  55. {
  56. foreach ( $this->parser->template->configuration->customBlocks as $class )
  57. {
  58. $def = call_user_func( array( $class, "getCustomBlockDefinition" ), $name );
  59. if ( $def instanceof ezcTemplateCustomBlockDefinition )
  60. {
  61. return $def;
  62. }
  63. }
  64. return false;
  65. }
  66. /**
  67. * Parses the expression by using the ezcTemplateExpressionSourceToTstParser class.
  68. *
  69. * @param ezcTemplateCursor $cursor
  70. * @return bool
  71. */
  72. protected function parseCurrent( ezcTemplateCursor $cursor )
  73. {
  74. if ( $this->block->isClosingBlock )
  75. {
  76. $this->findNextElement();
  77. $matches = $cursor->pregMatchComplete( "#^([a-zA-Z_][a-zA-Z0-9_-]*)(?:[^a-zA-Z])#i" );
  78. if ( $matches === false )
  79. return false;
  80. $name = $matches[1][0];
  81. // If the custom block is not defined we have to return false.
  82. $def = $this->getCustomBlockDefinition( $name );
  83. if ( $def === false )
  84. {
  85. return false;
  86. }
  87. $cursor->advance( strlen( $name ) );
  88. $this->findNextElement( $cursor );
  89. if ( !$cursor->match( "}" ) )
  90. {
  91. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_CURLY_BRACKET_CLOSE );
  92. }
  93. $cb = new ezcTemplateCustomBlockTstNode( $this->parser->source, $this->startCursor, $cursor );
  94. $cb->name = $name;
  95. $cb->isClosingBlock = true;
  96. $this->appendElement( $cb );
  97. return true;
  98. }
  99. // Check for the name of the custom block
  100. // Note: The code inside the ( ?: ) brace ensures that the next character
  101. // is not an alphabetical character ie. a word boundary
  102. $matches = $cursor->pregMatchComplete( "#^([a-zA-Z_][a-zA-Z0-9_-]*)(?:[^a-zA-Z])#i" );
  103. if ( $matches === false )
  104. {
  105. return false;
  106. }
  107. $name = $matches[1][0];
  108. $cursor->advance( strlen( $name ) );
  109. $this->findNextElement( $cursor );
  110. // $def = ezcTemplateCustomBlockManager::getInstance()->getDefinition( $name );
  111. $def = $this->getCustomBlockDefinition( $name );
  112. if ( $def === false )
  113. {
  114. return false;
  115. }
  116. $cb = new ezcTemplateCustomBlockTstNode( $this->parser->source, $this->startCursor, $cursor );
  117. $cb->definition = $def;
  118. $cb->name = $name;
  119. $this->block->isNestingBlock = $cb->isNestingBlock = $def->hasCloseTag;
  120. $excessParameters = isset( $def->excessParameters ) && $def->excessParameters ? true : false;
  121. if ( isset( $def->startExpressionName ) && $def->startExpressionName != "" )
  122. {
  123. if ( !in_array( $def->startExpressionName, $def->optionalParameters ) && !in_array( $def->startExpressionName, $def->requiredParameters ) )
  124. {
  125. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor,
  126. sprintf( ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_REQUIRED_OR_OPTIONAL_PARAMETER_DEFINITION_IN_CUSTOM_BLOCK, $def->startExpressionName ) );
  127. }
  128. if ( !$this->parseOptionalType( 'Expression', null, false ) )
  129. {
  130. if ( in_array( $def->startExpressionName, $def->requiredParameters ) )
  131. {
  132. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_EXPRESSION );
  133. }
  134. }
  135. else
  136. {
  137. if ( $this->lastParser->rootOperator instanceof ezcTemplateModifyingOperatorTstNode )
  138. {
  139. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_MODIFYING_EXPRESSION_NOT_ALLOWED );
  140. }
  141. $cb->namedParameters[ $def->startExpressionName ] = $this->lastParser->rootOperator;
  142. $this->findNextElement( $cursor );
  143. }
  144. }
  145. while ( !$cursor->match( "}" ) )
  146. {
  147. $match = $cursor->pregMatch( "#^[a-zA-Z_][a-zA-Z0-9_-]*#");
  148. if ( !$match )
  149. {
  150. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor,
  151. sprintf( ezcTemplateSourceToTstErrorMessages::MSG_UNEXPECTED_TOKEN, $cursor->current( 1 ) ) );
  152. }
  153. if ( !$excessParameters && !in_array( $match, $def->optionalParameters ) && !in_array( $match, $def->requiredParameters ) )
  154. {
  155. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor,
  156. sprintf( ezcTemplateSourceToTstErrorMessages::MSG_UNKNOWN_CUSTOM_BLOCK_PARAMETER, $match) );
  157. }
  158. if ( array_key_exists( $match, $cb->namedParameters ) )
  159. {
  160. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor,
  161. sprintf( ezcTemplateSourceToTstErrorMessages::MSG_REASSIGNMENT_CUSTOM_BLOCK_PARAMETER, $match ) );
  162. }
  163. $this->findNextElement( $cursor );
  164. // The '=' is optional.
  165. if ( $cursor->match( "=" ) )
  166. {
  167. $this->findNextElement( $cursor );
  168. }
  169. // The parameter has an expression.
  170. if ( !$this->parseOptionalType( 'Expression', null, false ) )
  171. {
  172. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_EXPECT_EXPRESSION );
  173. }
  174. if ( $this->lastParser->rootOperator instanceof ezcTemplateModifyingOperatorTstNode )
  175. {
  176. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor, ezcTemplateSourceToTstErrorMessages::MSG_MODIFYING_EXPRESSION_NOT_ALLOWED );
  177. }
  178. // Append the parameter to the "namedParameters" array.
  179. $cb->namedParameters[ $match ] = $this->lastParser->rootOperator;
  180. }
  181. // Check if all requiredParameters are set.
  182. foreach ( $def->requiredParameters as $val )
  183. {
  184. if ( !array_key_exists( $val, $cb->namedParameters) )
  185. {
  186. throw new ezcTemplateParserException( $this->parser->source, $this->startCursor, $this->currentCursor,
  187. sprintf( ezcTemplateSourceToTstErrorMessages::MSG_MISSING_CUSTOM_BLOCK_PARAMETER, $val ) );
  188. }
  189. }
  190. $this->appendElement( $cb );
  191. return true;
  192. }
  193. }
  194. ?>