2005-12-08 08:40:10 +00:00
< ? php
// $Id$
2008-05-26 17:12:55 +00:00
/**
* Indicates that a module has not been installed yet .
*/
2006-01-21 01:42:52 +00:00
define ( 'SCHEMA_UNINSTALLED' , - 1 );
2008-05-26 17:12:55 +00:00
/**
* Indicates that a module has been installed .
*/
2006-01-21 01:42:52 +00:00
define ( 'SCHEMA_INSTALLED' , 0 );
2005-12-08 08:40:10 +00:00
2008-05-26 17:12:55 +00:00
/**
* Requirement severity -- Informational message only .
*/
2006-09-01 09:23:45 +00:00
define ( 'REQUIREMENT_INFO' , - 1 );
2008-05-26 17:12:55 +00:00
/**
* Requirement severity -- Requirement successfully met .
*/
2006-09-01 08:44:53 +00:00
define ( 'REQUIREMENT_OK' , 0 );
2008-05-26 17:12:55 +00:00
/**
* Requirement severity -- Warning condition ; proceed but flag warning .
*/
2006-09-01 08:44:53 +00:00
define ( 'REQUIREMENT_WARNING' , 1 );
2008-05-26 17:12:55 +00:00
/**
* Requirement severity -- Error condition ; abort installation .
*/
2006-09-01 08:44:53 +00:00
define ( 'REQUIREMENT_ERROR' , 2 );
2005-12-08 08:40:10 +00:00
2008-05-26 17:12:55 +00:00
/**
* File permission check -- File exists .
*/
define ( 'FILE_EXIST' , 1 );
/**
* File permission check -- File is readable .
*/
define ( 'FILE_READABLE' , 2 );
/**
* File permission check -- File is writable .
*/
define ( 'FILE_WRITABLE' , 4 );
/**
* File permission check -- File is executable .
*/
define ( 'FILE_EXECUTABLE' , 8 );
/**
* File permission check -- File does not exist .
*/
define ( 'FILE_NOT_EXIST' , 16 );
/**
* File permission check -- File is not readable .
*/
define ( 'FILE_NOT_READABLE' , 32 );
/**
* File permission check -- File is not writable .
*/
define ( 'FILE_NOT_WRITABLE' , 64 );
/**
* File permission check -- File is not executable .
*/
2006-07-13 13:14:25 +00:00
define ( 'FILE_NOT_EXECUTABLE' , 128 );
2005-12-08 08:40:10 +00:00
2006-07-31 19:24:16 +00:00
/**
* Initialize the update system by loading all installed module ' s . install files .
*/
function drupal_load_updates () {
2007-12-17 12:23:01 +00:00
foreach ( drupal_get_installed_schema_version ( NULL , FALSE , TRUE ) as $module => $schema_version ) {
if ( $schema_version > - 1 ) {
module_load_install ( $module );
}
2005-12-08 08:40:10 +00:00
}
}
/**
2006-04-11 11:33:15 +00:00
* Returns an array of available schema versions for a module .
2005-12-08 08:40:10 +00:00
*
* @ param $module
* A module name .
* @ return
2008-11-11 16:49:38 +00:00
* If the module has updates , an array of available updates sorted by version .
2008-08-14 09:25:48 +00:00
* Otherwise , FALSE .
2005-12-08 08:40:10 +00:00
*/
function drupal_get_schema_versions ( $module ) {
2006-11-21 19:56:52 +00:00
$updates = array ();
2005-12-09 15:46:47 +00:00
$functions = get_defined_functions ();
foreach ( $functions [ 'user' ] as $function ) {
2008-04-14 17:48:46 +00:00
if ( strpos ( $function , $module . '_update_' ) === 0 ) {
$version = substr ( $function , strlen ( $module . '_update_' ));
2005-12-09 16:14:26 +00:00
if ( is_numeric ( $version )) {
$updates [] = $version ;
}
2005-12-09 15:46:47 +00:00
}
2005-12-08 08:40:10 +00:00
}
2005-12-09 15:46:47 +00:00
if ( count ( $updates ) == 0 ) {
return FALSE ;
2005-12-08 08:40:10 +00:00
}
2008-11-11 16:49:38 +00:00
2008-08-14 09:25:48 +00:00
// Make sure updates are run in numeric order, not in definition order.
sort ( $updates , SORT_NUMERIC );
2008-11-11 16:49:38 +00:00
2005-12-09 15:46:47 +00:00
return $updates ;
2005-12-08 08:40:10 +00:00
}
/**
* Returns the currently installed schema version for a module .
*
* @ param $module
* A module name .
2007-12-17 12:23:01 +00:00
* @ param $reset
* Set to TRUE after modifying the system table .
* @ param $array
2007-12-18 10:31:42 +00:00
* Set to TRUE if you want to get information about all modules in the
2007-12-17 12:23:01 +00:00
* system .
2005-12-08 08:40:10 +00:00
* @ return
* The currently installed schema version .
*/
2007-12-17 12:23:01 +00:00
function drupal_get_installed_schema_version ( $module , $reset = FALSE , $array = FALSE ) {
2007-02-04 21:21:44 +00:00
static $versions = array ();
2005-12-08 08:40:10 +00:00
if ( $reset ) {
2007-02-04 21:21:44 +00:00
$versions = array ();
2005-12-08 08:40:10 +00:00
}
if ( ! $versions ) {
$versions = array ();
2009-01-04 18:50:23 +00:00
$result = db_query ( " SELECT name, schema_version FROM { system} WHERE type = :type " , array ( ':type' => 'module' ));
foreach ( $result as $row ) {
2005-12-08 08:40:10 +00:00
$versions [ $row -> name ] = $row -> schema_version ;
}
}
2007-12-17 12:23:01 +00:00
return $array ? $versions : $versions [ $module ];
2005-12-08 08:40:10 +00:00
}
/**
* 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 ) {
2009-01-04 18:50:23 +00:00
db_update ( 'system' )
-> fields ( array ( 'schema_version' => $version ))
-> condition ( 'name' , $module )
-> execute ();
2005-12-08 08:40:10 +00:00
}
2006-07-13 13:14:25 +00:00
/**
2008-09-14 01:58:17 +00:00
* Loads the install profile definition , extracting its defined name .
2006-07-13 13:14:25 +00:00
*
* @ return
* The name defined in the profile ' s _profile_details () hook .
*/
function drupal_install_profile_name () {
global $profile ;
static $name = NULL ;
if ( ! isset ( $name )) {
// Load profile details.
2008-04-14 17:48:46 +00:00
$function = $profile . '_profile_details' ;
2006-07-13 13:14:25 +00:00
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' ) {
global $profile ;
$proto = $_SERVER [ 'HTTPS' ] ? 'https://' : 'http://' ;
$host = $_SERVER [ 'SERVER_NAME' ];
2008-04-14 17:48:46 +00:00
$port = ( $_SERVER [ 'SERVER_PORT' ] == 80 ? '' : ':' . $_SERVER [ 'SERVER_PORT' ]);
2006-09-01 08:44:53 +00:00
$uri = preg_replace ( " / \ ?.*/ " , '' , $_SERVER [ 'REQUEST_URI' ]);
2006-07-13 13:14:25 +00:00
$dir = str_replace ( " / $file " , '' , $uri );
return " $proto $host $port $dir " ;
}
/**
2008-09-14 01:58:17 +00:00
* Detect all supported databases that are compiled into PHP .
2006-07-13 13:14:25 +00:00
*
* @ return
* An array of database types compiled into PHP .
*/
function drupal_detect_database_types () {
$databases = array ();
2008-08-22 12:43:53 +00:00
// We define a driver as a directory in /includes/database that in turn
2008-12-20 18:24:41 +00:00
// contains a database.inc file. That allows us to drop in additional drivers
2008-08-22 12:43:53 +00:00
// without modifying the installer.
// Because we have no registry yet, we need to also include the install.inc
// file for the driver explicitly.
2008-10-24 18:21:54 +00:00
2009-02-18 15:07:27 +00:00
foreach ( file_scan_directory ( DRUPAL_ROOT . '/includes/database' , '/^[a-z]*$/i' , array ( 'recurse' => FALSE )) as $file ) {
2009-02-22 17:55:30 +00:00
include_once " { $file -> filepath } /install.inc " ;
include_once " { $file -> filepath } /database.inc " ;
$drivers [ $file -> filename ] = $file -> filepath ;
2008-08-22 12:43:53 +00:00
}
foreach ( $drivers as $driver => $file ) {
2008-08-21 19:36:39 +00:00
$class = 'DatabaseInstaller_' . $driver ;
$installer = new $class ();
if ( $installer -> installable ()) {
$databases [ $driver ] = $installer -> name ();
}
}
2008-08-22 12:43:53 +00:00
2008-12-30 16:43:20 +00:00
// Usability: unconditionally put the MySQL driver on top.
2008-08-28 08:40:33 +00:00
if ( isset ( $databases [ 'mysql' ])) {
$mysql_database = $databases [ 'mysql' ];
unset ( $databases [ 'mysql' ]);
$databases = array ( 'mysql' => $mysql_database ) + $databases ;
}
2008-11-11 16:49:38 +00:00
2008-08-21 19:36:39 +00:00
return $databases ;
}
abstract class DatabaseInstaller {
protected $success = array ();
protected $tests = array (
'testCreate' => array (
'query' => 'CREATE TABLE drupal_install_test (id int NULL)' ,
'success' => 'CREATE' ,
'message' => 'Failed to create a test table on your %name database server with the command %query. %name reports the following message: %error.<ul><li>Are you sure the configured username has the necessary %name permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.' ,
'fatal' => TRUE ,
),
'testInsert' => array (
'query' => 'INSERT INTO drupal_install_test (id) VALUES (1)' ,
'success' => 'INSERT' ,
'message' => '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.' ,
),
'testUpdate' => array (
'query' => 'UPDATE drupal_install_test SET id = 2' ,
'success' => 'UPDATE' ,
'message' => '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.' ,
),
'testDelete' => array (
'query' => 'DELETE FROM drupal_install_test' ,
'success' => 'DELETE' ,
'message' => '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.' ,
),
'testDrop' => array (
'query' => 'DROP TABLE drupal_install_test' ,
'success' => 'DELETE' ,
'message' => '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.' ,
),
);
public $error = FALSE ;
protected function hasPdoDriver () {
return in_array ( $this -> pdoDriver , PDO :: getAvailableDrivers ());
}
public function installable () {
return $this -> hasPdoDriver ();
}
abstract public function name ();
public function test () {
$return = $this -> testConnect ();
if ( $return === FALSE ) {
return FALSE ;
}
foreach ( $this -> tests as $test ) {
$return = $this -> runTestQuery ( $test [ 'query' ], $test [ 'success' ], $test [ 'message' ], ! empty ( $tests [ 'fatal' ]));
if ( $return === FALSE ) {
return FALSE ;
2006-07-13 13:14:25 +00:00
}
}
2008-08-21 19:36:39 +00:00
return $this -> success ;
2006-07-13 13:14:25 +00:00
}
2008-08-21 19:36:39 +00:00
/**
* Check if we can connect to the database .
*
* @ return
* FALSE on failure .
*/
protected function testConnect () {
try {
db_set_active ();
$this -> success [] = 'CONNECT' ;
}
catch ( Exception $e ) {
drupal_set_message ( st ( 'Failed to connect to your %name database server. %name reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.' , array ( '%error' => $e -> getMessage (), 'name' => $this -> name ())), 'error' );
return FALSE ;
}
}
protected function runTestQuery ( $query , $success , $message , $fatal = FALSE ) {
try {
db_query ( $query );
$this -> success [] = $success ;
}
catch ( Exception $e ) {
drupal_set_message ( st ( $message , array ( '%query' => $query , '%error' => $e -> getMessage (), '%name' => $this -> name ())), 'error' );
$this -> error = TRUE ;
if ( $fatal ) {
return FALSE ;
}
}
}
2006-07-13 13:14:25 +00:00
}
/**
2008-09-14 01:58:17 +00:00
* Replace values in settings . php with values in the submitted array .
2006-07-13 13:14:25 +00:00
*
* @ param $settings
* An array of settings that need to be updated .
*/
function drupal_rewrite_settings ( $settings = array (), $prefix = '' ) {
2008-09-20 20:22:25 +00:00
$default_settings = 'sites/default/default.settings.php' ;
2009-04-02 20:39:45 +00:00
drupal_static_reset ( 'conf_path' );
$settings_file = conf_path ( FALSE ) . '/' . $prefix . 'settings.php' ;
2006-07-13 13:14:25 +00:00
// 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 ;
2008-09-20 20:22:25 +00:00
if ( $fp = fopen ( DRUPAL_ROOT . '/' . $default_settings , 'r' )) {
2006-07-13 13:14:25 +00:00
// Step line by line through settings.php.
while ( ! feof ( $fp )) {
$line = fgets ( $fp );
if ( $first && substr ( $line , 0 , 5 ) != '<?php' ) {
$buffer = " <?php \n \n " ;
}
$first = FALSE ;
// Check for constants.
if ( substr ( $line , 0 , 7 ) == 'define(' ) {
preg_match ( '/define\(\s*[\'"]([A-Z_-]+)[\'"]\s*,(.*?)\);/' , $line , $variable );
if ( in_array ( $variable [ 1 ], $keys )) {
$setting = $settings [ $variable [ 1 ]];
2008-04-14 17:48:46 +00:00
$buffer .= str_replace ( $variable [ 2 ], " ' " . $setting [ 'value' ] . " ' " , $line );
2006-07-13 13:14:25 +00:00
unset ( $settings [ $variable [ 1 ]]);
unset ( $settings [ $variable [ 2 ]]);
}
else {
$buffer .= $line ;
}
}
// Check for variables.
elseif ( substr ( $line , 0 , 1 ) == '$' ) {
preg_match ( '/\$([^ ]*) /' , $line , $variable );
if ( in_array ( $variable [ 1 ], $keys )) {
// Write new value to settings.php in the following format:
// $'setting' = 'value'; // 'comment'
$setting = $settings [ $variable [ 1 ]];
2008-08-21 19:36:39 +00:00
$buffer .= '$' . $variable [ 1 ] . " = " . var_export ( $setting [ 'value' ], TRUE ) . " ; " . ( ! empty ( $setting [ 'comment' ]) ? ' // ' . $setting [ 'comment' ] . " \n " : " \n " );
2006-07-13 13:14:25 +00:00
unset ( $settings [ $variable [ 1 ]]);
}
else {
$buffer .= $line ;
}
}
else {
$buffer .= $line ;
}
}
fclose ( $fp );
// Add required settings that were missing from settings.php.
foreach ( $settings as $setting => $data ) {
if ( $data [ 'required' ]) {
2008-08-21 19:36:39 +00:00
$buffer .= " \$ $setting = " . var_export ( $data [ 'value' ], TRUE ) . " ; \n " ;
2006-07-13 13:14:25 +00:00
}
}
2008-09-20 20:22:25 +00:00
$fp = fopen ( DRUPAL_ROOT . '/' . $settings_file , 'w' );
2006-07-13 13:14:25 +00:00
if ( $fp && fwrite ( $fp , $buffer ) === FALSE ) {
2008-02-10 07:46:13 +00:00
drupal_set_message ( st ( 'Failed to modify %settings, please verify the file permissions.' , array ( '%settings' => $settings_file )), 'error' );
2006-07-13 13:14:25 +00:00
}
}
else {
2008-02-10 07:46:13 +00:00
drupal_set_message ( st ( 'Failed to open %settings, please verify the file permissions.' , array ( '%settings' => $default_settings )), 'error' );
2006-07-13 13:14:25 +00:00
}
}
/**
* 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 ) {
2009-05-24 17:39:35 +00:00
$installs = array_merge ( $installs , drupal_system_listing ( '/' . $module . '.install$/' , 'modules' ));
2006-07-13 13:14:25 +00:00
}
return $installs ;
}
2008-10-01 00:27:29 +00:00
/**
* Get a list of modules required by an installation profile .
*
* @ param profile
* Name of profile .
* @ param locale
* Name of locale used ( if any ) .
* @ return
* The list of modules to install .
*/
function drupal_get_profile_modules ( $profile , $locale = 'en' ) {
$profile_file = " ./profiles/ $profile / $profile .profile " ;
require_once ( $profile_file );
// Get a list of modules required by this profile.
$function = $profile . '_profile_modules' ;
2009-01-18 06:56:58 +00:00
return array_merge ( drupal_required_modules (), $function (), ( $locale != 'en' && ! empty ( $locale ) ? array ( 'locale' ) : array ()));
2008-10-01 00:27:29 +00:00
}
2006-07-13 13:14:25 +00:00
/**
2008-09-14 01:58:17 +00:00
* Verify an install profile for installation .
2006-07-13 13:14:25 +00:00
*
2008-09-14 01:58:17 +00:00
* @ param $profile
* Name of install profile to verify .
* @ param $locale
2006-09-01 05:38:40 +00:00
* Name of locale used ( if any ) .
2006-08-03 01:02:51 +00:00
* @ return
* The list of modules to install .
2006-07-13 13:14:25 +00:00
*/
2006-09-01 05:38:40 +00:00
function drupal_verify_profile ( $profile , $locale ) {
2008-09-20 20:22:25 +00:00
include_once DRUPAL_ROOT . '/includes/file.inc' ;
include_once DRUPAL_ROOT . '/includes/common.inc' ;
2006-07-13 13:14:25 +00:00
2008-09-20 20:22:25 +00:00
$profile_file = DRUPAL_ROOT . " /profiles/ $profile / $profile .profile " ;
2006-07-13 13:14:25 +00:00
if ( ! isset ( $profile ) || ! file_exists ( $profile_file )) {
2006-08-23 08:25:44 +00:00
install_no_profile_error ();
2006-07-13 13:14:25 +00:00
}
2008-10-01 00:27:29 +00:00
$module_list = drupal_get_profile_modules ( $profile , $locale );
2006-08-03 07:06:36 +00:00
2006-10-23 06:45:17 +00:00
// Get a list of modules that exist in Drupal's assorted subdirectories.
$present_modules = array ();
2008-09-20 03:49:24 +00:00
foreach ( drupal_system_listing ( '/\.module$/' , 'modules' , 'name' , 0 ) as $present_module ) {
2006-10-23 06:45:17 +00:00
$present_modules [] = $present_module -> name ;
}
// Verify that all of the profile's required modules are present.
$missing_modules = array_diff ( $module_list , $present_modules );
2008-10-01 00:27:29 +00:00
$requirements = array ();
2008-11-11 16:49:38 +00:00
2006-10-23 06:45:17 +00:00
if ( count ( $missing_modules )) {
2008-10-01 00:27:29 +00:00
$modules = array ();
2007-01-02 05:05:38 +00:00
foreach ( $missing_modules as $module ) {
2008-10-01 00:27:29 +00:00
$modules [] = '<span class="admin-missing">' . drupal_ucfirst ( $module ) . '</span>' ;
2006-08-03 01:02:51 +00:00
}
2008-10-01 00:27:29 +00:00
$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 <em>sites/all/modules</em>. Missing modules: !modules' , array ( '!modules' => implode ( ', ' , $modules ))),
);
2006-08-03 01:02:51 +00:00
}
2008-10-01 00:27:29 +00:00
return $requirements ;
2006-08-03 01:02:51 +00:00
}
2006-07-29 17:56:41 +00:00
2006-08-03 01:02:51 +00:00
/**
2008-09-14 01:58:17 +00:00
* Calls the install function for a given list of modules .
2006-08-03 01:02:51 +00:00
*
2008-09-14 01:58:17 +00:00
* @ param $module_list
2007-12-08 15:15:25 +00:00
* The modules to install .
2009-02-03 17:30:13 +00:00
* @ param $disable_modules_installed_hook
* Normally just testing wants to set this to TRUE .
2007-12-08 15:15:25 +00:00
*/
2009-02-03 17:30:13 +00:00
function drupal_install_modules ( $module_list = array (), $disable_modules_installed_hook = FALSE ) {
2007-12-13 10:46:43 +00:00
$files = module_rebuild_cache ();
$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 );
2008-10-11 22:46:22 +00:00
$modules_installed = array_filter ( $module_list , '_drupal_install_module' );
2009-02-03 17:30:13 +00:00
if ( ! $disable_modules_installed_hook && ! empty ( $modules_installed )) {
2008-10-11 22:46:22 +00:00
module_invoke_all ( 'modules_installed' , $modules_installed );
}
2007-12-08 15:15:25 +00:00
module_enable ( $module_list );
}
/**
2008-09-14 01:58:17 +00:00
* Callback to install an individual install profile module .
2007-12-08 15:15:25 +00:00
*
* 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 / build / modules .
2008-09-14 01:58:17 +00:00
*
* @ param $module
* The machine name of the module to install .
* @ return
* TRUE if the module got installed .
2006-08-03 01:02:51 +00:00
*/
2007-12-08 15:15:25 +00:00
function _drupal_install_module ( $module ) {
if ( drupal_get_installed_schema_version ( $module , TRUE ) == SCHEMA_UNINSTALLED ) {
module_load_install ( $module );
2009-05-03 19:38:53 +00:00
drupal_load ( 'module' , $module );
2007-12-08 15:15:25 +00:00
module_invoke ( $module , 'install' );
$versions = drupal_get_schema_versions ( $module );
drupal_set_installed_schema_version ( $module , $versions ? max ( $versions ) : SCHEMA_INSTALLED );
return TRUE ;
}
}
2006-08-03 01:02:51 +00:00
2008-08-21 19:36:39 +00:00
/**
* 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_init_database () {
static $included = FALSE ;
2008-11-11 16:49:38 +00:00
2008-08-21 19:36:39 +00:00
if ( ! $included ) {
$connection_info = Database :: getConnectionInfo ();
$driver = $connection_info [ 'default' ][ 'driver' ];
2008-09-20 20:22:25 +00:00
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 ;
2008-08-21 19:36:39 +00:00
}
2008-11-30 01:11:23 +00:00
$included = TRUE ;
2008-08-21 19:36:39 +00:00
}
}
2007-12-08 15:15:25 +00:00
/**
* 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 () {
2006-11-24 10:16:50 +00:00
$system_path = dirname ( drupal_get_filename ( 'module' , 'system' , NULL ));
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/' . $system_path . '/system.install' ;
2008-08-21 19:36:39 +00:00
drupal_install_init_database ();
2006-08-03 01:02:51 +00:00
module_invoke ( 'system' , 'install' );
2008-11-11 16:49:38 +00:00
2006-08-03 01:02:51 +00:00
$system_versions = drupal_get_schema_versions ( 'system' );
$system_version = $system_versions ? max ( $system_versions ) : SCHEMA_INSTALLED ;
2009-01-04 18:50:23 +00:00
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 ();
2006-08-03 01:02:51 +00:00
// Now that we've installed things properly, bootstrap the full Drupal environment
2006-07-19 07:45:35 +00:00
drupal_bootstrap ( DRUPAL_BOOTSTRAP_FULL );
2006-08-03 01:02:51 +00:00
module_rebuild_cache ();
2006-07-19 07:45:35 +00:00
}
2006-09-01 07:40:08 +00:00
/**
* Calls the uninstall function and updates the system table for a given module .
*
2008-10-11 22:46:22 +00:00
* @ param $module_list
* The modules to uninstall .
2006-09-01 07:40:08 +00:00
*/
2008-10-11 22:46:22 +00:00
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' );
2009-05-12 18:08:43 +00:00
watchdog ( 'system' , '%module module uninstalled.' , array ( '%module' => $module ), WATCHDOG_INFO );
2008-10-11 22:46:22 +00:00
// 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 ] = '%' ;
}
2007-08-29 20:46:18 +00:00
}
2008-10-11 22:46:22 +00:00
$paths [ $index ] = implode ( '/' , $parts );
2007-08-29 20:46:18 +00:00
}
2008-10-11 22:46:22 +00:00
$placeholders = implode ( ', ' , array_fill ( 0 , count ( $paths ), " '%s' " ));
2007-08-30 19:54:22 +00:00
2009-01-04 18:50:23 +00:00
$result = db_select ( 'menu_links' )
2009-05-24 17:39:35 +00:00
-> fields ( 'menu_links' )
-> condition ( 'router_path' , $paths , 'IN' )
-> condition ( 'external' , 0 )
-> orderBy ( 'depth' )
-> execute ();
2008-10-11 22:46:22 +00:00
// Remove all such items. Starting from those with the greatest depth will
// minimize the amount of re-parenting done by menu_link_delete().
2009-01-04 18:50:23 +00:00
foreach ( $result as $item ) {
2008-10-11 22:46:22 +00:00
_menu_delete_item ( $item , TRUE );
}
2007-08-29 20:46:18 +00:00
}
2008-10-11 22:46:22 +00:00
drupal_set_installed_schema_version ( $module , SCHEMA_UNINSTALLED );
2007-08-29 20:46:18 +00:00
}
2008-10-11 22:46:22 +00:00
if ( ! empty ( $module_list )) {
// Call hook_module_uninstall to let other modules act
module_invoke_all ( 'modules_uninstalled' , $module_list );
}
2006-09-01 07:40:08 +00:00
}
2006-07-13 13:14:25 +00:00
/**
* 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
2006-12-05 05:47:37 +00:00
* TRUE on success or FALSE on failure . A message is set for the latter .
2006-07-13 13:14:25 +00:00
*/
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 )) {
2008-04-14 17:48:46 +00:00
$check = 'is_' . $type ;
2006-07-13 13:14:25 +00:00
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 .
*
2008-09-14 01:58:17 +00:00
* @ param $file
2006-07-13 13:14:25 +00:00
* The name of the directory to create ;
2008-09-14 01:58:17 +00:00
* @ param $mask
2006-07-13 13:14:25 +00:00
* 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 .
*
2006-12-08 11:54:04 +00:00
* 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.
*
2006-07-13 13:14:25 +00:00
* @ 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 ) {
2008-09-27 20:03:35 +00:00
// If $file does not exist, fileperms() issues a PHP warning.
if ( ! file_exists ( $file )) {
return FALSE ;
}
2006-12-08 11:54:04 +00:00
$mod = fileperms ( $file ) & 0777 ;
2006-07-13 13:14:25 +00:00
$masks = array ( FILE_READABLE , FILE_WRITABLE , FILE_EXECUTABLE , FILE_NOT_READABLE , FILE_NOT_WRITABLE , FILE_NOT_EXECUTABLE );
2006-12-08 11:54:04 +00:00
// 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.
2006-07-13 13:14:25 +00:00
foreach ( $masks as $m ) {
if ( $mask & $m ) {
switch ( $m ) {
case FILE_READABLE :
if ( ! is_readable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod |= 0444 ;
2006-07-13 13:14:25 +00:00
}
break ;
case FILE_WRITABLE :
if ( ! is_writable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod |= 0222 ;
2006-07-13 13:14:25 +00:00
}
break ;
case FILE_EXECUTABLE :
if ( ! is_executable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod |= 0111 ;
2006-07-13 13:14:25 +00:00
}
break ;
case FILE_NOT_READABLE :
if ( is_readable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod &= ~ 0444 ;
2006-07-13 13:14:25 +00:00
}
break ;
case FILE_NOT_WRITABLE :
if ( is_writable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod &= ~ 0222 ;
2006-07-13 13:14:25 +00:00
}
break ;
case FILE_NOT_EXECUTABLE :
if ( is_executable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod &= ~ 0111 ;
2006-07-13 13:14:25 +00:00
}
break ;
}
}
}
2006-12-08 11:54:04 +00:00
// 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 )) {
2006-07-13 13:14:25 +00:00
return TRUE ;
}
else {
return FALSE ;
}
}
2006-07-31 19:24:16 +00:00
/**
2008-11-11 16:49:38 +00:00
* Send the user to a different installer page .
2008-09-14 01:58:17 +00:00
*
* This issues an on - site HTTP redirect . Messages ( and errors ) are erased .
2006-07-31 19:24:16 +00:00
*
* @ param $path
* An installer path .
*/
function install_goto ( $path ) {
2006-10-12 15:20:08 +00:00
global $base_url ;
2008-04-14 17:48:46 +00:00
header ( 'Location: ' . $base_url . '/' . $path );
2007-09-07 10:48:24 +00:00
header ( 'Cache-Control: no-cache' ); // Not a permanent redirect.
2006-07-31 19:24:16 +00:00
exit ();
}
2006-07-13 13:14:25 +00:00
/**
2008-09-14 01:58:17 +00:00
* Functional equivalent of t (), used when some systems are not available .
*
* Used during the install process , when database , theme , and localization
2007-11-11 16:14:45 +00:00
* system is possibly not yet available .
2008-09-14 01:58:17 +00:00
*
* @ see t ()
2006-07-13 13:14:25 +00:00
*/
function st ( $string , $args = array ()) {
2006-09-01 05:38:40 +00:00
static $locale_strings = NULL ;
global $profile , $install_locale ;
if ( ! isset ( $locale_strings )) {
$locale_strings = array ();
2008-09-20 20:22:25 +00:00
$filename = 'profiles/' . $profile . '/translations/' . $install_locale . '.po' ;
if ( file_exists ( DRUPAL_ROOT . '/' . $filename )) {
require_once DRUPAL_ROOT . '/includes/locale.inc' ;
2006-09-01 05:38:40 +00:00
$file = ( object ) array ( 'filepath' => $filename );
_locale_import_read_po ( 'mem-store' , $file );
$locale_strings = _locale_import_one_string ( 'mem-report' );
}
}
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/theme.inc' ;
2006-08-18 12:17:00 +00:00
// Transform arguments before inserting them
2007-01-02 05:05:38 +00:00
foreach ( $args as $key => $value ) {
2006-09-07 08:23:54 +00:00
switch ( $key [ 0 ]) {
// Escaped only
case '@' :
$args [ $key ] = check_plain ( $value );
break ;
// Escaped and placeholder
case '%' :
default :
2008-04-14 17:48:46 +00:00
$args [ $key ] = '<em>' . check_plain ( $value ) . '</em>' ;
2006-09-07 08:23:54 +00:00
break ;
// Pass-through
case '!' :
}
2006-08-18 12:17:00 +00:00
}
2006-09-07 08:23:54 +00:00
return strtr (( ! empty ( $locale_strings [ $string ]) ? $locale_strings [ $string ] : $string ), $args );
2006-08-08 21:18:04 +00:00
}
2006-09-01 08:44:53 +00:00
/**
2008-09-14 01:58:17 +00:00
* Check an install profile ' s requirements .
2006-09-01 08:44:53 +00:00
*
2008-09-14 01:58:17 +00:00
* @ param $profile
* Name of install profile to check .
* @ return
* Array of the install profile ' s requirements .
2006-09-01 08:44:53 +00:00
*/
function drupal_check_profile ( $profile ) {
2008-09-20 20:22:25 +00:00
include_once DRUPAL_ROOT . '/includes/file.inc' ;
2006-09-01 08:44:53 +00:00
2008-09-20 20:22:25 +00:00
$profile_file = DRUPAL_ROOT . " /profiles/ $profile / $profile .profile " ;
2006-09-01 08:44:53 +00:00
if ( ! isset ( $profile ) || ! file_exists ( $profile_file )) {
install_no_profile_error ();
}
2008-09-20 20:22:25 +00:00
require_once $profile_file ;
2006-09-01 08:44:53 +00:00
// Get a list of modules required by this profile.
2008-04-14 17:48:46 +00:00
$function = $profile . '_profile_modules' ;
2007-02-04 21:20:50 +00:00
$module_list = array_unique ( array_merge ( drupal_required_modules (), $function ()));
2006-09-01 08:44:53 +00:00
// Get a list of all .install files.
$installs = drupal_get_install_files ( $module_list );
// Collect requirement testing results
$requirements = array ();
foreach ( $installs as $install ) {
2009-02-22 17:55:30 +00:00
require_once DRUPAL_ROOT . '/' . $install -> filepath ;
2009-05-24 17:39:35 +00:00
$function = $install -> name . '_requirements' ;
2008-05-06 12:18:54 +00:00
if ( function_exists ( $function )) {
$requirements = array_merge ( $requirements , $function ( 'install' ));
2006-09-05 02:28:11 +00:00
}
2006-09-01 08:44:53 +00:00
}
return $requirements ;
}
/**
* Extract highest severity from requirements array .
2008-09-14 01:58:17 +00:00
*
* @ param $requirements
2008-11-11 16:49:38 +00:00
* An array of requirements , in the same format as is returned by
2008-09-14 01:58:17 +00:00
* hook_requirements () .
* @ return
* The highest severity in the array .
2006-09-01 08:44:53 +00:00
*/
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 .
2008-09-14 01:58:17 +00:00
*
* @ param $module
* Machine name of module to check .
* @ return
* TRUE / FALSE depending on the requirements are in place .
2006-09-01 08:44:53 +00:00
*/
function drupal_check_module ( $module ) {
// Include install file
$install = drupal_get_install_files ( array ( $module ));
if ( isset ( $install [ $module ])) {
2009-02-22 17:55:30 +00:00
require_once DRUPAL_ROOT . '/' . $install [ $module ] -> filepath ;
2006-09-01 08:44:53 +00:00
// 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 ) {
2007-12-19 11:15:18 +00:00
$message = $requirement [ 'description' ];
if ( isset ( $requirement [ 'value' ]) && $requirement [ 'value' ]) {
2008-04-14 17:48:46 +00:00
$message .= ' (' . t ( 'Currently using !item !version' , array ( '!item' => $requirement [ 'title' ], '!version' => $requirement [ 'value' ])) . ')' ;
2007-12-19 11:15:18 +00:00
}
drupal_set_message ( $message , 'error' );
2006-09-01 08:44:53 +00:00
}
}
return FALSE ;
}
}
return TRUE ;
}