/** * Matches an open with an closing block. * * @param ezcTemplateTstNode $element * @throws ezcTemplateParserException for non matching open and close blocks. * @return void */ protected function closeOpenBlock($element) { // The previous element must be a block element, // if not throw an exception if (!$this->lastBlock instanceof ezcTemplateBlockTstNode) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, "Found closing block {" . $element->name . "} without a previous block element <" . get_class($this->lastBlock) . ">"); } // Check for closing blocks that do not belong to an opening block. if ($this->lastBlock->parentBlock === null && $element->isClosingBlock) { if ($element instanceof ezcTemplateCustomBlockTstNode) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->startCursor, "The custom block: {" . $element->name . "} should not have a closing block. Check the custom block definition. "); } else { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->startCursor, "Found closing block {/" . $element->name . "} without an opening block."); } } // The name of the previous element must match the closing block, // if not throw an exception if ($this->lastBlock->name != $element->name) { throw new ezcTemplateParserException($this->parser->source, $this->startCursor, $this->currentCursor, "Open and close block do not match: {" . $this->lastBlock->name . "} and {/" . $element->name . "}"); } // Sanity check if ($this->lastBlock->parentBlock === null) { throw new ezcTemplateInternalException("Parent block of last block <" . get_class($this->lastBlock) . "> is null, should not happen."); } // Call the closing element with the block element it closes, // this allows it to update the open block if required. $element->closeOpenBlock($this->lastBlock); // Tell the main parser to trim indentation for the block, // the whitespace trimming rules are defined within the main parser. $this->parser->trimBlockLevelIndentation($this->lastBlock); // Get rid of whitespace for the block line $this->parser->trimBlockLine($this->lastBlock); // Go up (closer to program) one level in the nested tree structure $this->lastBlock = $this->lastBlock->parentBlock; }