diff -upNr ./includes/install.inc ./includes/install.inc --- ./includes/install.inc 2009-07-23 14:07:05.300210950 -0500 +++ ./includes/install.inc 2009-07-23 01:27:17.983029301 -0500 @@ -421,9 +421,8 @@ function drupal_get_install_files($modul return $installs; } - /** - * Verify an install profile for installation. + * Verify that dependencies for a profile are installed * * @param $install_state * An array of information about the current installation state. @@ -431,17 +430,6 @@ function drupal_get_install_files($modul * The list of modules to install. */ function drupal_verify_profile($install_state) { - $profile = $install_state['parameters']['profile']; - $locale = $install_state['parameters']['locale']; - - include_once DRUPAL_ROOT . '/includes/file.inc'; - include_once DRUPAL_ROOT . '/includes/common.inc'; - - $profile_file = DRUPAL_ROOT . "/profiles/$profile/$profile.profile"; - - if (!isset($profile) || !file_exists($profile_file)) { - throw new Exception(install_no_profile_error()); - } $info = $install_state['profile_info']; // Get a list of modules that exist in Drupal's assorted subdirectories. @@ -451,23 +439,16 @@ function drupal_verify_profile($install_ } // Verify that all of the profile's required modules are present. + if (empty($info['dependencies'])) { + return array(); + } $missing_modules = array_diff($info['dependencies'], $present_modules); + return $missing_modules; +} - $requirements = array(); - - if (count($missing_modules)) { - $modules = array(); - foreach ($missing_modules as $module) { - $modules[] = '' . drupal_ucfirst($module) . ''; - } - $requirements['required_modules'] = array( - 'title' => st('Required modules'), - 'value' => st('Required modules not found.'), - 'severity' => REQUIREMENT_ERROR, - 'description' => st('The following modules are required but were not found. Please move them into the appropriate modules subdirectory, such as sites/all/modules. Missing modules: !modules', array('!modules' => implode(', ', $modules))), - ); - } - return $requirements; +function drupal_dependencies_met($install_state) { + $dependencies = drupal_verify_profile($install_state); + return empty($dependencies) ? TRUE : FALSE; } /** diff -upNr ./install.php ./install.php --- ./install.php 2009-07-23 14:07:05.188454226 -0500 +++ ./install.php 2009-07-23 13:54:45.548945362 -0500 @@ -534,6 +534,11 @@ function install_tasks($install_state) { 'install_verify_requirements' => array( 'display_name' => st('Verify requirements'), ), + 'install_dependencies' => array( + 'display_name' => st('Install Dependencies'), + 'type' => 'form', + 'run' => drupal_dependencies_met($install_state) ? INSTALL_TASK_SKIP : INSTALL_TASK_RUN_IF_NOT_COMPLETED, + ), 'install_settings_form' => array( 'display_name' => st('Set up database'), 'type' => 'form', @@ -694,9 +699,6 @@ function install_verify_requirements(&$i // Check the installation requirements for Drupal and this profile. $requirements = install_check_requirements($install_state); - // Verify existence of all required modules. - $requirements += drupal_verify_profile($install_state); - // Check the severity of the requirements reported. $severity = drupal_requirements_severity($requirements); @@ -1681,3 +1683,47 @@ if (realpath($_SERVER['SCRIPT_FILENAME'] // Start the installer. install_drupal(); } + +/** + * Instead of failing outright, allow the user to install dependencies. + * + * If any dependencies are unmet, list them. Then show the user the login form + * that is used by the update subsystem. After collecting it, install the + * missing dependencies. + * + * @param $install_state + * An array of information about the current installation state. This is + * passed along to each task, so it can be modified if necessary. + * @return + * A form to be displayed if dependencies are unmet. + */ +function install_dependencies(&$form_state, &$install_state) { + // Load the files needed to use the update functionality. + require_once DRUPAL_ROOT . '/modules/update/update.module'; + require_once DRUPAL_ROOT . '/modules/update/update.admin.inc'; + require_once DRUPAL_ROOT . '/includes/filetransfer/filetransfer.inc'; + require_once DRUPAL_ROOT . '/includes/filetransfer/ssh.inc'; + require_once DRUPAL_ROOT . '/includes/filetransfer/ftp.inc'; + drupal_set_title(st('Install Dependencies')); + + // Display the backend selection form. + $form = _update_update_form_backend_chooser(array()); + $form['#validate'] = array('update_update_form_validate', 'install_mark_dependencies'); + $form['#submit'] = array('update_update_form_submit'); + + $form['dependencies'] = array( + '#type' => 'value', + '#value' => drupal_verify_profile($install_state), + ); + + return $form; +} + +/** + * Inject the list of dependencies into the update form form_state. + */ +function install_mark_dependencies($form, &$form_state) { + // Get a list of all of the modules that need installation. We will + // use this later on to actually install the dependencies. + $form_state['storage']['projects'] = $form_state['values']['dependencies']; +} + \ No newline at end of file diff -upNr ./profiles/testing/testing.info ./profiles/testing/testing.info --- ./profiles/testing/testing.info 1969-12-31 18:00:00.000000000 -0600 +++ ./profiles/testing/testing.info 2009-07-23 01:27:37.614604269 -0500 @@ -0,0 +1,17 @@ +; $Id: default.info,v 1.1 2009/07/15 02:08:41 webchick Exp $ +name = Testing +description = Create a Drupal site with the most commonly used features pre-installed. +version = VERSION +core = 7.x +dependencies[] = block +dependencies[] = color +dependencies[] = comment +dependencies[] = help +dependencies[] = image +dependencies[] = menu +dependencies[] = path +dependencies[] = taxonomy +dependencies[] = dblog +dependencies[] = search +dependencies[] = toolbar +dependencies[] = cck diff -upNr ./profiles/testing/testing.profile ./profiles/testing/testing.profile --- ./profiles/testing/testing.profile 1969-12-31 18:00:00.000000000 -0600 +++ ./profiles/testing/testing.profile 2009-07-23 01:27:37.614604269 -0500 @@ -0,0 +1,204 @@ + array(), + ); + return $tasks; +} + +/** + * Installation task; perform actions to set up the site for this profile. + * + * This task does not return any output, meaning that control will be passed + * along to the next task without ending the page request. + * + * @param $install_state + * An array of information about the current installation state. + */ +function testing_profile_site_setup(&$install_state) { + + // Enable some standard blocks. + $values = array( + array( + 'module' => 'system', + 'delta' => 'main', + 'theme' => 'garland', + 'status' => 1, + 'weight' => 0, + 'region' => 'content', + 'pages' => '', + 'cache' => -1, + ), + array( + 'module' => 'user', + 'delta' => 'login', + 'theme' => 'garland', + 'status' => 1, + 'weight' => 0, + 'region' => 'left', + 'pages' => '', + 'cache' => -1, + ), + array( + 'module' => 'system', + 'delta' => 'navigation', + 'theme' => 'garland', + 'status' => 1, + 'weight' => 0, + 'region' => 'left', + 'pages' => '', + 'cache' => -1, + ), + array( + 'module' => 'system', + 'delta' => 'management', + 'theme' => 'garland', + 'status' => 1, + 'weight' => 1, + 'region' => 'left', + 'pages' => '', + 'cache' => -1, + ), + array( + 'module' => 'system', + 'delta' => 'powered-by', + 'theme' => 'garland', + 'status' => 1, + 'weight' => 10, + 'region' => 'footer', + 'pages' => '', + 'cache' => -1, + ), + array( + 'module' => 'system', + 'delta' => 'help', + 'theme' => 'garland', + 'status' => 1, + 'weight' => 0, + 'region' => 'help', + 'pages' => '', + 'cache' => -1, + ), + ); + $query = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache')); + foreach ($values as $record) { + $query->values($record); + } + $query->execute(); + + // Insert default user-defined node types into the database. For a complete + // list of available node type attributes, refer to the node type API + // documentation at: http://api.drupal.org/api/HEAD/function/hook_node_info. + $types = array( + array( + 'type' => 'page', + 'name' => st('Page'), + 'base' => 'node_content', + 'description' => st("Use pages for your static content, such as an 'About us' page."), + 'custom' => 1, + 'modified' => 1, + 'locked' => 0, + ), + array( + 'type' => 'article', + 'name' => st('Article'), + 'base' => 'node_content', + 'description' => st('Use articles for time-specific content like news, press releases or blog posts.'), + 'custom' => 1, + 'modified' => 1, + 'locked' => 0, + ), + ); + + foreach ($types as $type) { + $type = node_type_set_defaults($type); + node_type_save($type); + } + + // Default page to not be promoted and have comments disabled. + variable_set('node_options_page', array('status')); + variable_set('comment_page', COMMENT_NODE_HIDDEN); + + // Don't display date and author information for page nodes by default. + variable_set('node_submitted_page', FALSE); + + // Create an image style. + $style = array('name' => 'thumbnail'); + $style = image_style_save($style); + $effect = array( + 'isid' => $style['isid'], + 'name' => 'image_scale_and_crop', + 'data' => array('width' => '85', 'height' => '85'), + ); + image_effect_save($effect); + + // Enable user picture support and set the default to a square thumbnail option. + variable_set('user_pictures', '1'); + variable_set('user_picture_dimensions', '1024x1024'); + variable_set('user_picture_file_size', '800'); + variable_set('user_picture_style', 'thumbnail'); + + $theme_settings = theme_get_settings(); + $theme_settings['toggle_node_user_picture'] = '1'; + $theme_settings['toggle_comment_user_picture'] = '1'; + variable_set('theme_settings', $theme_settings); + + // Create a default vocabulary named "Tags", enabled for the 'article' content type. + $description = st('Use tags to group articles on similar topics into categories.'); + $help = st('Enter a comma-separated list of words.'); + + $vid = db_insert('taxonomy_vocabulary')->fields(array( + 'name' => 'Tags', + 'description' => $description, + 'machine_name' => 'tags', + 'help' => $help, + 'relations' => 0, + 'hierarchy' => 0, + 'multiple' => 0, + 'required' => 0, + 'tags' => 1, + 'module' => 'taxonomy', + 'weight' => 0, + ))->execute(); + db_insert('taxonomy_vocabulary_node_type')->fields(array('vid' => $vid, 'type' => 'article'))->execute(); + + // Create a default role for site administrators. + $rid = db_insert('role')->fields(array('name' => 'administrator'))->execute(); + + // Set this as the administrator role. + variable_set('user_admin_role', $rid); + + // Assign all available permissions to this role. + foreach (module_invoke_all('permission') as $key => $value) { + db_insert('role_permission') + ->fields(array( + 'rid' => $rid, + 'permission' => $key, + ))->execute(); + } + + // Update the menu router information. + menu_rebuild(); + + // Save some default links. + $link = array('link_path' => 'admin/structure/menu-customize/main-menu/add', 'link_title' => 'Add a main menu link', 'menu_name' => 'main-menu'); + menu_link_save($link); +} + +/** + * Implement hook_form_alter(). + * + * Allows the profile to alter the site-configuration form. This is + * called through custom invocation, so $form_state is not populated. + */ +function testing_form_alter(&$form, $form_state, $form_id) { + if ($form_id == 'install_configure') { + // Set default for site name field. + $form['site_information']['site_name']['#default_value'] = $_SERVER['SERVER_NAME']; + } +}