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 */ 30final class BlockTokenParser extends AbstractTokenParser 31{ 32 public function parse(Token $token) 33 { 34 $lineno = $token->getLine(); 35 $stream = $this->parser->getStream(); 36 $name = $stream->expect(/* Token::NAME_TYPE */ 5)->getValue(); 37 if ($this->parser->hasBlock($name)) { 38 throw new SyntaxError(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()); 39 } 40 $this->parser->setBlock($name, $block = new BlockNode($name, new Node([]), $lineno)); 41 $this->parser->pushLocalScope(); 42 $this->parser->pushBlockStack($name); 43 44 if ($stream->nextIf(/* Token::BLOCK_END_TYPE */ 3)) { 45 $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); 46 if ($token = $stream->nextIf(/* Token::NAME_TYPE */ 5)) { 47 $value = $token->getValue(); 48 49 if ($value != $name) { 50 throw new SyntaxError(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); 51 } 52 } 53 } else { 54 $body = new Node([ 55 new PrintNode($this->parser->getExpressionParser()->parseExpression(), $lineno), 56 ]); 57 } 58 $stream->expect(/* Token::BLOCK_END_TYPE */ 3); 59 60 $block->setNode('body', $body); 61 $this->parser->popBlockStack(); 62 $this->parser->popLocalScope(); 63 64 return new BlockReferenceNode($name, $lineno, $this->getTag()); 65 } 66 67 public function decideBlockEnd(Token $token) 68 { 69 return $token->test('endblock'); 70 } 71 72 public function getTag() 73 { 74 return 'block'; 75 } 76} 77 78class_alias('Twig\TokenParser\BlockTokenParser', 'Twig_TokenParser_Block'); 79