$schema_version) { if ($schema_version > -1) { module_load_install($module); } } } /** * Returns an array of available schema versions for a module. * * @param $module * A module name. * @return * If the module has updates, an array of available updates sorted by version. * Otherwise, FALSE. */ function drupal_get_schema_versions($module) { $updates = array(); $functions = get_defined_functions(); foreach ($functions['user'] as $function) { if (strpos($function, $module . '_update_') === 0) { $version = substr($function, strlen($module . '_update_')); if (is_numeric($version)) { $updates[] = $version; } } } if (count($updates) == 0) { return FALSE; } // Make sure updates are run in numeric order, not in definition order. sort($updates, SORT_NUMERIC); return $updates; } /** * Returns the currently installed schema version for a module. * * @param $module * A module name. * @param $reset * Set to TRUE after modifying the system table. * @param $array * Set to TRUE if you want to get information about all modules in the * system. * @return * The currently installed schema version. */ function drupal_get_installed_schema_version($module, $reset = FALSE, $array = FALSE) { static $versions = array(); if ($reset) { $versions = array(); } if (!$versions) { $versions = array(); $result = db_query("SELECT name, schema_version FROM {system} WHERE type = :type", array(':type' => 'module')); foreach ($result as $row) { $versions[$row->name] = $row->schema_version; } } return $array ? $versions : $versions[$module]; } /** * Update the installed version information for a module. * * @param $module * A module name. * @param $version * The new schema version. */ function drupal_set_installed_schema_version($module, $version) { db_update('system') ->fields(array('schema_version' => $version)) ->condition('name', $module) ->execute(); } /** * Loads the install profile definition, extracting its defined name. * * @return * The name defined in the profile's _profile_details() hook. */ function drupal_install_profile_name() { global $install_state; $profile = $install_state['parameters']['profile']; static $name = NULL; if (!isset($name)) { // Load profile details. $function = $profile . '_profile_details'; if (function_exists($function)) { $details = $function(); } $name = isset($details['name']) ? $details['name'] : 'Drupal'; } return $name; } /** * Auto detect the base_url with PHP predefined variables. * * @param $file * The name of the file calling this function so we can strip it out of * the URI when generating the base_url. * @return * The auto-detected $base_url that should be configured in settings.php */ function drupal_detect_baseurl($file = 'install.php') { $proto = $_SERVER['HTTPS'] ? 'https://' : 'http://'; $host = $_SERVER['SERVER_NAME']; $port = ($_SERVER['SERVER_PORT'] == 80 ? '' : ':' . $_SERVER['SERVER_PORT']); $uri = preg_replace("/\?.*/", '', $_SERVER['REQUEST_URI']); $dir = str_replace("/$file", '', $uri); return "$proto$host$port$dir"; } /** * Detect all supported databases that are compiled into PHP. * * @return * An array of database types compiled into PHP. */ function drupal_detect_database_types() { $databases = array(); // We define a driver as a directory in /includes/database that in turn // contains a database.inc file. That allows us to drop in additional drivers // without modifying the installer. // Because we have no registry yet, we need to also include the install.inc // file for the driver explicitly. require_once DRUPAL_ROOT . '/includes/database/database.inc'; foreach (file_scan_directory(DRUPAL_ROOT . '/includes/database', '/^[a-z]*$/i', array('recurse' => FALSE)) as $file) { include_once "{$file->filepath}/install.inc"; include_once "{$file->filepath}/database.inc"; $drivers[$file->filename] = $file->filepath; } foreach ($drivers as $driver => $file) { $class = 'DatabaseTasks_' . $driver; $installer = new $class(); if ($installer->installable()) { $databases[$driver] = $installer->name(); } } // Usability: unconditionally put the MySQL driver on top. if (isset($databases['mysql'])) { $mysql_database = $databases['mysql']; unset($databases['mysql']); $databases = array('mysql' => $mysql_database) + $databases; } return $databases; } /** * Database installer structure. * * Defines basic Drupal requirements for databases. */ abstract class DatabaseTasks { /** * Structure that describes each task to run. * * @var array * * Each value of the tasks array is an associative array defining the function * to call (optional) and any arguments to be passed to the function. */ protected $tasks = array( array( 'arguments' => array( 'CREATE TABLE drupal_install_test (id int NULL)', 'Drupal can use CREATE TABLE database commands.', 'Failed to CREATE a test table on your %name database server with the command %query. %name reports the following message: %error.

Are you sure the configured username has the necessary %name permissions to create tables in the database?

', TRUE, ), ), array( 'arguments' => array( 'INSERT INTO drupal_install_test (id) VALUES (1)', 'Drupal can use INSERT database commands.', 'Failed to INSERT a value into a test table on your %name database server. We tried inserting a value with the command %query and %name reported the following error: %error.', ), ), array( 'arguments' => array( 'UPDATE drupal_install_test SET id = 2', 'Drupal can use UPDATE database commands.', 'Failed to UPDATE a value in a test table on your %name database server. We tried updating a value with the command %query and %name reported the following error: %error.', ), ), array( 'arguments' => array( 'DELETE FROM drupal_install_test', 'Drupal can use DELETE database commands.', 'Failed to DELETE a value from a test table on your %name database server. We tried deleting a value with the command %query and %name reported the following error: %error.', ), ), array( 'arguments' => array( 'DROP TABLE drupal_install_test', 'Drupal can use DROP TABLE database commands.', 'Failed to DROP a test table from your %name database server. We tried dropping a table with the command %query and %name reported the following error %error.', ), ), ); /** * Results from tasks. * * @var array */ protected $results = array(); /** * Ensure the PDO driver is supported by the version of PHP in use. */ protected function hasPdoDriver() { return in_array($this->pdoDriver, PDO::getAvailableDrivers()); } /** * Assert test as failed. */ protected function fail($message) { $this->results[$message] = FALSE; } /** * Assert test as a pass. */ protected function pass($message) { $this->results[$message] = TRUE; } /** * Check whether Drupal is installable on the database. */ public function installable() { return $this->hasPdoDriver() && empty($this->error); } abstract public function name(); /** * Run database tasks and tests to see if Drupal can run on the database. */ public function runTasks() { // We need to establish a connection before we can run tests. if ($this->connect()) { foreach ($this->tasks as $task) { if (!isset($task['function'])) { $task['function'] = 'runTestQuery'; } if (method_exists($this, $task['function'])) { // Returning false is fatal. No other tasks can run. if (FALSE === call_user_func_array(array($this, $task['function']), $task['arguments'])) { break; } } else { throw new DatabaseTaskException(st("Failed to run all tasks against the database server. The task %task wasn't found.", array('%task' => $task['function']))); } } } // Check for failed results and compile message $message = ''; foreach ($this->results as $result => $success) { if (!$success) { $message .= '

' . $result . '

'; } } if (!empty($message)) { $message = '

In order for Drupal to work, and to continue with the installation process, you must resolve all issues reported below. For more help with configuring your database server, see the Installation and upgrading handbook. If you are unsure what any of this means you should probably contact your hosting provider.

' . $message; throw new DatabaseTaskException($message); } } /** * Check if we can connect to the database. */ protected function connect() { try { // This doesn't actually test the connection. db_set_active(); // Now actually do a check. Database::getConnection(); $this->pass('Drupal can CONNECT to the database ok.'); } catch (Exception $e) { $this->fail(st('Failed to connect to your %name database server. %name reports the following message: %error.For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => $e->getMessage(), '%name' => $this->name()))); return FALSE; } return TRUE; } /** * Run SQL tests to ensure the database can execute commands with the current user. */ protected function runTestQuery($query, $pass, $fail, $fatal = FALSE) { try { db_query($query); $this->pass(st($pass)); } catch (Exception $e) { $this->fail(st($fail, array('%query' => $query, '%error' => $e->getMessage(), '%name' => $this->name()))); return !$fatal; } } } /** * @class Exception class used to throw error if the DatabaseInstaller fails. */ class DatabaseTaskException extends Exception { } /** * Replace values in settings.php with values in the submitted array. * * @param $settings * An array of settings that need to be updated. */ function drupal_rewrite_settings($settings = array(), $prefix = '') { $default_settings = 'sites/default/default.settings.php'; drupal_static_reset('conf_path'); $settings_file = conf_path(FALSE) . '/' . $prefix . 'settings.php'; // Build list of setting names and insert the values into the global namespace. $keys = array(); foreach ($settings as $setting => $data) { $GLOBALS[$setting] = $data['value']; $keys[] = $setting; } $buffer = NULL; $first = TRUE; if ($fp = fopen(DRUPAL_ROOT . '/' . $default_settings, 'r')) { // Step line by line through settings.php. while (!feof($fp)) { $line = fgets($fp); if ($first && substr($line, 0, 5) != ' $data) { if ($data['required']) { $buffer .= "\$$setting = " . var_export($data['value'], TRUE) . ";\n"; } } $fp = fopen(DRUPAL_ROOT . '/' . $settings_file, 'w'); if ($fp && fwrite($fp, $buffer) === FALSE) { throw new Exception(st('Failed to modify %settings, please verify the file permissions.', array('%settings' => $settings_file))); } } else { throw new Exception(st('Failed to open %settings, please verify the file permissions.', array('%settings' => $default_settings))); } } /** * Get list of all .install files. * * @param $module_list * An array of modules to search for their .install files. */ function drupal_get_install_files($module_list = array()) { $installs = array(); foreach ($module_list as $module) { $installs = array_merge($installs, drupal_system_listing('/' . $module . '.install$/', 'modules')); } return $installs; } /** * Verify an install profile for installation. * * @param $install_state * An array of information about the current installation state. * @return * 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. $present_modules = array(); foreach (drupal_system_listing('/\.module$/', 'modules', 'name', 0) as $present_module) { $present_modules[] = $present_module->name; } // Verify that all of the profile's required modules are present. $missing_modules = array_diff($info['dependencies'], $present_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; } /** * Calls the install function for a given list of modules. * * @param $module_list * The modules to install. * @param $disable_modules_installed_hook * Normally just testing wants to set this to TRUE. */ function drupal_install_modules($module_list = array(), $disable_modules_installed_hook = FALSE) { $files = system_get_module_data(); $module_list = array_flip(array_values($module_list)); do { $moved = FALSE; foreach ($module_list as $module => $weight) { $file = $files[$module]; if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) { foreach ($file->info['dependencies'] as $dependency) { if (isset($module_list[$dependency]) && $module_list[$module] < $module_list[$dependency] +1) { $module_list[$module] = $module_list[$dependency] +1; $moved = TRUE; } } } } } while ($moved); asort($module_list); $module_list = array_keys($module_list); module_enable($module_list, $disable_modules_installed_hook); } /** * Callback to install an individual install profile module. * * Used during installation to install modules one at a time and then * enable them, or to install a number of modules at one time * from admin/config/modules. * * @param $module * The machine name of the module to install. * @return * TRUE if the module got installed. */ function _drupal_install_module($module) { if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) { module_load_install($module); drupal_load('module', $module); module_invoke($module, 'install'); $versions = drupal_get_schema_versions($module); drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED); return TRUE; } } /** * Manually include all files for the active database. * * Because we have no registry yet, we need to manually include the * necessary database include files. */ function drupal_install_initialize_database() { static $included = FALSE; if (!$included) { $connection_info = Database::getConnectionInfo(); $driver = $connection_info['default']['driver']; require_once DRUPAL_ROOT . '/includes/database/query.inc'; require_once DRUPAL_ROOT . '/includes/database/select.inc'; require_once DRUPAL_ROOT . '/includes/database/schema.inc'; foreach (glob(DRUPAL_ROOT . '/includes/database/' . $driver . '/*.inc') as $include_file) { require_once $include_file; } $included = TRUE; } } /** * Callback to install the system module. * * Separated from the installation of other modules so core system * functions can be made available while other modules are installed. */ function drupal_install_system() { $system_path = dirname(drupal_get_filename('module', 'system', NULL)); require_once DRUPAL_ROOT . '/' . $system_path . '/system.install'; drupal_install_initialize_database(); module_invoke('system', 'install'); $system_versions = drupal_get_schema_versions('system'); $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; db_insert('system') ->fields(array('filename', 'name', 'type', 'owner', 'status', 'schema_version')) ->values(array( 'filename' => $system_path . '/system.module', 'name' => 'system', 'type' => 'module', 'owner' => '', 'status' => 1, 'schema_version' => $system_version )) ->execute(); // Now that we've installed things properly, bootstrap the full Drupal environment drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); system_get_module_data(); } /** * Calls the uninstall function and updates the system table for a given module. * * @param $module_list * The modules to uninstall. */ function drupal_uninstall_modules($module_list = array()) { foreach ($module_list as $module) { // First, retrieve all the module's menu paths from db. drupal_load('module', $module); $paths = module_invoke($module, 'menu'); // Uninstall the module. module_load_install($module); module_invoke($module, 'uninstall'); watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO); // Now remove the menu links for all paths declared by this module. if (!empty($paths)) { $paths = array_keys($paths); // Clean out the names of load functions. foreach ($paths as $index => $path) { $parts = explode('/', $path, MENU_MAX_PARTS); foreach ($parts as $k => $part) { if (preg_match('/^%[a-z_]*$/', $part)) { $parts[$k] = '%'; } } $paths[$index] = implode('/', $parts); } $result = db_select('menu_links') ->fields('menu_links') ->condition('router_path', $paths, 'IN') ->condition('external', 0) ->orderBy('depth') ->execute(); // Remove all such items. Starting from those with the greatest depth will // minimize the amount of re-parenting done by menu_link_delete(). foreach ($result as $item) { _menu_delete_item($item, TRUE); } } drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED); } if (!empty($module_list)) { // Call hook_module_uninstall to let other modules act module_invoke_all('modules_uninstalled', $module_list); } } /** * Verify the state of the specified file. * * @param $file * The file to check for. * @param $mask * An optional bitmask created from various FILE_* constants. * @param $type * The type of file. Can be file (default), dir, or link. * @return * TRUE on success or FALSE on failure. A message is set for the latter. */ function drupal_verify_install_file($file, $mask = NULL, $type = 'file') { $return = TRUE; // Check for files that shouldn't be there. if (isset($mask) && ($mask & FILE_NOT_EXIST) && file_exists($file)) { return FALSE; } // Verify that the file is the type of file it is supposed to be. if (isset($type) && file_exists($file)) { $check = 'is_' . $type; if (!function_exists($check) || !$check($file)) { $return = FALSE; } } // Verify file permissions. if (isset($mask)) { $masks = array(FILE_EXIST, FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); foreach ($masks as $current_mask) { if ($mask & $current_mask) { switch ($current_mask) { case FILE_EXIST: if (!file_exists($file)) { if ($type == 'dir') { drupal_install_mkdir($file, $mask); } if (!file_exists($file)) { $return = FALSE; } } break; case FILE_READABLE: if (!is_readable($file) && !drupal_install_fix_file($file, $mask)) { $return = FALSE; } break; case FILE_WRITABLE: if (!is_writable($file) && !drupal_install_fix_file($file, $mask)) { $return = FALSE; } break; case FILE_EXECUTABLE: if (!is_executable($file) && !drupal_install_fix_file($file, $mask)) { $return = FALSE; } break; case FILE_NOT_READABLE: if (is_readable($file) && !drupal_install_fix_file($file, $mask)) { $return = FALSE; } break; case FILE_NOT_WRITABLE: if (is_writable($file) && !drupal_install_fix_file($file, $mask)) { $return = FALSE; } break; case FILE_NOT_EXECUTABLE: if (is_executable($file) && !drupal_install_fix_file($file, $mask)) { $return = FALSE; } break; } } } } return $return; } /** * Create a directory with specified permissions. * * @param $file * The name of the directory to create; * @param $mask * The permissions of the directory to create. * @param $message * (optional) Whether to output messages. Defaults to TRUE. * @return * TRUE/FALSE whether or not the directory was successfully created. */ function drupal_install_mkdir($file, $mask, $message = TRUE) { $mod = 0; $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); foreach ($masks as $m) { if ($mask & $m) { switch ($m) { case FILE_READABLE: $mod += 444; break; case FILE_WRITABLE: $mod += 222; break; case FILE_EXECUTABLE: $mod += 111; break; } } } if (@mkdir($file, intval("0$mod", 8))) { return TRUE; } else { return FALSE; } } /** * Attempt to fix file permissions. * * The general approach here is that, because we do not know the security * setup of the webserver, we apply our permission changes to all three * digits of the file permission (i.e. user, group and all). * * To ensure that the values behave as expected (and numbers don't carry * from one digit to the next) we do the calculation on the octal value * using bitwise operations. This lets us remove, for example, 0222 from * 0700 and get the correct value of 0500. * * @param $file * The name of the file with permissions to fix. * @param $mask * The desired permissions for the file. * @param $message * (optional) Whether to output messages. Defaults to TRUE. * @return * TRUE/FALSE whether or not we were able to fix the file's permissions. */ function drupal_install_fix_file($file, $mask, $message = TRUE) { // If $file does not exist, fileperms() issues a PHP warning. if (!file_exists($file)) { return FALSE; } $mod = fileperms($file) & 0777; $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); // FILE_READABLE, FILE_WRITABLE, and FILE_EXECUTABLE permission strings // can theoretically be 0400, 0200, and 0100 respectively, but to be safe // we set all three access types in case the administrator intends to // change the owner of settings.php after installation. foreach ($masks as $m) { if ($mask & $m) { switch ($m) { case FILE_READABLE: if (!is_readable($file)) { $mod |= 0444; } break; case FILE_WRITABLE: if (!is_writable($file)) { $mod |= 0222; } break; case FILE_EXECUTABLE: if (!is_executable($file)) { $mod |= 0111; } break; case FILE_NOT_READABLE: if (is_readable($file)) { $mod &= ~0444; } break; case FILE_NOT_WRITABLE: if (is_writable($file)) { $mod &= ~0222; } break; case FILE_NOT_EXECUTABLE: if (is_executable($file)) { $mod &= ~0111; } break; } } } // chmod() will work if the web server is running as owner of the file. // If PHP safe_mode is enabled the currently executing script must also // have the same owner. if (@chmod($file, $mod)) { return TRUE; } else { return FALSE; } } /** * Send the user to a different installer page. * * This issues an on-site HTTP redirect. Messages (and errors) are erased. * * @param $path * An installer path. */ function install_goto($path) { global $base_url; header('Location: ' . $base_url . '/' . $path); header('Cache-Control: no-cache'); // Not a permanent redirect. exit(); } /** * Functional equivalent of t(), used when some systems are not available. * * Used during the install process, when database, theme, and localization * system is possibly not yet available. * * @see t() */ function st($string, $args = array()) { static $locale_strings = NULL; global $install_state; if (!isset($locale_strings)) { $locale_strings = array(); if (isset($install_state['parameters']['profile']) && isset($install_state['parameters']['locale'])) { $filename = 'profiles/' . $install_state['parameters']['profile'] . '/translations/' . $install_state['parameters']['locale'] . '.po'; if (file_exists(DRUPAL_ROOT . '/' . $filename)) { require_once DRUPAL_ROOT . '/includes/locale.inc'; $file = (object) array('filepath' => $filename); _locale_import_read_po('mem-store', $file); $locale_strings = _locale_import_one_string('mem-report'); } } } require_once DRUPAL_ROOT . '/includes/theme.inc'; // Transform arguments before inserting them foreach ($args as $key => $value) { switch ($key[0]) { // Escaped only case '@': $args[$key] = check_plain($value); break; // Escaped and placeholder case '%': default: $args[$key] = '' . check_plain($value) . ''; break; // Pass-through case '!': } } return strtr((!empty($locale_strings[$string]) ? $locale_strings[$string] : $string), $args); } /** * Check an install profile's requirements. * * @param $profile * Name of install profile to check. * @return * Array of the install profile's requirements. */ function drupal_check_profile($profile) { include_once DRUPAL_ROOT . '/includes/file.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_profile_info($profile); // Get a list of all .install files. $installs = drupal_get_install_files($info['dependencies']); // Collect requirement testing results $requirements = array(); foreach ($installs as $install) { require_once DRUPAL_ROOT . '/' . $install->filepath; $function = $install->name . '_requirements'; if (function_exists($function)) { $requirements = array_merge($requirements, $function('install')); } } return $requirements; } /** * Extract highest severity from requirements array. * * @param $requirements * An array of requirements, in the same format as is returned by * hook_requirements(). * @return * The highest severity in the array. */ function drupal_requirements_severity(&$requirements) { $severity = REQUIREMENT_OK; foreach ($requirements as $requirement) { if (isset($requirement['severity'])) { $severity = max($severity, $requirement['severity']); } } return $severity; } /** * Check a module's requirements. * * @param $module * Machine name of module to check. * @return * TRUE/FALSE depending on the requirements are in place. */ function drupal_check_module($module) { // Include install file $install = drupal_get_install_files(array($module)); if (isset($install[$module])) { require_once DRUPAL_ROOT . '/' . $install[$module]->filepath; // Check requirements $requirements = module_invoke($module, 'requirements', 'install'); if (is_array($requirements) && drupal_requirements_severity($requirements) == REQUIREMENT_ERROR) { // Print any error messages foreach ($requirements as $requirement) { if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) { $message = $requirement['description']; if (isset($requirement['value']) && $requirement['value']) { $message .= ' (' . t('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) . ')'; } drupal_set_message($message, 'error'); } } return FALSE; } } return TRUE; } /** * Retrieve info about an install profile from its .info file. * * Information stored in the profile.info file: * - name: The real name of the install profile for display purposes. * - description: A brief description of the profile. * - dependencies: An array of shortnames of other modules this install profile requires. * * Example of .info file: * @verbatim * name = Drupal (minimal) * description = Create a Drupal site with only required modules enabled. * dependencies[] = block * dependencies[] = dblog * @endverbatim * * @param profile * Name of profile. * @param locale * Name of locale used (if any). * @return * The info array. */ function install_profile_info($profile, $locale = 'en') { $cache = &drupal_static(__FUNCTION__, array()); if (!isset($cache[$profile])) { // Set defaults for module info. $defaults = array( 'dependencies' => array(), 'description' => '', 'version' => NULL, 'php' => DRUPAL_MINIMUM_PHP, ); $info = drupal_parse_info_file("profiles/$profile/$profile.info") + $defaults; $info['dependencies'] = array_unique(array_merge( drupal_required_modules(), $info['dependencies'], ($locale != 'en' && !empty($locale) ? array('locale') : array())) ); $cache[$profile] = $info; } return $cache[$profile]; } /** * Ensures the environment for a Drupal database on a predefined connection. * * This will run tasks that check that Drupal can perform all of the functions * on a database, that Drupal needs. Tasks include simple checks like CREATE * TABLE to database specfic functions like stored procedures and client * encoding. */ function db_run_tasks($driver) { $task_class = 'DatabaseTasks_' . $driver; $DatabaseTasks = new $task_class(); $DatabaseTasks->runTasks(); return true; }