Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/translation/Extractor/PhpExtractor.php @ 14:1fec387a4317
Update Drupal core to 8.5.2 via Composer
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:46:53 +0100 |
parents | |
children | 129ea1e6d783 |
comparison
equal
deleted
inserted
replaced
13:5fb285c0d0e3 | 14:1fec387a4317 |
---|---|
1 <?php | |
2 | |
3 /* | |
4 * This file is part of the Symfony package. | |
5 * | |
6 * (c) Fabien Potencier <fabien@symfony.com> | |
7 * | |
8 * For the full copyright and license information, please view the LICENSE | |
9 * file that was distributed with this source code. | |
10 */ | |
11 | |
12 namespace Symfony\Component\Translation\Extractor; | |
13 | |
14 use Symfony\Component\Finder\Finder; | |
15 use Symfony\Component\Translation\MessageCatalogue; | |
16 | |
17 /** | |
18 * PhpExtractor extracts translation messages from a PHP template. | |
19 * | |
20 * @author Michel Salib <michelsalib@hotmail.com> | |
21 */ | |
22 class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface | |
23 { | |
24 const MESSAGE_TOKEN = 300; | |
25 const METHOD_ARGUMENTS_TOKEN = 1000; | |
26 const DOMAIN_TOKEN = 1001; | |
27 | |
28 /** | |
29 * Prefix for new found message. | |
30 * | |
31 * @var string | |
32 */ | |
33 private $prefix = ''; | |
34 | |
35 /** | |
36 * The sequence that captures translation messages. | |
37 * | |
38 * @var array | |
39 */ | |
40 protected $sequences = array( | |
41 array( | |
42 '->', | |
43 'trans', | |
44 '(', | |
45 self::MESSAGE_TOKEN, | |
46 ',', | |
47 self::METHOD_ARGUMENTS_TOKEN, | |
48 ',', | |
49 self::DOMAIN_TOKEN, | |
50 ), | |
51 array( | |
52 '->', | |
53 'transChoice', | |
54 '(', | |
55 self::MESSAGE_TOKEN, | |
56 ',', | |
57 self::METHOD_ARGUMENTS_TOKEN, | |
58 ',', | |
59 self::METHOD_ARGUMENTS_TOKEN, | |
60 ',', | |
61 self::DOMAIN_TOKEN, | |
62 ), | |
63 array( | |
64 '->', | |
65 'trans', | |
66 '(', | |
67 self::MESSAGE_TOKEN, | |
68 ), | |
69 array( | |
70 '->', | |
71 'transChoice', | |
72 '(', | |
73 self::MESSAGE_TOKEN, | |
74 ), | |
75 ); | |
76 | |
77 /** | |
78 * {@inheritdoc} | |
79 */ | |
80 public function extract($resource, MessageCatalogue $catalog) | |
81 { | |
82 $files = $this->extractFiles($resource); | |
83 foreach ($files as $file) { | |
84 $this->parseTokens(token_get_all(file_get_contents($file)), $catalog); | |
85 | |
86 if (\PHP_VERSION_ID >= 70000) { | |
87 // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 | |
88 gc_mem_caches(); | |
89 } | |
90 } | |
91 } | |
92 | |
93 /** | |
94 * {@inheritdoc} | |
95 */ | |
96 public function setPrefix($prefix) | |
97 { | |
98 $this->prefix = $prefix; | |
99 } | |
100 | |
101 /** | |
102 * Normalizes a token. | |
103 * | |
104 * @param mixed $token | |
105 * | |
106 * @return string | |
107 */ | |
108 protected function normalizeToken($token) | |
109 { | |
110 if (isset($token[1]) && 'b"' !== $token) { | |
111 return $token[1]; | |
112 } | |
113 | |
114 return $token; | |
115 } | |
116 | |
117 /** | |
118 * Seeks to a non-whitespace token. | |
119 */ | |
120 private function seekToNextRelevantToken(\Iterator $tokenIterator) | |
121 { | |
122 for (; $tokenIterator->valid(); $tokenIterator->next()) { | |
123 $t = $tokenIterator->current(); | |
124 if (T_WHITESPACE !== $t[0]) { | |
125 break; | |
126 } | |
127 } | |
128 } | |
129 | |
130 private function skipMethodArgument(\Iterator $tokenIterator) | |
131 { | |
132 $openBraces = 0; | |
133 | |
134 for (; $tokenIterator->valid(); $tokenIterator->next()) { | |
135 $t = $tokenIterator->current(); | |
136 | |
137 if ('[' === $t[0] || '(' === $t[0]) { | |
138 ++$openBraces; | |
139 } | |
140 | |
141 if (']' === $t[0] || ')' === $t[0]) { | |
142 --$openBraces; | |
143 } | |
144 | |
145 if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) { | |
146 break; | |
147 } | |
148 } | |
149 } | |
150 | |
151 /** | |
152 * Extracts the message from the iterator while the tokens | |
153 * match allowed message tokens. | |
154 */ | |
155 private function getValue(\Iterator $tokenIterator) | |
156 { | |
157 $message = ''; | |
158 $docToken = ''; | |
159 | |
160 for (; $tokenIterator->valid(); $tokenIterator->next()) { | |
161 $t = $tokenIterator->current(); | |
162 if (!isset($t[1])) { | |
163 break; | |
164 } | |
165 | |
166 switch ($t[0]) { | |
167 case T_START_HEREDOC: | |
168 $docToken = $t[1]; | |
169 break; | |
170 case T_ENCAPSED_AND_WHITESPACE: | |
171 case T_CONSTANT_ENCAPSED_STRING: | |
172 $message .= $t[1]; | |
173 break; | |
174 case T_END_HEREDOC: | |
175 return PhpStringTokenParser::parseDocString($docToken, $message); | |
176 default: | |
177 break 2; | |
178 } | |
179 } | |
180 | |
181 if ($message) { | |
182 $message = PhpStringTokenParser::parse($message); | |
183 } | |
184 | |
185 return $message; | |
186 } | |
187 | |
188 /** | |
189 * Extracts trans message from PHP tokens. | |
190 * | |
191 * @param array $tokens | |
192 * @param MessageCatalogue $catalog | |
193 */ | |
194 protected function parseTokens($tokens, MessageCatalogue $catalog) | |
195 { | |
196 $tokenIterator = new \ArrayIterator($tokens); | |
197 | |
198 for ($key = 0; $key < $tokenIterator->count(); ++$key) { | |
199 foreach ($this->sequences as $sequence) { | |
200 $message = ''; | |
201 $domain = 'messages'; | |
202 $tokenIterator->seek($key); | |
203 | |
204 foreach ($sequence as $sequenceKey => $item) { | |
205 $this->seekToNextRelevantToken($tokenIterator); | |
206 | |
207 if ($this->normalizeToken($tokenIterator->current()) === $item) { | |
208 $tokenIterator->next(); | |
209 continue; | |
210 } elseif (self::MESSAGE_TOKEN === $item) { | |
211 $message = $this->getValue($tokenIterator); | |
212 | |
213 if (count($sequence) === ($sequenceKey + 1)) { | |
214 break; | |
215 } | |
216 } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) { | |
217 $this->skipMethodArgument($tokenIterator); | |
218 } elseif (self::DOMAIN_TOKEN === $item) { | |
219 $domain = $this->getValue($tokenIterator); | |
220 | |
221 break; | |
222 } else { | |
223 break; | |
224 } | |
225 } | |
226 | |
227 if ($message) { | |
228 $catalog->set($message, $this->prefix.$message, $domain); | |
229 break; | |
230 } | |
231 } | |
232 } | |
233 } | |
234 | |
235 /** | |
236 * @param string $file | |
237 * | |
238 * @return bool | |
239 * | |
240 * @throws \InvalidArgumentException | |
241 */ | |
242 protected function canBeExtracted($file) | |
243 { | |
244 return $this->isFile($file) && 'php' === pathinfo($file, PATHINFO_EXTENSION); | |
245 } | |
246 | |
247 /** | |
248 * @param string|array $directory | |
249 * | |
250 * @return array | |
251 */ | |
252 protected function extractFromDirectory($directory) | |
253 { | |
254 $finder = new Finder(); | |
255 | |
256 return $finder->files()->name('*.php')->in($directory); | |
257 } | |
258 } |