1<?php 2 3/* 4 * This file is part of Twig. 5 * 6 * (c) Fabien Potencier 7 * (c) Armin Ronacher 8 * 9 * For the full copyright and license information, please view the LICENSE 10 * file that was distributed with this source code. 11 */ 12 13namespace Twig\TokenParser; 14 15use Twig\Error\SyntaxError; 16use Twig\Node\BlockNode; 17use Twig\Node\BlockReferenceNode; 18use Twig\Node\Node; 19use Twig\Node\PrintNode; 20use Twig\Token; 21 22/** 23 * Marks a section of a template as being reusable. 24 * 25 * {% block head %} 26 * <link rel="stylesheet" href="style.css" /> 27 * <title>{% block title %}{% endblock %} - My Webpage</title> 28 * {% endblock %} 29 * 30 * @final 31 */ 32class BlockTokenParser extends AbstractTokenParser 33{ 34 public function parse(Token $token) 35 { 36 $lineno = $token->getLine(); 37 $stream = $this->parser->getStream(); 38 $name = $stream->expect(Token::NAME_TYPE)->getValue(); 39 if ($this->parser->hasBlock($name)) { 40 throw new SyntaxError(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()); 41 } 42 $this->parser->setBlock($name, $block = new BlockNode($name, new Node([]), $lineno)); 43 $this->parser->pushLocalScope(); 44 $this->parser->pushBlockStack($name); 45 46 if ($stream->nextIf(Token::BLOCK_END_TYPE)) { 47 $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); 48 if ($token = $stream->nextIf(Token::NAME_TYPE)) { 49 $value = $token->getValue(); 50 51 if ($value != $name) { 52 throw new SyntaxError(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); 53 } 54 } 55 } else { 56 $body = new Node([ 57 new PrintNode($this->parser->getExpressionParser()->parseExpression(), $lineno), 58 ]); 59 } 60 $stream->expect(Token::BLOCK_END_TYPE); 61 62 $block->setNode('body', $body); 63 $this->parser->popBlockStack(); 64 $this->parser->popLocalScope(); 65 66 return new BlockReferenceNode($name, $lineno, $this->getTag()); 67 } 68 69 public function decideBlockEnd(Token $token) 70 { 71 return $token->test('endblock'); 72 } 73 74 public function getTag() 75 { 76 return 'block'; 77 } 78} 79 80class_alias('Twig\TokenParser\BlockTokenParser', 'Twig_TokenParser_Block'); 81