diff --git a/core/lib/Drupal/Core/Update/UpdateKernel.php b/core/lib/Drupal/Core/Update/UpdateKernel.php new file mode 100644 index 0000000..5ae068c --- /dev/null +++ b/core/lib/Drupal/Core/Update/UpdateKernel.php @@ -0,0 +1,111 @@ +initializeSettings($request); + $this->boot(); + + $container = $this->getContainer(); + /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ + $request_stack = $container->get('request_stack'); + $request_stack->push($request); + + $this->preHandle($request); + $this->bootSession($request, $type); + $result = $this->handleRaw($request); + $this->shutdownSession($request); + + return $result; + } + catch (\Exception $e) { + return $this->handleException($e, $request, $type); + } + } + + protected function handleRaw(Request $request) { + + $container = $this->getContainer(); + /** @var \Drupal\Core\Authentication\AuthenticationManager $authentication_manager */ + $authentication_manager = $container->get('authentication'); + $account = $authentication_manager->authenticate($request) ?: new AnonymousUserSession(); + + /** @var \Drupal\system\Access\DbUpdateAccessCheck $db_update_access */ + $db_update_access = $container->get('access_check.db_update'); + + if (!$db_update_access->access($account) && !Settings::get('update_free_access', FALSE)) { + throw new AccessDeniedHttpException('In order to run update.php you need to either be logged in as admin or have set $update_free_access in your settings.php.'); + } + + /** @var \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver */ + $controller_resolver = $container->get('controller_resolver'); + + /** @var callable $db_update_controller */ + $db_update_controller = $controller_resolver->getControllerFromDefinition('\Drupal\system\Controller\DbUpdateController::handle'); + + $this->setupRequestMatch($request); + + $arguments = $controller_resolver->getArguments($request, $db_update_controller); + return call_user_func_array($db_update_controller, $arguments); + } + + /** + * @param \Symfony\Component\HttpFoundation\Request $request + * @param $type + */ + protected function bootSession(Request $request, $type) { + if ($type === self::MASTER_REQUEST && PHP_SAPI !== 'cli') { + $container = $this->getContainer(); + /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ + $session = $container->get('session'); + $session->start(); + $request->setSession($session); + } + } + + /** + */ + protected function setupRequestMatch(Request $request) { + $path = $request->getPathInfo(); + $args = explode('/', ltrim($path, '/')); + + $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'system.db_update'); + $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/update.php/{op}', ['op' => 'info'], ['_access' => 'TRUE'])); + $op = $args[0] ?: 'info'; + $request->attributes->set('op', $op); + $request->attributes->set('_raw_variables', new ParameterBag(['op' => $op])); + } + + protected function shutdownSession(Request $request) { + if ($request->hasSession()) { + $request->getSession()->save(); + } + } + +} diff --git a/core/modules/system/src/Controller/DbUpdateController.php b/core/modules/system/src/Controller/DbUpdateController.php index c2e195e..5fdbfee 100644 --- a/core/modules/system/src/Controller/DbUpdateController.php +++ b/core/modules/system/src/Controller/DbUpdateController.php @@ -166,7 +166,7 @@ public function handle($op, Request $request) { switch ($op) { case 'selection': $regions['sidebar_first'] = $this->updateTasksList('selection'); - $output = $this->selection(); + $output = $this->selection($request); break; case 'run': @@ -176,12 +176,12 @@ public function handle($op, Request $request) { case 'info': $regions['sidebar_first'] = $this->updateTasksList('info'); - $output = $this->info(); + $output = $this->info($request); break; case 'results': $regions['sidebar_first'] = $this->updateTasksList('results'); - $output = $this->results(); + $output = $this->results($request); break; // Regular batch ops : defer to batch processing API. @@ -207,7 +207,7 @@ public function handle($op, Request $request) { * @return array * A render array. */ - protected function info() { + protected function info(Request $request) { // Change query-strings on css/js files to enforce reload for all users. _drupal_flush_css_js(); // Flush the cache of all data for the update status module. @@ -233,12 +233,11 @@ protected function info() { '#markup' => '

' . $this->t('When you have performed the steps above, you may proceed.') . '

', ); - $url = new Url('system.db_update', array('op' => 'selection')); $build['link'] = array( '#type' => 'link', '#title' => $this->t('Continue'), '#attributes' => array('class' => array('button', 'button--primary')), - '#url' => $url, + '#url' => Url::fromUri($request->getUriForPath('/selection')), ); return $build; } @@ -246,10 +245,13 @@ protected function info() { /** * Renders a list of available database updates. * - * @return array - * A render array. + * @param \Symfony\Component\HttpFoundation\Request $request + * The request. + * + * @return array A render array. + * A render array. */ - protected function selection() { + protected function selection(Request $request) { // Make sure there is no stale theme registry. $this->cache->deleteAll(); @@ -342,7 +344,7 @@ protected function selection() { unset($build); $build['links'] = array( '#theme' => 'links', - '#links' => $this->helpfulLinks(), + '#links' => $this->helpfulLinks($request), ); // No updates to run, so caches won't get flushed later. Clear them now. @@ -364,7 +366,8 @@ protected function selection() { else { $build['start']['#title'] = $this->formatPlural($count, '1 pending update', '@count pending updates'); } - $url = new Url('system.db_update', array('op' => 'run')); + $base_url = str_replace('/update.php', '', $request->getBaseUrl()); + $url = (new Url('system.db_update', array('op' => 'run')))->setOption('base_url', $base_url); $build['link'] = array( '#type' => 'link', '#title' => $this->t('Apply pending updates'), @@ -380,10 +383,13 @@ protected function selection() { /** * Displays results of the update script with any accompanying errors. * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request. + * * @return array * A render array. */ - protected function results() { + protected function results(Request $request) { // Report end result. $dblog_exists = $this->moduleHandler->moduleExists('dblog'); if ($dblog_exists && $this->account->hasPermission('access site reports')) { @@ -420,7 +426,7 @@ protected function results() { ); $build['links'] = array( '#theme' => 'links', - '#links' => $this->helpfulLinks(), + '#links' => $this->helpfulLinks($request), ); // Output a list of info messages. @@ -603,7 +609,7 @@ protected function triggerBatch(Request $request) { ); batch_set($batch); - return batch_process('update.php/results', Url::fromRoute('system.db_update', array('op' => 'start'))); + return batch_process(Url::fromUri($request->getUriForPath('/results')), Url::fromUri($request->getUriForPath('/start'))); } /** @@ -640,18 +646,22 @@ public static function batchFinished($success, $results, $operations) { /** * Provides links to the homepage and administration pages. * - * @return array - * An array of links. + * @param \Symfony\Component\HttpFoundation\Request $request + * The request. + * + * @return array An array of links. + * An array of links. */ - protected function helpfulLinks() { + protected function helpfulLinks(Request $request) { + $base_url = str_replace('/update.php', '', $request->getBaseUrl()); $links['front'] = array( 'title' => $this->t('Front page'), - 'url' => Url::fromRoute(''), + 'url' => Url::fromRoute('')->setOption('base_url', $base_url), ); if ($this->account->hasPermission('access administration pages')) { $links['admin-pages'] = array( 'title' => $this->t('Administration pages'), - 'url' => Url::fromRoute('system.admin'), + 'url' => Url::fromRoute('system.admin')->setOption('base_url', $base_url), ); } return $links; diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml index a656ab3..9ef3720 100644 --- a/core/modules/system/system.routing.yml +++ b/core/modules/system/system.routing.yml @@ -451,13 +451,9 @@ system.batch_page.json: system.db_update: path: '/update.php/{op}' defaults: - _title: 'Drupal database update' - _controller: '\Drupal\system\Controller\DbUpdateController::handle' op: 'info' - options: - _maintenance_access: TRUE requirements: - _access_system_update: 'TRUE' + _access: 'TRUE' system.admin_content: path: '/admin/content' diff --git a/update.php b/update.php new file mode 100644 index 0000000..04125a3 --- /dev/null +++ b/update.php @@ -0,0 +1,14 @@ +handle($request); +$response->send(); + +$kernel->terminate($request, $response);