This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Foundation/bootstrap.php

722 lines
17 KiB
PHP

<?php
namespace Symfony\Foundation\Bundle;
use Symfony\Components\DependencyInjection\ContainerInterface;
abstract class Bundle implements BundleInterface
{
public function buildContainer(ContainerInterface $container)
{
}
public function boot(ContainerInterface $container)
{
}
}
namespace Symfony\Foundation\Bundle;
use Symfony\Components\DependencyInjection\ContainerInterface;
interface BundleInterface
{
public function buildContainer(ContainerInterface $container);
public function boot(ContainerInterface $container);
}
namespace Symfony\Foundation\Bundle;
use Symfony\Foundation\Bundle\Bundle;
use Symfony\Foundation\ClassCollectionLoader;
use Symfony\Components\DependencyInjection\ContainerInterface;
use Symfony\Components\DependencyInjection\Loader\Loader;
use Symfony\Components\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Components\DependencyInjection\BuilderConfiguration;
class KernelBundle extends Bundle
{
public function buildContainer(ContainerInterface $container)
{
Loader::registerExtension(new KernelExtension());
$configuration = new BuilderConfiguration();
$loader = new XmlFileLoader(array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config'));
$configuration->merge($loader->load('services.xml'));
if ($container->getParameter('kernel.debug'))
{
$configuration->merge($loader->load('debug.xml'));
$configuration->setDefinition('event_dispatcher', $configuration->findDefinition('debug.event_dispatcher'));
}
return $configuration;
}
public function boot(ContainerInterface $container)
{
$container->getErrorHandlerService();
ClassCollectionLoader::load($container->getParameter('kernel.compiled_classes'), $container->getParameter('kernel.cache_dir'), 'classes', $container->getParameter('kernel.debug'));
}
}
namespace Symfony\Foundation\Bundle;
use Symfony\Components\DependencyInjection\Loader\LoaderExtension;
use Symfony\Components\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Components\DependencyInjection\BuilderConfiguration;
class KernelExtension extends LoaderExtension
{
public function configLoad($config)
{
$configuration = new BuilderConfiguration();
if (isset($config['charset']))
{
$configuration->setParameter('kernel.charset', $config['charset']);
}
if (!array_key_exists('compilation', $config))
{
$classes = array(
'Symfony\\Components\\Routing\\Router',
'Symfony\\Components\\Routing\\RouterInterface',
'Symfony\\Components\\EventDispatcher\\Event',
'Symfony\\Components\\Routing\\Matcher\\UrlMatcherInterface',
'Symfony\\Components\\Routing\\Matcher\\UrlMatcher',
'Symfony\\Components\\RequestHandler\\RequestInterface',
'Symfony\\Components\\RequestHandler\\Request',
'Symfony\\Components\\RequestHandler\\RequestHandler',
'Symfony\\Components\\RequestHandler\\ResponseInterface',
'Symfony\\Components\\RequestHandler\\Response',
'Symfony\\Components\\Templating\\Loader\\LoaderInterface',
'Symfony\\Components\\Templating\\Loader\\Loader',
'Symfony\\Components\\Templating\\Loader\\FilesystemLoader',
'Symfony\\Components\\Templating\\Engine',
'Symfony\\Components\\Templating\\Renderer\\RendererInterface',
'Symfony\\Components\\Templating\\Renderer\\Renderer',
'Symfony\\Components\\Templating\\Renderer\\PhpRenderer',
'Symfony\\Components\\Templating\\Storage\\Storage',
'Symfony\\Components\\Templating\\Storage\\FileStorage',
'Symfony\\Framework\\WebBundle\\Controller',
'Symfony\\Framework\\WebBundle\\Listener\\RequestParser',
'Symfony\\Framework\\WebBundle\\Listener\\ControllerLoader',
'Symfony\\Framework\\WebBundle\\Listener\\ResponseFilter',
'Symfony\\Framework\\WebBundle\\Templating\\Engine',
);
}
else
{
$classes = array();
foreach (explode("\n", $config['compilation']) as $class)
{
if ($class)
{
$classes[] = trim($class);
}
}
}
$configuration->setParameter('kernel.compiled_classes', $classes);
if (array_key_exists('error_handler_level', $config))
{
$configuration->setParameter('error_handler.level', $config['error_handler_level']);
}
return $configuration;
}
public function getXsdValidationBasePath()
{
return false;
}
public function getNamespace()
{
return 'http://www.symfony-project.org/schema/dic/symfony/kernel';
}
public function getAlias()
{
return 'kernel';
}
}
namespace Symfony\Foundation\Debug;
class ErrorHandler
{
protected $levels = array(
E_WARNING => 'Warning',
E_NOTICE => 'Notice',
E_USER_ERROR => 'User Error',
E_USER_WARNING => 'User Warning',
E_USER_NOTICE => 'User Notice',
E_STRICT => 'Runtime Notice',
E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
);
protected $level;
public function __construct($level = null)
{
$this->level = null === $level ? error_reporting() : $level;
}
public function register()
{
set_error_handler(array($this, 'handle'));
}
public function handle($level, $message, $file, $line, $context)
{
if (0 === $this->level)
{
return false;
}
if (error_reporting() & $level && $this->level & $level)
{
throw new \ErrorException(sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line));
}
return false;
}
}
namespace Symfony\Foundation;
class ClassCollectionLoader
{
static public function load($classes, $cacheDir, $name, $autoReload)
{
$cache = $cacheDir.'/'.$name.'.php';
$reload = false;
if ($autoReload)
{
$metadata = $cacheDir.'/'.$name.'.meta';
if (!file_exists($metadata) || !file_exists($cache))
{
$reload = true;
}
else
{
$time = filemtime($cache);
$meta = unserialize(file_get_contents($metadata));
if ($meta[1] != $classes)
{
$reload = true;
}
else
{
foreach ($meta[0] as $resource)
{
if (!file_exists($resource) || filemtime($resource) > $time)
{
$reload = true;
break;
}
}
}
}
}
if (!$reload && file_exists($cache))
{
require_once $cache;
return;
}
$files = array();
$content = '';
foreach ($classes as $class)
{
if (!class_exists($class) && !interface_exists($class))
{
throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class));
}
$r = new \ReflectionClass($class);
$files[] = $r->getFileName();
$content .= preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName()));
}
if (!is_dir(dirname($cache)))
{
mkdir(dirname($cache), 0777, true);
}
self::writeCacheFile($cache, Kernel::stripComments('<?php '.$content));
if ($autoReload)
{
self::writeCacheFile($metadata, serialize(array($files, $classes)));
}
}
static protected function writeCacheFile($file, $content)
{
$tmpFile = tempnam(dirname($file), basename($file));
if (!$fp = @fopen($tmpFile, 'wb'))
{
die(sprintf('Failed to write cache file "%s".', $tmpFile));
}
@fwrite($fp, $content);
@fclose($fp);
if ($content != file_get_contents($tmpFile))
{
die(sprintf('Failed to write cache file "%s" (cache corrupted).', $tmpFile));
}
@rename($tmpFile, $file);
chmod($file, 0644);
}
}
namespace Symfony\Foundation;
use Symfony\Components\DependencyInjection\ContainerInterface;
use Symfony\Components\DependencyInjection\Builder;
use Symfony\Components\DependencyInjection\BuilderConfiguration;
use Symfony\Components\DependencyInjection\Dumper\PhpDumper;
use Symfony\Components\DependencyInjection\FileResource;
use Symfony\Components\RequestHandler\RequestInterface;
abstract class Kernel implements \Serializable
{
protected $bundles;
protected $bundleDirs;
protected $container;
protected $rootDir;
protected $environment;
protected $debug;
protected $booted;
protected $name;
protected $startTime;
const VERSION = '2.0.0-DEV';
public function __construct($environment, $debug)
{
$this->debug = (Boolean) $debug;
if ($this->debug)
{
ini_set('display_errors', 1);
error_reporting(-1);
}
else
{
ini_set('display_errors', 0);
}
if ($this->debug)
{
$this->startTime = microtime(true);
}
$this->booted = false;
$this->environment = $environment;
$this->bundles = $this->registerBundles();
$this->bundleDirs = $this->registerBundleDirs();
$this->rootDir = realpath($this->registerRootDir());
$this->name = basename($this->rootDir);
}
abstract public function registerRootDir();
abstract public function registerBundles();
abstract public function registerBundleDirs();
abstract public function registerContainerConfiguration();
abstract public function registerRoutes();
public function isBooted()
{
return $this->booted;
}
public function boot()
{
if (true === $this->booted)
{
throw new \LogicException('The kernel is already booted.');
}
$this->container = $this->initializeContainer();
$this->container->setService('kernel', $this);
foreach ($this->bundles as $bundle)
{
$bundle->boot($this->container);
}
$this->booted = true;
return $this;
}
public function run()
{
$this->handle()->send();
}
public function handle(RequestInterface $request = null)
{
if (false === $this->booted)
{
$this->boot();
}
if (null === $request)
{
$request = $this->container->getRequestService();
}
else
{
$this->container->setService('request', $request);
}
return $this->container->getRequestHandlerService()->handle($request);
}
public function getBundleDirs()
{
return $this->bundleDirs;
}
public function getBundles()
{
return $this->bundles;
}
public function getName()
{
return $this->name;
}
public function getEnvironment()
{
return $this->environment;
}
public function isDebug()
{
return $this->debug;
}
public function getRootDir()
{
return $this->rootDir;
}
public function getContainer()
{
return $this->container;
}
public function getStartTime()
{
return $this->debug ? $this->startTime : -INF;
}
public function getCacheDir()
{
return $this->rootDir.'/cache/'.$this->environment;
}
public function getLogDir()
{
return $this->rootDir.'/logs';
}
protected function initializeContainer()
{
$class = $this->name.'ProjectContainer';
$location = $this->getCacheDir().'/'.$class;
$reload = $this->debug ? $this->needsReload($class, $location) : false;
if ($reload || !file_exists($location.'.php'))
{
$this->buildContainer($class, $location.'.php');
}
require_once $location.'.php';
return new $class();
}
public function getKernelParameters()
{
$bundles = array();
foreach ($this->bundles as $bundle)
{
$bundles[] = get_class($bundle);
}
return array_merge(
array(
'kernel.root_dir' => $this->rootDir,
'kernel.environment' => $this->environment,
'kernel.debug' => $this->debug,
'kernel.name' => $this->name,
'kernel.cache_dir' => $this->getCacheDir(),
'kernel.logs_dir' => $this->getLogDir(),
'kernel.bundle_dirs' => $this->bundleDirs,
'kernel.bundles' => $bundles,
'kernel.charset' => 'UTF-8',
),
$this->getEnvParameters()
);
}
protected function getEnvParameters()
{
$parameters = array();
foreach ($_SERVER as $key => $value)
{
if ('SYMFONY__' === substr($key, 0, 9))
{
$parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
}
}
return $parameters;
}
protected function needsReload($class, $location)
{
if (!file_exists($location.'.meta') || !file_exists($location.'.php'))
{
return true;
}
$meta = unserialize(file_get_contents($location.'.meta'));
$time = filemtime($location.'.php');
foreach ($meta as $resource)
{
if (!$resource->isUptodate($time))
{
return true;
}
}
return false;
}
protected function buildContainer($class, $file)
{
$container = new Builder($this->getKernelParameters());
$configuration = new BuilderConfiguration();
foreach ($this->bundles as $bundle)
{
$configuration->merge($bundle->buildContainer($container));
}
$configuration->merge($this->registerContainerConfiguration());
$container->merge($configuration);
$this->optimizeContainer($container);
foreach (array('cache', 'logs') as $name)
{
$dir = $container->getParameter(sprintf('kernel.%s_dir', $name));
if (!is_dir($dir))
{
if (false === @mkdir($dir, 0777, true))
{
die(sprintf('Unable to create the %s directory (%s)', $name, dirname($dir)));
}
}
elseif (!is_writable($dir))
{
die(sprintf('Unable to write in the %s directory (%s)', $name, $dir));
}
}
$dumper = new PhpDumper($container);
$content = $dumper->dump(array('class' => $class));
if (!$this->debug)
{
$content = self::stripComments($content);
}
$this->writeCacheFile($file, $content);
if ($this->debug)
{
$parent = new \ReflectionObject($this);
$configuration->addResource(new FileResource($parent->getFileName()));
while ($parent = $parent->getParentClass())
{
$configuration->addResource(new FileResource($parent->getFileName()));
}
$this->writeCacheFile($this->getCacheDir().'/'.$class.'.meta', serialize($configuration->getResources()));
}
}
public function optimizeContainer(Builder $container)
{
foreach ($container->getDefinitions() as $definition)
{
if (false !== strpos($class = $definition->getClass(), '%'))
{
$definition->setClass(Builder::resolveValue($class, $container->getParameters()));
unset($container[substr($class, 1, -1)]);
}
}
}
static public function stripComments($source)
{
if (!function_exists('token_get_all'))
{
return $source;
}
$ignore = array(T_COMMENT => true, T_DOC_COMMENT => true);
$output = '';
foreach (token_get_all($source) as $token)
{
if (isset($token[1]))
{
if (!isset($ignore[$token[0]]))
{
$output .= $token[1];
}
}
else
{
$output .= $token;
}
}
return $output;
}
protected function writeCacheFile($file, $content)
{
$tmpFile = tempnam(dirname($file), basename($file));
if (!$fp = @fopen($tmpFile, 'wb'))
{
die(sprintf('Failed to write cache file "%s".', $tmpFile));
}
@fwrite($fp, $content);
@fclose($fp);
if ($content != file_get_contents($tmpFile))
{
die(sprintf('Failed to write cache file "%s" (cache corrupted).', $tmpFile));
}
@rename($tmpFile, $file);
chmod($file, 0644);
}
public function serialize()
{
return serialize(array($this->environment, $this->debug));
}
public function unserialize($data)
{
list($environment, $debug) = unserialize($data);
$this->__construct($environment, $debug);
}
}
namespace Symfony\Foundation;
use Symfony\Components\EventDispatcher\EventDispatcher as BaseEventDispatcher;
use Symfony\Components\EventDispatcher\Event;
use Symfony\Components\DependencyInjection\ContainerInterface;
class EventDispatcher extends BaseEventDispatcher
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
foreach ($container->findAnnotatedServiceIds('kernel.listener') as $id => $attributes)
{
foreach ($attributes as $attribute)
{
if (isset($attribute['event']))
{
$this->connect($attribute['event'], array($id, isset($attribute['method']) ? $attribute['method'] : 'handle'));
}
}
}
}
public function getListeners($name)
{
if (!isset($this->listeners[$name]))
{
return array();
}
foreach ($this->listeners[$name] as $i => $listener)
{
if (is_array($listener) && is_string($listener[0]))
{
$this->listeners[$name][$i] = array($this->container->getService($listener[0]), $listener[1]);
}
}
return $this->listeners[$name];
}
}