Skip to content
Snippets Groups Projects
Commit e3573a2a authored by catch's avatar catch
Browse files

Issue #2296009 by fgm, Fabianx, AjitS: Use APC Classloader by default (when available)

parent 77394530
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
...@@ -15,14 +15,14 @@ ...@@ -15,14 +15,14 @@
/** /**
* Rebuilds all caches even when Drupal itself does not work. * Rebuilds all caches even when Drupal itself does not work.
* *
* @param \Composer\Autoload\ClassLoader $classloader * @param \Composer\Autoload\ClassLoader $class_loader
* The classloader. * The class loader.
* @param \Symfony\Component\HttpFoundation\Request $request * @param \Symfony\Component\HttpFoundation\Request $request
* The current request. * The current request.
* *
* @see rebuild.php * @see rebuild.php
*/ */
function drupal_rebuild(ClassLoader $classloader, Request $request) { function drupal_rebuild(ClassLoader $class_loader, Request $request) {
// Remove Drupal's error and exception handlers; they rely on a working // Remove Drupal's error and exception handlers; they rely on a working
// service container and other subsystems and will only cause a fatal error // service container and other subsystems and will only cause a fatal error
// that hides the actual error. // that hides the actual error.
...@@ -34,7 +34,7 @@ function drupal_rebuild(ClassLoader $classloader, Request $request) { ...@@ -34,7 +34,7 @@ function drupal_rebuild(ClassLoader $classloader, Request $request) {
PhpStorageFactory::get('twig')->deleteAll(); PhpStorageFactory::get('twig')->deleteAll();
// Bootstrap up to where caches exist and clear them. // Bootstrap up to where caches exist and clear them.
$kernel = new DrupalKernel('prod', $classloader); $kernel = new DrupalKernel('prod', $class_loader);
$kernel->setSitePath(DrupalKernel::findSitePath($request)); $kernel->setSitePath(DrupalKernel::findSitePath($request));
$kernel->prepareLegacyRequest($request); $kernel->prepareLegacyRequest($request);
......
...@@ -108,7 +108,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { ...@@ -108,7 +108,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
protected $storage; protected $storage;
/** /**
* The classloader object. * The class loader object.
* *
* @var \Composer\Autoload\ClassLoader * @var \Composer\Autoload\ClassLoader
*/ */
...@@ -217,6 +217,7 @@ public static function createFromRequest(Request $request, $class_loader, $envir ...@@ -217,6 +217,7 @@ public static function createFromRequest(Request $request, $class_loader, $envir
// Include our bootstrap file. // Include our bootstrap file.
$core_root = dirname(dirname(dirname(__DIR__))); $core_root = dirname(dirname(dirname(__DIR__)));
require_once $core_root . '/includes/bootstrap.inc'; require_once $core_root . '/includes/bootstrap.inc';
$class_loader_class = get_class($class_loader);
$kernel = new static($environment, $class_loader, $allow_dumping); $kernel = new static($environment, $class_loader, $allow_dumping);
...@@ -245,6 +246,19 @@ public static function createFromRequest(Request $request, $class_loader, $envir ...@@ -245,6 +246,19 @@ public static function createFromRequest(Request $request, $class_loader, $envir
$response->prepare($request)->send(); $response->prepare($request)->send();
} }
// If the class loader is still the same, possibly upgrade to the APC class
// loader.
if ($class_loader_class == get_class($class_loader)
&& Settings::get('class_loader_auto_detect', TRUE)
&& Settings::get('hash_salt', FALSE)
&& function_exists('apc_fetch')) {
$prefix = 'drupal.' . hash('sha256', 'drupal.' . Settings::getHashSalt());
$apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader($prefix, $class_loader);
$class_loader->unregister();
$apc_loader->register();
$class_loader = $apc_loader;
}
return $kernel; return $kernel;
} }
......
...@@ -122,9 +122,9 @@ public function testCompileDIC() { ...@@ -122,9 +122,9 @@ public function testCompileDIC() {
$this->assertEqual(array_values($modules_enabled), $module_list); $this->assertEqual(array_values($modules_enabled), $module_list);
// Test that our synthetic services are there. // Test that our synthetic services are there.
$classloader = $container->get('class_loader'); $class_loader = $container->get('class_loader');
$refClass = new \ReflectionClass($classloader); $refClass = new \ReflectionClass($class_loader);
$this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a classloader'); $this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a class loader');
// We make this assertion here purely to show that the new container below // We make this assertion here purely to show that the new container below
// is functioning correctly, i.e. we get a brand new ContainerBuilder // is functioning correctly, i.e. we get a brand new ContainerBuilder
...@@ -150,9 +150,9 @@ public function testCompileDIC() { ...@@ -150,9 +150,9 @@ public function testCompileDIC() {
$this->assertTrue($container->has('service_provider_test_class'), 'Container has test service'); $this->assertTrue($container->has('service_provider_test_class'), 'Container has test service');
// Test that our synthetic services are there. // Test that our synthetic services are there.
$classloader = $container->get('class_loader'); $class_loader = $container->get('class_loader');
$refClass = new \ReflectionClass($classloader); $refClass = new \ReflectionClass($class_loader);
$this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a classloader'); $this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a class loader');
// Check that the location of the new module is registered. // Check that the location of the new module is registered.
$modules = $container->getParameter('container.modules'); $modules = $container->getParameter('container.modules');
......
...@@ -20,7 +20,12 @@ ...@@ -20,7 +20,12 @@
// Change the directory to the Drupal root. // Change the directory to the Drupal root.
chdir('..'); chdir('..');
$autoloader = require_once 'autoload.php'; // Clear the APC cache to ensure APC class loader is reset.
if (function_exists('apc_fetch')) {
apc_clear_cache('user');
}
$autoloader = require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/includes/utility.inc'; require_once __DIR__ . '/includes/utility.inc';
$request = Request::createFromGlobals(); $request = Request::createFromGlobals();
......
...@@ -383,18 +383,29 @@ ...@@ -383,18 +383,29 @@
/** /**
* Class Loader. * Class Loader.
* *
* By default, Composer's ClassLoader is used, which is best for development, as * If the APC extension is detected, the Symfony APC class loader is used for
* it does not break when code is moved in the file system. You can decorate the * performance reasons. Detection can be prevented by setting
* class loader with a cached solution for better performance, which is * class_loader_auto_detect to false, as in the example below.
* recommended for production sites. */
* # $settings['class_loader_auto_detect'] = FALSE;
* To do so, you may decorate and replace the local $class_loader variable.
* /*
* For example, to use Symfony's APC class loader, uncomment the code below. * If the APC extension is not detected, either because APC is missing or
* because auto-detection has been disabled, auto-loading falls back to
* Composer's ClassLoader, which is good for development as it does not break
* when code is moved in the file system. You can also decorate the base class
* loader with another cached solution than the Symfony APC class loader, as
* all production sites should have a cached class loader of some sort enabled.
*
* To do so, you may decorate and replace the local $class_loader variable. For
* example, to use Symfony's APC class loader without automatic detection,
* uncomment the code below.
*/ */
/* /*
if ($settings['hash_salt']) { if ($settings['hash_salt']) {
$apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader('drupal.' . $settings['hash_salt'], $class_loader); $prefix = 'drupal.' . hash('sha256', 'drupal.' . $settings['hash_salt']);
$apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader($prefix, $class_loader);
unset($prefix);
$class_loader->unregister(); $class_loader->unregister();
$apc_loader->register(); $apc_loader->register();
$class_loader = $apc_loader; $class_loader = $apc_loader;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment