PageRenderTime 26ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/symfony/http-kernel/Kernel.php

https://gitlab.com/Pasantias/pasantiasASLG
PHP | 765 lines | 464 code | 106 blank | 195 comment | 62 complexity | cf7feae6f52f38571e9aca97b99b0bea MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpKernel;
  11. use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
  12. use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
  13. use Symfony\Component\DependencyInjection\ContainerInterface;
  14. use Symfony\Component\DependencyInjection\ContainerBuilder;
  15. use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
  16. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  17. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  18. use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
  19. use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
  20. use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
  21. use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
  22. use Symfony\Component\HttpFoundation\Request;
  23. use Symfony\Component\HttpFoundation\Response;
  24. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  25. use Symfony\Component\HttpKernel\Config\EnvParametersResource;
  26. use Symfony\Component\HttpKernel\Config\FileLocator;
  27. use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
  28. use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;
  29. use Symfony\Component\Config\Loader\LoaderResolver;
  30. use Symfony\Component\Config\Loader\DelegatingLoader;
  31. use Symfony\Component\Config\ConfigCache;
  32. use Symfony\Component\ClassLoader\ClassCollectionLoader;
  33. /**
  34. * The Kernel is the heart of the Symfony system.
  35. *
  36. * It manages an environment made of bundles.
  37. *
  38. * @author Fabien Potencier <fabien@symfony.com>
  39. */
  40. abstract class Kernel implements KernelInterface, TerminableInterface
  41. {
  42. /**
  43. * @var BundleInterface[]
  44. */
  45. protected $bundles = array();
  46. protected $bundleMap;
  47. protected $container;
  48. protected $rootDir;
  49. protected $environment;
  50. protected $debug;
  51. protected $booted = false;
  52. protected $name;
  53. protected $startTime;
  54. protected $loadClassCache;
  55. const VERSION = '2.7.12';
  56. const VERSION_ID = 20712;
  57. const MAJOR_VERSION = 2;
  58. const MINOR_VERSION = 7;
  59. const RELEASE_VERSION = 12;
  60. const EXTRA_VERSION = '';
  61. const END_OF_MAINTENANCE = '05/2018';
  62. const END_OF_LIFE = '05/2019';
  63. /**
  64. * Constructor.
  65. *
  66. * @param string $environment The environment
  67. * @param bool $debug Whether to enable debugging or not
  68. */
  69. public function __construct($environment, $debug)
  70. {
  71. $this->environment = $environment;
  72. $this->debug = (bool) $debug;
  73. $this->rootDir = $this->getRootDir();
  74. $this->name = $this->getName();
  75. if ($this->debug) {
  76. $this->startTime = microtime(true);
  77. }
  78. $defClass = new \ReflectionMethod($this, 'init');
  79. $defClass = $defClass->getDeclaringClass()->name;
  80. if (__CLASS__ !== $defClass) {
  81. @trigger_error(sprintf('Calling the %s::init() method is deprecated since version 2.3 and will be removed in 3.0. Move your logic to the constructor method instead.', $defClass), E_USER_DEPRECATED);
  82. $this->init();
  83. }
  84. }
  85. /**
  86. * @deprecated since version 2.3, to be removed in 3.0. Move your logic in the constructor instead.
  87. */
  88. public function init()
  89. {
  90. @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0. Move your logic to the constructor method instead.', E_USER_DEPRECATED);
  91. }
  92. public function __clone()
  93. {
  94. if ($this->debug) {
  95. $this->startTime = microtime(true);
  96. }
  97. $this->booted = false;
  98. $this->container = null;
  99. }
  100. /**
  101. * Boots the current kernel.
  102. */
  103. public function boot()
  104. {
  105. if (true === $this->booted) {
  106. return;
  107. }
  108. if ($this->loadClassCache) {
  109. $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]);
  110. }
  111. // init bundles
  112. $this->initializeBundles();
  113. // init container
  114. $this->initializeContainer();
  115. foreach ($this->getBundles() as $bundle) {
  116. $bundle->setContainer($this->container);
  117. $bundle->boot();
  118. }
  119. $this->booted = true;
  120. }
  121. /**
  122. * {@inheritdoc}
  123. */
  124. public function terminate(Request $request, Response $response)
  125. {
  126. if (false === $this->booted) {
  127. return;
  128. }
  129. if ($this->getHttpKernel() instanceof TerminableInterface) {
  130. $this->getHttpKernel()->terminate($request, $response);
  131. }
  132. }
  133. /**
  134. * {@inheritdoc}
  135. */
  136. public function shutdown()
  137. {
  138. if (false === $this->booted) {
  139. return;
  140. }
  141. $this->booted = false;
  142. foreach ($this->getBundles() as $bundle) {
  143. $bundle->shutdown();
  144. $bundle->setContainer(null);
  145. }
  146. $this->container = null;
  147. }
  148. /**
  149. * {@inheritdoc}
  150. */
  151. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  152. {
  153. if (false === $this->booted) {
  154. $this->boot();
  155. }
  156. return $this->getHttpKernel()->handle($request, $type, $catch);
  157. }
  158. /**
  159. * Gets a HTTP kernel from the container.
  160. *
  161. * @return HttpKernel
  162. */
  163. protected function getHttpKernel()
  164. {
  165. return $this->container->get('http_kernel');
  166. }
  167. /**
  168. * {@inheritdoc}
  169. */
  170. public function getBundles()
  171. {
  172. return $this->bundles;
  173. }
  174. /**
  175. * {@inheritdoc}
  176. *
  177. * @deprecated since version 2.6, to be removed in 3.0.
  178. */
  179. public function isClassInActiveBundle($class)
  180. {
  181. @trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in version 3.0.', E_USER_DEPRECATED);
  182. foreach ($this->getBundles() as $bundle) {
  183. if (0 === strpos($class, $bundle->getNamespace())) {
  184. return true;
  185. }
  186. }
  187. return false;
  188. }
  189. /**
  190. * {@inheritdoc}
  191. */
  192. public function getBundle($name, $first = true)
  193. {
  194. if (!isset($this->bundleMap[$name])) {
  195. 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, get_class($this)));
  196. }
  197. if (true === $first) {
  198. return $this->bundleMap[$name][0];
  199. }
  200. return $this->bundleMap[$name];
  201. }
  202. /**
  203. * {@inheritdoc}
  204. *
  205. * @throws \RuntimeException if a custom resource is hidden by a resource in a derived bundle
  206. */
  207. public function locateResource($name, $dir = null, $first = true)
  208. {
  209. if ('@' !== $name[0]) {
  210. throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
  211. }
  212. if (false !== strpos($name, '..')) {
  213. throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
  214. }
  215. $bundleName = substr($name, 1);
  216. $path = '';
  217. if (false !== strpos($bundleName, '/')) {
  218. list($bundleName, $path) = explode('/', $bundleName, 2);
  219. }
  220. $isResource = 0 === strpos($path, 'Resources') && null !== $dir;
  221. $overridePath = substr($path, 9);
  222. $resourceBundle = null;
  223. $bundles = $this->getBundle($bundleName, false);
  224. $files = array();
  225. foreach ($bundles as $bundle) {
  226. if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
  227. if (null !== $resourceBundle) {
  228. 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.',
  229. $file,
  230. $resourceBundle,
  231. $dir.'/'.$bundles[0]->getName().$overridePath
  232. ));
  233. }
  234. if ($first) {
  235. return $file;
  236. }
  237. $files[] = $file;
  238. }
  239. if (file_exists($file = $bundle->getPath().'/'.$path)) {
  240. if ($first && !$isResource) {
  241. return $file;
  242. }
  243. $files[] = $file;
  244. $resourceBundle = $bundle->getName();
  245. }
  246. }
  247. if (count($files) > 0) {
  248. return $first && $isResource ? $files[0] : $files;
  249. }
  250. throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name));
  251. }
  252. /**
  253. * {@inheritdoc}
  254. */
  255. public function getName()
  256. {
  257. if (null === $this->name) {
  258. $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
  259. }
  260. return $this->name;
  261. }
  262. /**
  263. * {@inheritdoc}
  264. */
  265. public function getEnvironment()
  266. {
  267. return $this->environment;
  268. }
  269. /**
  270. * {@inheritdoc}
  271. */
  272. public function isDebug()
  273. {
  274. return $this->debug;
  275. }
  276. /**
  277. * {@inheritdoc}
  278. */
  279. public function getRootDir()
  280. {
  281. if (null === $this->rootDir) {
  282. $r = new \ReflectionObject($this);
  283. $this->rootDir = dirname($r->getFileName());
  284. }
  285. return $this->rootDir;
  286. }
  287. /**
  288. * {@inheritdoc}
  289. */
  290. public function getContainer()
  291. {
  292. return $this->container;
  293. }
  294. /**
  295. * Loads the PHP class cache.
  296. *
  297. * This methods only registers the fact that you want to load the cache classes.
  298. * The cache will actually only be loaded when the Kernel is booted.
  299. *
  300. * That optimization is mainly useful when using the HttpCache class in which
  301. * case the class cache is not loaded if the Response is in the cache.
  302. *
  303. * @param string $name The cache name prefix
  304. * @param string $extension File extension of the resulting file
  305. */
  306. public function loadClassCache($name = 'classes', $extension = '.php')
  307. {
  308. $this->loadClassCache = array($name, $extension);
  309. }
  310. /**
  311. * Used internally.
  312. */
  313. public function setClassCache(array $classes)
  314. {
  315. file_put_contents($this->getCacheDir().'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
  316. }
  317. /**
  318. * {@inheritdoc}
  319. */
  320. public function getStartTime()
  321. {
  322. return $this->debug ? $this->startTime : -INF;
  323. }
  324. /**
  325. * {@inheritdoc}
  326. */
  327. public function getCacheDir()
  328. {
  329. return $this->rootDir.'/cache/'.$this->environment;
  330. }
  331. /**
  332. * {@inheritdoc}
  333. */
  334. public function getLogDir()
  335. {
  336. return $this->rootDir.'/logs';
  337. }
  338. /**
  339. * {@inheritdoc}
  340. */
  341. public function getCharset()
  342. {
  343. return 'UTF-8';
  344. }
  345. protected function doLoadClassCache($name, $extension)
  346. {
  347. if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) {
  348. ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
  349. }
  350. }
  351. /**
  352. * Initializes the data structures related to the bundle management.
  353. *
  354. * - the bundles property maps a bundle name to the bundle instance,
  355. * - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first).
  356. *
  357. * @throws \LogicException if two bundles share a common name
  358. * @throws \LogicException if a bundle tries to extend a non-registered bundle
  359. * @throws \LogicException if a bundle tries to extend itself
  360. * @throws \LogicException if two bundles extend the same ancestor
  361. */
  362. protected function initializeBundles()
  363. {
  364. // init bundles
  365. $this->bundles = array();
  366. $topMostBundles = array();
  367. $directChildren = array();
  368. foreach ($this->registerBundles() as $bundle) {
  369. $name = $bundle->getName();
  370. if (isset($this->bundles[$name])) {
  371. throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
  372. }
  373. $this->bundles[$name] = $bundle;
  374. if ($parentName = $bundle->getParent()) {
  375. if (isset($directChildren[$parentName])) {
  376. throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
  377. }
  378. if ($parentName == $name) {
  379. throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name));
  380. }
  381. $directChildren[$parentName] = $name;
  382. } else {
  383. $topMostBundles[$name] = $bundle;
  384. }
  385. }
  386. // look for orphans
  387. if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) {
  388. $diff = array_keys($diff);
  389. throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
  390. }
  391. // inheritance
  392. $this->bundleMap = array();
  393. foreach ($topMostBundles as $name => $bundle) {
  394. $bundleMap = array($bundle);
  395. $hierarchy = array($name);
  396. while (isset($directChildren[$name])) {
  397. $name = $directChildren[$name];
  398. array_unshift($bundleMap, $this->bundles[$name]);
  399. $hierarchy[] = $name;
  400. }
  401. foreach ($hierarchy as $bundle) {
  402. $this->bundleMap[$bundle] = $bundleMap;
  403. array_pop($bundleMap);
  404. }
  405. }
  406. }
  407. /**
  408. * Gets the container class.
  409. *
  410. * @return string The container class
  411. */
  412. protected function getContainerClass()
  413. {
  414. return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
  415. }
  416. /**
  417. * Gets the container's base class.
  418. *
  419. * All names except Container must be fully qualified.
  420. *
  421. * @return string
  422. */
  423. protected function getContainerBaseClass()
  424. {
  425. return 'Container';
  426. }
  427. /**
  428. * Initializes the service container.
  429. *
  430. * The cached version of the service container is used when fresh, otherwise the
  431. * container is built.
  432. */
  433. protected function initializeContainer()
  434. {
  435. $class = $this->getContainerClass();
  436. $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
  437. $fresh = true;
  438. if (!$cache->isFresh()) {
  439. $container = $this->buildContainer();
  440. $container->compile();
  441. $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
  442. $fresh = false;
  443. }
  444. require_once $cache->getPath();
  445. $this->container = new $class();
  446. $this->container->set('kernel', $this);
  447. if (!$fresh && $this->container->has('cache_warmer')) {
  448. $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
  449. }
  450. }
  451. /**
  452. * Returns the kernel parameters.
  453. *
  454. * @return array An array of kernel parameters
  455. */
  456. protected function getKernelParameters()
  457. {
  458. $bundles = array();
  459. foreach ($this->bundles as $name => $bundle) {
  460. $bundles[$name] = get_class($bundle);
  461. }
  462. return array_merge(
  463. array(
  464. 'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir,
  465. 'kernel.environment' => $this->environment,
  466. 'kernel.debug' => $this->debug,
  467. 'kernel.name' => $this->name,
  468. 'kernel.cache_dir' => realpath($this->getCacheDir()) ?: $this->getCacheDir(),
  469. 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(),
  470. 'kernel.bundles' => $bundles,
  471. 'kernel.charset' => $this->getCharset(),
  472. 'kernel.container_class' => $this->getContainerClass(),
  473. ),
  474. $this->getEnvParameters()
  475. );
  476. }
  477. /**
  478. * Gets the environment parameters.
  479. *
  480. * Only the parameters starting with "SYMFONY__" are considered.
  481. *
  482. * @return array An array of parameters
  483. */
  484. protected function getEnvParameters()
  485. {
  486. $parameters = array();
  487. foreach ($_SERVER as $key => $value) {
  488. if (0 === strpos($key, 'SYMFONY__')) {
  489. $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
  490. }
  491. }
  492. return $parameters;
  493. }
  494. /**
  495. * Builds the service container.
  496. *
  497. * @return ContainerBuilder The compiled service container
  498. *
  499. * @throws \RuntimeException
  500. */
  501. protected function buildContainer()
  502. {
  503. foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) {
  504. if (!is_dir($dir)) {
  505. if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
  506. throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir));
  507. }
  508. } elseif (!is_writable($dir)) {
  509. throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir));
  510. }
  511. }
  512. $container = $this->getContainerBuilder();
  513. $container->addObjectResource($this);
  514. $this->prepareContainer($container);
  515. if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
  516. $container->merge($cont);
  517. }
  518. $container->addCompilerPass(new AddClassesToCachePass($this));
  519. $container->addResource(new EnvParametersResource('SYMFONY__'));
  520. return $container;
  521. }
  522. /**
  523. * Prepares the ContainerBuilder before it is compiled.
  524. *
  525. * @param ContainerBuilder $container A ContainerBuilder instance
  526. */
  527. protected function prepareContainer(ContainerBuilder $container)
  528. {
  529. $extensions = array();
  530. foreach ($this->bundles as $bundle) {
  531. if ($extension = $bundle->getContainerExtension()) {
  532. $container->registerExtension($extension);
  533. $extensions[] = $extension->getAlias();
  534. }
  535. if ($this->debug) {
  536. $container->addObjectResource($bundle);
  537. }
  538. }
  539. foreach ($this->bundles as $bundle) {
  540. $bundle->build($container);
  541. }
  542. // ensure these extensions are implicitly loaded
  543. $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));
  544. }
  545. /**
  546. * Gets a new ContainerBuilder instance used to build the service container.
  547. *
  548. * @return ContainerBuilder
  549. */
  550. protected function getContainerBuilder()
  551. {
  552. $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters()));
  553. if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) {
  554. $container->setProxyInstantiator(new RuntimeInstantiator());
  555. }
  556. return $container;
  557. }
  558. /**
  559. * Dumps the service container to PHP code in the cache.
  560. *
  561. * @param ConfigCache $cache The config cache
  562. * @param ContainerBuilder $container The service container
  563. * @param string $class The name of the class to generate
  564. * @param string $baseClass The name of the container's base class
  565. */
  566. protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass)
  567. {
  568. // cache the container
  569. $dumper = new PhpDumper($container);
  570. if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper')) {
  571. $dumper->setProxyDumper(new ProxyDumper(md5($cache->getPath())));
  572. }
  573. $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass, 'file' => $cache->getPath(), 'debug' => $this->debug));
  574. $cache->write($content, $container->getResources());
  575. }
  576. /**
  577. * Returns a loader for the container.
  578. *
  579. * @param ContainerInterface $container The service container
  580. *
  581. * @return DelegatingLoader The loader
  582. */
  583. protected function getContainerLoader(ContainerInterface $container)
  584. {
  585. $locator = new FileLocator($this);
  586. $resolver = new LoaderResolver(array(
  587. new XmlFileLoader($container, $locator),
  588. new YamlFileLoader($container, $locator),
  589. new IniFileLoader($container, $locator),
  590. new PhpFileLoader($container, $locator),
  591. new ClosureLoader($container),
  592. ));
  593. return new DelegatingLoader($resolver);
  594. }
  595. /**
  596. * Removes comments from a PHP source string.
  597. *
  598. * We don't use the PHP php_strip_whitespace() function
  599. * as we want the content to be readable and well-formatted.
  600. *
  601. * @param string $source A PHP string
  602. *
  603. * @return string The PHP string with the comments removed
  604. */
  605. public static function stripComments($source)
  606. {
  607. if (!function_exists('token_get_all')) {
  608. return $source;
  609. }
  610. $rawChunk = '';
  611. $output = '';
  612. $tokens = token_get_all($source);
  613. $ignoreSpace = false;
  614. for ($i = 0; isset($tokens[$i]); ++$i) {
  615. $token = $tokens[$i];
  616. if (!isset($token[1]) || 'b"' === $token) {
  617. $rawChunk .= $token;
  618. } elseif (T_START_HEREDOC === $token[0]) {
  619. $output .= $rawChunk.$token[1];
  620. do {
  621. $token = $tokens[++$i];
  622. $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token;
  623. } while ($token[0] !== T_END_HEREDOC);
  624. $rawChunk = '';
  625. } elseif (T_WHITESPACE === $token[0]) {
  626. if ($ignoreSpace) {
  627. $ignoreSpace = false;
  628. continue;
  629. }
  630. // replace multiple new lines with a single newline
  631. $rawChunk .= preg_replace(array('/\n{2,}/S'), "\n", $token[1]);
  632. } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
  633. $ignoreSpace = true;
  634. } else {
  635. $rawChunk .= $token[1];
  636. // The PHP-open tag already has a new-line
  637. if (T_OPEN_TAG === $token[0]) {
  638. $ignoreSpace = true;
  639. }
  640. }
  641. }
  642. $output .= $rawChunk;
  643. if (PHP_VERSION_ID >= 70000) {
  644. // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
  645. unset($tokens, $rawChunk);
  646. gc_mem_caches();
  647. }
  648. return $output;
  649. }
  650. public function serialize()
  651. {
  652. return serialize(array($this->environment, $this->debug));
  653. }
  654. public function unserialize($data)
  655. {
  656. list($environment, $debug) = unserialize($data);
  657. $this->__construct($environment, $debug);
  658. }
  659. }