annotate core/lib/Drupal/Core/Update/UpdateKernel.php @ 14:1fec387a4317

Update Drupal core to 8.5.2 via Composer
author Chris Cannam
date Mon, 23 Apr 2018 09:46:53 +0100
parents 4c8ae668cc8c
children c2387f117808
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Core\Update;
Chris@0 4
Chris@0 5 use Drupal\Core\DrupalKernel;
Chris@0 6 use Drupal\Core\Session\AnonymousUserSession;
Chris@0 7 use Drupal\Core\Site\Settings;
Chris@0 8 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
Chris@0 9 use Symfony\Component\HttpFoundation\ParameterBag;
Chris@0 10 use Symfony\Component\HttpFoundation\Request;
Chris@0 11 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
Chris@0 12
Chris@0 13 /**
Chris@0 14 * Defines a kernel which is used primarily to run the update of Drupal.
Chris@0 15 *
Chris@0 16 * We use a dedicated kernel + front controller (update.php) in order to be able
Chris@0 17 * to repair Drupal if it is in a broken state.
Chris@0 18 *
Chris@0 19 * @see update.php
Chris@0 20 * @see \Drupal\system\Controller\DbUpdateController
Chris@0 21 */
Chris@0 22 class UpdateKernel extends DrupalKernel {
Chris@0 23
Chris@0 24 /**
Chris@0 25 * {@inheritdoc}
Chris@0 26 */
Chris@0 27 public function discoverServiceProviders() {
Chris@0 28 parent::discoverServiceProviders();
Chris@0 29
Chris@0 30 $this->serviceProviderClasses['app']['update_kernel'] = 'Drupal\Core\Update\UpdateServiceProvider';
Chris@0 31 }
Chris@0 32
Chris@0 33 /**
Chris@0 34 * {@inheritdoc}
Chris@0 35 */
Chris@0 36 protected function initializeContainer() {
Chris@0 37 // Always force a container rebuild, in order to be able to override some
Chris@0 38 // services, see \Drupal\Core\Update\UpdateServiceProvider.
Chris@0 39 $this->containerNeedsRebuild = TRUE;
Chris@0 40 $container = parent::initializeContainer();
Chris@0 41 return $container;
Chris@0 42 }
Chris@0 43
Chris@0 44 /**
Chris@0 45 * {@inheritdoc}
Chris@0 46 */
Chris@0 47 protected function cacheDrupalContainer(array $container_definition) {
Chris@0 48 // Don't save this particular container to cache, so it does not leak into
Chris@0 49 // the main site at all.
Chris@0 50 return FALSE;
Chris@0 51 }
Chris@0 52
Chris@0 53 /**
Chris@0 54 * {@inheritdoc}
Chris@0 55 */
Chris@0 56 public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
Chris@0 57 try {
Chris@0 58 static::bootEnvironment();
Chris@0 59
Chris@0 60 // First boot up basic things, like loading the include files.
Chris@0 61 $this->initializeSettings($request);
Chris@0 62 $this->boot();
Chris@0 63 $container = $this->getContainer();
Chris@0 64 /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */
Chris@0 65 $request_stack = $container->get('request_stack');
Chris@0 66 $request_stack->push($request);
Chris@0 67 $this->preHandle($request);
Chris@0 68
Chris@0 69 // Handle the actual request. We need the session both for authentication
Chris@0 70 // as well as the DB update, like
Chris@0 71 // \Drupal\system\Controller\DbUpdateController::batchFinished.
Chris@0 72 $this->bootSession($request, $type);
Chris@0 73 $result = $this->handleRaw($request);
Chris@0 74 $this->shutdownSession($request);
Chris@0 75
Chris@0 76 return $result;
Chris@0 77 }
Chris@0 78 catch (\Exception $e) {
Chris@0 79 return $this->handleException($e, $request, $type);
Chris@0 80 }
Chris@0 81 }
Chris@0 82
Chris@0 83 /**
Chris@0 84 * Generates the actual result of update.php.
Chris@0 85 *
Chris@0 86 * The actual logic of the update is done in the db update controller.
Chris@0 87 *
Chris@0 88 * @param \Symfony\Component\HttpFoundation\Request $request
Chris@0 89 * The incoming request.
Chris@0 90 *
Chris@0 91 * @return \Symfony\Component\HttpFoundation\Response
Chris@0 92 * A response object.
Chris@0 93 *
Chris@0 94 * @see \Drupal\system\Controller\DbUpdateController
Chris@0 95 */
Chris@0 96 protected function handleRaw(Request $request) {
Chris@0 97 $container = $this->getContainer();
Chris@0 98
Chris@0 99 $this->handleAccess($request, $container);
Chris@0 100
Chris@0 101 /** @var \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver */
Chris@0 102 $controller_resolver = $container->get('controller_resolver');
Chris@0 103
Chris@0 104 /** @var callable $db_update_controller */
Chris@0 105 $db_update_controller = $controller_resolver->getControllerFromDefinition('\Drupal\system\Controller\DbUpdateController::handle');
Chris@0 106
Chris@0 107 $this->setupRequestMatch($request);
Chris@0 108
Chris@0 109 $arguments = $controller_resolver->getArguments($request, $db_update_controller);
Chris@0 110 return call_user_func_array($db_update_controller, $arguments);
Chris@0 111 }
Chris@0 112
Chris@0 113 /**
Chris@0 114 * Boots up the session.
Chris@0 115 *
Chris@0 116 * bootSession() + shutdownSession() basically simulates what
Chris@0 117 * \Drupal\Core\StackMiddleware\Session does.
Chris@0 118 *
Chris@0 119 * @param \Symfony\Component\HttpFoundation\Request $request
Chris@0 120 * The incoming request.
Chris@0 121 */
Chris@0 122 protected function bootSession(Request $request) {
Chris@0 123 $container = $this->getContainer();
Chris@0 124 /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */
Chris@0 125 $session = $container->get('session');
Chris@0 126 $session->start();
Chris@0 127 $request->setSession($session);
Chris@0 128 }
Chris@0 129
Chris@0 130 /**
Chris@0 131 * Ensures that the session is saved.
Chris@0 132 *
Chris@0 133 * @param \Symfony\Component\HttpFoundation\Request $request
Chris@0 134 * The incoming request.
Chris@0 135 */
Chris@0 136 protected function shutdownSession(Request $request) {
Chris@0 137 if ($request->hasSession()) {
Chris@0 138 $request->getSession()->save();
Chris@0 139 }
Chris@0 140 }
Chris@0 141
Chris@0 142 /**
Chris@0 143 * Set up the request with fake routing data for update.php.
Chris@0 144 *
Chris@0 145 * This fake routing data is needed in order to make batch API work properly.
Chris@0 146 *
Chris@0 147 * @param \Symfony\Component\HttpFoundation\Request $request
Chris@0 148 * The incoming request.
Chris@0 149 */
Chris@0 150 protected function setupRequestMatch(Request $request) {
Chris@0 151 $path = $request->getPathInfo();
Chris@0 152 $args = explode('/', ltrim($path, '/'));
Chris@0 153
Chris@0 154 $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'system.db_update');
Chris@0 155 $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $this->getContainer()->get('router.route_provider')->getRouteByName('system.db_update'));
Chris@0 156 $op = $args[0] ?: 'info';
Chris@0 157 $request->attributes->set('op', $op);
Chris@0 158 $request->attributes->set('_raw_variables', new ParameterBag(['op' => $op]));
Chris@0 159 }
Chris@0 160
Chris@0 161 /**
Chris@0 162 * Checks if the current user has rights to access updates page.
Chris@0 163 *
Chris@0 164 * If the current user does not have the rights, an exception is thrown.
Chris@0 165 *
Chris@0 166 * @param \Symfony\Component\HttpFoundation\Request $request
Chris@0 167 * The incoming request.
Chris@0 168 *
Chris@0 169 * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
Chris@0 170 * Thrown when update.php should not be accessible.
Chris@0 171 */
Chris@0 172 protected function handleAccess(Request $request) {
Chris@0 173 /** @var \Drupal\Core\Authentication\AuthenticationManager $authentication_manager */
Chris@0 174 $authentication_manager = $this->getContainer()->get('authentication');
Chris@0 175 $account = $authentication_manager->authenticate($request) ?: new AnonymousUserSession();
Chris@0 176
Chris@0 177 /** @var \Drupal\Core\Session\AccountProxyInterface $current_user */
Chris@0 178 $current_user = $this->getContainer()->get('current_user');
Chris@0 179 $current_user->setAccount($account);
Chris@0 180
Chris@0 181 /** @var \Drupal\system\Access\DbUpdateAccessCheck $db_update_access */
Chris@0 182 $db_update_access = $this->getContainer()->get('access_check.db_update');
Chris@0 183
Chris@0 184 if (!Settings::get('update_free_access', FALSE) && !$db_update_access->access($account)->isAllowed()) {
Chris@0 185 throw new AccessDeniedHttpException('In order to run update.php you need to either be logged in as admin or have set $settings[\'update_free_access\'] in your settings.php.');
Chris@0 186 }
Chris@0 187 }
Chris@0 188
Chris@0 189 }