AsseticTokenParser.php 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <?php
  2. /*
  3. * This file is part of the Assetic package, an OpenSky project.
  4. *
  5. * (c) 2010-2012 OpenSky Project Inc
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Assetic\Extension\Twig;
  11. use Assetic\Asset\AssetInterface;
  12. use Assetic\Factory\AssetFactory;
  13. class AsseticTokenParser extends \Twig_TokenParser
  14. {
  15. private $factory;
  16. private $tag;
  17. private $output;
  18. private $single;
  19. private $extensions;
  20. /**
  21. * Constructor.
  22. *
  23. * Attributes can be added to the tag by passing names as the options
  24. * array. These values, if found, will be passed to the factory and node.
  25. *
  26. * @param AssetFactory $factory The asset factory
  27. * @param string $tag The tag name
  28. * @param string $output The default output string
  29. * @param Boolean $single Whether to force a single asset
  30. * @param array $extensions Additional attribute names to look for
  31. */
  32. public function __construct(AssetFactory $factory, $tag, $output, $single = false, array $extensions = array())
  33. {
  34. $this->factory = $factory;
  35. $this->tag = $tag;
  36. $this->output = $output;
  37. $this->single = $single;
  38. $this->extensions = $extensions;
  39. }
  40. public function parse(\Twig_Token $token)
  41. {
  42. $inputs = array();
  43. $filters = array();
  44. $name = null;
  45. $attributes = array(
  46. 'output' => $this->output,
  47. 'var_name' => 'asset_url',
  48. );
  49. $stream = $this->parser->getStream();
  50. while (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
  51. if ($stream->test(\Twig_Token::STRING_TYPE)) {
  52. // '@jquery', 'js/src/core/*', 'js/src/extra.js'
  53. $inputs[] = $stream->next()->getValue();
  54. } elseif ($stream->test(\Twig_Token::NAME_TYPE, 'filter')) {
  55. // filter='yui_js'
  56. $stream->next();
  57. $stream->expect(\Twig_Token::OPERATOR_TYPE, '=');
  58. $filters = array_merge($filters, array_filter(array_map('trim', explode(',', $stream->expect(\Twig_Token::STRING_TYPE)->getValue()))));
  59. } elseif ($stream->test(\Twig_Token::NAME_TYPE, 'output')) {
  60. // output='js/packed/*.js' OR output='js/core.js'
  61. $stream->next();
  62. $stream->expect(\Twig_Token::OPERATOR_TYPE, '=');
  63. $attributes['output'] = $stream->expect(\Twig_Token::STRING_TYPE)->getValue();
  64. } elseif ($stream->test(\Twig_Token::NAME_TYPE, 'name')) {
  65. // name='core_js'
  66. $stream->next();
  67. $stream->expect(\Twig_Token::OPERATOR_TYPE, '=');
  68. $name = $stream->expect(\Twig_Token::STRING_TYPE)->getValue();
  69. } elseif ($stream->test(\Twig_Token::NAME_TYPE, 'as')) {
  70. // as='the_url'
  71. $stream->next();
  72. $stream->expect(\Twig_Token::OPERATOR_TYPE, '=');
  73. $attributes['var_name'] = $stream->expect(\Twig_Token::STRING_TYPE)->getValue();
  74. } elseif ($stream->test(\Twig_Token::NAME_TYPE, 'debug')) {
  75. // debug=true
  76. $stream->next();
  77. $stream->expect(\Twig_Token::OPERATOR_TYPE, '=');
  78. $attributes['debug'] = 'true' == $stream->expect(\Twig_Token::NAME_TYPE, array('true', 'false'))->getValue();
  79. } elseif ($stream->test(\Twig_Token::NAME_TYPE, 'combine')) {
  80. // combine=true
  81. $stream->next();
  82. $stream->expect(\Twig_Token::OPERATOR_TYPE, '=');
  83. $attributes['combine'] = 'true' == $stream->expect(\Twig_Token::NAME_TYPE, array('true', 'false'))->getValue();
  84. } elseif ($stream->test(\Twig_Token::NAME_TYPE, $this->extensions)) {
  85. // an arbitrary configured attribute
  86. $key = $stream->next()->getValue();
  87. $stream->expect(\Twig_Token::OPERATOR_TYPE, '=');
  88. $attributes[$key] = $stream->expect(\Twig_Token::STRING_TYPE)->getValue();
  89. } else {
  90. $token = $stream->getCurrent();
  91. throw new \Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', \Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine());
  92. }
  93. }
  94. $stream->expect(\Twig_Token::BLOCK_END_TYPE);
  95. $body = $this->parser->subparse(array($this, 'testEndTag'), true);
  96. $stream->expect(\Twig_Token::BLOCK_END_TYPE);
  97. if ($this->single && 1 < count($inputs)) {
  98. $inputs = array_slice($inputs, -1);
  99. }
  100. if (!$name) {
  101. $name = $this->factory->generateAssetName($inputs, $filters, $attributes);
  102. }
  103. $asset = $this->factory->createAsset($inputs, $filters, $attributes + array('name' => $name));
  104. return $this->createNode($asset, $body, $inputs, $filters, $name, $attributes, $token->getLine(), $this->getTag());
  105. }
  106. public function getTag()
  107. {
  108. return $this->tag;
  109. }
  110. public function testEndTag(\Twig_Token $token)
  111. {
  112. return $token->test(array('end'.$this->getTag()));
  113. }
  114. protected function createNode(AssetInterface $asset, \Twig_NodeInterface $body, array $inputs, array $filters, $name, array $attributes = array(), $lineno = 0, $tag = null)
  115. {
  116. return new AsseticNode($asset, $body, $inputs, $filters, $name, $attributes, $lineno, $tag);
  117. }
  118. }