diff options
Diffstat (limited to 'includes')
-rw-r--r-- | includes/database/database.inc | 15 | ||||
-rw-r--r-- | includes/database/mysql/install.inc | 2 | ||||
-rw-r--r-- | includes/database/pgsql/install.inc | 33 | ||||
-rw-r--r-- | includes/database/sqlite/install.inc | 2 | ||||
-rw-r--r-- | includes/install.inc | 169 |
5 files changed, 169 insertions, 52 deletions
diff --git a/includes/database/database.inc b/includes/database/database.inc index 9da091231..ce470789a 100644 --- a/includes/database/database.inc +++ b/includes/database/database.inc @@ -2694,5 +2694,20 @@ function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $ } /** + * 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; +} + +/** * @} End of "ingroup database-legacy". */ diff --git a/includes/database/mysql/install.inc b/includes/database/mysql/install.inc index cee986225..f443944d8 100644 --- a/includes/database/mysql/install.inc +++ b/includes/database/mysql/install.inc @@ -9,7 +9,7 @@ // MySQL specific install functions -class DatabaseInstaller_mysql extends DatabaseInstaller { +class DatabaseTasks_mysql extends DatabaseTasks { protected $pdoDriver = 'mysql'; public function name() { return 'MySQL'; diff --git a/includes/database/pgsql/install.inc b/includes/database/pgsql/install.inc index b301cb672..222d7e734 100644 --- a/includes/database/pgsql/install.inc +++ b/includes/database/pgsql/install.inc @@ -9,10 +9,41 @@ // PostgreSQL specific install functions -class DatabaseInstaller_pgsql extends DatabaseInstaller { +class DatabaseTasks_pgsql extends DatabaseTasks { protected $pdoDriver = 'pgsql'; + + public function __construct() { + $this->tasks[] = array( + 'function' => 'checkEncoding', + 'arguments' => array(), + ); + } + public function name() { return 'PostgreSQL'; } + + /** + * Check encoding is UTF8. + */ + protected function checkEncoding() { + try { + if (db_query('SHOW server_encoding')->fetchField() == 'UTF8') { + $this->pass(st('Database is encoded in UTF-8')); + } + else { + $replacements = array( + '%encoding' => 'UTF8', + '%driver' => $this->name(), + '!link' => '<a href="INSTALL.pgsql.txt">INSTALL.pgsql.txt</a>' + ); + $text = 'The %driver database must use %encoding encoding to work with Drupal.'; + $text .= 'Please recreate the database with %encoding encoding. See !link for more details.'; + $this->fail(st($text, $replacements)); + } + } catch (Exception $e) { + $this->fail(st('Drupal could not determine the encoding of the database was set to UTF-8')); + } + } } diff --git a/includes/database/sqlite/install.inc b/includes/database/sqlite/install.inc index 096c20901..334e09dfd 100644 --- a/includes/database/sqlite/install.inc +++ b/includes/database/sqlite/install.inc @@ -6,7 +6,7 @@ * SQLite specific install functions */ -class DatabaseInstaller_sqlite extends DatabaseInstaller { +class DatabaseTasks_sqlite extends DatabaseTasks { protected $pdoDriver = 'sqlite'; public function name() { return 'SQLite'; diff --git a/includes/install.inc b/includes/install.inc index 0b5f0b8f9..bfa39d067 100644 --- a/includes/install.inc +++ b/includes/install.inc @@ -222,7 +222,7 @@ function drupal_detect_database_types() { } foreach ($drivers as $driver => $file) { - $class = 'DatabaseInstaller_' . $driver; + $class = 'DatabaseTasks_' . $driver; $installer = new $class(); if ($installer->installable()) { $databases[$driver] = $installer->name(); @@ -239,96 +239,167 @@ function drupal_detect_database_types() { 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, +/** + * 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 <strong>CREATE</strong> a test table on your %name database server with the command %query. %name reports the following message: %error.<p>Are you sure the configured username has the necessary %name permissions to create tables in the database?</p>', + 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.', + array( + 'arguments' => array( + 'INSERT INTO drupal_install_test (id) VALUES (1)', + 'Drupal can use INSERT database commands.', + 'Failed to <strong>INSERT</strong> 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.', + array( + 'arguments' => array( + 'UPDATE drupal_install_test SET id = 2', + 'Drupal can use UPDATE database commands.', + 'Failed to <strong>UPDATE</strong> 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.', + array( + 'arguments' => array( + 'DELETE FROM drupal_install_test', + 'Drupal can use DELETE database commands.', + 'Failed to <strong>DELETE</strong> 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.', + array( + 'arguments' => array( + 'DROP TABLE drupal_install_test', + 'Drupal can use DROP TABLE database commands.', + 'Failed to <strong>DROP</strong> 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; + /** + * 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(); + return $this->hasPdoDriver() && empty($this->error); } abstract public function name(); - public function test() { - $return = $this->testConnect(); - if ($return === FALSE) { - return FALSE; + /** + * 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 { + drupal_set_message(st('Failed to run all tasks against the database server. The task %task wasn\'t found.', array('%task' => $task['function'])), 'error'); + } + } } - foreach ($this->tests as $test) { - $return = $this->runTestQuery($test['query'], $test['success'], $test['message'], !empty($test['fatal'])); - if ($return === FALSE) { - return FALSE; + // Check for failed results and compile message + $message = ''; + foreach ($this->results as $result => $success) { + if (!$success) { + $message .= '<p class="error">' . $result . '</p>'; } } - return $this->success; + if (!empty($message)) { + $message = '<p>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 <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.</p>' . $message; + throw new DatabaseTaskException($message); + } } /** * Check if we can connect to the database. - * - * @return - * FALSE on failure. */ - protected function testConnect() { + protected function connect() { try { // This doesn't actually test the connection. db_set_active(); // Now actually do a check. Database::getConnection(); - $this->success[] = 'CONNECT'; + $this->pass('Drupal can CONNECT to the database ok.'); } catch (Exception $e) { - drupal_set_message(st('Failed to connect to your %name database server. %name reports the following message: <strong>%error</strong>.<ul><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li><li>Are you sure you have the correct database name?</li><li>Are you sure you have the correct username and password?</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'); + $this->fail(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()))); return FALSE; } + return TRUE; } - protected function runTestQuery($query, $success, $message, $fatal = FALSE) { + /** + * 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->success[] = $success; + $this->pass(st($pass)); } 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; - } + $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. |