Index: modules/system/system.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v retrieving revision 1.158 diff -u -p -r1.158 system.admin.inc --- modules/system/system.admin.inc 19 Jun 2009 20:35:05 -0000 1.158 +++ modules/system/system.admin.inc 26 Jun 2009 02:18:58 -0000 @@ -1082,6 +1082,174 @@ function system_modules_uninstall_submit } /** + * Menu callback for the module/theme installer. + */ +function system_installer() { + $errors = array(); + $data_set = array(); + + $modules = empty($_GET['modules']) ? array() : $_GET['modules']; + $existing_modules = system_get_module_data(); + $md5s = empty($_GET['md5s']) ? array() : $_GET['md5s']; + list($errors['modules'], $data_set['modules']) = _system_installer_data($modules, $existing_modules, $md5s, 'module'); + + $themes = empty($_GET['themes']) ? array() : $_GET['themes']; + $existing_themes = system_get_theme_data(); + list($errors['themes'], $data_set['themes']) = _system_installer_data($themes, $existing_themes, $md5s, 'theme'); + + if (empty($data_set['modules']) && empty($data_set['themes'])) { + $errors['modules'][0][] = t('You must choose at least one module or theme.'); + } + + foreach ($errors as $type => $objects) { + foreach ($objects as $name => $error_set) { + foreach ($error_set as $error) { + drupal_set_message($error, 'error'); + } + } + } + return drupal_get_form('system_installer_form', $data_set, $errors); +} + +function _system_installer_data($plugins, $existing_plugins, $md5s, $type) { + foreach ($plugins as $plugin => $release) { + if (isset($existing_plugins[$plugin])) { + $errors[$plugin]['install'] = t('The %plugin @type is already available on the @types page.', array('%plugin' => $existing_plugins[$plugin]->info['name'], '@url' => url('admin/build/' . $type .'s'), '@type' => $type)); + $data_set[$plugin] = array(array('title' => $existing_plugins[$plugin]->info['name']), $existing_plugins[$plugin]->info['version']); + } + else { + $project = array( + 'name' => $plugin, + 'info' => array( + 'version' => $release, + ), + ); + drupal_function_exists('_update_build_fetch_url'); + $url = _update_build_fetch_url($project); + $result = drupal_http_request($url); + $data = @update_parse_xml(array($result->data)); + if (empty($data[$plugin]) || empty($data[$plugin]['releases']) || empty($data[$plugin]['releases'][$release])) { + $errors[$plugin]['invalid'] = t('Could not find the %plugin @type.', array('%plugin' => $plugin, '@type' => $type)); + $data_set[$plugin] = array(array('title' => $plugin), $release); + continue; + } + else { + $data_set[$plugin] = array($data[$plugin], $release); + } + $mdhash = isset($data[$plugin]['releases'][$release]['mdhash']) ? $data[$plugin]['releases'][$release]['mdhash'] : FALSE; + if (!isset($md5s[$plugin]) || !$mdhash) { + $errors[$plugin]['md5'] = t('No md5 checksum was provided for %plugin.', array('%plugin' => $data[$plugin]['title'])); + } + elseif ($mdhash != $md5s[$plugin]) { + $errors[$plugin]['md5'] = t('Incorrect md5 checksum was provided for %plugin.', array('%plugin' => $data[$plugin]['title'])); + } + } + } + + return array($errors, $data_set); +} + +/** + * Forms API callback for the installer page. + */ +function system_installer_form($form_state, $data_set, $errors) { + $form = array(); + + $form['data'] = array( + '#type' => 'value', + '#value' => $data_set, + ); + + $form['#errors'] = $errors; + + foreach (array('themes', 'modules') as $type) { + if (!empty($data_set[$type])) { + foreach ($data_set[$type] as $plugin => $data) { + $form[$type][$plugin] = array('#tree' => TRUE); + if (isset($errors[$type][$plugin])) { + // Set the "fetch" element to FALSE because an error occurred and the + // module or theme should not be installed. + $form[$type][$plugin]['fetch'] = array( + '#type' => 'value', + '#value' => FALSE, + ); + $form[$type][$plugin]['error'] = array( + '#markup' => theme('image', 'misc/watchdog-error.png'), + ); + } + else { + $form[$type][$plugin]['fetch'] = array( + '#type' => 'checkbox', + '#default_value' => TRUE, + ); + } + } + } + } + + // @TODO: Create a reusable function to create a list of radios/settings for + // individual backends that can be used both for this form and the update + // form. + $form['file_transfer'] = array(); + + $form['install'] = array( + '#type' => 'submit', + '#value' => t('Install'), + ); + + return $form; +} + +/** + * Theming callback for system_installer_form(). + */ +function theme_system_installer_form($form) { + $output = ''; + + $output .= '
' . t('The following modules and themes are about to be installed on the site. Please take a moment to look this over and make sure everything is correct.') . '
'; + + $data_set = $form['data']['#value']; + $errors = $form['#errors']; + + foreach (array('modules', 'themes') as $type) { + if (!empty($data_set['modules'])) { + $title = ($type == 'modules' ? t('Modules') : t('Themes')); + $output .= '