[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
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\HttpKernel; 13 14 use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; 15 use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; 16 use Symfony\Component\ClassLoader\ClassCollectionLoader; 17 use Symfony\Component\Config\ConfigCache; 18 use Symfony\Component\Config\Loader\DelegatingLoader; 19 use Symfony\Component\Config\Loader\LoaderResolver; 20 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 21 use Symfony\Component\DependencyInjection\Compiler\PassConfig; 22 use Symfony\Component\DependencyInjection\ContainerBuilder; 23 use Symfony\Component\DependencyInjection\ContainerInterface; 24 use Symfony\Component\DependencyInjection\Dumper\PhpDumper; 25 use Symfony\Component\DependencyInjection\Loader\ClosureLoader; 26 use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; 27 use Symfony\Component\DependencyInjection\Loader\GlobFileLoader; 28 use Symfony\Component\DependencyInjection\Loader\IniFileLoader; 29 use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; 30 use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; 31 use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; 32 use Symfony\Component\Filesystem\Filesystem; 33 use Symfony\Component\HttpFoundation\Request; 34 use Symfony\Component\HttpFoundation\Response; 35 use Symfony\Component\HttpKernel\Bundle\BundleInterface; 36 use Symfony\Component\HttpKernel\Config\EnvParametersResource; 37 use Symfony\Component\HttpKernel\Config\FileLocator; 38 use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass; 39 use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; 40 41 /** 42 * The Kernel is the heart of the Symfony system. 43 * 44 * It manages an environment made of bundles. 45 * 46 * @author Fabien Potencier <fabien@symfony.com> 47 */ 48 abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface 49 { 50 /** 51 * @var BundleInterface[] 52 */ 53 protected $bundles = []; 54 55 protected $bundleMap; 56 protected $container; 57 protected $rootDir; 58 protected $environment; 59 protected $debug; 60 protected $booted = false; 61 protected $name; 62 protected $startTime; 63 protected $loadClassCache; 64 65 private $projectDir; 66 private $warmupDir; 67 private $requestStackSize = 0; 68 private $resetServices = false; 69 70 const VERSION = '3.4.49'; 71 const VERSION_ID = 30449; 72 const MAJOR_VERSION = 3; 73 const MINOR_VERSION = 4; 74 const RELEASE_VERSION = 49; 75 const EXTRA_VERSION = ''; 76 77 const END_OF_MAINTENANCE = '11/2020'; 78 const END_OF_LIFE = '11/2021'; 79 80 /** 81 * @param string $environment The environment 82 * @param bool $debug Whether to enable debugging or not 83 */ 84 public function __construct($environment, $debug) 85 { 86 $this->environment = $environment; 87 $this->debug = (bool) $debug; 88 $this->rootDir = $this->getRootDir(); 89 $this->name = $this->getName(); 90 } 91 92 public function __clone() 93 { 94 $this->booted = false; 95 $this->container = null; 96 $this->requestStackSize = 0; 97 $this->resetServices = false; 98 } 99 100 /** 101 * {@inheritdoc} 102 */ 103 public function boot() 104 { 105 if (true === $this->booted) { 106 if (!$this->requestStackSize && $this->resetServices) { 107 if ($this->container->has('services_resetter')) { 108 $this->container->get('services_resetter')->reset(); 109 } 110 $this->resetServices = false; 111 if ($this->debug) { 112 $this->startTime = microtime(true); 113 } 114 } 115 116 return; 117 } 118 if ($this->debug) { 119 $this->startTime = microtime(true); 120 } 121 if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) { 122 putenv('SHELL_VERBOSITY=3'); 123 $_ENV['SHELL_VERBOSITY'] = 3; 124 $_SERVER['SHELL_VERBOSITY'] = 3; 125 } 126 127 if ($this->loadClassCache) { 128 $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]); 129 } 130 131 // init bundles 132 $this->initializeBundles(); 133 134 // init container 135 $this->initializeContainer(); 136 137 foreach ($this->getBundles() as $bundle) { 138 $bundle->setContainer($this->container); 139 $bundle->boot(); 140 } 141 142 $this->booted = true; 143 } 144 145 /** 146 * {@inheritdoc} 147 */ 148 public function reboot($warmupDir) 149 { 150 $this->shutdown(); 151 $this->warmupDir = $warmupDir; 152 $this->boot(); 153 } 154 155 /** 156 * {@inheritdoc} 157 */ 158 public function terminate(Request $request, Response $response) 159 { 160 if (false === $this->booted) { 161 return; 162 } 163 164 if ($this->getHttpKernel() instanceof TerminableInterface) { 165 $this->getHttpKernel()->terminate($request, $response); 166 } 167 } 168 169 /** 170 * {@inheritdoc} 171 */ 172 public function shutdown() 173 { 174 if (false === $this->booted) { 175 return; 176 } 177 178 $this->booted = false; 179 180 foreach ($this->getBundles() as $bundle) { 181 $bundle->shutdown(); 182 $bundle->setContainer(null); 183 } 184 185 $this->container = null; 186 $this->requestStackSize = 0; 187 $this->resetServices = false; 188 } 189 190 /** 191 * {@inheritdoc} 192 */ 193 public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) 194 { 195 $this->boot(); 196 ++$this->requestStackSize; 197 $this->resetServices = true; 198 199 try { 200 return $this->getHttpKernel()->handle($request, $type, $catch); 201 } finally { 202 --$this->requestStackSize; 203 } 204 } 205 206 /** 207 * Gets a HTTP kernel from the container. 208 * 209 * @return HttpKernelInterface 210 */ 211 protected function getHttpKernel() 212 { 213 return $this->container->get('http_kernel'); 214 } 215 216 /** 217 * {@inheritdoc} 218 */ 219 public function getBundles() 220 { 221 return $this->bundles; 222 } 223 224 /** 225 * {@inheritdoc} 226 */ 227 public function getBundle($name, $first = true/*, $noDeprecation = false */) 228 { 229 $noDeprecation = false; 230 if (\func_num_args() >= 3) { 231 $noDeprecation = func_get_arg(2); 232 } 233 234 if (!$first && !$noDeprecation) { 235 @trigger_error(sprintf('Passing "false" as the second argument to "%s()" is deprecated as of 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED); 236 } 237 238 if (!isset($this->bundleMap[$name])) { 239 throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your "%s.php" file?', $name, static::class)); 240 } 241 242 if (true === $first) { 243 return $this->bundleMap[$name][0]; 244 } 245 246 return $this->bundleMap[$name]; 247 } 248 249 /** 250 * {@inheritdoc} 251 * 252 * @throws \RuntimeException if a custom resource is hidden by a resource in a derived bundle 253 */ 254 public function locateResource($name, $dir = null, $first = true) 255 { 256 if ('@' !== $name[0]) { 257 throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name)); 258 } 259 260 if (false !== strpos($name, '..')) { 261 throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name)); 262 } 263 264 $bundleName = substr($name, 1); 265 $path = ''; 266 if (false !== strpos($bundleName, '/')) { 267 list($bundleName, $path) = explode('/', $bundleName, 2); 268 } 269 270 $isResource = 0 === strpos($path, 'Resources') && null !== $dir; 271 $overridePath = substr($path, 9); 272 $resourceBundle = null; 273 $bundles = $this->getBundle($bundleName, false, true); 274 $files = []; 275 276 foreach ($bundles as $bundle) { 277 if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) { 278 if (null !== $resourceBundle) { 279 throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.', $file, $resourceBundle, $dir.'/'.$bundles[0]->getName().$overridePath)); 280 } 281 282 if ($first) { 283 return $file; 284 } 285 $files[] = $file; 286 } 287 288 if (file_exists($file = $bundle->getPath().'/'.$path)) { 289 if ($first && !$isResource) { 290 return $file; 291 } 292 $files[] = $file; 293 $resourceBundle = $bundle->getName(); 294 } 295 } 296 297 if (\count($files) > 0) { 298 return $first && $isResource ? $files[0] : $files; 299 } 300 301 throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name)); 302 } 303 304 /** 305 * {@inheritdoc} 306 */ 307 public function getName() 308 { 309 if (null === $this->name) { 310 $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir)); 311 if (ctype_digit($this->name[0])) { 312 $this->name = '_'.$this->name; 313 } 314 } 315 316 return $this->name; 317 } 318 319 /** 320 * {@inheritdoc} 321 */ 322 public function getEnvironment() 323 { 324 return $this->environment; 325 } 326 327 /** 328 * {@inheritdoc} 329 */ 330 public function isDebug() 331 { 332 return $this->debug; 333 } 334 335 /** 336 * {@inheritdoc} 337 */ 338 public function getRootDir() 339 { 340 if (null === $this->rootDir) { 341 $r = new \ReflectionObject($this); 342 $this->rootDir = \dirname($r->getFileName()); 343 } 344 345 return $this->rootDir; 346 } 347 348 /** 349 * Gets the application root dir (path of the project's composer file). 350 * 351 * @return string The project root dir 352 */ 353 public function getProjectDir() 354 { 355 if (null === $this->projectDir) { 356 $r = new \ReflectionObject($this); 357 358 if (!file_exists($dir = $r->getFileName())) { 359 throw new \LogicException(sprintf('Cannot auto-detect project dir for kernel of class "%s".', $r->name)); 360 } 361 362 $dir = $rootDir = \dirname($dir); 363 while (!file_exists($dir.'/composer.json')) { 364 if ($dir === \dirname($dir)) { 365 return $this->projectDir = $rootDir; 366 } 367 $dir = \dirname($dir); 368 } 369 $this->projectDir = $dir; 370 } 371 372 return $this->projectDir; 373 } 374 375 /** 376 * {@inheritdoc} 377 */ 378 public function getContainer() 379 { 380 return $this->container; 381 } 382 383 /** 384 * Loads the PHP class cache. 385 * 386 * This methods only registers the fact that you want to load the cache classes. 387 * The cache will actually only be loaded when the Kernel is booted. 388 * 389 * That optimization is mainly useful when using the HttpCache class in which 390 * case the class cache is not loaded if the Response is in the cache. 391 * 392 * @param string $name The cache name prefix 393 * @param string $extension File extension of the resulting file 394 * 395 * @deprecated since version 3.3, to be removed in 4.0. The class cache is not needed anymore when using PHP 7.0. 396 */ 397 public function loadClassCache($name = 'classes', $extension = '.php') 398 { 399 if (\PHP_VERSION_ID >= 70000) { 400 @trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', \E_USER_DEPRECATED); 401 } 402 403 $this->loadClassCache = [$name, $extension]; 404 } 405 406 /** 407 * @internal 408 * 409 * @deprecated since version 3.3, to be removed in 4.0. 410 */ 411 public function setClassCache(array $classes) 412 { 413 if (\PHP_VERSION_ID >= 70000) { 414 @trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', \E_USER_DEPRECATED); 415 } 416 417 file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/classes.map', sprintf('<?php return %s;', var_export($classes, true))); 418 } 419 420 /** 421 * @internal 422 */ 423 public function setAnnotatedClassCache(array $annotatedClasses) 424 { 425 file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/annotations.map', sprintf('<?php return %s;', var_export($annotatedClasses, true))); 426 } 427 428 /** 429 * {@inheritdoc} 430 */ 431 public function getStartTime() 432 { 433 return $this->debug && null !== $this->startTime ? $this->startTime : -\INF; 434 } 435 436 /** 437 * {@inheritdoc} 438 */ 439 public function getCacheDir() 440 { 441 return $this->rootDir.'/cache/'.$this->environment; 442 } 443 444 /** 445 * {@inheritdoc} 446 */ 447 public function getLogDir() 448 { 449 return $this->rootDir.'/logs'; 450 } 451 452 /** 453 * {@inheritdoc} 454 */ 455 public function getCharset() 456 { 457 return 'UTF-8'; 458 } 459 460 /** 461 * @deprecated since version 3.3, to be removed in 4.0. 462 */ 463 protected function doLoadClassCache($name, $extension) 464 { 465 if (\PHP_VERSION_ID >= 70000) { 466 @trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', \E_USER_DEPRECATED); 467 } 468 $cacheDir = $this->warmupDir ?: $this->getCacheDir(); 469 470 if (!$this->booted && is_file($cacheDir.'/classes.map')) { 471 ClassCollectionLoader::load(include($cacheDir.'/classes.map'), $cacheDir, $name, $this->debug, false, $extension); 472 } 473 } 474 475 /** 476 * Initializes the data structures related to the bundle management. 477 * 478 * - the bundles property maps a bundle name to the bundle instance, 479 * - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first). 480 * 481 * @throws \LogicException if two bundles share a common name 482 * @throws \LogicException if a bundle tries to extend a non-registered bundle 483 * @throws \LogicException if a bundle tries to extend itself 484 * @throws \LogicException if two bundles extend the same ancestor 485 */ 486 protected function initializeBundles() 487 { 488 // init bundles 489 $this->bundles = []; 490 $topMostBundles = []; 491 $directChildren = []; 492 493 foreach ($this->registerBundles() as $bundle) { 494 $name = $bundle->getName(); 495 if (isset($this->bundles[$name])) { 496 throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s".', $name)); 497 } 498 $this->bundles[$name] = $bundle; 499 500 if ($parentName = $bundle->getParent()) { 501 @trigger_error('Bundle inheritance is deprecated as of 3.4 and will be removed in 4.0.', \E_USER_DEPRECATED); 502 503 if (isset($directChildren[$parentName])) { 504 throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName])); 505 } 506 if ($parentName == $name) { 507 throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name)); 508 } 509 $directChildren[$parentName] = $name; 510 } else { 511 $topMostBundles[$name] = $bundle; 512 } 513 } 514 515 // look for orphans 516 if (!empty($directChildren) && \count($diff = array_diff_key($directChildren, $this->bundles))) { 517 $diff = array_keys($diff); 518 519 throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0])); 520 } 521 522 // inheritance 523 $this->bundleMap = []; 524 foreach ($topMostBundles as $name => $bundle) { 525 $bundleMap = [$bundle]; 526 $hierarchy = [$name]; 527 528 while (isset($directChildren[$name])) { 529 $name = $directChildren[$name]; 530 array_unshift($bundleMap, $this->bundles[$name]); 531 $hierarchy[] = $name; 532 } 533 534 foreach ($hierarchy as $hierarchyBundle) { 535 $this->bundleMap[$hierarchyBundle] = $bundleMap; 536 array_pop($bundleMap); 537 } 538 } 539 } 540 541 /** 542 * The extension point similar to the Bundle::build() method. 543 * 544 * Use this method to register compiler passes and manipulate the container during the building process. 545 */ 546 protected function build(ContainerBuilder $container) 547 { 548 } 549 550 /** 551 * Gets the container class. 552 * 553 * @return string The container class 554 */ 555 protected function getContainerClass() 556 { 557 return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer'; 558 } 559 560 /** 561 * Gets the container's base class. 562 * 563 * All names except Container must be fully qualified. 564 * 565 * @return string 566 */ 567 protected function getContainerBaseClass() 568 { 569 return 'Container'; 570 } 571 572 /** 573 * Initializes the service container. 574 * 575 * The cached version of the service container is used when fresh, otherwise the 576 * container is built. 577 */ 578 protected function initializeContainer() 579 { 580 $class = $this->getContainerClass(); 581 $cacheDir = $this->warmupDir ?: $this->getCacheDir(); 582 $cache = new ConfigCache($cacheDir.'/'.$class.'.php', $this->debug); 583 $oldContainer = null; 584 if ($fresh = $cache->isFresh()) { 585 // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors 586 $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); 587 $fresh = $oldContainer = false; 588 try { 589 if (file_exists($cache->getPath()) && \is_object($this->container = include $cache->getPath())) { 590 $this->container->set('kernel', $this); 591 $oldContainer = $this->container; 592 $fresh = true; 593 } 594 } catch (\Throwable $e) { 595 } catch (\Exception $e) { 596 } finally { 597 error_reporting($errorLevel); 598 } 599 } 600 601 if ($fresh) { 602 return; 603 } 604 605 if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { 606 $collectedLogs = []; 607 $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { 608 if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) { 609 return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; 610 } 611 612 if (isset($collectedLogs[$message])) { 613 ++$collectedLogs[$message]['count']; 614 615 return null; 616 } 617 618 $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3); 619 // Clean the trace by removing first frames added by the error handler itself. 620 for ($i = 0; isset($backtrace[$i]); ++$i) { 621 if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { 622 $backtrace = \array_slice($backtrace, 1 + $i); 623 break; 624 } 625 } 626 627 $collectedLogs[$message] = [ 628 'type' => $type, 629 'message' => $message, 630 'file' => $file, 631 'line' => $line, 632 'trace' => $backtrace, 633 'count' => 1, 634 ]; 635 636 return null; 637 }); 638 } 639 640 try { 641 $container = null; 642 $container = $this->buildContainer(); 643 $container->compile(); 644 } finally { 645 if ($collectDeprecations) { 646 restore_error_handler(); 647 648 file_put_contents($cacheDir.'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs))); 649 file_put_contents($cacheDir.'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); 650 } 651 } 652 653 if (null === $oldContainer && file_exists($cache->getPath())) { 654 $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); 655 try { 656 $oldContainer = include $cache->getPath(); 657 } catch (\Throwable $e) { 658 } catch (\Exception $e) { 659 } finally { 660 error_reporting($errorLevel); 661 } 662 } 663 $oldContainer = \is_object($oldContainer) ? new \ReflectionClass($oldContainer) : false; 664 665 $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); 666 $this->container = require $cache->getPath(); 667 $this->container->set('kernel', $this); 668 669 if ($oldContainer && \get_class($this->container) !== $oldContainer->name) { 670 // Because concurrent requests might still be using them, 671 // old container files are not removed immediately, 672 // but on a next dump of the container. 673 static $legacyContainers = []; 674 $oldContainerDir = \dirname($oldContainer->getFileName()); 675 $legacyContainers[$oldContainerDir.'.legacy'] = true; 676 foreach (glob(\dirname($oldContainerDir).\DIRECTORY_SEPARATOR.'*.legacy', \GLOB_NOSORT) as $legacyContainer) { 677 if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) { 678 (new Filesystem())->remove(substr($legacyContainer, 0, -7)); 679 } 680 } 681 682 touch($oldContainerDir.'.legacy'); 683 } 684 685 if ($this->container->has('cache_warmer')) { 686 $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); 687 } 688 } 689 690 /** 691 * Returns the kernel parameters. 692 * 693 * @return array An array of kernel parameters 694 */ 695 protected function getKernelParameters() 696 { 697 $bundles = []; 698 $bundlesMetadata = []; 699 700 foreach ($this->bundles as $name => $bundle) { 701 $bundles[$name] = \get_class($bundle); 702 $bundlesMetadata[$name] = [ 703 'parent' => $bundle->getParent(), 704 'path' => $bundle->getPath(), 705 'namespace' => $bundle->getNamespace(), 706 ]; 707 } 708 709 return array_merge( 710 [ 711 'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir, 712 'kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(), 713 'kernel.environment' => $this->environment, 714 'kernel.debug' => $this->debug, 715 'kernel.name' => $this->name, 716 'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir, 717 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), 718 'kernel.bundles' => $bundles, 719 'kernel.bundles_metadata' => $bundlesMetadata, 720 'kernel.charset' => $this->getCharset(), 721 'kernel.container_class' => $this->getContainerClass(), 722 ], 723 $this->getEnvParameters(false) 724 ); 725 } 726 727 /** 728 * Gets the environment parameters. 729 * 730 * Only the parameters starting with "SYMFONY__" are considered. 731 * 732 * @return array An array of parameters 733 * 734 * @deprecated since version 3.3, to be removed in 4.0 735 */ 736 protected function getEnvParameters() 737 { 738 if (0 === \func_num_args() || func_get_arg(0)) { 739 @trigger_error(sprintf('The "%s()" method is deprecated as of 3.3 and will be removed in 4.0. Use the %%env()%% syntax to get the value of any environment variable from configuration files instead.', __METHOD__), \E_USER_DEPRECATED); 740 } 741 742 $parameters = []; 743 foreach ($_SERVER as $key => $value) { 744 if (0 === strpos($key, 'SYMFONY__')) { 745 @trigger_error(sprintf('The support of special environment variables that start with SYMFONY__ (such as "%s") is deprecated as of 3.3 and will be removed in 4.0. Use the %%env()%% syntax instead to get the value of environment variables in configuration files.', $key), \E_USER_DEPRECATED); 746 $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value; 747 } 748 } 749 750 return $parameters; 751 } 752 753 /** 754 * Builds the service container. 755 * 756 * @return ContainerBuilder The compiled service container 757 * 758 * @throws \RuntimeException 759 */ 760 protected function buildContainer() 761 { 762 foreach (['cache' => $this->warmupDir ?: $this->getCacheDir(), 'logs' => $this->getLogDir()] as $name => $dir) { 763 if (!is_dir($dir)) { 764 if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) { 765 throw new \RuntimeException(sprintf('Unable to create the "%s" directory (%s).', $name, $dir)); 766 } 767 } elseif (!is_writable($dir)) { 768 throw new \RuntimeException(sprintf('Unable to write in the "%s" directory (%s).', $name, $dir)); 769 } 770 } 771 772 $container = $this->getContainerBuilder(); 773 $container->addObjectResource($this); 774 $this->prepareContainer($container); 775 776 if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) { 777 $container->merge($cont); 778 } 779 780 $container->addCompilerPass(new AddAnnotatedClassesToCachePass($this)); 781 $container->addResource(new EnvParametersResource('SYMFONY__')); 782 783 return $container; 784 } 785 786 /** 787 * Prepares the ContainerBuilder before it is compiled. 788 */ 789 protected function prepareContainer(ContainerBuilder $container) 790 { 791 $extensions = []; 792 foreach ($this->bundles as $bundle) { 793 if ($extension = $bundle->getContainerExtension()) { 794 $container->registerExtension($extension); 795 } 796 797 if ($this->debug) { 798 $container->addObjectResource($bundle); 799 } 800 } 801 802 foreach ($this->bundles as $bundle) { 803 $bundle->build($container); 804 } 805 806 $this->build($container); 807 808 foreach ($container->getExtensions() as $extension) { 809 $extensions[] = $extension->getAlias(); 810 } 811 812 // ensure these extensions are implicitly loaded 813 $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); 814 } 815 816 /** 817 * Gets a new ContainerBuilder instance used to build the service container. 818 * 819 * @return ContainerBuilder 820 */ 821 protected function getContainerBuilder() 822 { 823 $container = new ContainerBuilder(); 824 $container->getParameterBag()->add($this->getKernelParameters()); 825 826 if ($this instanceof CompilerPassInterface) { 827 $container->addCompilerPass($this, PassConfig::TYPE_BEFORE_OPTIMIZATION, -10000); 828 } 829 if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) { 830 $container->setProxyInstantiator(new RuntimeInstantiator()); 831 } 832 833 return $container; 834 } 835 836 /** 837 * Dumps the service container to PHP code in the cache. 838 * 839 * @param ConfigCache $cache The config cache 840 * @param ContainerBuilder $container The service container 841 * @param string $class The name of the class to generate 842 * @param string $baseClass The name of the container's base class 843 */ 844 protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass) 845 { 846 // cache the container 847 $dumper = new PhpDumper($container); 848 849 if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper')) { 850 $dumper->setProxyDumper(new ProxyDumper()); 851 } 852 853 $content = $dumper->dump([ 854 'class' => $class, 855 'base_class' => $baseClass, 856 'file' => $cache->getPath(), 857 'as_files' => true, 858 'debug' => $this->debug, 859 'inline_class_loader_parameter' => \PHP_VERSION_ID >= 70000 && !$this->loadClassCache && !class_exists(ClassCollectionLoader::class, false) ? 'container.dumper.inline_class_loader' : null, 860 'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(), 861 ]); 862 863 $rootCode = array_pop($content); 864 $dir = \dirname($cache->getPath()).'/'; 865 $fs = new Filesystem(); 866 867 foreach ($content as $file => $code) { 868 $fs->dumpFile($dir.$file, $code); 869 @chmod($dir.$file, 0666 & ~umask()); 870 } 871 $legacyFile = \dirname($dir.key($content)).'.legacy'; 872 if (file_exists($legacyFile)) { 873 @unlink($legacyFile); 874 } 875 876 $cache->write($rootCode, $container->getResources()); 877 } 878 879 /** 880 * Returns a loader for the container. 881 * 882 * @return DelegatingLoader The loader 883 */ 884 protected function getContainerLoader(ContainerInterface $container) 885 { 886 $locator = new FileLocator($this); 887 $resolver = new LoaderResolver([ 888 new XmlFileLoader($container, $locator), 889 new YamlFileLoader($container, $locator), 890 new IniFileLoader($container, $locator), 891 new PhpFileLoader($container, $locator), 892 new GlobFileLoader($container, $locator), 893 new DirectoryLoader($container, $locator), 894 new ClosureLoader($container), 895 ]); 896 897 return new DelegatingLoader($resolver); 898 } 899 900 /** 901 * Removes comments from a PHP source string. 902 * 903 * We don't use the PHP php_strip_whitespace() function 904 * as we want the content to be readable and well-formatted. 905 * 906 * @param string $source A PHP string 907 * 908 * @return string The PHP string with the comments removed 909 */ 910 public static function stripComments($source) 911 { 912 if (!\function_exists('token_get_all')) { 913 return $source; 914 } 915 916 $rawChunk = ''; 917 $output = ''; 918 $tokens = token_get_all($source); 919 $ignoreSpace = false; 920 for ($i = 0; isset($tokens[$i]); ++$i) { 921 $token = $tokens[$i]; 922 if (!isset($token[1]) || 'b"' === $token) { 923 $rawChunk .= $token; 924 } elseif (\T_START_HEREDOC === $token[0]) { 925 $output .= $rawChunk.$token[1]; 926 do { 927 $token = $tokens[++$i]; 928 $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token; 929 } while (\T_END_HEREDOC !== $token[0]); 930 $rawChunk = ''; 931 } elseif (\T_WHITESPACE === $token[0]) { 932 if ($ignoreSpace) { 933 $ignoreSpace = false; 934 935 continue; 936 } 937 938 // replace multiple new lines with a single newline 939 $rawChunk .= preg_replace(['/\n{2,}/S'], "\n", $token[1]); 940 } elseif (\in_array($token[0], [\T_COMMENT, \T_DOC_COMMENT])) { 941 $ignoreSpace = true; 942 } else { 943 $rawChunk .= $token[1]; 944 945 // The PHP-open tag already has a new-line 946 if (\T_OPEN_TAG === $token[0]) { 947 $ignoreSpace = true; 948 } 949 } 950 } 951 952 $output .= $rawChunk; 953 954 if (\PHP_VERSION_ID >= 70000) { 955 // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 956 unset($tokens, $rawChunk); 957 gc_mem_caches(); 958 } 959 960 return $output; 961 } 962 963 public function serialize() 964 { 965 return serialize([$this->environment, $this->debug]); 966 } 967 968 public function unserialize($data) 969 { 970 if (\PHP_VERSION_ID >= 70000) { 971 list($environment, $debug) = unserialize($data, ['allowed_classes' => false]); 972 } else { 973 list($environment, $debug) = unserialize($data); 974 } 975 976 $this->__construct($environment, $debug); 977 } 978 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |