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; 14 15/** 16 * @author Fabien Potencier <fabien@symfony.com> 17 */ 18final class Token 19{ 20 public const EOF_TYPE = -1; 21 public const TEXT_TYPE = 0; 22 public const BLOCK_START_TYPE = 1; 23 public const VAR_START_TYPE = 2; 24 public const BLOCK_END_TYPE = 3; 25 public const VAR_END_TYPE = 4; 26 public const NAME_TYPE = 5; 27 public const NUMBER_TYPE = 6; 28 public const STRING_TYPE = 7; 29 public const OPERATOR_TYPE = 8; 30 public const PUNCTUATION_TYPE = 9; 31 public const INTERPOLATION_START_TYPE = 10; 32 public const INTERPOLATION_END_TYPE = 11; 33 /** 34 * @deprecated since Twig 3.21, "arrow" is now an operator 35 */ 36 public const ARROW_TYPE = 12; 37 /** 38 * @deprecated since Twig 3.21, "spread" is now an operator 39 */ 40 public const SPREAD_TYPE = 13; 41 42 public function __construct( 43 private int $type, 44 private $value, 45 private int $lineno, 46 ) { 47 if (self::ARROW_TYPE === $type) { 48 trigger_deprecation('twig/twig', '3.21', 'The "%s" token type is deprecated, "arrow" is now an operator.', self::ARROW_TYPE); 49 } 50 if (self::SPREAD_TYPE === $type) { 51 trigger_deprecation('twig/twig', '3.21', 'The "%s" token type is deprecated, "spread" is now an operator.', self::SPREAD_TYPE); 52 } 53 } 54 55 public function __toString(): string 56 { 57 return \sprintf('%s(%s)', self::typeToString($this->type, true), $this->value); 58 } 59 60 /** 61 * Tests the current token for a type and/or a value. 62 * 63 * Parameters may be: 64 * * just type 65 * * type and value (or array of possible values) 66 * * just value (or array of possible values) (NAME_TYPE is used as type) 67 * 68 * @param array|string|int $type The type to test 69 * @param array|string|null $values The token value 70 */ 71 public function test($type, $values = null): bool 72 { 73 if (null === $values && !\is_int($type)) { 74 $values = $type; 75 $type = self::NAME_TYPE; 76 } 77 78 if (self::ARROW_TYPE === $type) { 79 trigger_deprecation('twig/twig', '3.21', 'The "%s" token type is deprecated, "arrow" is now an operator.', self::typeToEnglish(self::ARROW_TYPE)); 80 81 return self::OPERATOR_TYPE === $this->type && '=>' === $this->value; 82 } 83 if (self::SPREAD_TYPE === $type) { 84 trigger_deprecation('twig/twig', '3.21', 'The "%s" token type is deprecated, "spread" is now an operator.', self::typeToEnglish(self::SPREAD_TYPE)); 85 86 return self::OPERATOR_TYPE === $this->type && '...' === $this->value; 87 } 88 89 $typeMatches = $this->type === $type; 90 if ($typeMatches && self::PUNCTUATION_TYPE === $type && \in_array($this->value, ['(', '[', '|', '.', '?', '?:'], true) && $values) { 91 foreach ((array) $values as $value) { 92 if (\in_array($value, ['(', '[', '|', '.', '?', '?:'], true)) { 93 trigger_deprecation('twig/twig', '3.21', 'The "%s" token is now an "%s" token instead of a "%s" one.', $this->value, self::typeToEnglish(self::OPERATOR_TYPE), $this->toEnglish()); 94 95 break; 96 } 97 } 98 } 99 if (!$typeMatches) { 100 if (self::OPERATOR_TYPE === $type && self::PUNCTUATION_TYPE === $this->type) { 101 if ($values) { 102 foreach ((array) $values as $value) { 103 if (\in_array($value, ['(', '[', '|', '.', '?', '?:'], true)) { 104 $typeMatches = true; 105 106 break; 107 } 108 } 109 } else { 110 $typeMatches = true; 111 } 112 } 113 } 114 115 return $typeMatches && ( 116 null === $values 117 || (\is_array($values) && \in_array($this->value, $values, true)) 118 || $this->value == $values 119 ); 120 } 121 122 public function getLine(): int 123 { 124 return $this->lineno; 125 } 126 127 /** 128 * @deprecated since Twig 3.19 129 */ 130 public function getType(): int 131 { 132 trigger_deprecation('twig/twig', '3.19', \sprintf('The "%s()" method is deprecated.', __METHOD__)); 133 134 return $this->type; 135 } 136 137 public function getValue() 138 { 139 return $this->value; 140 } 141 142 public function toEnglish(): string 143 { 144 return self::typeToEnglish($this->type); 145 } 146 147 public static function typeToString(int $type, bool $short = false): string 148 { 149 switch ($type) { 150 case self::EOF_TYPE: 151 $name = 'EOF_TYPE'; 152 break; 153 case self::TEXT_TYPE: 154 $name = 'TEXT_TYPE'; 155 break; 156 case self::BLOCK_START_TYPE: 157 $name = 'BLOCK_START_TYPE'; 158 break; 159 case self::VAR_START_TYPE: 160 $name = 'VAR_START_TYPE'; 161 break; 162 case self::BLOCK_END_TYPE: 163 $name = 'BLOCK_END_TYPE'; 164 break; 165 case self::VAR_END_TYPE: 166 $name = 'VAR_END_TYPE'; 167 break; 168 case self::NAME_TYPE: 169 $name = 'NAME_TYPE'; 170 break; 171 case self::NUMBER_TYPE: 172 $name = 'NUMBER_TYPE'; 173 break; 174 case self::STRING_TYPE: 175 $name = 'STRING_TYPE'; 176 break; 177 case self::OPERATOR_TYPE: 178 $name = 'OPERATOR_TYPE'; 179 break; 180 case self::PUNCTUATION_TYPE: 181 $name = 'PUNCTUATION_TYPE'; 182 break; 183 case self::INTERPOLATION_START_TYPE: 184 $name = 'INTERPOLATION_START_TYPE'; 185 break; 186 case self::INTERPOLATION_END_TYPE: 187 $name = 'INTERPOLATION_END_TYPE'; 188 break; 189 case self::ARROW_TYPE: 190 $name = 'ARROW_TYPE'; 191 break; 192 case self::SPREAD_TYPE: 193 $name = 'SPREAD_TYPE'; 194 break; 195 default: 196 throw new \LogicException(\sprintf('Token of type "%s" does not exist.', $type)); 197 } 198 199 return $short ? $name : 'Twig\Token::'.$name; 200 } 201 202 public static function typeToEnglish(int $type): string 203 { 204 switch ($type) { 205 case self::EOF_TYPE: 206 return 'end of template'; 207 case self::TEXT_TYPE: 208 return 'text'; 209 case self::BLOCK_START_TYPE: 210 return 'begin of statement block'; 211 case self::VAR_START_TYPE: 212 return 'begin of print statement'; 213 case self::BLOCK_END_TYPE: 214 return 'end of statement block'; 215 case self::VAR_END_TYPE: 216 return 'end of print statement'; 217 case self::NAME_TYPE: 218 return 'name'; 219 case self::NUMBER_TYPE: 220 return 'number'; 221 case self::STRING_TYPE: 222 return 'string'; 223 case self::OPERATOR_TYPE: 224 return 'operator'; 225 case self::PUNCTUATION_TYPE: 226 return 'punctuation'; 227 case self::INTERPOLATION_START_TYPE: 228 return 'begin of string interpolation'; 229 case self::INTERPOLATION_END_TYPE: 230 return 'end of string interpolation'; 231 case self::ARROW_TYPE: 232 return 'arrow function'; 233 case self::SPREAD_TYPE: 234 return 'spread operator'; 235 default: 236 throw new \LogicException(\sprintf('Token of type "%s" does not exist.', $type)); 237 } 238 } 239} 240