Verzeichnisstruktur phpBB-3.1.0
- Veröffentlicht
- 27.10.2014
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 |
Kernel.php
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\DependencyInjection\ContainerInterface;
017 use Symfony\Component\DependencyInjection\ContainerBuilder;
018 use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
019 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
020 use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
021 use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
022 use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
023 use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
024 use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
025 use Symfony\Component\HttpFoundation\Request;
026 use Symfony\Component\HttpFoundation\Response;
027 use Symfony\Component\HttpKernel\Bundle\BundleInterface;
028 use Symfony\Component\HttpKernel\Config\FileLocator;
029 use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
030 use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;
031 use Symfony\Component\Config\Loader\LoaderResolver;
032 use Symfony\Component\Config\Loader\DelegatingLoader;
033 use Symfony\Component\Config\ConfigCache;
034 use Symfony\Component\ClassLoader\ClassCollectionLoader;
035
036 /**
037 * The Kernel is the heart of the Symfony system.
038 *
039 * It manages an environment made of bundles.
040 *
041 * @author Fabien Potencier <fabien@symfony.com>
042 *
043 * @api
044 */
045 abstract class Kernel implements KernelInterface, TerminableInterface
046 {
047 /**
048 * @var BundleInterface[]
049 */
050 protected $bundles;
051
052 protected $bundleMap;
053 protected $container;
054 protected $rootDir;
055 protected $environment;
056 protected $debug;
057 protected $booted;
058 protected $name;
059 protected $startTime;
060 protected $loadClassCache;
061
062 const VERSION = '2.3.21';
063 const VERSION_ID = '20321';
064 const MAJOR_VERSION = '2';
065 const MINOR_VERSION = '3';
066 const RELEASE_VERSION = '21';
067 const EXTRA_VERSION = '';
068
069 /**
070 * Constructor.
071 *
072 * @param string $environment The environment
073 * @param bool $debug Whether to enable debugging or not
074 *
075 * @api
076 */
077 public function __construct($environment, $debug)
078 {
079 $this->environment = $environment;
080 $this->debug = (bool) $debug;
081 $this->booted = false;
082 $this->rootDir = $this->getRootDir();
083 $this->name = $this->getName();
084 $this->bundles = array();
085
086 if ($this->debug) {
087 $this->startTime = microtime(true);
088 }
089
090 $this->init();
091 }
092
093 /**
094 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Move your logic in the constructor instead.
095 */
096 public function init()
097 {
098 }
099
100 public function __clone()
101 {
102 if ($this->debug) {
103 $this->startTime = microtime(true);
104 }
105
106 $this->booted = false;
107 $this->container = null;
108 }
109
110 /**
111 * Boots the current kernel.
112 *
113 * @api
114 */
115 public function boot()
116 {
117 if (true === $this->booted) {
118 return;
119 }
120
121 if ($this->loadClassCache) {
122 $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]);
123 }
124
125 // init bundles
126 $this->initializeBundles();
127
128 // init container
129 $this->initializeContainer();
130
131 foreach ($this->getBundles() as $bundle) {
132 $bundle->setContainer($this->container);
133 $bundle->boot();
134 }
135
136 $this->booted = true;
137 }
138
139 /**
140 * {@inheritdoc}
141 *
142 * @api
143 */
144 public function terminate(Request $request, Response $response)
145 {
146 if (false === $this->booted) {
147 return;
148 }
149
150 if ($this->getHttpKernel() instanceof TerminableInterface) {
151 $this->getHttpKernel()->terminate($request, $response);
152 }
153 }
154
155 /**
156 * {@inheritdoc}
157 *
158 * @api
159 */
160 public function shutdown()
161 {
162 if (false === $this->booted) {
163 return;
164 }
165
166 $this->booted = false;
167
168 foreach ($this->getBundles() as $bundle) {
169 $bundle->shutdown();
170 $bundle->setContainer(null);
171 }
172
173 $this->container = null;
174 }
175
176 /**
177 * {@inheritdoc}
178 *
179 * @api
180 */
181 public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
182 {
183 if (false === $this->booted) {
184 $this->boot();
185 }
186
187 return $this->getHttpKernel()->handle($request, $type, $catch);
188 }
189
190 /**
191 * Gets a HTTP kernel from the container
192 *
193 * @return HttpKernel
194 */
195 protected function getHttpKernel()
196 {
197 return $this->container->get('http_kernel');
198 }
199
200 /**
201 * {@inheritdoc}
202 *
203 * @api
204 */
205 public function getBundles()
206 {
207 return $this->bundles;
208 }
209
210 /**
211 * {@inheritdoc}
212 *
213 * @api
214 */
215 public function isClassInActiveBundle($class)
216 {
217 foreach ($this->getBundles() as $bundle) {
218 if (0 === strpos($class, $bundle->getNamespace())) {
219 return true;
220 }
221 }
222
223 return false;
224 }
225
226 /**
227 * {@inheritdoc}
228 *
229 * @api
230 */
231 public function getBundle($name, $first = true)
232 {
233 if (!isset($this->bundleMap[$name])) {
234 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)));
235 }
236
237 if (true === $first) {
238 return $this->bundleMap[$name][0];
239 }
240
241 return $this->bundleMap[$name];
242 }
243
244 /**
245 * Returns the file path for a given resource.
246 *
247 * A Resource can be a file or a directory.
248 *
249 * The resource name must follow the following pattern:
250 *
251 * @<BundleName>/path/to/a/file.something
252 *
253 * where BundleName is the name of the bundle
254 * and the remaining part is the relative path in the bundle.
255 *
256 * If $dir is passed, and the first segment of the path is "Resources",
257 * this method will look for a file named:
258 *
259 * $dir/<BundleName>/path/without/Resources
260 *
261 * before looking in the bundle resource folder.
262 *
263 * @param string $name A resource name to locate
264 * @param string $dir A directory where to look for the resource first
265 * @param bool $first Whether to return the first path or paths for all matching bundles
266 *
267 * @return string|array The absolute path of the resource or an array if $first is false
268 *
269 * @throws \InvalidArgumentException if the file cannot be found or the name is not valid
270 * @throws \RuntimeException if the name contains invalid/unsafe
271 * @throws \RuntimeException if a custom resource is hidden by a resource in a derived bundle
272 *
273 * @api
274 */
275 public function locateResource($name, $dir = null, $first = true)
276 {
277 if ('@' !== $name[0]) {
278 throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
279 }
280
281 if (false !== strpos($name, '..')) {
282 throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
283 }
284
285 $bundleName = substr($name, 1);
286 $path = '';
287 if (false !== strpos($bundleName, '/')) {
288 list($bundleName, $path) = explode('/', $bundleName, 2);
289 }
290
291 $isResource = 0 === strpos($path, 'Resources') && null !== $dir;
292 $overridePath = substr($path, 9);
293 $resourceBundle = null;
294 $bundles = $this->getBundle($bundleName, false);
295 $files = array();
296
297 foreach ($bundles as $bundle) {
298 if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
299 if (null !== $resourceBundle) {
300 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.',
301 $file,
302 $resourceBundle,
303 $dir.'/'.$bundles[0]->getName().$overridePath
304 ));
305 }
306
307 if ($first) {
308 return $file;
309 }
310 $files[] = $file;
311 }
312
313 if (file_exists($file = $bundle->getPath().'/'.$path)) {
314 if ($first && !$isResource) {
315 return $file;
316 }
317 $files[] = $file;
318 $resourceBundle = $bundle->getName();
319 }
320 }
321
322 if (count($files) > 0) {
323 return $first && $isResource ? $files[0] : $files;
324 }
325
326 throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name));
327 }
328
329 /**
330 * {@inheritdoc}
331 *
332 * @api
333 */
334 public function getName()
335 {
336 if (null === $this->name) {
337 $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
338 }
339
340 return $this->name;
341 }
342
343 /**
344 * {@inheritdoc}
345 *
346 * @api
347 */
348 public function getEnvironment()
349 {
350 return $this->environment;
351 }
352
353 /**
354 * {@inheritdoc}
355 *
356 * @api
357 */
358 public function isDebug()
359 {
360 return $this->debug;
361 }
362
363 /**
364 * {@inheritdoc}
365 *
366 * @api
367 */
368 public function getRootDir()
369 {
370 if (null === $this->rootDir) {
371 $r = new \ReflectionObject($this);
372 $this->rootDir = str_replace('\\', '/', dirname($r->getFileName()));
373 }
374
375 return $this->rootDir;
376 }
377
378 /**
379 * {@inheritdoc}
380 *
381 * @api
382 */
383 public function getContainer()
384 {
385 return $this->container;
386 }
387
388 /**
389 * Loads the PHP class cache.
390 *
391 * This methods only registers the fact that you want to load the cache classes.
392 * The cache will actually only be loaded when the Kernel is booted.
393 *
394 * That optimization is mainly useful when using the HttpCache class in which
395 * case the class cache is not loaded if the Response is in the cache.
396 *
397 * @param string $name The cache name prefix
398 * @param string $extension File extension of the resulting file
399 */
400 public function loadClassCache($name = 'classes', $extension = '.php')
401 {
402 $this->loadClassCache = array($name, $extension);
403 }
404
405 /**
406 * Used internally.
407 */
408 public function setClassCache(array $classes)
409 {
410 file_put_contents($this->getCacheDir().'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
411 }
412
413 /**
414 * {@inheritdoc}
415 *
416 * @api
417 */
418 public function getStartTime()
419 {
420 return $this->debug ? $this->startTime : -INF;
421 }
422
423 /**
424 * {@inheritdoc}
425 *
426 * @api
427 */
428 public function getCacheDir()
429 {
430 return $this->rootDir.'/cache/'.$this->environment;
431 }
432
433 /**
434 * {@inheritdoc}
435 *
436 * @api
437 */
438 public function getLogDir()
439 {
440 return $this->rootDir.'/logs';
441 }
442
443 /**
444 * {@inheritdoc}
445 *
446 * @api
447 */
448 public function getCharset()
449 {
450 return 'UTF-8';
451 }
452
453 protected function doLoadClassCache($name, $extension)
454 {
455 if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) {
456 ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
457 }
458 }
459
460 /**
461 * Initializes the data structures related to the bundle management.
462 *
463 * - the bundles property maps a bundle name to the bundle instance,
464 * - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first).
465 *
466 * @throws \LogicException if two bundles share a common name
467 * @throws \LogicException if a bundle tries to extend a non-registered bundle
468 * @throws \LogicException if a bundle tries to extend itself
469 * @throws \LogicException if two bundles extend the same ancestor
470 */
471 protected function initializeBundles()
472 {
473 // init bundles
474 $this->bundles = array();
475 $topMostBundles = array();
476 $directChildren = array();
477
478 foreach ($this->registerBundles() as $bundle) {
479 $name = $bundle->getName();
480 if (isset($this->bundles[$name])) {
481 throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
482 }
483 $this->bundles[$name] = $bundle;
484
485 if ($parentName = $bundle->getParent()) {
486 if (isset($directChildren[$parentName])) {
487 throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
488 }
489 if ($parentName == $name) {
490 throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name));
491 }
492 $directChildren[$parentName] = $name;
493 } else {
494 $topMostBundles[$name] = $bundle;
495 }
496 }
497
498 // look for orphans
499 if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) {
500 $diff = array_keys($diff);
501
502 throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
503 }
504
505 // inheritance
506 $this->bundleMap = array();
507 foreach ($topMostBundles as $name => $bundle) {
508 $bundleMap = array($bundle);
509 $hierarchy = array($name);
510
511 while (isset($directChildren[$name])) {
512 $name = $directChildren[$name];
513 array_unshift($bundleMap, $this->bundles[$name]);
514 $hierarchy[] = $name;
515 }
516
517 foreach ($hierarchy as $bundle) {
518 $this->bundleMap[$bundle] = $bundleMap;
519 array_pop($bundleMap);
520 }
521 }
522 }
523
524 /**
525 * Gets the container class.
526 *
527 * @return string The container class
528 */
529 protected function getContainerClass()
530 {
531 return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
532 }
533
534 /**
535 * Gets the container's base class.
536 *
537 * All names except Container must be fully qualified.
538 *
539 * @return string
540 */
541 protected function getContainerBaseClass()
542 {
543 return 'Container';
544 }
545
546 /**
547 * Initializes the service container.
548 *
549 * The cached version of the service container is used when fresh, otherwise the
550 * container is built.
551 */
552 protected function initializeContainer()
553 {
554 $class = $this->getContainerClass();
555 $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
556 $fresh = true;
557 if (!$cache->isFresh()) {
558 $container = $this->buildContainer();
559 $container->compile();
560 $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
561
562 $fresh = false;
563 }
564
565 require_once $cache;
566
567 $this->container = new $class();
568 $this->container->set('kernel', $this);
569
570 if (!$fresh && $this->container->has('cache_warmer')) {
571 $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
572 }
573 }
574
575 /**
576 * Returns the kernel parameters.
577 *
578 * @return array An array of kernel parameters
579 */
580 protected function getKernelParameters()
581 {
582 $bundles = array();
583 foreach ($this->bundles as $name => $bundle) {
584 $bundles[$name] = get_class($bundle);
585 }
586
587 return array_merge(
588 array(
589 'kernel.root_dir' => $this->rootDir,
590 'kernel.environment' => $this->environment,
591 'kernel.debug' => $this->debug,
592 'kernel.name' => $this->name,
593 'kernel.cache_dir' => $this->getCacheDir(),
594 'kernel.logs_dir' => $this->getLogDir(),
595 'kernel.bundles' => $bundles,
596 'kernel.charset' => $this->getCharset(),
597 'kernel.container_class' => $this->getContainerClass(),
598 ),
599 $this->getEnvParameters()
600 );
601 }
602
603 /**
604 * Gets the environment parameters.
605 *
606 * Only the parameters starting with "SYMFONY__" are considered.
607 *
608 * @return array An array of parameters
609 */
610 protected function getEnvParameters()
611 {
612 $parameters = array();
613 foreach ($_SERVER as $key => $value) {
614 if (0 === strpos($key, 'SYMFONY__')) {
615 $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
616 }
617 }
618
619 return $parameters;
620 }
621
622 /**
623 * Builds the service container.
624 *
625 * @return ContainerBuilder The compiled service container
626 *
627 * @throws \RuntimeException
628 */
629 protected function buildContainer()
630 {
631 foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) {
632 if (!is_dir($dir)) {
633 if (false === @mkdir($dir, 0777, true)) {
634 throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir));
635 }
636 } elseif (!is_writable($dir)) {
637 throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir));
638 }
639 }
640
641 $container = $this->getContainerBuilder();
642 $container->addObjectResource($this);
643 $this->prepareContainer($container);
644
645 if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
646 $container->merge($cont);
647 }
648
649 $container->addCompilerPass(new AddClassesToCachePass($this));
650
651 return $container;
652 }
653
654 /**
655 * Prepares the ContainerBuilder before it is compiled.
656 *
657 * @param ContainerBuilder $container A ContainerBuilder instance
658 */
659 protected function prepareContainer(ContainerBuilder $container)
660 {
661 $extensions = array();
662 foreach ($this->bundles as $bundle) {
663 if ($extension = $bundle->getContainerExtension()) {
664 $container->registerExtension($extension);
665 $extensions[] = $extension->getAlias();
666 }
667
668 if ($this->debug) {
669 $container->addObjectResource($bundle);
670 }
671 }
672 foreach ($this->bundles as $bundle) {
673 $bundle->build($container);
674 }
675
676 // ensure these extensions are implicitly loaded
677 $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));
678 }
679
680 /**
681 * Gets a new ContainerBuilder instance used to build the service container.
682 *
683 * @return ContainerBuilder
684 */
685 protected function getContainerBuilder()
686 {
687 $container = new ContainerBuilder(new ParameterBag($this->getKernelParameters()));
688
689 if (class_exists('ProxyManager\Configuration')) {
690 $container->setProxyInstantiator(new RuntimeInstantiator());
691 }
692
693 return $container;
694 }
695
696 /**
697 * Dumps the service container to PHP code in the cache.
698 *
699 * @param ConfigCache $cache The config cache
700 * @param ContainerBuilder $container The service container
701 * @param string $class The name of the class to generate
702 * @param string $baseClass The name of the container's base class
703 */
704 protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass)
705 {
706 // cache the container
707 $dumper = new PhpDumper($container);
708
709 if (class_exists('ProxyManager\Configuration')) {
710 $dumper->setProxyDumper(new ProxyDumper());
711 }
712
713 $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass));
714 if (!$this->debug) {
715 $content = static::stripComments($content);
716 }
717
718 $cache->write($content, $container->getResources());
719 }
720
721 /**
722 * Returns a loader for the container.
723 *
724 * @param ContainerInterface $container The service container
725 *
726 * @return DelegatingLoader The loader
727 */
728 protected function getContainerLoader(ContainerInterface $container)
729 {
730 $locator = new FileLocator($this);
731 $resolver = new LoaderResolver(array(
732 new XmlFileLoader($container, $locator),
733 new YamlFileLoader($container, $locator),
734 new IniFileLoader($container, $locator),
735 new PhpFileLoader($container, $locator),
736 new ClosureLoader($container),
737 ));
738
739 return new DelegatingLoader($resolver);
740 }
741
742 /**
743 * Removes comments from a PHP source string.
744 *
745 * We don't use the PHP php_strip_whitespace() function
746 * as we want the content to be readable and well-formatted.
747 *
748 * @param string $source A PHP string
749 *
750 * @return string The PHP string with the comments removed
751 */
752 public static function stripComments($source)
753 {
754 if (!function_exists('token_get_all')) {
755 return $source;
756 }
757
758 $rawChunk = '';
759 $output = '';
760 $tokens = token_get_all($source);
761 $ignoreSpace = false;
762 for (reset($tokens); false !== $token = current($tokens); next($tokens)) {
763 if (is_string($token)) {
764 $rawChunk .= $token;
765 } elseif (T_START_HEREDOC === $token[0]) {
766 $output .= $rawChunk.$token[1];
767 do {
768 $token = next($tokens);
769 $output .= $token[1];
770 } while ($token[0] !== T_END_HEREDOC);
771 $rawChunk = '';
772 } elseif (T_WHITESPACE === $token[0]) {
773 if ($ignoreSpace) {
774 $ignoreSpace = false;
775
776 continue;
777 }
778
779 // replace multiple new lines with a single newline
780 $rawChunk .= preg_replace(array('/\n{2,}/S'), "\n", $token[1]);
781 } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
782 $ignoreSpace = true;
783 } else {
784 $rawChunk .= $token[1];
785
786 // The PHP-open tag already has a new-line
787 if (T_OPEN_TAG === $token[0]) {
788 $ignoreSpace = true;
789 }
790 }
791 }
792
793 $output .= $rawChunk;
794
795 return $output;
796 }
797
798 public function serialize()
799 {
800 return serialize(array($this->environment, $this->debug));
801 }
802
803 public function unserialize($data)
804 {
805 list($environment, $debug) = unserialize($data);
806
807 $this->__construct($environment, $debug);
808 }
809 }
810