Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
ExtensionSet.php
001 <?php
002
003 /*
004 * This file is part of Twig.
005 *
006 * (c) Fabien Potencier
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Twig;
013
014 use Twig\Error\RuntimeError;
015 use Twig\Extension\ExtensionInterface;
016 use Twig\Extension\GlobalsInterface;
017 use Twig\Extension\InitRuntimeInterface;
018 use Twig\Extension\StagingExtension;
019 use Twig\NodeVisitor\NodeVisitorInterface;
020 use Twig\TokenParser\TokenParserInterface;
021
022 /**
023 * @author Fabien Potencier <fabien@symfony.com>
024 *
025 * @internal
026 */
027 final class ExtensionSet
028 {
029 private $extensions;
030 private $initialized = false;
031 private $runtimeInitialized = false;
032 private $staging;
033 private $parsers;
034 private $visitors;
035 private $filters;
036 private $tests;
037 private $functions;
038 private $unaryOperators;
039 private $binaryOperators;
040 private $globals;
041 private $functionCallbacks = [];
042 private $filterCallbacks = [];
043 private $lastModified = 0;
044
045 public function __construct()
046 {
047 $this->staging = new StagingExtension();
048 }
049
050 /**
051 * Initializes the runtime environment.
052 *
053 * @deprecated since Twig 2.7
054 */
055 public function initRuntime(Environment $env)
056 {
057 if ($this->runtimeInitialized) {
058 return;
059 }
060
061 $this->runtimeInitialized = true;
062
063 foreach ($this->extensions as $extension) {
064 if ($extension instanceof InitRuntimeInterface) {
065 $extension->initRuntime($env);
066 }
067 }
068 }
069
070 public function hasExtension(string $class): bool
071 {
072 $class = ltrim($class, '\\');
073 if (!isset($this->extensions[$class]) && class_exists($class, false)) {
074 // For BC/FC with namespaced aliases
075 $class = (new \ReflectionClass($class))->name;
076 }
077
078 return isset($this->extensions[$class]);
079 }
080
081 public function getExtension(string $class): ExtensionInterface
082 {
083 $class = ltrim($class, '\\');
084 if (!isset($this->extensions[$class]) && class_exists($class, false)) {
085 // For BC/FC with namespaced aliases
086 $class = (new \ReflectionClass($class))->name;
087 }
088
089 if (!isset($this->extensions[$class])) {
090 throw new RuntimeError(sprintf('The "%s" extension is not enabled.', $class));
091 }
092
093 return $this->extensions[$class];
094 }
095
096 /**
097 * @param ExtensionInterface[] $extensions
098 */
099 public function setExtensions(array $extensions)
100 {
101 foreach ($extensions as $extension) {
102 $this->addExtension($extension);
103 }
104 }
105
106 /**
107 * @return ExtensionInterface[]
108 */
109 public function getExtensions(): array
110 {
111 return $this->extensions;
112 }
113
114 public function getSignature(): string
115 {
116 return json_encode(array_keys($this->extensions));
117 }
118
119 public function isInitialized(): bool
120 {
121 return $this->initialized || $this->runtimeInitialized;
122 }
123
124 public function getLastModified(): int
125 {
126 if (0 !== $this->lastModified) {
127 return $this->lastModified;
128 }
129
130 foreach ($this->extensions as $extension) {
131 $r = new \ReflectionObject($extension);
132 if (file_exists($r->getFileName()) && ($extensionTime = filemtime($r->getFileName())) > $this->lastModified) {
133 $this->lastModified = $extensionTime;
134 }
135 }
136
137 return $this->lastModified;
138 }
139
140 public function addExtension(ExtensionInterface $extension)
141 {
142 $class = \get_class($extension);
143
144 if ($this->initialized) {
145 throw new \LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $class));
146 }
147
148 if (isset($this->extensions[$class])) {
149 throw new \LogicException(sprintf('Unable to register extension "%s" as it is already registered.', $class));
150 }
151
152 $this->extensions[$class] = $extension;
153 }
154
155 public function addFunction(TwigFunction $function)
156 {
157 if ($this->initialized) {
158 throw new \LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $function->getName()));
159 }
160
161 $this->staging->addFunction($function);
162 }
163
164 /**
165 * @return TwigFunction[]
166 */
167 public function getFunctions(): array
168 {
169 if (!$this->initialized) {
170 $this->initExtensions();
171 }
172
173 return $this->functions;
174 }
175
176 /**
177 * @return TwigFunction|false
178 */
179 public function getFunction(string $name)
180 {
181 if (!$this->initialized) {
182 $this->initExtensions();
183 }
184
185 if (isset($this->functions[$name])) {
186 return $this->functions[$name];
187 }
188
189 foreach ($this->functions as $pattern => $function) {
190 $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
191
192 if ($count && preg_match('#^'.$pattern.'$#', $name, $matches)) {
193 array_shift($matches);
194 $function->setArguments($matches);
195
196 return $function;
197 }
198 }
199
200 foreach ($this->functionCallbacks as $callback) {
201 if (false !== $function = $callback($name)) {
202 return $function;
203 }
204 }
205
206 return false;
207 }
208
209 public function registerUndefinedFunctionCallback(callable $callable)
210 {
211 $this->functionCallbacks[] = $callable;
212 }
213
214 public function addFilter(TwigFilter $filter)
215 {
216 if ($this->initialized) {
217 throw new \LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $filter->getName()));
218 }
219
220 $this->staging->addFilter($filter);
221 }
222
223 /**
224 * @return TwigFilter[]
225 */
226 public function getFilters(): array
227 {
228 if (!$this->initialized) {
229 $this->initExtensions();
230 }
231
232 return $this->filters;
233 }
234
235 /**
236 * @return TwigFilter|false
237 */
238 public function getFilter(string $name)
239 {
240 if (!$this->initialized) {
241 $this->initExtensions();
242 }
243
244 if (isset($this->filters[$name])) {
245 return $this->filters[$name];
246 }
247
248 foreach ($this->filters as $pattern => $filter) {
249 $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
250
251 if ($count && preg_match('#^'.$pattern.'$#', $name, $matches)) {
252 array_shift($matches);
253 $filter->setArguments($matches);
254
255 return $filter;
256 }
257 }
258
259 foreach ($this->filterCallbacks as $callback) {
260 if (false !== $filter = $callback($name)) {
261 return $filter;
262 }
263 }
264
265 return false;
266 }
267
268 public function registerUndefinedFilterCallback(callable $callable)
269 {
270 $this->filterCallbacks[] = $callable;
271 }
272
273 public function addNodeVisitor(NodeVisitorInterface $visitor)
274 {
275 if ($this->initialized) {
276 throw new \LogicException('Unable to add a node visitor as extensions have already been initialized.');
277 }
278
279 $this->staging->addNodeVisitor($visitor);
280 }
281
282 /**
283 * @return NodeVisitorInterface[]
284 */
285 public function getNodeVisitors(): array
286 {
287 if (!$this->initialized) {
288 $this->initExtensions();
289 }
290
291 return $this->visitors;
292 }
293
294 public function addTokenParser(TokenParserInterface $parser)
295 {
296 if ($this->initialized) {
297 throw new \LogicException('Unable to add a token parser as extensions have already been initialized.');
298 }
299
300 $this->staging->addTokenParser($parser);
301 }
302
303 /**
304 * @return TokenParserInterface[]
305 */
306 public function getTokenParsers(): array
307 {
308 if (!$this->initialized) {
309 $this->initExtensions();
310 }
311
312 return $this->parsers;
313 }
314
315 public function getGlobals(): array
316 {
317 if (null !== $this->globals) {
318 return $this->globals;
319 }
320
321 $globals = [];
322 foreach ($this->extensions as $extension) {
323 if (!$extension instanceof GlobalsInterface) {
324 continue;
325 }
326
327 $extGlobals = $extension->getGlobals();
328 if (!\is_array($extGlobals)) {
329 throw new \UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', \get_class($extension)));
330 }
331
332 $globals = array_merge($globals, $extGlobals);
333 }
334
335 if ($this->initialized) {
336 $this->globals = $globals;
337 }
338
339 return $globals;
340 }
341
342 public function addTest(TwigTest $test)
343 {
344 if ($this->initialized) {
345 throw new \LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $test->getName()));
346 }
347
348 $this->staging->addTest($test);
349 }
350
351 /**
352 * @return TwigTest[]
353 */
354 public function getTests(): array
355 {
356 if (!$this->initialized) {
357 $this->initExtensions();
358 }
359
360 return $this->tests;
361 }
362
363 /**
364 * @return TwigTest|false
365 */
366 public function getTest(string $name)
367 {
368 if (!$this->initialized) {
369 $this->initExtensions();
370 }
371
372 if (isset($this->tests[$name])) {
373 return $this->tests[$name];
374 }
375
376 foreach ($this->tests as $pattern => $test) {
377 $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
378
379 if ($count) {
380 if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
381 array_shift($matches);
382 $test->setArguments($matches);
383
384 return $test;
385 }
386 }
387 }
388
389 return false;
390 }
391
392 public function getUnaryOperators(): array
393 {
394 if (!$this->initialized) {
395 $this->initExtensions();
396 }
397
398 return $this->unaryOperators;
399 }
400
401 public function getBinaryOperators(): array
402 {
403 if (!$this->initialized) {
404 $this->initExtensions();
405 }
406
407 return $this->binaryOperators;
408 }
409
410 private function initExtensions()
411 {
412 $this->parsers = [];
413 $this->filters = [];
414 $this->functions = [];
415 $this->tests = [];
416 $this->visitors = [];
417 $this->unaryOperators = [];
418 $this->binaryOperators = [];
419
420 foreach ($this->extensions as $extension) {
421 $this->initExtension($extension);
422 }
423 $this->initExtension($this->staging);
424 // Done at the end only, so that an exception during initialization does not mark the environment as initialized when catching the exception
425 $this->initialized = true;
426 }
427
428 private function initExtension(ExtensionInterface $extension)
429 {
430 // filters
431 foreach ($extension->getFilters() as $filter) {
432 $this->filters[$filter->getName()] = $filter;
433 }
434
435 // functions
436 foreach ($extension->getFunctions() as $function) {
437 $this->functions[$function->getName()] = $function;
438 }
439
440 // tests
441 foreach ($extension->getTests() as $test) {
442 $this->tests[$test->getName()] = $test;
443 }
444
445 // token parsers
446 foreach ($extension->getTokenParsers() as $parser) {
447 if (!$parser instanceof TokenParserInterface) {
448 throw new \LogicException('getTokenParsers() must return an array of \Twig\TokenParser\TokenParserInterface.');
449 }
450
451 $this->parsers[] = $parser;
452 }
453
454 // node visitors
455 foreach ($extension->getNodeVisitors() as $visitor) {
456 $this->visitors[] = $visitor;
457 }
458
459 // operators
460 if ($operators = $extension->getOperators()) {
461 if (!\is_array($operators)) {
462 throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array with operators, got "%s".', \get_class($extension), \is_object($operators) ? \get_class($operators) : \gettype($operators).(\is_resource($operators) ? '' : '#'.$operators)));
463 }
464
465 if (2 !== \count($operators)) {
466 throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', \get_class($extension), \count($operators)));
467 }
468
469 $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
470 $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]);
471 }
472 }
473 }
474
475 class_alias('Twig\ExtensionSet', 'Twig_ExtensionSet');
476