/** * Returns a system batch page. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return \Symfony\Component\HttpFoundation\Response|array * A \Symfony\Component\HttpFoundation\Response object or render array. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException */ public function batchPage(Request $request) { require_once $this->root . '/core/includes/batch.inc'; $output = _batch_page($request); if ($output === FALSE) { throw new AccessDeniedHttpException(); } elseif ($output instanceof Response) { return $output; } elseif (isset($output)) { $page = ['#type' => 'page', '#show_messages' => FALSE, 'content' => $output]; return $page; } }
/** * Returns a system batch page. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return mixed * A \Symfony\Component\HttpFoundation\Response object or page element or * NULL. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException */ public function batchPage(Request $request) { require_once DRUPAL_ROOT . '/core/includes/batch.inc'; $output = _batch_page($request); if ($output === FALSE) { throw new AccessDeniedHttpException(); } elseif ($output instanceof Response) { return $output; } elseif (isset($output)) { // Force a page without blocks or messages to // display a list of collected messages later. drupal_set_page_content($output); $page = element_info('page'); $page['#show_messages'] = FALSE; $page = $this->render($page); return $page; } }
/** * Tasks performed after the database is initialized. */ function install_tasks($profile, $task) { global $base_url, $install_locale; // Bootstrap newly installed Drupal, while preserving existing messages. $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : ''; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); $_SESSION['messages'] = $messages; // URL used to direct page requests. $url = $base_url . '/install.php?locale=' . $install_locale . '&profile=' . $profile; // Build a page for final tasks. if (empty($task)) { variable_set('install_task', 'profile-install'); $task = 'profile-install'; } // We are using a list of if constructs here to allow for // passing from one task to the other in the same request. // Install profile modules. if ($task == 'profile-install') { $modules = variable_get('install_profile_modules', array()); $files = module_rebuild_cache(); variable_del('install_profile_modules'); $operations = array(); foreach ($modules as $module) { $operations[] = array('_install_module_batch', array($module, $files[$module]->info['name'])); } $batch = array('operations' => $operations, 'finished' => '_install_profile_batch_finished', 'title' => st('Installing @drupal', array('@drupal' => drupal_install_profile_name())), 'error_message' => st('The installation has encountered an error.')); // Start a batch, switch to 'profile-install-batch' task. We need to // set the variable here, because batch_process() redirects. variable_set('install_task', 'profile-install-batch'); batch_set($batch); batch_process($url, $url); } // We are running a batch install of the profile's modules. // This might run in multiple HTTP requests, constantly redirecting // to the same address, until the batch finished callback is invoked // and the task advances to 'locale-initial-import'. if ($task == 'profile-install-batch') { include_once 'includes/batch.inc'; $output = _batch_page(); } // Import interface translations for the enabled modules. if ($task == 'locale-initial-import') { if (!empty($install_locale) && $install_locale != 'en') { include_once 'includes/locale.inc'; // Enable installation language as default site language. locale_add_language($install_locale, NULL, NULL, NULL, NULL, NULL, 1, TRUE); // Collect files to import for this language. $batch = locale_batch_by_language($install_locale, '_install_locale_initial_batch_finished'); if (!empty($batch)) { // Remember components we cover in this batch set. variable_set('install_locale_batch_components', $batch['#components']); // Start a batch, switch to 'locale-batch' task. We need to // set the variable here, because batch_process() redirects. variable_set('install_task', 'locale-initial-batch'); batch_set($batch); batch_process($url, $url); } } // Found nothing to import or not foreign language, go to next task. $task = 'configure'; } if ($task == 'locale-initial-batch') { include_once 'includes/batch.inc'; include_once 'includes/locale.inc'; $output = _batch_page(); } if ($task == 'configure') { if (variable_get('site_name', FALSE) || variable_get('site_mail', FALSE)) { // Site already configured: This should never happen, means re-running // the installer, possibly by an attacker after the 'install_task' variable // got accidentally blown somewhere. Stop it now. install_already_done_error(); } $form = drupal_get_form('install_configure_form', $url); if (!variable_get('site_name', FALSE) && !variable_get('site_mail', FALSE)) { // Not submitted yet: Prepare to display the form. $output = $form; drupal_set_title(st('Configure site')); // Warn about settings.php permissions risk $settings_dir = './' . conf_path(); $settings_file = $settings_dir . '/settings.php'; if (!drupal_verify_install_file($settings_file, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE) || !drupal_verify_install_file($settings_dir, FILE_NOT_WRITABLE, 'dir')) { drupal_set_message(st('All necessary changes to %dir and %file have been made, so you should remove write permissions to them now in order to avoid security risks. If you are unsure how to do so, please consult the <a href="@handbook_url">on-line handbook</a>.', array('%dir' => $settings_dir, '%file' => $settings_file, '@handbook_url' => 'http://drupal.org/getting-started')), 'error'); } else { drupal_set_message(st('All necessary changes to %dir and %file have been made. They have been set to read-only for security.', array('%dir' => $settings_dir, '%file' => $settings_file))); } // Add JavaScript validation. _user_password_dynamic_validation(); drupal_add_js(drupal_get_path('module', 'system') . '/system.js', 'module'); // We add these strings as settings because JavaScript translation does not // work on install time. drupal_add_js(array('copyFieldValue' => array('edit-site-mail' => array('edit-account-mail')), 'cleanURL' => array('success' => st('Your server has been successfully tested to support this feature.'), 'failure' => st('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.'), 'testing' => st('Testing clean URLs...'))), 'setting'); drupal_add_js(' // Global Killswitch if (Drupal.jsEnabled) { $(document).ready(function() { Drupal.cleanURLsInstallCheck(); Drupal.setDefaultTimezone(); }); }', 'inline'); // Build menu to allow clean URL check. menu_rebuild(); } else { $task = 'profile'; } } // If found an unknown task or the 'profile' task, which is // reserved for profiles, hand over the control to the profile, // so it can run any number of custom tasks it defines. if (!in_array($task, install_reserved_tasks())) { $function = $profile . '_profile_tasks'; if (function_exists($function)) { // The profile needs to run more code, maybe even more tasks. // $task is sent through as a reference and may be changed! $output = $function($task, $url); } // If the profile doesn't move on to a new task we assume // that it is done. if ($task == 'profile') { $task = 'profile-finished'; } } // Profile custom tasks are done, so let the installer regain // control and proceed with importing the remaining translations. if ($task == 'profile-finished') { if (!empty($install_locale) && $install_locale != 'en') { include_once 'includes/locale.inc'; // Collect files to import for this language. Skip components // already covered in the initial batch set. $batch = locale_batch_by_language($install_locale, '_install_locale_remaining_batch_finished', variable_get('install_locale_batch_components', array())); // Remove temporary variable. variable_del('install_locale_batch_components'); if (!empty($batch)) { // Start a batch, switch to 'locale-remaining-batch' task. We need to // set the variable here, because batch_process() redirects. variable_set('install_task', 'locale-remaining-batch'); batch_set($batch); batch_process($url, $url); } } // Found nothing to import or not foreign language, go to next task. $task = 'finished'; } if ($task == 'locale-remaining-batch') { include_once 'includes/batch.inc'; include_once 'includes/locale.inc'; $output = _batch_page(); } // Display a 'finished' page to user. if ($task == 'finished') { drupal_set_title(st('@drupal installation complete', array('@drupal' => drupal_install_profile_name()))); $messages = drupal_set_message(); $output = '<p>' . st('Congratulations, @drupal has been successfully installed.', array('@drupal' => drupal_install_profile_name())) . '</p>'; $output .= '<p>' . (isset($messages['error']) ? st('Please review the messages above before continuing on to <a href="@url">your new site</a>.', array('@url' => url(''))) : st('You may now visit <a href="@url">your new site</a>.', array('@url' => url('')))) . '</p>'; $task = 'done'; } // The end of the install process. Remember profile used. if ($task == 'done') { // Rebuild menu to get content type links registered by the profile, // and possibly any other menu items created through the tasks. menu_rebuild(); // Register actions declared by any modules. actions_synchronize(); // Randomize query-strings on css/js files, to hide the fact that // this is a new install, not upgraded yet. _drupal_flush_css_js(); variable_set('install_profile', $profile); } // Set task for user, and remember the task in the database. install_task_list($task); variable_set('install_task', $task); // Output page, if some output was required. Otherwise it is possible // that we are printing a JSON page and theme output should not be there. if (isset($output)) { print theme('maintenance_page', $output); } }
/** * Returns a database update page. * * @param string $op * The update operation to perform. Can be any of the below: * - info * - selection * - run * - results * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return \Symfony\Component\HttpFoundation\Response * A response object object. */ public function handle($op, Request $request) { require_once $this->root . '/core/includes/install.inc'; require_once $this->root . '/core/includes/update.inc'; drupal_load_updates(); update_fix_compatibility(); if ($request->query->get('continue')) { $_SESSION['update_ignore_warnings'] = TRUE; } $regions = array(); $requirements = update_check_requirements(); $severity = drupal_requirements_severity($requirements); if ($severity == REQUIREMENT_ERROR || $severity == REQUIREMENT_WARNING && empty($_SESSION['update_ignore_warnings'])) { $regions['sidebar_first'] = $this->updateTasksList('requirements'); $output = $this->requirements($severity, $requirements, $request); } else { switch ($op) { case 'selection': $regions['sidebar_first'] = $this->updateTasksList('selection'); $output = $this->selection($request); break; case 'run': $regions['sidebar_first'] = $this->updateTasksList('run'); $output = $this->triggerBatch($request); break; case 'info': $regions['sidebar_first'] = $this->updateTasksList('info'); $output = $this->info($request); break; case 'results': $regions['sidebar_first'] = $this->updateTasksList('results'); $output = $this->results($request); break; // Regular batch ops : defer to batch processing API. // Regular batch ops : defer to batch processing API. default: require_once $this->root . '/core/includes/batch.inc'; $regions['sidebar_first'] = $this->updateTasksList('run'); $output = _batch_page($request); break; } } if ($output instanceof Response) { return $output; } $title = isset($output['#title']) ? $output['#title'] : $this->t('Drupal database update'); return $this->bareHtmlPageRenderer->renderBarePage($output, $title, 'maintenance_page', $regions); }
case 'selection': if (isset($_GET['token']) && $_GET['token'] == drupal_get_token('update')) { $output = update_selection_page(); break; } case 'Apply pending updates': if (isset($_GET['token']) && $_GET['token'] == drupal_get_token('update')) { update_batch(); break; } case 'info': $output = update_info_page(); break; case 'results': $output = update_results_page(); break; // Regular batch ops : defer to batch processing API // Regular batch ops : defer to batch processing API default: update_task_list('run'); $output = _batch_page(); break; } } else { $output = update_access_denied_page(); } if (isset($output) && $output) { // We defer the display of messages until all updates are done. $progress_page = ($batch = batch_get()) && isset($batch['running']); print theme('update_page', $output, !$progress_page); }
/** * Run an individual installation task. * * @param $task * An array of information about the task to be run. * @param $install_state * An array of information about the current installation state. This is * passed in by reference so that it can be modified by the task. * @return * The output of the task function, if there is any. */ function install_run_task($task, &$install_state) { $function = $task['function']; if ($task['type'] == 'form') { require_once DRUPAL_ROOT . '/includes/form.inc'; if ($install_state['interactive']) { // For interactive forms, build the form and ensure that it will not // redirect, since the installer handles its own redirection only after // marking the form submission task complete. $form_state = array('args' => array(&$install_state), 'no_redirect' => TRUE); $form = drupal_build_form($function, $form_state); // If a successful form submission did not occur, the form needs to be // rendered, which means the task is not complete yet. if (empty($form_state['executed'])) { $install_state['task_not_complete'] = TRUE; return drupal_render($form); } // Otherwise, return nothing so the next task will run in the same // request. return; } else { // For non-interactive forms, submit the form programmatically with the // values taken from the installation state. Throw an exception if any // errors were encountered. $form_state = array('values' => !empty($install_state['forms'][$function]) ? $install_state['forms'][$function] : array()); drupal_form_submit($function, $form_state, $install_state); $errors = form_get_errors(); if (!empty($errors)) { throw new Exception(implode("\n", $errors)); } } } elseif ($task['type'] == 'batch') { // Start a new batch based on the task function, if one is not running // already. $current_batch = variable_get('install_current_batch'); if (!$install_state['interactive'] || !$current_batch) { $batch = $function($install_state); if (empty($batch)) { // If the task did some processing and decided no batch was necessary, // there is nothing more to do here. return; } batch_set($batch); // For interactive batches, we need to store the fact that this batch // task is currently running. Otherwise, we need to make sure the batch // will complete in one page request. if ($install_state['interactive']) { variable_set('install_current_batch', $function); } else { $batch =& batch_get(); $batch['progressive'] = FALSE; } // Process the batch. For progressive batches, this will redirect. // Otherwise, the batch will complete. batch_process(install_redirect_url($install_state), install_full_redirect_url($install_state)); } elseif ($current_batch == $function) { include_once DRUPAL_ROOT . '/includes/batch.inc'; $output = _batch_page(); // The task is complete when we try to access the batch page and receive // FALSE in return, since this means we are at a URL where we are no // longer requesting a batch ID. if ($output === FALSE) { // Return nothing so the next task will run in the same request. variable_del('install_current_batch'); return; } else { // We need to force the page request to end if the task is not // complete, since the batch API sometimes prints JSON output // rather than returning a themed page. $install_state['task_not_complete'] = $install_state['stop_page_request'] = TRUE; return $output; } } } else { // For normal tasks, just return the function result, whatever it is. return $function($install_state); } }
} if (!empty($results['page_message'])) { drupal_set_message($results['page_message']['message'], $results['page_message']['type']); } $authorize_report = array('#theme' => 'authorize_report', '#messages' => $results['messages']); $output = drupal_render_root($authorize_report); $links = array(); if (is_array($results['tasks'])) { $links += $results['tasks']; } else { $links = array_merge($links, array(\Drupal::l(t('Administration pages'), new Url('system.admin')), \Drupal::l(t('Front page'), new Url('<front>')))); } $item_list = array('#theme' => 'item_list', '#items' => $links, '#title' => t('Next steps')); $output .= drupal_render_root($item_list); } elseif ($request->query->has('batch')) { $output = _batch_page($request); } else { if (empty($_SESSION['authorize_operation']) || empty($_SESSION['authorize_filetransfer_info'])) { $output = t('It appears you have reached this page in error.'); } elseif (!($batch = batch_get())) { // We have a batch to process, show the filetransfer form. $elements = \Drupal::formBuilder()->getForm('Drupal\\Core\\FileTransfer\\Form\\FileTransferAuthorizeForm'); $output = drupal_render_root($elements); } } // We defer the display of messages until all operations are done. $show_messages = !(($batch = batch_get()) && isset($batch['running'])); } else { $response->setStatusCode(403); \Drupal::logger('access denied')->warning('authorize.php'); $page_title = t('Access denied');
drupal_set_message($results['page_message']['message'], $results['page_message']['type']); } $content['authorize_report'] = array('#theme' => 'authorize_report', '#messages' => $results['messages']); if (is_array($results['tasks'])) { $links = $results['tasks']; } else { // Since this is being called outsite of the primary front controller, // the base_url needs to be set explicitly to ensure that links are // relative to the site root. // @todo Simplify with https://www.drupal.org/node/2548095 $default_options = ['#type' => 'link', '#options' => ['absolute' => TRUE, 'base_url' => $GLOBALS['base_url']]]; $links = [$default_options + ['#url' => Url::fromRoute('system.admin'), '#title' => t('Administration pages')], $default_options + ['#url' => Url::fromRoute('<front>'), '#title' => t('Front page')]]; } $content['next_steps'] = array('#theme' => 'item_list', '#items' => $links, '#title' => t('Next steps')); } elseif ($request->query->has('batch')) { $content = _batch_page($request); // If _batch_page() returns a response object (likely a JsonResponse for // JavaScript-based batch processing), send it immediately. if ($content instanceof Response) { $content->send(); exit; } } else { if (empty($_SESSION['authorize_operation']) || empty($_SESSION['authorize_filetransfer_info'])) { $content = ['#markup' => t('It appears you have reached this page in error.')]; } elseif (!($batch = batch_get())) { // We have a batch to process, show the filetransfer form. $content = \Drupal::formBuilder()->getForm('Drupal\\Core\\FileTransfer\\Form\\FileTransferAuthorizeForm'); } } // We defer the display of messages until all operations are done.
if (!empty($results['page_title'])) { $page_title = $results['page_title']; } if (!empty($results['page_message'])) { drupal_set_message($results['page_message']['message'], $results['page_message']['type']); } $content['authorize_report'] = array('#theme' => 'authorize_report', '#messages' => $results['messages']); $links = array(); if (is_array($results['tasks'])) { $links += $results['tasks']; } else { $links = array_merge($links, array(\Drupal::l(t('Administration pages'), new Url('system.admin')), \Drupal::l(t('Front page'), new Url('<front>')))); } $content['next_steps'] = array('#theme' => 'item_list', '#items' => $links, '#title' => t('Next steps')); } elseif ($request->query->has('batch')) { $content = ['#markup' => _batch_page($request)]; } else { if (empty($_SESSION['authorize_operation']) || empty($_SESSION['authorize_filetransfer_info'])) { $content = ['#markup' => t('It appears you have reached this page in error.')]; } elseif (!($batch = batch_get())) { // We have a batch to process, show the filetransfer form. $content = \Drupal::formBuilder()->getForm('Drupal\\Core\\FileTransfer\\Form\\FileTransferAuthorizeForm'); } } // We defer the display of messages until all operations are done. $show_messages = !(($batch = batch_get()) && isset($batch['running'])); } else { \Drupal::logger('access denied')->warning('authorize.php'); $page_title = t('Access denied'); $content = ['#markup' => t('You are not allowed to access this page.')]; }