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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

Kernel.php

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 32.14 KiB


001  <?php
002   
003  /*
004   * This file is part of the Symfony package.
005   *
006   * (c) Fabien Potencier <fabien@symfony.com>
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 Symfony\Component\HttpKernel;
013   
014  use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
015  use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
016  use Symfony\Component\ClassLoader\ClassCollectionLoader;
017  use Symfony\Component\Config\ConfigCache;
018  use Symfony\Component\Config\Loader\DelegatingLoader;
019  use Symfony\Component\Config\Loader\LoaderResolver;
020  use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
021  use Symfony\Component\DependencyInjection\Compiler\PassConfig;
022  use Symfony\Component\DependencyInjection\ContainerBuilder;
023  use Symfony\Component\DependencyInjection\ContainerInterface;
024  use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
025  use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
026  use Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
027  use Symfony\Component\DependencyInjection\Loader\GlobFileLoader;
028  use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
029  use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
030  use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
031  use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
032  use Symfony\Component\Filesystem\Filesystem;
033  use Symfony\Component\HttpFoundation\Request;
034  use Symfony\Component\HttpFoundation\Response;
035  use Symfony\Component\HttpKernel\Bundle\BundleInterface;
036  use Symfony\Component\HttpKernel\Config\EnvParametersResource;
037  use Symfony\Component\HttpKernel\Config\FileLocator;
038  use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass;
039  use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
040   
041  /**
042   * The Kernel is the heart of the Symfony system.
043   *
044   * It manages an environment made of bundles.
045   *
046   * @author Fabien Potencier <fabien@symfony.com>
047   */
048  abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface
049  {
050      /**
051       * @var BundleInterface[]
052       */
053      protected $bundles = [];
054   
055      protected $bundleMap;
056      protected $container;
057      protected $rootDir;
058      protected $environment;
059      protected $debug;
060      protected $booted = false;
061      protected $name;
062      protected $startTime;
063      protected $loadClassCache;
064   
065      private $projectDir;
066      private $warmupDir;
067      private $requestStackSize = 0;
068      private $resetServices = false;
069   
070      const VERSION = '3.4.49';
071      const VERSION_ID = 30449;
072      const MAJOR_VERSION = 3;
073      const MINOR_VERSION = 4;
074      const RELEASE_VERSION = 49;
075      const EXTRA_VERSION = '';
076   
077      const END_OF_MAINTENANCE = '11/2020';
078      const END_OF_LIFE = '11/2021';
079   
080      /**
081       * @param string $environment The environment
082       * @param bool   $debug       Whether to enable debugging or not
083       */
084      public function __construct($environment, $debug)
085      {
086          $this->environment = $environment;
087          $this->debug = (bool) $debug;
088          $this->rootDir = $this->getRootDir();
089          $this->name = $this->getName();
090      }
091   
092      public function __clone()
093      {
094          $this->booted = false;
095          $this->container = null;
096          $this->requestStackSize = 0;
097          $this->resetServices = false;
098      }
099   
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  }
979