Commit 6aeb7e9a authored by catch's avatar catch

Issue #2325197 by tstoeckler, sun: Remove drupal_classloader().

parent 5289c3e3
...@@ -1024,7 +1024,8 @@ function drupal_bootstrap($phase = NULL) { ...@@ -1024,7 +1024,8 @@ function drupal_bootstrap($phase = NULL) {
switch ($current_phase) { switch ($current_phase) {
case DRUPAL_BOOTSTRAP_CONFIGURATION: case DRUPAL_BOOTSTRAP_CONFIGURATION:
$kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod'); $classloader = require __DIR__ . '/../vendor/autoload.php';
$kernel = DrupalKernel::createFromRequest($request, $classloader, 'prod');
break; break;
case DRUPAL_BOOTSTRAP_KERNEL: case DRUPAL_BOOTSTRAP_KERNEL:
...@@ -1398,50 +1399,6 @@ function _current_path($path = NULL) { ...@@ -1398,50 +1399,6 @@ function _current_path($path = NULL) {
return $current_path; return $current_path;
} }
/**
* Initializes and returns the class loader.
*
* The class loader is responsible for lazy-loading all PSR-0 compatible
* classes, interfaces, and traits (PHP 5.4 and later). It's only dependency
* is DRUPAL_ROOT. Otherwise it may be called as early as possible.
*
* @param $class_loader
* The name of class loader to use. This can be used to change the class
* loader class when calling drupal_classloader() from settings.php. It is
* ignored otherwise.
*
* @return \Composer\Autoload\ClassLoader
* A ClassLoader class instance (or extension thereof).
*/
function drupal_classloader($class_loader = NULL) {
// By default, use the ClassLoader which is best for development, as it does
// not break when code is moved on the file system. However, as it is slow,
// allow to use the APC class loader in production.
static $loader;
if (!isset($loader)) {
// Retrieve the Composer ClassLoader for loading classes.
$loader = include __DIR__ . '/../vendor/autoload.php';
// Register the class loader.
// When configured to use APC, the ApcClassLoader is registered instead.
// Note that ApcClassLoader decorates ClassLoader and only provides the
// findFile() method, but none of the others. The actual registry is still
// in ClassLoader.
if (!isset($class_loader)) {
$class_loader = Settings::get('class_loader', 'default');
}
if ($class_loader === 'apc') {
require_once __DIR__ . '/../vendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcClassLoader.php';
$apc_loader = new ApcClassLoader('drupal.' . Settings::getHashSalt(), $loader);
$loader->unregister();
$apc_loader->register();
}
}
return $loader;
}
/** /**
* Registers an additional namespace. * Registers an additional namespace.
* *
...@@ -1451,7 +1408,7 @@ function drupal_classloader($class_loader = NULL) { ...@@ -1451,7 +1408,7 @@ function drupal_classloader($class_loader = NULL) {
* The relative path to the Drupal component in the filesystem. * The relative path to the Drupal component in the filesystem.
*/ */
function drupal_classloader_register($name, $path) { function drupal_classloader_register($name, $path) {
$loader = drupal_classloader(); $loader = \Drupal::service('class_loader');
$loader->addPsr4('Drupal\\' . $name . '\\', DRUPAL_ROOT . '/' . $path . '/src'); $loader->addPsr4('Drupal\\' . $name . '\\', DRUPAL_ROOT . '/' . $path . '/src');
} }
......
...@@ -286,7 +286,8 @@ function install_begin_request(&$install_state) { ...@@ -286,7 +286,8 @@ function install_begin_request(&$install_state) {
} }
$site_path = DrupalKernel::findSitePath($request, FALSE); $site_path = DrupalKernel::findSitePath($request, FALSE);
Settings::initialize($site_path); $class_loader = require __DIR__ . '/../vendor/autoload.php';
Settings::initialize($site_path, $class_loader);
// Ensure that procedural dependencies are loaded as early as possible, // Ensure that procedural dependencies are loaded as early as possible,
// since the error/exception handlers depend on them. // since the error/exception handlers depend on them.
...@@ -358,7 +359,7 @@ function install_begin_request(&$install_state) { ...@@ -358,7 +359,7 @@ function install_begin_request(&$install_state) {
} }
// Only allow dumping the container once the hash salt has been created. // Only allow dumping the container once the hash salt has been created.
$kernel = InstallerKernel::createFromRequest($request, drupal_classloader(), $environment, (bool) Settings::get('hash_salt', FALSE)); $kernel = InstallerKernel::createFromRequest($request, $class_loader, $environment, (bool) Settings::get('hash_salt', FALSE));
$kernel->setSitePath($site_path); $kernel->setSitePath($site_path);
$kernel->boot(); $kernel->boot();
$container = $kernel->getContainer(); $container = $kernel->getContainer();
......
...@@ -182,19 +182,20 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { ...@@ -182,19 +182,20 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
* Create a DrupalKernel object from a request. * Create a DrupalKernel object from a request.
* *
* @param \Symfony\Component\HttpFoundation\Request $request * @param \Symfony\Component\HttpFoundation\Request $request
* @param \Composer\Autoload\ClassLoader $class_loader * The request.
* (optional) The classloader is only used if $storage is not given or * @param $class_loader
* the load from storage fails and a container rebuild is required. In * The class loader. Normally Composer's ClassLoader, as included by the
* this case, the loaded modules will be registered with this loader in * front controller, but may also be decorated; e.g.,
* order to be able to find the module serviceProviders. * \Symfony\Component\ClassLoader\ApcClassLoader.
* @param string $environment * @param string $environment
* String indicating the environment, e.g. 'prod' or 'dev'. * String indicating the environment, e.g. 'prod' or 'dev'.
* @param bool $allow_dumping * @param bool $allow_dumping
* (optional) FALSE to stop the container from being written to or read * (optional) FALSE to stop the container from being written to or read
* from disk. Defaults to TRUE. * from disk. Defaults to TRUE.
*
* @return static * @return static
*/ */
public static function createFromRequest(Request $request, ClassLoader $class_loader, $environment, $allow_dumping = TRUE) { public static function createFromRequest(Request $request, $class_loader, $environment, $allow_dumping = TRUE) {
// Include our bootstrap file. // Include our bootstrap file.
require_once dirname(dirname(dirname(__DIR__))) . '/includes/bootstrap.inc'; require_once dirname(dirname(dirname(__DIR__))) . '/includes/bootstrap.inc';
...@@ -204,9 +205,7 @@ public static function createFromRequest(Request $request, ClassLoader $class_lo ...@@ -204,9 +205,7 @@ public static function createFromRequest(Request $request, ClassLoader $class_lo
static::bootEnvironment(); static::bootEnvironment();
// Get our most basic settings setup. // Get our most basic settings setup.
$site_path = static::findSitePath($request); $kernel->initializeSettings($request);
$kernel->setSitePath($site_path);
Settings::initialize($site_path);
// Redirect the user to the installation script if Drupal has not been // Redirect the user to the installation script if Drupal has not been
// installed yet (i.e., if no $databases array has been defined in the // installed yet (i.e., if no $databases array has been defined in the
...@@ -219,21 +218,32 @@ public static function createFromRequest(Request $request, ClassLoader $class_lo ...@@ -219,21 +218,32 @@ public static function createFromRequest(Request $request, ClassLoader $class_lo
return $kernel; return $kernel;
} }
/**
* Initializes the kernel's site path and the Settings singleton.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request that will be used to determine the site path.
*/
protected function initializeSettings(Request $request) {
$site_path = static::findSitePath($request);
$this->setSitePath($site_path);
Settings::initialize($site_path, $this->classLoader);
}
/** /**
* Constructs a DrupalKernel object. * Constructs a DrupalKernel object.
* *
* @param string $environment * @param string $environment
* String indicating the environment, e.g. 'prod' or 'dev'. * String indicating the environment, e.g. 'prod' or 'dev'.
* @param \Composer\Autoload\ClassLoader $class_loader * @param $class_loader
* (optional) The class loader is only used if $storage is not given or * The class loader. Normally \Composer\Autoload\ClassLoader, as included by
* the load from storage fails and a container rebuild is required. In * the front controller, but may also be decorated; e.g.,
* this case, the loaded modules will be registered with this loader in * \Symfony\Component\ClassLoader\ApcClassLoader.
* order to be able to find the module serviceProviders.
* @param bool $allow_dumping * @param bool $allow_dumping
* (optional) FALSE to stop the container from being written to or read * (optional) FALSE to stop the container from being written to or read
* from disk. Defaults to TRUE. * from disk. Defaults to TRUE.
*/ */
public function __construct($environment, ClassLoader $class_loader, $allow_dumping = TRUE) { public function __construct($environment, $class_loader, $allow_dumping = TRUE) {
$this->environment = $environment; $this->environment = $environment;
$this->classLoader = $class_loader; $this->classLoader = $class_loader;
$this->allowDumping = $allow_dumping; $this->allowDumping = $allow_dumping;
...@@ -349,8 +359,6 @@ public function boot() { ...@@ -349,8 +359,6 @@ public function boot() {
// Start a page timer: // Start a page timer:
Timer::start('page'); Timer::start('page');
drupal_classloader();
// Load legacy and other functional code. // Load legacy and other functional code.
require_once DRUPAL_ROOT . '/core/includes/common.inc'; require_once DRUPAL_ROOT . '/core/includes/common.inc';
require_once DRUPAL_ROOT . '/core/includes/database.inc'; require_once DRUPAL_ROOT . '/core/includes/database.inc';
......
...@@ -87,8 +87,14 @@ public static function getAll() { ...@@ -87,8 +87,14 @@ public static function getAll() {
* *
* @param string $site_path * @param string $site_path
* The current site path. * The current site path.
* @param \Composer\Autoload\ClassLoader $class_loader
* The class loader that is used for this request. Passed by reference and
* exposed to the local scope of settings.php, so as to allow it to be
* decorated with Symfony's ApcClassLoader, for example.
*
* @see default.settings.php
*/ */
public static function initialize($site_path) { public static function initialize($site_path, &$class_loader) {
// Export these settings.php variables to the global namespace. // Export these settings.php variables to the global namespace.
global $base_url, $cookie_domain, $config_directories, $config; global $base_url, $cookie_domain, $config_directories, $config;
$settings = array(); $settings = array();
......
...@@ -138,7 +138,8 @@ protected function setUp() { ...@@ -138,7 +138,8 @@ protected function setUp() {
// Import new settings.php written by the installer. // Import new settings.php written by the installer.
$request = Request::createFromGlobals(); $request = Request::createFromGlobals();
Settings::initialize(DrupalKernel::findSitePath($request)); $class_loader = require DRUPAL_ROOT . '/core/vendor/autoload.php';
Settings::initialize(DrupalKernel::findSitePath($request), $class_loader);
foreach ($GLOBALS['config_directories'] as $type => $path) { foreach ($GLOBALS['config_directories'] as $type => $path) {
$this->configDirectories[$type] = $path; $this->configDirectories[$type] = $path;
} }
...@@ -150,7 +151,7 @@ protected function setUp() { ...@@ -150,7 +151,7 @@ protected function setUp() {
// WebTestBase::tearDown() will delete the entire test site directory. // WebTestBase::tearDown() will delete the entire test site directory.
// Not using File API; a potential error must trigger a PHP warning. // Not using File API; a potential error must trigger a PHP warning.
chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777); chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777);
$this->kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod', FALSE); $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE);
$this->kernel->prepareLegacyRequest($request); $this->kernel->prepareLegacyRequest($request);
$this->container = $this->kernel->getContainer(); $this->container = $this->kernel->getContainer();
$config = $this->container->get('config.factory'); $config = $this->container->get('config.factory');
......
...@@ -155,7 +155,8 @@ protected function setUp() { ...@@ -155,7 +155,8 @@ protected function setUp() {
// Back up settings from TestBase::prepareEnvironment(). // Back up settings from TestBase::prepareEnvironment().
$settings = Settings::getAll(); $settings = Settings::getAll();
// Bootstrap a new kernel. Don't use createFromRequest so we don't mess with settings. // Bootstrap a new kernel. Don't use createFromRequest so we don't mess with settings.
$this->kernel = new DrupalKernel('testing', drupal_classloader(), FALSE); $class_loader = require DRUPAL_ROOT . '/core/vendor/autoload.php';
$this->kernel = new DrupalKernel('testing', $class_loader, FALSE);
$request = Request::create('/'); $request = Request::create('/');
$this->kernel->setSitePath(DrupalKernel::findSitePath($request)); $this->kernel->setSitePath(DrupalKernel::findSitePath($request));
$this->kernel->boot(); $this->kernel->boot();
......
...@@ -861,14 +861,15 @@ protected function setUp() { ...@@ -861,14 +861,15 @@ protected function setUp() {
// Since Drupal is bootstrapped already, install_begin_request() will not // Since Drupal is bootstrapped already, install_begin_request() will not
// bootstrap into DRUPAL_BOOTSTRAP_CONFIGURATION (again). Hence, we have to // bootstrap into DRUPAL_BOOTSTRAP_CONFIGURATION (again). Hence, we have to
// reload the newly written custom settings.php manually. // reload the newly written custom settings.php manually.
Settings::initialize($directory); $class_loader = require DRUPAL_ROOT . '/core/vendor/autoload.php';
Settings::initialize($directory, $class_loader);
// Execute the non-interactive installer. // Execute the non-interactive installer.
require_once DRUPAL_ROOT . '/core/includes/install.core.inc'; require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
install_drupal($parameters); install_drupal($parameters);
// Import new settings.php written by the installer. // Import new settings.php written by the installer.
Settings::initialize($directory); Settings::initialize($directory, $class_loader);
foreach ($GLOBALS['config_directories'] as $type => $path) { foreach ($GLOBALS['config_directories'] as $type => $path) {
$this->configDirectories[$type] = $path; $this->configDirectories[$type] = $path;
} }
...@@ -882,7 +883,7 @@ protected function setUp() { ...@@ -882,7 +883,7 @@ protected function setUp() {
chmod($directory, 0777); chmod($directory, 0777);
$request = \Drupal::request(); $request = \Drupal::request();
$this->kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod', TRUE); $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', TRUE);
$this->kernel->prepareLegacyRequest($request); $this->kernel->prepareLegacyRequest($request);
// Force the container to be built from scratch instead of loaded from the // Force the container to be built from scratch instead of loaded from the
// disk. This forces us to not accidently load the parent site. // disk. This forces us to not accidently load the parent site.
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
use Drupal\Core\DrupalKernel; use Drupal\Core\DrupalKernel;
use Drupal\Core\Site\Settings; use Drupal\Core\Site\Settings;
use Drupal\simpletest\DrupalUnitTestBase; use Drupal\simpletest\KernelTestBase;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
/** /**
...@@ -17,12 +17,7 @@ ...@@ -17,12 +17,7 @@
* *
* @group DrupalKernel * @group DrupalKernel
*/ */
class DrupalKernelTest extends DrupalUnitTestBase { class DrupalKernelTest extends KernelTestBase {
/**
* @var \Composer\Autoload\ClassLoader
*/
protected $classloader;
protected function setUp() { protected function setUp() {
// DrupalKernel relies on global $config_directories and requires those // DrupalKernel relies on global $config_directories and requires those
...@@ -38,8 +33,6 @@ protected function setUp() { ...@@ -38,8 +33,6 @@ protected function setUp() {
'directory' => DRUPAL_ROOT . '/' . $this->public_files_directory . '/php', 'directory' => DRUPAL_ROOT . '/' . $this->public_files_directory . '/php',
'secret' => Settings::getHashSalt(), 'secret' => Settings::getHashSalt(),
))); )));
$this->classloader = drupal_classloader();
} }
/** /**
...@@ -59,7 +52,8 @@ protected function setUp() { ...@@ -59,7 +52,8 @@ protected function setUp() {
*/ */
protected function getTestKernel(Request $request, array $modules_enabled = NULL, $read_only = FALSE) { protected function getTestKernel(Request $request, array $modules_enabled = NULL, $read_only = FALSE) {
// Manually create kernel to avoid replacing settings. // Manually create kernel to avoid replacing settings.
$kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'testing'); $class_loader = require DRUPAL_ROOT . '/core/vendor/autoload.php';
$kernel = DrupalKernel::createFromRequest($request, $class_loader, 'testing');
$this->settingsSet('hash_salt', $this->databasePrefix); $this->settingsSet('hash_salt', $this->databasePrefix);
if (isset($modules_enabled)) { if (isset($modules_enabled)) {
$kernel->updateModules($modules_enabled); $kernel->updateModules($modules_enabled);
......
...@@ -32,7 +32,8 @@ function testSystemInitIgnoresSecondaries() { ...@@ -32,7 +32,8 @@ function testSystemInitIgnoresSecondaries() {
Database::addConnectionInfo('default', 'replica', $connection_info['default']); Database::addConnectionInfo('default', 'replica', $connection_info['default']);
db_ignore_replica(); db_ignore_replica();
$kernel = new DrupalKernel('testing', drupal_classloader(), FALSE); $class_loader = require DRUPAL_ROOT . '/core/vendor/autoload.php';
$kernel = new DrupalKernel('testing', $class_loader, FALSE);
$event = new GetResponseEvent($kernel, Request::create('http://example.com'), HttpKernelInterface::MASTER_REQUEST); $event = new GetResponseEvent($kernel, Request::create('http://example.com'), HttpKernelInterface::MASTER_REQUEST);
$subscriber = new ReplicaDatabaseIgnoreSubscriber(); $subscriber = new ReplicaDatabaseIgnoreSubscriber();
$subscriber->checkReplicaServer($event); $subscriber->checkReplicaServer($event);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
// Manually resemble early bootstrap of DrupalKernel::boot(). // Manually resemble early bootstrap of DrupalKernel::boot().
require_once __DIR__ . '/includes/bootstrap.inc'; require_once __DIR__ . '/includes/bootstrap.inc';
DrupalKernel::bootEnvironment(); DrupalKernel::bootEnvironment();
Settings::initialize(DrupalKernel::findSitePath($request)); Settings::initialize(DrupalKernel::findSitePath($request), $autoloader);
if (Settings::get('rebuild_access', FALSE) || if (Settings::get('rebuild_access', FALSE) ||
($request->get('token') && $request->get('timestamp') && ($request->get('token') && $request->get('timestamp') &&
......
...@@ -371,17 +371,23 @@ ...@@ -371,17 +371,23 @@
/** /**
* Class Loader. * Class Loader.
* *
* By default, Drupal uses Composer's ClassLoader, which is best for * By default, Composer's ClassLoader is used, which is best for development, as
* development, as it does not break when code is moved on the file * it does not break when code is moved in the file system. You can decorate the
* system. It is possible, however, to wrap the class loader with a * class loader with a cached solution for better performance, which is
* cached class loader solution for better performance, which is
* recommended for production sites. * recommended for production sites.
* *
* Examples: * To do so, you may decorate and replace the local $class_loader variable.
* $settings['class_loader'] = 'apc'; *
* $settings['class_loader'] = 'default'; * For example, to use Symfony's APC class loader, uncomment the code below.
*/ */
# $settings['class_loader'] = 'apc'; /*
if ($settings['hash_salt']) {
$apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader('drupal.' . $settings['hash_salt'], $class_loader);
$class_loader->unregister();
$apc_loader->register();
$class_loader = $apc_loader;
}
*/
/** /**
* Authorized file system operations: * Authorized file system operations:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment