annotate includes/install.inc @ 13:134d4b2e75f6

updated quicktabs and google analytics modules
author danieleb <danielebarchiesi@me.com>
date Tue, 29 Oct 2013 13:48:59 +0000
parents ff03f76ab3fe
children
rev   line source
danielebarchiesi@0 1 <?php
danielebarchiesi@0 2
danielebarchiesi@0 3 /**
danielebarchiesi@0 4 * @file
danielebarchiesi@0 5 * API functions for installing modules and themes.
danielebarchiesi@0 6 */
danielebarchiesi@0 7
danielebarchiesi@0 8 /**
danielebarchiesi@0 9 * Indicates that a module has not been installed yet.
danielebarchiesi@0 10 */
danielebarchiesi@0 11 define('SCHEMA_UNINSTALLED', -1);
danielebarchiesi@0 12
danielebarchiesi@0 13 /**
danielebarchiesi@0 14 * Indicates that a module has been installed.
danielebarchiesi@0 15 */
danielebarchiesi@0 16 define('SCHEMA_INSTALLED', 0);
danielebarchiesi@0 17
danielebarchiesi@0 18 /**
danielebarchiesi@0 19 * Requirement severity -- Informational message only.
danielebarchiesi@0 20 */
danielebarchiesi@0 21 define('REQUIREMENT_INFO', -1);
danielebarchiesi@0 22
danielebarchiesi@0 23 /**
danielebarchiesi@0 24 * Requirement severity -- Requirement successfully met.
danielebarchiesi@0 25 */
danielebarchiesi@0 26 define('REQUIREMENT_OK', 0);
danielebarchiesi@0 27
danielebarchiesi@0 28 /**
danielebarchiesi@0 29 * Requirement severity -- Warning condition; proceed but flag warning.
danielebarchiesi@0 30 */
danielebarchiesi@0 31 define('REQUIREMENT_WARNING', 1);
danielebarchiesi@0 32
danielebarchiesi@0 33 /**
danielebarchiesi@0 34 * Requirement severity -- Error condition; abort installation.
danielebarchiesi@0 35 */
danielebarchiesi@0 36 define('REQUIREMENT_ERROR', 2);
danielebarchiesi@0 37
danielebarchiesi@0 38 /**
danielebarchiesi@0 39 * File permission check -- File exists.
danielebarchiesi@0 40 */
danielebarchiesi@0 41 define('FILE_EXIST', 1);
danielebarchiesi@0 42
danielebarchiesi@0 43 /**
danielebarchiesi@0 44 * File permission check -- File is readable.
danielebarchiesi@0 45 */
danielebarchiesi@0 46 define('FILE_READABLE', 2);
danielebarchiesi@0 47
danielebarchiesi@0 48 /**
danielebarchiesi@0 49 * File permission check -- File is writable.
danielebarchiesi@0 50 */
danielebarchiesi@0 51 define('FILE_WRITABLE', 4);
danielebarchiesi@0 52
danielebarchiesi@0 53 /**
danielebarchiesi@0 54 * File permission check -- File is executable.
danielebarchiesi@0 55 */
danielebarchiesi@0 56 define('FILE_EXECUTABLE', 8);
danielebarchiesi@0 57
danielebarchiesi@0 58 /**
danielebarchiesi@0 59 * File permission check -- File does not exist.
danielebarchiesi@0 60 */
danielebarchiesi@0 61 define('FILE_NOT_EXIST', 16);
danielebarchiesi@0 62
danielebarchiesi@0 63 /**
danielebarchiesi@0 64 * File permission check -- File is not readable.
danielebarchiesi@0 65 */
danielebarchiesi@0 66 define('FILE_NOT_READABLE', 32);
danielebarchiesi@0 67
danielebarchiesi@0 68 /**
danielebarchiesi@0 69 * File permission check -- File is not writable.
danielebarchiesi@0 70 */
danielebarchiesi@0 71 define('FILE_NOT_WRITABLE', 64);
danielebarchiesi@0 72
danielebarchiesi@0 73 /**
danielebarchiesi@0 74 * File permission check -- File is not executable.
danielebarchiesi@0 75 */
danielebarchiesi@0 76 define('FILE_NOT_EXECUTABLE', 128);
danielebarchiesi@0 77
danielebarchiesi@0 78 /**
danielebarchiesi@0 79 * Loads .install files for installed modules to initialize the update system.
danielebarchiesi@0 80 */
danielebarchiesi@0 81 function drupal_load_updates() {
danielebarchiesi@0 82 foreach (drupal_get_installed_schema_version(NULL, FALSE, TRUE) as $module => $schema_version) {
danielebarchiesi@0 83 if ($schema_version > -1) {
danielebarchiesi@0 84 module_load_install($module);
danielebarchiesi@0 85 }
danielebarchiesi@0 86 }
danielebarchiesi@0 87 }
danielebarchiesi@0 88
danielebarchiesi@0 89 /**
danielebarchiesi@0 90 * Returns an array of available schema versions for a module.
danielebarchiesi@0 91 *
danielebarchiesi@0 92 * @param $module
danielebarchiesi@0 93 * A module name.
danielebarchiesi@0 94 * @return
danielebarchiesi@0 95 * If the module has updates, an array of available updates sorted by version.
danielebarchiesi@0 96 * Otherwise, FALSE.
danielebarchiesi@0 97 */
danielebarchiesi@0 98 function drupal_get_schema_versions($module) {
danielebarchiesi@0 99 $updates = &drupal_static(__FUNCTION__, NULL);
danielebarchiesi@0 100 if (!isset($updates[$module])) {
danielebarchiesi@0 101 $updates = array();
danielebarchiesi@0 102
danielebarchiesi@0 103 foreach (module_list() as $loaded_module) {
danielebarchiesi@0 104 $updates[$loaded_module] = array();
danielebarchiesi@0 105 }
danielebarchiesi@0 106
danielebarchiesi@0 107 // Prepare regular expression to match all possible defined hook_update_N().
danielebarchiesi@0 108 $regexp = '/^(?P<module>.+)_update_(?P<version>\d+)$/';
danielebarchiesi@0 109 $functions = get_defined_functions();
danielebarchiesi@0 110 // Narrow this down to functions ending with an integer, since all
danielebarchiesi@0 111 // hook_update_N() functions end this way, and there are other
danielebarchiesi@0 112 // possible functions which match '_update_'. We use preg_grep() here
danielebarchiesi@0 113 // instead of foreaching through all defined functions, since the loop
danielebarchiesi@0 114 // through all PHP functions can take significant page execution time
danielebarchiesi@0 115 // and this function is called on every administrative page via
danielebarchiesi@0 116 // system_requirements().
danielebarchiesi@0 117 foreach (preg_grep('/_\d+$/', $functions['user']) as $function) {
danielebarchiesi@0 118 // If this function is a module update function, add it to the list of
danielebarchiesi@0 119 // module updates.
danielebarchiesi@0 120 if (preg_match($regexp, $function, $matches)) {
danielebarchiesi@0 121 $updates[$matches['module']][] = $matches['version'];
danielebarchiesi@0 122 }
danielebarchiesi@0 123 }
danielebarchiesi@0 124 // Ensure that updates are applied in numerical order.
danielebarchiesi@0 125 foreach ($updates as &$module_updates) {
danielebarchiesi@0 126 sort($module_updates, SORT_NUMERIC);
danielebarchiesi@0 127 }
danielebarchiesi@0 128 }
danielebarchiesi@0 129 return empty($updates[$module]) ? FALSE : $updates[$module];
danielebarchiesi@0 130 }
danielebarchiesi@0 131
danielebarchiesi@0 132 /**
danielebarchiesi@0 133 * Returns the currently installed schema version for a module.
danielebarchiesi@0 134 *
danielebarchiesi@0 135 * @param $module
danielebarchiesi@0 136 * A module name.
danielebarchiesi@0 137 * @param $reset
danielebarchiesi@0 138 * Set to TRUE after modifying the system table.
danielebarchiesi@0 139 * @param $array
danielebarchiesi@0 140 * Set to TRUE if you want to get information about all modules in the
danielebarchiesi@0 141 * system.
danielebarchiesi@0 142 * @return
danielebarchiesi@0 143 * The currently installed schema version, or SCHEMA_UNINSTALLED if the
danielebarchiesi@0 144 * module is not installed.
danielebarchiesi@0 145 */
danielebarchiesi@0 146 function drupal_get_installed_schema_version($module, $reset = FALSE, $array = FALSE) {
danielebarchiesi@0 147 static $versions = array();
danielebarchiesi@0 148
danielebarchiesi@0 149 if ($reset) {
danielebarchiesi@0 150 $versions = array();
danielebarchiesi@0 151 }
danielebarchiesi@0 152
danielebarchiesi@0 153 if (!$versions) {
danielebarchiesi@0 154 $versions = array();
danielebarchiesi@0 155 $result = db_query("SELECT name, schema_version FROM {system} WHERE type = :type", array(':type' => 'module'));
danielebarchiesi@0 156 foreach ($result as $row) {
danielebarchiesi@0 157 $versions[$row->name] = $row->schema_version;
danielebarchiesi@0 158 }
danielebarchiesi@0 159 }
danielebarchiesi@0 160
danielebarchiesi@0 161 if ($array) {
danielebarchiesi@0 162 return $versions;
danielebarchiesi@0 163 }
danielebarchiesi@0 164 else {
danielebarchiesi@0 165 return isset($versions[$module]) ? $versions[$module] : SCHEMA_UNINSTALLED;
danielebarchiesi@0 166 }
danielebarchiesi@0 167 }
danielebarchiesi@0 168
danielebarchiesi@0 169 /**
danielebarchiesi@0 170 * Update the installed version information for a module.
danielebarchiesi@0 171 *
danielebarchiesi@0 172 * @param $module
danielebarchiesi@0 173 * A module name.
danielebarchiesi@0 174 * @param $version
danielebarchiesi@0 175 * The new schema version.
danielebarchiesi@0 176 */
danielebarchiesi@0 177 function drupal_set_installed_schema_version($module, $version) {
danielebarchiesi@0 178 db_update('system')
danielebarchiesi@0 179 ->fields(array('schema_version' => $version))
danielebarchiesi@0 180 ->condition('name', $module)
danielebarchiesi@0 181 ->execute();
danielebarchiesi@0 182
danielebarchiesi@0 183 // Reset the static cache of module schema versions.
danielebarchiesi@0 184 drupal_get_installed_schema_version(NULL, TRUE);
danielebarchiesi@0 185 }
danielebarchiesi@0 186
danielebarchiesi@0 187 /**
danielebarchiesi@0 188 * Loads the installation profile, extracting its defined distribution name.
danielebarchiesi@0 189 *
danielebarchiesi@0 190 * @return
danielebarchiesi@0 191 * The distribution name defined in the profile's .info file. Defaults to
danielebarchiesi@0 192 * "Drupal" if none is explicitly provided by the installation profile.
danielebarchiesi@0 193 *
danielebarchiesi@0 194 * @see install_profile_info()
danielebarchiesi@0 195 */
danielebarchiesi@0 196 function drupal_install_profile_distribution_name() {
danielebarchiesi@0 197 // During installation, the profile information is stored in the global
danielebarchiesi@0 198 // installation state (it might not be saved anywhere yet).
danielebarchiesi@0 199 if (drupal_installation_attempted()) {
danielebarchiesi@0 200 global $install_state;
danielebarchiesi@0 201 return $install_state['profile_info']['distribution_name'];
danielebarchiesi@0 202 }
danielebarchiesi@0 203 // At all other times, we load the profile via standard methods.
danielebarchiesi@0 204 else {
danielebarchiesi@0 205 $profile = drupal_get_profile();
danielebarchiesi@0 206 $info = system_get_info('module', $profile);
danielebarchiesi@0 207 return $info['distribution_name'];
danielebarchiesi@0 208 }
danielebarchiesi@0 209 }
danielebarchiesi@0 210
danielebarchiesi@0 211 /**
danielebarchiesi@0 212 * Detects the base URL using the PHP $_SERVER variables.
danielebarchiesi@0 213 *
danielebarchiesi@0 214 * @param $file
danielebarchiesi@0 215 * The name of the file calling this function so we can strip it out of
danielebarchiesi@0 216 * the URI when generating the base_url.
danielebarchiesi@0 217 *
danielebarchiesi@0 218 * @return
danielebarchiesi@0 219 * The auto-detected $base_url that should be configured in settings.php
danielebarchiesi@0 220 */
danielebarchiesi@0 221 function drupal_detect_baseurl($file = 'install.php') {
danielebarchiesi@0 222 $proto = $_SERVER['HTTPS'] ? 'https://' : 'http://';
danielebarchiesi@0 223 $host = $_SERVER['SERVER_NAME'];
danielebarchiesi@0 224 $port = ($_SERVER['SERVER_PORT'] == 80 ? '' : ':' . $_SERVER['SERVER_PORT']);
danielebarchiesi@0 225 $uri = preg_replace("/\?.*/", '', $_SERVER['REQUEST_URI']);
danielebarchiesi@0 226 $dir = str_replace("/$file", '', $uri);
danielebarchiesi@0 227
danielebarchiesi@0 228 return "$proto$host$port$dir";
danielebarchiesi@0 229 }
danielebarchiesi@0 230
danielebarchiesi@0 231 /**
danielebarchiesi@0 232 * Detects all supported databases that are compiled into PHP.
danielebarchiesi@0 233 *
danielebarchiesi@0 234 * @return
danielebarchiesi@0 235 * An array of database types compiled into PHP.
danielebarchiesi@0 236 */
danielebarchiesi@0 237 function drupal_detect_database_types() {
danielebarchiesi@0 238 $databases = drupal_get_database_types();
danielebarchiesi@0 239
danielebarchiesi@0 240 foreach ($databases as $driver => $installer) {
danielebarchiesi@0 241 $databases[$driver] = $installer->name();
danielebarchiesi@0 242 }
danielebarchiesi@0 243
danielebarchiesi@0 244 return $databases;
danielebarchiesi@0 245 }
danielebarchiesi@0 246
danielebarchiesi@0 247 /**
danielebarchiesi@0 248 * Returns all supported database installer objects that are compiled into PHP.
danielebarchiesi@0 249 *
danielebarchiesi@0 250 * @return
danielebarchiesi@0 251 * An array of database installer objects compiled into PHP.
danielebarchiesi@0 252 */
danielebarchiesi@0 253 function drupal_get_database_types() {
danielebarchiesi@0 254 $databases = array();
danielebarchiesi@0 255
danielebarchiesi@0 256 // We define a driver as a directory in /includes/database that in turn
danielebarchiesi@0 257 // contains a database.inc file. That allows us to drop in additional drivers
danielebarchiesi@0 258 // without modifying the installer.
danielebarchiesi@0 259 // Because we have no registry yet, we need to also include the install.inc
danielebarchiesi@0 260 // file for the driver explicitly.
danielebarchiesi@0 261 require_once DRUPAL_ROOT . '/includes/database/database.inc';
danielebarchiesi@0 262 foreach (file_scan_directory(DRUPAL_ROOT . '/includes/database', '/^[a-z]*$/i', array('recurse' => FALSE)) as $file) {
danielebarchiesi@0 263 if (file_exists($file->uri . '/database.inc') && file_exists($file->uri . '/install.inc')) {
danielebarchiesi@0 264 $drivers[$file->filename] = $file->uri;
danielebarchiesi@0 265 }
danielebarchiesi@0 266 }
danielebarchiesi@0 267
danielebarchiesi@0 268 foreach ($drivers as $driver => $file) {
danielebarchiesi@0 269 $installer = db_installer_object($driver);
danielebarchiesi@0 270 if ($installer->installable()) {
danielebarchiesi@0 271 $databases[$driver] = $installer;
danielebarchiesi@0 272 }
danielebarchiesi@0 273 }
danielebarchiesi@0 274
danielebarchiesi@0 275 // Usability: unconditionally put the MySQL driver on top.
danielebarchiesi@0 276 if (isset($databases['mysql'])) {
danielebarchiesi@0 277 $mysql_database = $databases['mysql'];
danielebarchiesi@0 278 unset($databases['mysql']);
danielebarchiesi@0 279 $databases = array('mysql' => $mysql_database) + $databases;
danielebarchiesi@0 280 }
danielebarchiesi@0 281
danielebarchiesi@0 282 return $databases;
danielebarchiesi@0 283 }
danielebarchiesi@0 284
danielebarchiesi@0 285 /**
danielebarchiesi@0 286 * Database installer structure.
danielebarchiesi@0 287 *
danielebarchiesi@0 288 * Defines basic Drupal requirements for databases.
danielebarchiesi@0 289 */
danielebarchiesi@0 290 abstract class DatabaseTasks {
danielebarchiesi@0 291
danielebarchiesi@0 292 /**
danielebarchiesi@0 293 * Structure that describes each task to run.
danielebarchiesi@0 294 *
danielebarchiesi@0 295 * @var array
danielebarchiesi@0 296 *
danielebarchiesi@0 297 * Each value of the tasks array is an associative array defining the function
danielebarchiesi@0 298 * to call (optional) and any arguments to be passed to the function.
danielebarchiesi@0 299 */
danielebarchiesi@0 300 protected $tasks = array(
danielebarchiesi@0 301 array(
danielebarchiesi@0 302 'function' => 'checkEngineVersion',
danielebarchiesi@0 303 'arguments' => array(),
danielebarchiesi@0 304 ),
danielebarchiesi@0 305 array(
danielebarchiesi@0 306 'arguments' => array(
danielebarchiesi@0 307 'CREATE TABLE {drupal_install_test} (id int NULL)',
danielebarchiesi@0 308 'Drupal can use CREATE TABLE database commands.',
danielebarchiesi@0 309 'Failed to <strong>CREATE</strong> a test table on your database server with the command %query. The server reports the following message: %error.<p>Are you sure the configured username has the necessary permissions to create tables in the database?</p>',
danielebarchiesi@0 310 TRUE,
danielebarchiesi@0 311 ),
danielebarchiesi@0 312 ),
danielebarchiesi@0 313 array(
danielebarchiesi@0 314 'arguments' => array(
danielebarchiesi@0 315 'INSERT INTO {drupal_install_test} (id) VALUES (1)',
danielebarchiesi@0 316 'Drupal can use INSERT database commands.',
danielebarchiesi@0 317 'Failed to <strong>INSERT</strong> a value into a test table on your database server. We tried inserting a value with the command %query and the server reported the following error: %error.',
danielebarchiesi@0 318 ),
danielebarchiesi@0 319 ),
danielebarchiesi@0 320 array(
danielebarchiesi@0 321 'arguments' => array(
danielebarchiesi@0 322 'UPDATE {drupal_install_test} SET id = 2',
danielebarchiesi@0 323 'Drupal can use UPDATE database commands.',
danielebarchiesi@0 324 'Failed to <strong>UPDATE</strong> a value in a test table on your database server. We tried updating a value with the command %query and the server reported the following error: %error.',
danielebarchiesi@0 325 ),
danielebarchiesi@0 326 ),
danielebarchiesi@0 327 array(
danielebarchiesi@0 328 'arguments' => array(
danielebarchiesi@0 329 'DELETE FROM {drupal_install_test}',
danielebarchiesi@0 330 'Drupal can use DELETE database commands.',
danielebarchiesi@0 331 'Failed to <strong>DELETE</strong> a value from a test table on your database server. We tried deleting a value with the command %query and the server reported the following error: %error.',
danielebarchiesi@0 332 ),
danielebarchiesi@0 333 ),
danielebarchiesi@0 334 array(
danielebarchiesi@0 335 'arguments' => array(
danielebarchiesi@0 336 'DROP TABLE {drupal_install_test}',
danielebarchiesi@0 337 'Drupal can use DROP TABLE database commands.',
danielebarchiesi@0 338 'Failed to <strong>DROP</strong> a test table from your database server. We tried dropping a table with the command %query and the server reported the following error %error.',
danielebarchiesi@0 339 ),
danielebarchiesi@0 340 ),
danielebarchiesi@0 341 );
danielebarchiesi@0 342
danielebarchiesi@0 343 /**
danielebarchiesi@0 344 * Results from tasks.
danielebarchiesi@0 345 *
danielebarchiesi@0 346 * @var array
danielebarchiesi@0 347 */
danielebarchiesi@0 348 protected $results = array();
danielebarchiesi@0 349
danielebarchiesi@0 350 /**
danielebarchiesi@0 351 * Ensure the PDO driver is supported by the version of PHP in use.
danielebarchiesi@0 352 */
danielebarchiesi@0 353 protected function hasPdoDriver() {
danielebarchiesi@0 354 return in_array($this->pdoDriver, PDO::getAvailableDrivers());
danielebarchiesi@0 355 }
danielebarchiesi@0 356
danielebarchiesi@0 357 /**
danielebarchiesi@0 358 * Assert test as failed.
danielebarchiesi@0 359 */
danielebarchiesi@0 360 protected function fail($message) {
danielebarchiesi@0 361 $this->results[$message] = FALSE;
danielebarchiesi@0 362 }
danielebarchiesi@0 363
danielebarchiesi@0 364 /**
danielebarchiesi@0 365 * Assert test as a pass.
danielebarchiesi@0 366 */
danielebarchiesi@0 367 protected function pass($message) {
danielebarchiesi@0 368 $this->results[$message] = TRUE;
danielebarchiesi@0 369 }
danielebarchiesi@0 370
danielebarchiesi@0 371 /**
danielebarchiesi@0 372 * Check whether Drupal is installable on the database.
danielebarchiesi@0 373 */
danielebarchiesi@0 374 public function installable() {
danielebarchiesi@0 375 return $this->hasPdoDriver() && empty($this->error);
danielebarchiesi@0 376 }
danielebarchiesi@0 377
danielebarchiesi@0 378 /**
danielebarchiesi@0 379 * Return the human-readable name of the driver.
danielebarchiesi@0 380 */
danielebarchiesi@0 381 abstract public function name();
danielebarchiesi@0 382
danielebarchiesi@0 383 /**
danielebarchiesi@0 384 * Return the minimum required version of the engine.
danielebarchiesi@0 385 *
danielebarchiesi@0 386 * @return
danielebarchiesi@0 387 * A version string. If not NULL, it will be checked against the version
danielebarchiesi@0 388 * reported by the Database engine using version_compare().
danielebarchiesi@0 389 */
danielebarchiesi@0 390 public function minimumVersion() {
danielebarchiesi@0 391 return NULL;
danielebarchiesi@0 392 }
danielebarchiesi@0 393
danielebarchiesi@0 394 /**
danielebarchiesi@0 395 * Run database tasks and tests to see if Drupal can run on the database.
danielebarchiesi@0 396 */
danielebarchiesi@0 397 public function runTasks() {
danielebarchiesi@0 398 // We need to establish a connection before we can run tests.
danielebarchiesi@0 399 if ($this->connect()) {
danielebarchiesi@0 400 foreach ($this->tasks as $task) {
danielebarchiesi@0 401 if (!isset($task['function'])) {
danielebarchiesi@0 402 $task['function'] = 'runTestQuery';
danielebarchiesi@0 403 }
danielebarchiesi@0 404 if (method_exists($this, $task['function'])) {
danielebarchiesi@0 405 // Returning false is fatal. No other tasks can run.
danielebarchiesi@0 406 if (FALSE === call_user_func_array(array($this, $task['function']), $task['arguments'])) {
danielebarchiesi@0 407 break;
danielebarchiesi@0 408 }
danielebarchiesi@0 409 }
danielebarchiesi@0 410 else {
danielebarchiesi@0 411 throw new DatabaseTaskException(st("Failed to run all tasks against the database server. The task %task wasn't found.", array('%task' => $task['function'])));
danielebarchiesi@0 412 }
danielebarchiesi@0 413 }
danielebarchiesi@0 414 }
danielebarchiesi@0 415 // Check for failed results and compile message
danielebarchiesi@0 416 $message = '';
danielebarchiesi@0 417 foreach ($this->results as $result => $success) {
danielebarchiesi@0 418 if (!$success) {
danielebarchiesi@0 419 $message .= '<p class="error">' . $result . '</p>';
danielebarchiesi@0 420 }
danielebarchiesi@0 421 }
danielebarchiesi@0 422 if (!empty($message)) {
danielebarchiesi@0 423 $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/getting-started/install">installation handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.</p>' . $message;
danielebarchiesi@0 424 throw new DatabaseTaskException($message);
danielebarchiesi@0 425 }
danielebarchiesi@0 426 }
danielebarchiesi@0 427
danielebarchiesi@0 428 /**
danielebarchiesi@0 429 * Check if we can connect to the database.
danielebarchiesi@0 430 */
danielebarchiesi@0 431 protected function connect() {
danielebarchiesi@0 432 try {
danielebarchiesi@0 433 // This doesn't actually test the connection.
danielebarchiesi@0 434 db_set_active();
danielebarchiesi@0 435 // Now actually do a check.
danielebarchiesi@0 436 Database::getConnection();
danielebarchiesi@0 437 $this->pass('Drupal can CONNECT to the database ok.');
danielebarchiesi@0 438 }
danielebarchiesi@0 439 catch (Exception $e) {
danielebarchiesi@0 440 $this->fail(st('Failed to connect to your database server. The server reports the following message: %error.<ul><li>Is the database server running?</li><li>Does the database exist, and have you entered the correct database name?</li><li>Have you entered the correct username and password?</li><li>Have you entered the correct database hostname?</li></ul>', array('%error' => $e->getMessage())));
danielebarchiesi@0 441 return FALSE;
danielebarchiesi@0 442 }
danielebarchiesi@0 443 return TRUE;
danielebarchiesi@0 444 }
danielebarchiesi@0 445
danielebarchiesi@0 446 /**
danielebarchiesi@0 447 * Run SQL tests to ensure the database can execute commands with the current user.
danielebarchiesi@0 448 */
danielebarchiesi@0 449 protected function runTestQuery($query, $pass, $fail, $fatal = FALSE) {
danielebarchiesi@0 450 try {
danielebarchiesi@0 451 db_query($query);
danielebarchiesi@0 452 $this->pass(st($pass));
danielebarchiesi@0 453 }
danielebarchiesi@0 454 catch (Exception $e) {
danielebarchiesi@0 455 $this->fail(st($fail, array('%query' => $query, '%error' => $e->getMessage(), '%name' => $this->name())));
danielebarchiesi@0 456 return !$fatal;
danielebarchiesi@0 457 }
danielebarchiesi@0 458 }
danielebarchiesi@0 459
danielebarchiesi@0 460 /**
danielebarchiesi@0 461 * Check the engine version.
danielebarchiesi@0 462 */
danielebarchiesi@0 463 protected function checkEngineVersion() {
danielebarchiesi@0 464 if ($this->minimumVersion() && version_compare(Database::getConnection()->version(), $this->minimumVersion(), '<')) {
danielebarchiesi@0 465 $this->fail(st("The database version %version is less than the minimum required version %minimum_version.", array('%version' => Database::getConnection()->version(), '%minimum_version' => $this->minimumVersion())));
danielebarchiesi@0 466 }
danielebarchiesi@0 467 }
danielebarchiesi@0 468
danielebarchiesi@0 469 /**
danielebarchiesi@0 470 * Return driver specific configuration options.
danielebarchiesi@0 471 *
danielebarchiesi@0 472 * @param $database
danielebarchiesi@0 473 * An array of driver specific configuration options.
danielebarchiesi@0 474 *
danielebarchiesi@0 475 * @return
danielebarchiesi@0 476 * The options form array.
danielebarchiesi@0 477 */
danielebarchiesi@0 478 public function getFormOptions($database) {
danielebarchiesi@0 479 $form['database'] = array(
danielebarchiesi@0 480 '#type' => 'textfield',
danielebarchiesi@0 481 '#title' => st('Database name'),
danielebarchiesi@0 482 '#default_value' => empty($database['database']) ? '' : $database['database'],
danielebarchiesi@0 483 '#size' => 45,
danielebarchiesi@0 484 '#required' => TRUE,
danielebarchiesi@0 485 '#description' => st('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => drupal_install_profile_distribution_name())),
danielebarchiesi@0 486 );
danielebarchiesi@0 487
danielebarchiesi@0 488 $form['username'] = array(
danielebarchiesi@0 489 '#type' => 'textfield',
danielebarchiesi@0 490 '#title' => st('Database username'),
danielebarchiesi@0 491 '#default_value' => empty($database['username']) ? '' : $database['username'],
danielebarchiesi@0 492 '#required' => TRUE,
danielebarchiesi@0 493 '#size' => 45,
danielebarchiesi@0 494 );
danielebarchiesi@0 495
danielebarchiesi@0 496 $form['password'] = array(
danielebarchiesi@0 497 '#type' => 'password',
danielebarchiesi@0 498 '#title' => st('Database password'),
danielebarchiesi@0 499 '#default_value' => empty($database['password']) ? '' : $database['password'],
danielebarchiesi@0 500 '#required' => FALSE,
danielebarchiesi@0 501 '#size' => 45,
danielebarchiesi@0 502 );
danielebarchiesi@0 503
danielebarchiesi@0 504 $form['advanced_options'] = array(
danielebarchiesi@0 505 '#type' => 'fieldset',
danielebarchiesi@0 506 '#title' => st('Advanced options'),
danielebarchiesi@0 507 '#collapsible' => TRUE,
danielebarchiesi@0 508 '#collapsed' => TRUE,
danielebarchiesi@0 509 '#description' => st("These options are only necessary for some sites. If you're not sure what you should enter here, leave the default settings or check with your hosting provider."),
danielebarchiesi@0 510 '#weight' => 10,
danielebarchiesi@0 511 );
danielebarchiesi@0 512
danielebarchiesi@0 513 $profile = drupal_get_profile();
danielebarchiesi@0 514 $db_prefix = ($profile == 'standard') ? 'drupal_' : $profile . '_';
danielebarchiesi@0 515 $form['advanced_options']['db_prefix'] = array(
danielebarchiesi@0 516 '#type' => 'textfield',
danielebarchiesi@0 517 '#title' => st('Table prefix'),
danielebarchiesi@0 518 '#default_value' => '',
danielebarchiesi@0 519 '#size' => 45,
danielebarchiesi@0 520 '#description' => st('If more than one application will be sharing this database, enter a table prefix such as %prefix for your @drupal site here.', array('@drupal' => drupal_install_profile_distribution_name(), '%prefix' => $db_prefix)),
danielebarchiesi@0 521 '#weight' => 10,
danielebarchiesi@0 522 );
danielebarchiesi@0 523
danielebarchiesi@0 524 $form['advanced_options']['host'] = array(
danielebarchiesi@0 525 '#type' => 'textfield',
danielebarchiesi@0 526 '#title' => st('Database host'),
danielebarchiesi@0 527 '#default_value' => empty($database['host']) ? 'localhost' : $database['host'],
danielebarchiesi@0 528 '#size' => 45,
danielebarchiesi@0 529 // Hostnames can be 255 characters long.
danielebarchiesi@0 530 '#maxlength' => 255,
danielebarchiesi@0 531 '#required' => TRUE,
danielebarchiesi@0 532 '#description' => st('If your database is located on a different server, change this.'),
danielebarchiesi@0 533 );
danielebarchiesi@0 534
danielebarchiesi@0 535 $form['advanced_options']['port'] = array(
danielebarchiesi@0 536 '#type' => 'textfield',
danielebarchiesi@0 537 '#title' => st('Database port'),
danielebarchiesi@0 538 '#default_value' => empty($database['port']) ? '' : $database['port'],
danielebarchiesi@0 539 '#size' => 45,
danielebarchiesi@0 540 // The maximum port number is 65536, 5 digits.
danielebarchiesi@0 541 '#maxlength' => 5,
danielebarchiesi@0 542 '#description' => st('If your database server is listening to a non-standard port, enter its number.'),
danielebarchiesi@0 543 );
danielebarchiesi@0 544
danielebarchiesi@0 545 return $form;
danielebarchiesi@0 546 }
danielebarchiesi@0 547
danielebarchiesi@0 548 /**
danielebarchiesi@0 549 * Validates driver specific configuration settings.
danielebarchiesi@0 550 *
danielebarchiesi@0 551 * Checks to ensure correct basic database settings and that a proper
danielebarchiesi@0 552 * connection to the database can be established.
danielebarchiesi@0 553 *
danielebarchiesi@0 554 * @param $database
danielebarchiesi@0 555 * An array of driver specific configuration options.
danielebarchiesi@0 556 *
danielebarchiesi@0 557 * @return
danielebarchiesi@0 558 * An array of driver configuration errors, keyed by form element name.
danielebarchiesi@0 559 */
danielebarchiesi@0 560 public function validateDatabaseSettings($database) {
danielebarchiesi@0 561 $errors = array();
danielebarchiesi@0 562
danielebarchiesi@0 563 // Verify the table prefix.
danielebarchiesi@0 564 if (!empty($database['prefix']) && is_string($database['prefix']) && !preg_match('/^[A-Za-z0-9_.]+$/', $database['prefix'])) {
danielebarchiesi@0 565 $errors[$database['driver'] . '][advanced_options][db_prefix'] = st('The database table prefix you have entered, %prefix, is invalid. The table prefix can only contain alphanumeric characters, periods, or underscores.', array('%prefix' => $database['prefix']));
danielebarchiesi@0 566 }
danielebarchiesi@0 567
danielebarchiesi@0 568 // Verify the database port.
danielebarchiesi@0 569 if (!empty($database['port']) && !is_numeric($database['port'])) {
danielebarchiesi@0 570 $errors[$database['driver'] . '][advanced_options][port'] = st('Database port must be a number.');
danielebarchiesi@0 571 }
danielebarchiesi@0 572
danielebarchiesi@0 573 return $errors;
danielebarchiesi@0 574 }
danielebarchiesi@0 575
danielebarchiesi@0 576 }
danielebarchiesi@0 577
danielebarchiesi@0 578 /**
danielebarchiesi@0 579 * Exception thrown if the database installer fails.
danielebarchiesi@0 580 */
danielebarchiesi@0 581 class DatabaseTaskException extends Exception {
danielebarchiesi@0 582 }
danielebarchiesi@0 583
danielebarchiesi@0 584 /**
danielebarchiesi@0 585 * Replaces values in settings.php with values in the submitted array.
danielebarchiesi@0 586 *
danielebarchiesi@0 587 * @param $settings
danielebarchiesi@0 588 * An array of settings that need to be updated.
danielebarchiesi@0 589 */
danielebarchiesi@0 590 function drupal_rewrite_settings($settings = array(), $prefix = '') {
danielebarchiesi@0 591 $default_settings = 'sites/default/default.settings.php';
danielebarchiesi@0 592 drupal_static_reset('conf_path');
danielebarchiesi@0 593 $settings_file = conf_path(FALSE) . '/' . $prefix . 'settings.php';
danielebarchiesi@0 594
danielebarchiesi@0 595 // Build list of setting names and insert the values into the global namespace.
danielebarchiesi@0 596 $keys = array();
danielebarchiesi@0 597 foreach ($settings as $setting => $data) {
danielebarchiesi@0 598 $GLOBALS[$setting] = $data['value'];
danielebarchiesi@0 599 $keys[] = $setting;
danielebarchiesi@0 600 }
danielebarchiesi@0 601
danielebarchiesi@0 602 $buffer = NULL;
danielebarchiesi@0 603 $first = TRUE;
danielebarchiesi@0 604 if ($fp = fopen(DRUPAL_ROOT . '/' . $default_settings, 'r')) {
danielebarchiesi@0 605 // Step line by line through settings.php.
danielebarchiesi@0 606 while (!feof($fp)) {
danielebarchiesi@0 607 $line = fgets($fp);
danielebarchiesi@0 608 if ($first && substr($line, 0, 5) != '<?php') {
danielebarchiesi@0 609 $buffer = "<?php\n\n";
danielebarchiesi@0 610 }
danielebarchiesi@0 611 $first = FALSE;
danielebarchiesi@0 612 // Check for constants.
danielebarchiesi@0 613 if (substr($line, 0, 7) == 'define(') {
danielebarchiesi@0 614 preg_match('/define\(\s*[\'"]([A-Z_-]+)[\'"]\s*,(.*?)\);/', $line, $variable);
danielebarchiesi@0 615 if (in_array($variable[1], $keys)) {
danielebarchiesi@0 616 $setting = $settings[$variable[1]];
danielebarchiesi@0 617 $buffer .= str_replace($variable[2], " '" . $setting['value'] . "'", $line);
danielebarchiesi@0 618 unset($settings[$variable[1]]);
danielebarchiesi@0 619 unset($settings[$variable[2]]);
danielebarchiesi@0 620 }
danielebarchiesi@0 621 else {
danielebarchiesi@0 622 $buffer .= $line;
danielebarchiesi@0 623 }
danielebarchiesi@0 624 }
danielebarchiesi@0 625 // Check for variables.
danielebarchiesi@0 626 elseif (substr($line, 0, 1) == '$') {
danielebarchiesi@0 627 preg_match('/\$([^ ]*) /', $line, $variable);
danielebarchiesi@0 628 if (in_array($variable[1], $keys)) {
danielebarchiesi@0 629 // Write new value to settings.php in the following format:
danielebarchiesi@0 630 // $'setting' = 'value'; // 'comment'
danielebarchiesi@0 631 $setting = $settings[$variable[1]];
danielebarchiesi@0 632 $buffer .= '$' . $variable[1] . " = " . var_export($setting['value'], TRUE) . ";" . (!empty($setting['comment']) ? ' // ' . $setting['comment'] . "\n" : "\n");
danielebarchiesi@0 633 unset($settings[$variable[1]]);
danielebarchiesi@0 634 }
danielebarchiesi@0 635 else {
danielebarchiesi@0 636 $buffer .= $line;
danielebarchiesi@0 637 }
danielebarchiesi@0 638 }
danielebarchiesi@0 639 else {
danielebarchiesi@0 640 $buffer .= $line;
danielebarchiesi@0 641 }
danielebarchiesi@0 642 }
danielebarchiesi@0 643 fclose($fp);
danielebarchiesi@0 644
danielebarchiesi@0 645 // Add required settings that were missing from settings.php.
danielebarchiesi@0 646 foreach ($settings as $setting => $data) {
danielebarchiesi@0 647 if ($data['required']) {
danielebarchiesi@0 648 $buffer .= "\$$setting = " . var_export($data['value'], TRUE) . ";\n";
danielebarchiesi@0 649 }
danielebarchiesi@0 650 }
danielebarchiesi@0 651
danielebarchiesi@0 652 $fp = fopen(DRUPAL_ROOT . '/' . $settings_file, 'w');
danielebarchiesi@0 653 if ($fp && fwrite($fp, $buffer) === FALSE) {
danielebarchiesi@0 654 throw new Exception(st('Failed to modify %settings. Verify the file permissions.', array('%settings' => $settings_file)));
danielebarchiesi@0 655 }
danielebarchiesi@0 656 }
danielebarchiesi@0 657 else {
danielebarchiesi@0 658 throw new Exception(st('Failed to open %settings. Verify the file permissions.', array('%settings' => $default_settings)));
danielebarchiesi@0 659 }
danielebarchiesi@0 660 }
danielebarchiesi@0 661
danielebarchiesi@0 662 /**
danielebarchiesi@0 663 * Verifies an installation profile for installation.
danielebarchiesi@0 664 *
danielebarchiesi@0 665 * @param $install_state
danielebarchiesi@0 666 * An array of information about the current installation state.
danielebarchiesi@0 667 *
danielebarchiesi@0 668 * @return
danielebarchiesi@0 669 * The list of modules to install.
danielebarchiesi@0 670 */
danielebarchiesi@0 671 function drupal_verify_profile($install_state) {
danielebarchiesi@0 672 $profile = $install_state['parameters']['profile'];
danielebarchiesi@0 673 $locale = $install_state['parameters']['locale'];
danielebarchiesi@0 674
danielebarchiesi@0 675 include_once DRUPAL_ROOT . '/includes/file.inc';
danielebarchiesi@0 676 include_once DRUPAL_ROOT . '/includes/common.inc';
danielebarchiesi@0 677
danielebarchiesi@0 678 $profile_file = DRUPAL_ROOT . "/profiles/$profile/$profile.profile";
danielebarchiesi@0 679
danielebarchiesi@0 680 if (!isset($profile) || !file_exists($profile_file)) {
danielebarchiesi@0 681 throw new Exception(install_no_profile_error());
danielebarchiesi@0 682 }
danielebarchiesi@0 683 $info = $install_state['profile_info'];
danielebarchiesi@0 684
danielebarchiesi@0 685 // Get a list of modules that exist in Drupal's assorted subdirectories.
danielebarchiesi@0 686 $present_modules = array();
danielebarchiesi@0 687 foreach (drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules', 'name', 0) as $present_module) {
danielebarchiesi@0 688 $present_modules[] = $present_module->name;
danielebarchiesi@0 689 }
danielebarchiesi@0 690
danielebarchiesi@0 691 // The installation profile is also a module, which needs to be installed
danielebarchiesi@0 692 // after all the other dependencies have been installed.
danielebarchiesi@0 693 $present_modules[] = drupal_get_profile();
danielebarchiesi@0 694
danielebarchiesi@0 695 // Verify that all of the profile's required modules are present.
danielebarchiesi@0 696 $missing_modules = array_diff($info['dependencies'], $present_modules);
danielebarchiesi@0 697
danielebarchiesi@0 698 $requirements = array();
danielebarchiesi@0 699
danielebarchiesi@0 700 if (count($missing_modules)) {
danielebarchiesi@0 701 $modules = array();
danielebarchiesi@0 702 foreach ($missing_modules as $module) {
danielebarchiesi@0 703 $modules[] = '<span class="admin-missing">' . drupal_ucfirst($module) . '</span>';
danielebarchiesi@0 704 }
danielebarchiesi@0 705 $requirements['required_modules'] = array(
danielebarchiesi@0 706 'title' => st('Required modules'),
danielebarchiesi@0 707 'value' => st('Required modules not found.'),
danielebarchiesi@0 708 'severity' => REQUIREMENT_ERROR,
danielebarchiesi@0 709 'description' => st('The following modules are required but were not found. Move them into the appropriate modules subdirectory, such as <em>sites/all/modules</em>. Missing modules: !modules', array('!modules' => implode(', ', $modules))),
danielebarchiesi@0 710 );
danielebarchiesi@0 711 }
danielebarchiesi@0 712 return $requirements;
danielebarchiesi@0 713 }
danielebarchiesi@0 714
danielebarchiesi@0 715 /**
danielebarchiesi@0 716 * Installs the system module.
danielebarchiesi@0 717 *
danielebarchiesi@0 718 * Separated from the installation of other modules so core system
danielebarchiesi@0 719 * functions can be made available while other modules are installed.
danielebarchiesi@0 720 */
danielebarchiesi@0 721 function drupal_install_system() {
danielebarchiesi@0 722 $system_path = drupal_get_path('module', 'system');
danielebarchiesi@0 723 require_once DRUPAL_ROOT . '/' . $system_path . '/system.install';
danielebarchiesi@0 724 module_invoke('system', 'install');
danielebarchiesi@0 725
danielebarchiesi@0 726 $system_versions = drupal_get_schema_versions('system');
danielebarchiesi@0 727 $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED;
danielebarchiesi@0 728 db_insert('system')
danielebarchiesi@0 729 ->fields(array('filename', 'name', 'type', 'owner', 'status', 'schema_version', 'bootstrap'))
danielebarchiesi@0 730 ->values(array(
danielebarchiesi@0 731 'filename' => $system_path . '/system.module',
danielebarchiesi@0 732 'name' => 'system',
danielebarchiesi@0 733 'type' => 'module',
danielebarchiesi@0 734 'owner' => '',
danielebarchiesi@0 735 'status' => 1,
danielebarchiesi@0 736 'schema_version' => $system_version,
danielebarchiesi@0 737 'bootstrap' => 0,
danielebarchiesi@0 738 ))
danielebarchiesi@0 739 ->execute();
danielebarchiesi@0 740 system_rebuild_module_data();
danielebarchiesi@0 741 }
danielebarchiesi@0 742
danielebarchiesi@0 743 /**
danielebarchiesi@0 744 * Uninstalls a given list of disabled modules.
danielebarchiesi@0 745 *
danielebarchiesi@0 746 * @param array $module_list
danielebarchiesi@0 747 * The modules to uninstall. It is the caller's responsibility to ensure that
danielebarchiesi@0 748 * all modules in this list have already been disabled before this function
danielebarchiesi@0 749 * is called.
danielebarchiesi@0 750 * @param bool $uninstall_dependents
danielebarchiesi@0 751 * (optional) If TRUE, the function will check that all modules which depend
danielebarchiesi@0 752 * on the passed-in module list either are already uninstalled or contained in
danielebarchiesi@0 753 * the list, and it will ensure that the modules are uninstalled in the
danielebarchiesi@0 754 * correct order. This incurs a significant performance cost, so use FALSE if
danielebarchiesi@0 755 * you know $module_list is already complete and in the correct order.
danielebarchiesi@0 756 * Defaults to TRUE.
danielebarchiesi@0 757 *
danielebarchiesi@0 758 * @return bool
danielebarchiesi@0 759 * Returns TRUE if the operation succeeds or FALSE if it aborts due to an
danielebarchiesi@0 760 * unsafe condition, namely, $uninstall_dependents is TRUE and a module in
danielebarchiesi@0 761 * $module_list has dependents which are not already uninstalled and not also
danielebarchiesi@0 762 * included in $module_list).
danielebarchiesi@0 763 *
danielebarchiesi@0 764 * @see module_disable()
danielebarchiesi@0 765 */
danielebarchiesi@0 766 function drupal_uninstall_modules($module_list = array(), $uninstall_dependents = TRUE) {
danielebarchiesi@0 767 if ($uninstall_dependents) {
danielebarchiesi@0 768 // Get all module data so we can find dependents and sort.
danielebarchiesi@0 769 $module_data = system_rebuild_module_data();
danielebarchiesi@0 770 // Create an associative array with weights as values.
danielebarchiesi@0 771 $module_list = array_flip(array_values($module_list));
danielebarchiesi@0 772
danielebarchiesi@0 773 $profile = drupal_get_profile();
danielebarchiesi@0 774 while (list($module) = each($module_list)) {
danielebarchiesi@0 775 if (!isset($module_data[$module]) || drupal_get_installed_schema_version($module) == SCHEMA_UNINSTALLED) {
danielebarchiesi@0 776 // This module doesn't exist or is already uninstalled. Skip it.
danielebarchiesi@0 777 unset($module_list[$module]);
danielebarchiesi@0 778 continue;
danielebarchiesi@0 779 }
danielebarchiesi@0 780 $module_list[$module] = $module_data[$module]->sort;
danielebarchiesi@0 781
danielebarchiesi@0 782 // If the module has any dependents which are not already uninstalled and
danielebarchiesi@0 783 // not included in the passed-in list, abort. It is not safe to uninstall
danielebarchiesi@0 784 // them automatically because uninstalling a module is a destructive
danielebarchiesi@0 785 // operation.
danielebarchiesi@0 786 foreach (array_keys($module_data[$module]->required_by) as $dependent) {
danielebarchiesi@0 787 if (!isset($module_list[$dependent]) && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED && $dependent != $profile) {
danielebarchiesi@0 788 return FALSE;
danielebarchiesi@0 789 }
danielebarchiesi@0 790 }
danielebarchiesi@0 791 }
danielebarchiesi@0 792
danielebarchiesi@0 793 // Sort the module list by pre-calculated weights.
danielebarchiesi@0 794 asort($module_list);
danielebarchiesi@0 795 $module_list = array_keys($module_list);
danielebarchiesi@0 796 }
danielebarchiesi@0 797
danielebarchiesi@0 798 foreach ($module_list as $module) {
danielebarchiesi@0 799 // Uninstall the module.
danielebarchiesi@0 800 module_load_install($module);
danielebarchiesi@0 801 module_invoke($module, 'uninstall');
danielebarchiesi@0 802 drupal_uninstall_schema($module);
danielebarchiesi@0 803
danielebarchiesi@0 804 watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO);
danielebarchiesi@0 805 drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED);
danielebarchiesi@0 806 }
danielebarchiesi@0 807
danielebarchiesi@0 808 if (!empty($module_list)) {
danielebarchiesi@0 809 // Let other modules react.
danielebarchiesi@0 810 module_invoke_all('modules_uninstalled', $module_list);
danielebarchiesi@0 811 }
danielebarchiesi@0 812
danielebarchiesi@0 813 return TRUE;
danielebarchiesi@0 814 }
danielebarchiesi@0 815
danielebarchiesi@0 816 /**
danielebarchiesi@0 817 * Verifies the state of the specified file.
danielebarchiesi@0 818 *
danielebarchiesi@0 819 * @param $file
danielebarchiesi@0 820 * The file to check for.
danielebarchiesi@0 821 * @param $mask
danielebarchiesi@0 822 * An optional bitmask created from various FILE_* constants.
danielebarchiesi@0 823 * @param $type
danielebarchiesi@0 824 * The type of file. Can be file (default), dir, or link.
danielebarchiesi@0 825 *
danielebarchiesi@0 826 * @return
danielebarchiesi@0 827 * TRUE on success or FALSE on failure. A message is set for the latter.
danielebarchiesi@0 828 */
danielebarchiesi@0 829 function drupal_verify_install_file($file, $mask = NULL, $type = 'file') {
danielebarchiesi@0 830 $return = TRUE;
danielebarchiesi@0 831 // Check for files that shouldn't be there.
danielebarchiesi@0 832 if (isset($mask) && ($mask & FILE_NOT_EXIST) && file_exists($file)) {
danielebarchiesi@0 833 return FALSE;
danielebarchiesi@0 834 }
danielebarchiesi@0 835 // Verify that the file is the type of file it is supposed to be.
danielebarchiesi@0 836 if (isset($type) && file_exists($file)) {
danielebarchiesi@0 837 $check = 'is_' . $type;
danielebarchiesi@0 838 if (!function_exists($check) || !$check($file)) {
danielebarchiesi@0 839 $return = FALSE;
danielebarchiesi@0 840 }
danielebarchiesi@0 841 }
danielebarchiesi@0 842
danielebarchiesi@0 843 // Verify file permissions.
danielebarchiesi@0 844 if (isset($mask)) {
danielebarchiesi@0 845 $masks = array(FILE_EXIST, FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE);
danielebarchiesi@0 846 foreach ($masks as $current_mask) {
danielebarchiesi@0 847 if ($mask & $current_mask) {
danielebarchiesi@0 848 switch ($current_mask) {
danielebarchiesi@0 849 case FILE_EXIST:
danielebarchiesi@0 850 if (!file_exists($file)) {
danielebarchiesi@0 851 if ($type == 'dir') {
danielebarchiesi@0 852 drupal_install_mkdir($file, $mask);
danielebarchiesi@0 853 }
danielebarchiesi@0 854 if (!file_exists($file)) {
danielebarchiesi@0 855 $return = FALSE;
danielebarchiesi@0 856 }
danielebarchiesi@0 857 }
danielebarchiesi@0 858 break;
danielebarchiesi@0 859 case FILE_READABLE:
danielebarchiesi@0 860 if (!is_readable($file) && !drupal_install_fix_file($file, $mask)) {
danielebarchiesi@0 861 $return = FALSE;
danielebarchiesi@0 862 }
danielebarchiesi@0 863 break;
danielebarchiesi@0 864 case FILE_WRITABLE:
danielebarchiesi@0 865 if (!is_writable($file) && !drupal_install_fix_file($file, $mask)) {
danielebarchiesi@0 866 $return = FALSE;
danielebarchiesi@0 867 }
danielebarchiesi@0 868 break;
danielebarchiesi@0 869 case FILE_EXECUTABLE:
danielebarchiesi@0 870 if (!is_executable($file) && !drupal_install_fix_file($file, $mask)) {
danielebarchiesi@0 871 $return = FALSE;
danielebarchiesi@0 872 }
danielebarchiesi@0 873 break;
danielebarchiesi@0 874 case FILE_NOT_READABLE:
danielebarchiesi@0 875 if (is_readable($file) && !drupal_install_fix_file($file, $mask)) {
danielebarchiesi@0 876 $return = FALSE;
danielebarchiesi@0 877 }
danielebarchiesi@0 878 break;
danielebarchiesi@0 879 case FILE_NOT_WRITABLE:
danielebarchiesi@0 880 if (is_writable($file) && !drupal_install_fix_file($file, $mask)) {
danielebarchiesi@0 881 $return = FALSE;
danielebarchiesi@0 882 }
danielebarchiesi@0 883 break;
danielebarchiesi@0 884 case FILE_NOT_EXECUTABLE:
danielebarchiesi@0 885 if (is_executable($file) && !drupal_install_fix_file($file, $mask)) {
danielebarchiesi@0 886 $return = FALSE;
danielebarchiesi@0 887 }
danielebarchiesi@0 888 break;
danielebarchiesi@0 889 }
danielebarchiesi@0 890 }
danielebarchiesi@0 891 }
danielebarchiesi@0 892 }
danielebarchiesi@0 893 return $return;
danielebarchiesi@0 894 }
danielebarchiesi@0 895
danielebarchiesi@0 896 /**
danielebarchiesi@0 897 * Creates a directory with the specified permissions.
danielebarchiesi@0 898 *
danielebarchiesi@0 899 * @param $file
danielebarchiesi@0 900 * The name of the directory to create;
danielebarchiesi@0 901 * @param $mask
danielebarchiesi@0 902 * The permissions of the directory to create.
danielebarchiesi@0 903 * @param $message
danielebarchiesi@0 904 * (optional) Whether to output messages. Defaults to TRUE.
danielebarchiesi@0 905 *
danielebarchiesi@0 906 * @return
danielebarchiesi@0 907 * TRUE/FALSE whether or not the directory was successfully created.
danielebarchiesi@0 908 */
danielebarchiesi@0 909 function drupal_install_mkdir($file, $mask, $message = TRUE) {
danielebarchiesi@0 910 $mod = 0;
danielebarchiesi@0 911 $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE);
danielebarchiesi@0 912 foreach ($masks as $m) {
danielebarchiesi@0 913 if ($mask & $m) {
danielebarchiesi@0 914 switch ($m) {
danielebarchiesi@0 915 case FILE_READABLE:
danielebarchiesi@0 916 $mod |= 0444;
danielebarchiesi@0 917 break;
danielebarchiesi@0 918 case FILE_WRITABLE:
danielebarchiesi@0 919 $mod |= 0222;
danielebarchiesi@0 920 break;
danielebarchiesi@0 921 case FILE_EXECUTABLE:
danielebarchiesi@0 922 $mod |= 0111;
danielebarchiesi@0 923 break;
danielebarchiesi@0 924 }
danielebarchiesi@0 925 }
danielebarchiesi@0 926 }
danielebarchiesi@0 927
danielebarchiesi@0 928 if (@drupal_mkdir($file, $mod)) {
danielebarchiesi@0 929 return TRUE;
danielebarchiesi@0 930 }
danielebarchiesi@0 931 else {
danielebarchiesi@0 932 return FALSE;
danielebarchiesi@0 933 }
danielebarchiesi@0 934 }
danielebarchiesi@0 935
danielebarchiesi@0 936 /**
danielebarchiesi@0 937 * Attempts to fix file permissions.
danielebarchiesi@0 938 *
danielebarchiesi@0 939 * The general approach here is that, because we do not know the security
danielebarchiesi@0 940 * setup of the webserver, we apply our permission changes to all three
danielebarchiesi@0 941 * digits of the file permission (i.e. user, group and all).
danielebarchiesi@0 942 *
danielebarchiesi@0 943 * To ensure that the values behave as expected (and numbers don't carry
danielebarchiesi@0 944 * from one digit to the next) we do the calculation on the octal value
danielebarchiesi@0 945 * using bitwise operations. This lets us remove, for example, 0222 from
danielebarchiesi@0 946 * 0700 and get the correct value of 0500.
danielebarchiesi@0 947 *
danielebarchiesi@0 948 * @param $file
danielebarchiesi@0 949 * The name of the file with permissions to fix.
danielebarchiesi@0 950 * @param $mask
danielebarchiesi@0 951 * The desired permissions for the file.
danielebarchiesi@0 952 * @param $message
danielebarchiesi@0 953 * (optional) Whether to output messages. Defaults to TRUE.
danielebarchiesi@0 954 *
danielebarchiesi@0 955 * @return
danielebarchiesi@0 956 * TRUE/FALSE whether or not we were able to fix the file's permissions.
danielebarchiesi@0 957 */
danielebarchiesi@0 958 function drupal_install_fix_file($file, $mask, $message = TRUE) {
danielebarchiesi@0 959 // If $file does not exist, fileperms() issues a PHP warning.
danielebarchiesi@0 960 if (!file_exists($file)) {
danielebarchiesi@0 961 return FALSE;
danielebarchiesi@0 962 }
danielebarchiesi@0 963
danielebarchiesi@0 964 $mod = fileperms($file) & 0777;
danielebarchiesi@0 965 $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE);
danielebarchiesi@0 966
danielebarchiesi@0 967 // FILE_READABLE, FILE_WRITABLE, and FILE_EXECUTABLE permission strings
danielebarchiesi@0 968 // can theoretically be 0400, 0200, and 0100 respectively, but to be safe
danielebarchiesi@0 969 // we set all three access types in case the administrator intends to
danielebarchiesi@0 970 // change the owner of settings.php after installation.
danielebarchiesi@0 971 foreach ($masks as $m) {
danielebarchiesi@0 972 if ($mask & $m) {
danielebarchiesi@0 973 switch ($m) {
danielebarchiesi@0 974 case FILE_READABLE:
danielebarchiesi@0 975 if (!is_readable($file)) {
danielebarchiesi@0 976 $mod |= 0444;
danielebarchiesi@0 977 }
danielebarchiesi@0 978 break;
danielebarchiesi@0 979 case FILE_WRITABLE:
danielebarchiesi@0 980 if (!is_writable($file)) {
danielebarchiesi@0 981 $mod |= 0222;
danielebarchiesi@0 982 }
danielebarchiesi@0 983 break;
danielebarchiesi@0 984 case FILE_EXECUTABLE:
danielebarchiesi@0 985 if (!is_executable($file)) {
danielebarchiesi@0 986 $mod |= 0111;
danielebarchiesi@0 987 }
danielebarchiesi@0 988 break;
danielebarchiesi@0 989 case FILE_NOT_READABLE:
danielebarchiesi@0 990 if (is_readable($file)) {
danielebarchiesi@0 991 $mod &= ~0444;
danielebarchiesi@0 992 }
danielebarchiesi@0 993 break;
danielebarchiesi@0 994 case FILE_NOT_WRITABLE:
danielebarchiesi@0 995 if (is_writable($file)) {
danielebarchiesi@0 996 $mod &= ~0222;
danielebarchiesi@0 997 }
danielebarchiesi@0 998 break;
danielebarchiesi@0 999 case FILE_NOT_EXECUTABLE:
danielebarchiesi@0 1000 if (is_executable($file)) {
danielebarchiesi@0 1001 $mod &= ~0111;
danielebarchiesi@0 1002 }
danielebarchiesi@0 1003 break;
danielebarchiesi@0 1004 }
danielebarchiesi@0 1005 }
danielebarchiesi@0 1006 }
danielebarchiesi@0 1007
danielebarchiesi@0 1008 // chmod() will work if the web server is running as owner of the file.
danielebarchiesi@0 1009 // If PHP safe_mode is enabled the currently executing script must also
danielebarchiesi@0 1010 // have the same owner.
danielebarchiesi@0 1011 if (@chmod($file, $mod)) {
danielebarchiesi@0 1012 return TRUE;
danielebarchiesi@0 1013 }
danielebarchiesi@0 1014 else {
danielebarchiesi@0 1015 return FALSE;
danielebarchiesi@0 1016 }
danielebarchiesi@0 1017 }
danielebarchiesi@0 1018
danielebarchiesi@0 1019 /**
danielebarchiesi@0 1020 * Sends the user to a different installer page.
danielebarchiesi@0 1021 *
danielebarchiesi@0 1022 * This issues an on-site HTTP redirect. Messages (and errors) are erased.
danielebarchiesi@0 1023 *
danielebarchiesi@0 1024 * @param $path
danielebarchiesi@0 1025 * An installer path.
danielebarchiesi@0 1026 */
danielebarchiesi@0 1027 function install_goto($path) {
danielebarchiesi@0 1028 global $base_url;
danielebarchiesi@0 1029 include_once DRUPAL_ROOT . '/includes/common.inc';
danielebarchiesi@0 1030 header('Location: ' . $base_url . '/' . $path);
danielebarchiesi@0 1031 header('Cache-Control: no-cache'); // Not a permanent redirect.
danielebarchiesi@0 1032 drupal_exit();
danielebarchiesi@0 1033 }
danielebarchiesi@0 1034
danielebarchiesi@0 1035 /**
danielebarchiesi@0 1036 * Returns the URL of the current script, with modified query parameters.
danielebarchiesi@0 1037 *
danielebarchiesi@0 1038 * This function can be called by low-level scripts (such as install.php and
danielebarchiesi@0 1039 * update.php) and returns the URL of the current script. Existing query
danielebarchiesi@0 1040 * parameters are preserved by default, but new ones can optionally be merged
danielebarchiesi@0 1041 * in.
danielebarchiesi@0 1042 *
danielebarchiesi@0 1043 * This function is used when the script must maintain certain query parameters
danielebarchiesi@0 1044 * over multiple page requests in order to work correctly. In such cases (for
danielebarchiesi@0 1045 * example, update.php, which requires the 'continue=1' parameter to remain in
danielebarchiesi@0 1046 * the URL throughout the update process if there are any requirement warnings
danielebarchiesi@0 1047 * that need to be bypassed), using this function to generate the URL for links
danielebarchiesi@0 1048 * to the next steps of the script ensures that the links will work correctly.
danielebarchiesi@0 1049 *
danielebarchiesi@0 1050 * @param $query
danielebarchiesi@0 1051 * (optional) An array of query parameters to merge in to the existing ones.
danielebarchiesi@0 1052 *
danielebarchiesi@0 1053 * @return
danielebarchiesi@0 1054 * The URL of the current script, with query parameters modified by the
danielebarchiesi@0 1055 * passed-in $query. The URL is not sanitized, so it still needs to be run
danielebarchiesi@0 1056 * through check_url() if it will be used as an HTML attribute value.
danielebarchiesi@0 1057 *
danielebarchiesi@0 1058 * @see drupal_requirements_url()
danielebarchiesi@0 1059 */
danielebarchiesi@0 1060 function drupal_current_script_url($query = array()) {
danielebarchiesi@0 1061 $uri = $_SERVER['SCRIPT_NAME'];
danielebarchiesi@0 1062 $query = array_merge(drupal_get_query_parameters(), $query);
danielebarchiesi@0 1063 if (!empty($query)) {
danielebarchiesi@0 1064 $uri .= '?' . drupal_http_build_query($query);
danielebarchiesi@0 1065 }
danielebarchiesi@0 1066 return $uri;
danielebarchiesi@0 1067 }
danielebarchiesi@0 1068
danielebarchiesi@0 1069 /**
danielebarchiesi@0 1070 * Returns a URL for proceeding to the next page after a requirements problem.
danielebarchiesi@0 1071 *
danielebarchiesi@0 1072 * This function can be called by low-level scripts (such as install.php and
danielebarchiesi@0 1073 * update.php) and returns a URL that can be used to attempt to proceed to the
danielebarchiesi@0 1074 * next step of the script.
danielebarchiesi@0 1075 *
danielebarchiesi@0 1076 * @param $severity
danielebarchiesi@0 1077 * The severity of the requirements problem, as returned by
danielebarchiesi@0 1078 * drupal_requirements_severity().
danielebarchiesi@0 1079 *
danielebarchiesi@0 1080 * @return
danielebarchiesi@0 1081 * A URL for attempting to proceed to the next step of the script. The URL is
danielebarchiesi@0 1082 * not sanitized, so it still needs to be run through check_url() if it will
danielebarchiesi@0 1083 * be used as an HTML attribute value.
danielebarchiesi@0 1084 *
danielebarchiesi@0 1085 * @see drupal_current_script_url()
danielebarchiesi@0 1086 */
danielebarchiesi@0 1087 function drupal_requirements_url($severity) {
danielebarchiesi@0 1088 $query = array();
danielebarchiesi@0 1089 // If there are no errors, only warnings, append 'continue=1' to the URL so
danielebarchiesi@0 1090 // the user can bypass this screen on the next page load.
danielebarchiesi@0 1091 if ($severity == REQUIREMENT_WARNING) {
danielebarchiesi@0 1092 $query['continue'] = 1;
danielebarchiesi@0 1093 }
danielebarchiesi@0 1094 return drupal_current_script_url($query);
danielebarchiesi@0 1095 }
danielebarchiesi@0 1096
danielebarchiesi@0 1097 /**
danielebarchiesi@0 1098 * Translates a string when some systems are not available.
danielebarchiesi@0 1099 *
danielebarchiesi@0 1100 * Used during the install process, when database, theme, and localization
danielebarchiesi@0 1101 * system is possibly not yet available.
danielebarchiesi@0 1102 *
danielebarchiesi@0 1103 * Use t() if your code will never run during the Drupal installation phase.
danielebarchiesi@0 1104 * Use st() if your code will only run during installation and never any other
danielebarchiesi@0 1105 * time. Use get_t() if your code could run in either circumstance.
danielebarchiesi@0 1106 *
danielebarchiesi@0 1107 * @see t()
danielebarchiesi@0 1108 * @see get_t()
danielebarchiesi@0 1109 * @ingroup sanitization
danielebarchiesi@0 1110 */
danielebarchiesi@0 1111 function st($string, array $args = array(), array $options = array()) {
danielebarchiesi@0 1112 static $locale_strings = NULL;
danielebarchiesi@0 1113 global $install_state;
danielebarchiesi@0 1114
danielebarchiesi@0 1115 if (empty($options['context'])) {
danielebarchiesi@0 1116 $options['context'] = '';
danielebarchiesi@0 1117 }
danielebarchiesi@0 1118
danielebarchiesi@0 1119 if (!isset($locale_strings)) {
danielebarchiesi@0 1120 $locale_strings = array();
danielebarchiesi@0 1121 if (isset($install_state['parameters']['profile']) && isset($install_state['parameters']['locale'])) {
danielebarchiesi@0 1122 // If the given locale was selected, there should be at least one .po file
danielebarchiesi@0 1123 // with its name ending in {$install_state['parameters']['locale']}.po
danielebarchiesi@0 1124 // This might or might not be the entire filename. It is also possible
danielebarchiesi@0 1125 // that multiple files end with the same extension, even if unlikely.
danielebarchiesi@0 1126 $po_files = file_scan_directory('./profiles/' . $install_state['parameters']['profile'] . '/translations', '/'. $install_state['parameters']['locale'] .'\.po$/', array('recurse' => FALSE));
danielebarchiesi@0 1127 if (count($po_files)) {
danielebarchiesi@0 1128 require_once DRUPAL_ROOT . '/includes/locale.inc';
danielebarchiesi@0 1129 foreach ($po_files as $po_file) {
danielebarchiesi@0 1130 _locale_import_read_po('mem-store', $po_file);
danielebarchiesi@0 1131 }
danielebarchiesi@0 1132 $locale_strings = _locale_import_one_string('mem-report');
danielebarchiesi@0 1133 }
danielebarchiesi@0 1134 }
danielebarchiesi@0 1135 }
danielebarchiesi@0 1136
danielebarchiesi@0 1137 require_once DRUPAL_ROOT . '/includes/theme.inc';
danielebarchiesi@0 1138 // Transform arguments before inserting them
danielebarchiesi@0 1139 foreach ($args as $key => $value) {
danielebarchiesi@0 1140 switch ($key[0]) {
danielebarchiesi@0 1141 // Escaped only
danielebarchiesi@0 1142 case '@':
danielebarchiesi@0 1143 $args[$key] = check_plain($value);
danielebarchiesi@0 1144 break;
danielebarchiesi@0 1145 // Escaped and placeholder
danielebarchiesi@0 1146 case '%':
danielebarchiesi@0 1147 default:
danielebarchiesi@0 1148 $args[$key] = '<em>' . check_plain($value) . '</em>';
danielebarchiesi@0 1149 break;
danielebarchiesi@0 1150 // Pass-through
danielebarchiesi@0 1151 case '!':
danielebarchiesi@0 1152 }
danielebarchiesi@0 1153 }
danielebarchiesi@0 1154 return strtr((!empty($locale_strings[$options['context']][$string]) ? $locale_strings[$options['context']][$string] : $string), $args);
danielebarchiesi@0 1155 }
danielebarchiesi@0 1156
danielebarchiesi@0 1157 /**
danielebarchiesi@0 1158 * Checks an installation profile's requirements.
danielebarchiesi@0 1159 *
danielebarchiesi@0 1160 * @param $profile
danielebarchiesi@0 1161 * Name of installation profile to check.
danielebarchiesi@0 1162 * @return
danielebarchiesi@0 1163 * Array of the installation profile's requirements.
danielebarchiesi@0 1164 */
danielebarchiesi@0 1165 function drupal_check_profile($profile) {
danielebarchiesi@0 1166 include_once DRUPAL_ROOT . '/includes/file.inc';
danielebarchiesi@0 1167
danielebarchiesi@0 1168 $profile_file = DRUPAL_ROOT . "/profiles/$profile/$profile.profile";
danielebarchiesi@0 1169
danielebarchiesi@0 1170 if (!isset($profile) || !file_exists($profile_file)) {
danielebarchiesi@0 1171 throw new Exception(install_no_profile_error());
danielebarchiesi@0 1172 }
danielebarchiesi@0 1173
danielebarchiesi@0 1174 $info = install_profile_info($profile);
danielebarchiesi@0 1175
danielebarchiesi@0 1176 // Collect requirement testing results.
danielebarchiesi@0 1177 $requirements = array();
danielebarchiesi@0 1178 foreach ($info['dependencies'] as $module) {
danielebarchiesi@0 1179 module_load_install($module);
danielebarchiesi@0 1180 $function = $module . '_requirements';
danielebarchiesi@0 1181 if (function_exists($function)) {
danielebarchiesi@0 1182 $requirements = array_merge($requirements, $function('install'));
danielebarchiesi@0 1183 }
danielebarchiesi@0 1184 }
danielebarchiesi@0 1185 return $requirements;
danielebarchiesi@0 1186 }
danielebarchiesi@0 1187
danielebarchiesi@0 1188 /**
danielebarchiesi@0 1189 * Extracts the highest severity from the requirements array.
danielebarchiesi@0 1190 *
danielebarchiesi@0 1191 * @param $requirements
danielebarchiesi@0 1192 * An array of requirements, in the same format as is returned by
danielebarchiesi@0 1193 * hook_requirements().
danielebarchiesi@0 1194 *
danielebarchiesi@0 1195 * @return
danielebarchiesi@0 1196 * The highest severity in the array.
danielebarchiesi@0 1197 */
danielebarchiesi@0 1198 function drupal_requirements_severity(&$requirements) {
danielebarchiesi@0 1199 $severity = REQUIREMENT_OK;
danielebarchiesi@0 1200 foreach ($requirements as $requirement) {
danielebarchiesi@0 1201 if (isset($requirement['severity'])) {
danielebarchiesi@0 1202 $severity = max($severity, $requirement['severity']);
danielebarchiesi@0 1203 }
danielebarchiesi@0 1204 }
danielebarchiesi@0 1205 return $severity;
danielebarchiesi@0 1206 }
danielebarchiesi@0 1207
danielebarchiesi@0 1208 /**
danielebarchiesi@0 1209 * Checks a module's requirements.
danielebarchiesi@0 1210 *
danielebarchiesi@0 1211 * @param $module
danielebarchiesi@0 1212 * Machine name of module to check.
danielebarchiesi@0 1213 *
danielebarchiesi@0 1214 * @return
danielebarchiesi@0 1215 * TRUE or FALSE, depending on whether the requirements are met.
danielebarchiesi@0 1216 */
danielebarchiesi@0 1217 function drupal_check_module($module) {
danielebarchiesi@0 1218 module_load_install($module);
danielebarchiesi@0 1219 if (module_hook($module, 'requirements')) {
danielebarchiesi@0 1220 // Check requirements
danielebarchiesi@0 1221 $requirements = module_invoke($module, 'requirements', 'install');
danielebarchiesi@0 1222 if (is_array($requirements) && drupal_requirements_severity($requirements) == REQUIREMENT_ERROR) {
danielebarchiesi@0 1223 // Print any error messages
danielebarchiesi@0 1224 foreach ($requirements as $requirement) {
danielebarchiesi@0 1225 if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) {
danielebarchiesi@0 1226 $message = $requirement['description'];
danielebarchiesi@0 1227 if (isset($requirement['value']) && $requirement['value']) {
danielebarchiesi@0 1228 $message .= ' (' . t('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) . ')';
danielebarchiesi@0 1229 }
danielebarchiesi@0 1230 drupal_set_message($message, 'error');
danielebarchiesi@0 1231 }
danielebarchiesi@0 1232 }
danielebarchiesi@0 1233 return FALSE;
danielebarchiesi@0 1234 }
danielebarchiesi@0 1235 }
danielebarchiesi@0 1236 return TRUE;
danielebarchiesi@0 1237 }
danielebarchiesi@0 1238
danielebarchiesi@0 1239 /**
danielebarchiesi@0 1240 * Retrieves information about an installation profile from its .info file.
danielebarchiesi@0 1241 *
danielebarchiesi@0 1242 * The information stored in a profile .info file is similar to that stored in
danielebarchiesi@0 1243 * a normal Drupal module .info file. For example:
danielebarchiesi@0 1244 * - name: The real name of the installation profile for display purposes.
danielebarchiesi@0 1245 * - description: A brief description of the profile.
danielebarchiesi@0 1246 * - dependencies: An array of shortnames of other modules that this install
danielebarchiesi@0 1247 * profile requires.
danielebarchiesi@0 1248 *
danielebarchiesi@0 1249 * Additional, less commonly-used information that can appear in a profile.info
danielebarchiesi@0 1250 * file but not in a normal Drupal module .info file includes:
danielebarchiesi@0 1251 * - distribution_name: The name of the Drupal distribution that is being
danielebarchiesi@0 1252 * installed, to be shown throughout the installation process. Defaults to
danielebarchiesi@0 1253 * 'Drupal'.
danielebarchiesi@0 1254 * - exclusive: If the install profile is intended to be the only eligible
danielebarchiesi@0 1255 * choice in a distribution, setting exclusive = TRUE will auto-select it
danielebarchiesi@0 1256 * during installation, and the install profile selection screen will be
danielebarchiesi@0 1257 * skipped. If more than one profile is found where exclusive = TRUE then
danielebarchiesi@0 1258 * this property will have no effect and the profile selection screen will
danielebarchiesi@0 1259 * be shown as normal with all available profiles shown.
danielebarchiesi@0 1260 *
danielebarchiesi@0 1261 * Note that this function does an expensive file system scan to get info file
danielebarchiesi@0 1262 * information for dependencies. If you only need information from the info
danielebarchiesi@0 1263 * file itself, use system_get_info().
danielebarchiesi@0 1264 *
danielebarchiesi@0 1265 * Example of .info file:
danielebarchiesi@0 1266 * @code
danielebarchiesi@0 1267 * name = Minimal
danielebarchiesi@0 1268 * description = Start fresh, with only a few modules enabled.
danielebarchiesi@0 1269 * dependencies[] = block
danielebarchiesi@0 1270 * dependencies[] = dblog
danielebarchiesi@0 1271 * @endcode
danielebarchiesi@0 1272 *
danielebarchiesi@0 1273 * @param $profile
danielebarchiesi@0 1274 * Name of profile.
danielebarchiesi@0 1275 * @param $locale
danielebarchiesi@0 1276 * Name of locale used (if any).
danielebarchiesi@0 1277 *
danielebarchiesi@0 1278 * @return
danielebarchiesi@0 1279 * The info array.
danielebarchiesi@0 1280 */
danielebarchiesi@0 1281 function install_profile_info($profile, $locale = 'en') {
danielebarchiesi@0 1282 $cache = &drupal_static(__FUNCTION__, array());
danielebarchiesi@0 1283
danielebarchiesi@0 1284 if (!isset($cache[$profile])) {
danielebarchiesi@0 1285 // Set defaults for module info.
danielebarchiesi@0 1286 $defaults = array(
danielebarchiesi@0 1287 'dependencies' => array(),
danielebarchiesi@0 1288 'description' => '',
danielebarchiesi@0 1289 'distribution_name' => 'Drupal',
danielebarchiesi@0 1290 'version' => NULL,
danielebarchiesi@0 1291 'hidden' => FALSE,
danielebarchiesi@0 1292 'php' => DRUPAL_MINIMUM_PHP,
danielebarchiesi@0 1293 );
danielebarchiesi@0 1294 $info = drupal_parse_info_file("profiles/$profile/$profile.info") + $defaults;
danielebarchiesi@0 1295 $info['dependencies'] = array_unique(array_merge(
danielebarchiesi@0 1296 drupal_required_modules(),
danielebarchiesi@0 1297 $info['dependencies'],
danielebarchiesi@0 1298 ($locale != 'en' && !empty($locale) ? array('locale') : array()))
danielebarchiesi@0 1299 );
danielebarchiesi@0 1300
danielebarchiesi@0 1301 // drupal_required_modules() includes the current profile as a dependency.
danielebarchiesi@0 1302 // Since a module can't depend on itself we remove that element of the array.
danielebarchiesi@0 1303 array_shift($info['dependencies']);
danielebarchiesi@0 1304
danielebarchiesi@0 1305 $cache[$profile] = $info;
danielebarchiesi@0 1306 }
danielebarchiesi@0 1307 return $cache[$profile];
danielebarchiesi@0 1308 }
danielebarchiesi@0 1309
danielebarchiesi@0 1310 /**
danielebarchiesi@0 1311 * Ensures the environment for a Drupal database on a predefined connection.
danielebarchiesi@0 1312 *
danielebarchiesi@0 1313 * This will run tasks that check that Drupal can perform all of the functions
danielebarchiesi@0 1314 * on a database, that Drupal needs. Tasks include simple checks like CREATE
danielebarchiesi@0 1315 * TABLE to database specific functions like stored procedures and client
danielebarchiesi@0 1316 * encoding.
danielebarchiesi@0 1317 */
danielebarchiesi@0 1318 function db_run_tasks($driver) {
danielebarchiesi@0 1319 db_installer_object($driver)->runTasks();
danielebarchiesi@0 1320 return TRUE;
danielebarchiesi@0 1321 }
danielebarchiesi@0 1322
danielebarchiesi@0 1323 /**
danielebarchiesi@0 1324 * Returns a database installer object.
danielebarchiesi@0 1325 *
danielebarchiesi@0 1326 * @param $driver
danielebarchiesi@0 1327 * The name of the driver.
danielebarchiesi@0 1328 */
danielebarchiesi@0 1329 function db_installer_object($driver) {
danielebarchiesi@0 1330 Database::loadDriverFile($driver, array('install.inc'));
danielebarchiesi@0 1331 $task_class = 'DatabaseTasks_' . $driver;
danielebarchiesi@0 1332 return new $task_class();
danielebarchiesi@0 1333 }