Code coverage for /20080809/includes/install.inc

Line #Times calledCode
1
<?php
2
// $Id: install.inc,v 1.62 2008/05/26 17:12:54 dries Exp $
3
4
/**
5
 * Indicates that a module has not been installed yet.
6
 */
788
define('SCHEMA_UNINSTALLED', -1);
8
9
/**
10
 * Indicates that a module has been installed.
11
 */
1288
define('SCHEMA_INSTALLED', 0);
13
14
/**
15
 * Requirement severity -- Informational message only.
16
 */
1788
define('REQUIREMENT_INFO', -1);
18
19
/**
20
 * Requirement severity -- Requirement successfully met.
21
 */
2288
define('REQUIREMENT_OK', 0);
23
24
/**
25
 * Requirement severity -- Warning condition; proceed but flag warning.
26
 */
2788
define('REQUIREMENT_WARNING', 1);
28
29
/**
30
 * Requirement severity -- Error condition; abort installation.
31
 */
3288
define('REQUIREMENT_ERROR', 2);
33
34
/**
35
 * File permission check -- File exists.
36
 */
3788
define('FILE_EXIST', 1);
38
39
/**
40
 * File permission check -- File is readable.
41
 */
4288
define('FILE_READABLE', 2);
43
44
/**
45
 * File permission check -- File is writable.
46
 */
4788
define('FILE_WRITABLE', 4);
48
49
/**
50
 * File permission check -- File is executable.
51
 */
5288
define('FILE_EXECUTABLE', 8);
53
54
/**
55
 * File permission check -- File does not exist.
56
 */
5788
define('FILE_NOT_EXIST', 16);
58
59
/**
60
 * File permission check -- File is not readable.
61
 */
6288
define('FILE_NOT_READABLE', 32);
63
64
/**
65
 * File permission check -- File is not writable.
66
 */
6788
define('FILE_NOT_WRITABLE', 64);
68
69
/**
70
 * File permission check -- File is not executable.
71
 */
7288
define('FILE_NOT_EXECUTABLE', 128);
73
74
/**
75
 * Initialize the update system by loading all installed module's .install
files.
76
 */
7788
function drupal_load_updates() {
783
  foreach (drupal_get_installed_schema_version(NULL, FALSE, TRUE) as
$module => $schema_version) {
793
    if ($schema_version > -1) {
803
      module_load_install($module);
813
    }
823
  }
833
}
84
85
/**
86
 * Returns an array of available schema versions for a module.
87
 *
88
 * @param $module
89
 *   A module name.
90
 * @return
91
 *   If the module has updates, an array of available updates. Otherwise,
92
 *   FALSE.
93
 */
9488
function drupal_get_schema_versions($module) {
9567
  $updates = array();
9667
  $functions = get_defined_functions();
9767
  foreach ($functions['user'] as $function) {
9867
    if (strpos($function, $module . '_update_') === 0) {
9966
      $version = substr($function, strlen($module . '_update_'));
10066
      if (is_numeric($version)) {
10166
        $updates[] = $version;
10266
      }
10366
    }
10467
  }
10567
  if (count($updates) == 0) {
10667
    return FALSE;
1070
  }
10866
  return $updates;
1090
}
110
111
/**
112
 * Returns the currently installed schema version for a module.
113
 *
114
 * @param $module
115
 *   A module name.
116
 * @param $reset
117
 *   Set to TRUE after modifying the system table.
118
 * @param $array
119
 *   Set to TRUE if you want to get information about all modules in the
120
 *   system.
121
 * @return
122
 *   The currently installed schema version.
123
 */
12488
function drupal_get_installed_schema_version($module, $reset = FALSE,
$array = FALSE) {
12569
  static $versions = array();
126
12769
  if ($reset) {
12864
    $versions = array();
12964
  }
130
13169
  if (!$versions) {
13269
    $versions = array();
13369
    $result = db_query("SELECT name, schema_version FROM {system} WHERE
type = '%s'", 'module');
13469
    while ($row = db_fetch_object($result)) {
13569
      $versions[$row->name] = $row->schema_version;
13669
    }
13769
  }
138
13969
  return $array ? $versions : $versions[$module];
1400
}
141
142
/**
143
 * Update the installed version information for a module.
144
 *
145
 * @param $module
146
 *   A module name.
147
 * @param $version
148
 *   The new schema version.
149
 */
15088
function drupal_set_installed_schema_version($module, $version) {
15165
  db_query("UPDATE {system} SET schema_version = %d WHERE name = '%s'",
$version, $module);
15265
}
153
154
/**
155
 * Loads the profile definition, extracting the profile's defined name.
156
 *
157
 * @return
158
 *   The name defined in the profile's _profile_details() hook.
159
 */
16088
function drupal_install_profile_name() {
1610
  global $profile;
1620
  static $name = NULL;
163
1640
  if (!isset($name)) {
165
    // Load profile details.
1660
    $function = $profile . '_profile_details';
1670
    if (function_exists($function)) {
1680
      $details = $function();
1690
    }
1700
    $name = isset($details['name']) ? $details['name'] : 'Drupal';
1710
  }
172
1730
  return $name;
1740
}
175
176
/**
177
 * Auto detect the base_url with PHP predefined variables.
178
 *
179
 * @param $file
180
 *   The name of the file calling this function so we can strip it out of
181
 *   the URI when generating the base_url.
182
 *
183
 * @return
184
 *   The auto-detected $base_url that should be configured in settings.php
185
 */
18688
function drupal_detect_baseurl($file = 'install.php') {
1870
  global $profile;
1880
  $proto = $_SERVER['HTTPS'] ? 'https://' : 'http://';
1890
  $host = $_SERVER['SERVER_NAME'];
1900
  $port = ($_SERVER['SERVER_PORT'] == 80 ? '' : ':' .
$_SERVER['SERVER_PORT']);
1910
  $uri = preg_replace("/\?.*/", '', $_SERVER['REQUEST_URI']);
1920
  $dir = str_replace("/$file", '', $uri);
193
1940
  return "$proto$host$port$dir";
1950
}
196
197
/**
198
 * Detect all databases supported by Drupal that are compiled into the
current
199
 * PHP installation.
200
 *
201
 * @return
202
 *  An array of database types compiled into PHP.
203
 */
20488
function drupal_detect_database_types() {
2050
  $databases = array();
206
2070
  foreach (array('mysql', 'mysqli', 'pgsql') as $type) {
2080
    if (file_exists('./includes/install.' . $type . '.inc')) {
2090
      include_once './includes/install.' . $type . '.inc';
2100
      $function = $type . '_is_available';
2110
      if ($function()) {
2120
        $databases[$type] = $type;
2130
      }
2140
    }
2150
  }
216
2170
  return $databases;
2180
}
219
220
/**
221
 * Read settings.php into a buffer line by line, changing values specified
in
222
 * $settings array, then over-writing the old settings.php file.
223
 *
224
 * @param $settings
225
 *   An array of settings that need to be updated.
226
 */
22788
function drupal_rewrite_settings($settings = array(), $prefix = '') {
2280
  $default_settings = './sites/default/default.settings.php';
2290
  $settings_file = './' . conf_path(FALSE, TRUE) . '/' . $prefix .
'settings.php';
230
231
  // Build list of setting names and insert the values into the global
namespace.
2320
  $keys = array();
2330
  foreach ($settings as $setting => $data) {
2340
    $GLOBALS[$setting] = $data['value'];
2350
    $keys[] = $setting;
2360
  }
237
2380
  $buffer = NULL;
2390
  $first = TRUE;
2400
  if ($fp = fopen($default_settings, 'r')) {
241
    // Step line by line through settings.php.
2420
    while (!feof($fp)) {
2430
      $line = fgets($fp);
2440
      if ($first && substr($line, 0, 5) != '<?php') {
2450
        $buffer = "<?php\n\n";
2460
      }
2470
      $first = FALSE;
248
      // Check for constants.
2490
      if (substr($line, 0, 7) == 'define(') {
2500
        preg_match('/define\(\s*[\'"]([A-Z_-]+)[\'"]\s*,(.*?)\);/', $line,
$variable);
2510
        if (in_array($variable[1], $keys)) {
2520
          $setting = $settings[$variable[1]];
2530
          $buffer .= str_replace($variable[2], " '" . $setting['value'] .
"'", $line);
2540
          unset($settings[$variable[1]]);
2550
          unset($settings[$variable[2]]);
2560
        }
257
        else {
2580
          $buffer .= $line;
259
        }
2600
      }
261
      // Check for variables.
2620
      elseif (substr($line, 0, 1) == '$') {
2630
        preg_match('/\$([^ ]*) /', $line, $variable);
2640
        if (in_array($variable[1], $keys)) {
265
          // Write new value to settings.php in the following format:
266
          //    $'setting' = 'value'; // 'comment'
2670
          $setting = $settings[$variable[1]];
2680
          $buffer .= '$' . $variable[1] . " = '" . $setting['value'] . "';"
. (!empty($setting['comment']) ? ' // ' . $setting['comment'] . "\n" :
"\n");
2690
          unset($settings[$variable[1]]);
2700
        }
271
        else {
2720
          $buffer .= $line;
273
        }
2740
      }
275
      else {
2760
        $buffer .= $line;
277
      }
2780
    }
2790
    fclose($fp);
280
281
    // Add required settings that were missing from settings.php.
2820
    foreach ($settings as $setting => $data) {
2830
      if ($data['required']) {
2840
        $buffer .= "\$$setting = '" . $data['value'] . "';\n";
2850
      }
2860
    }
287
2880
    $fp = fopen($settings_file, 'w');
2890
    if ($fp && fwrite($fp, $buffer) === FALSE) {
2900
      drupal_set_message(st('Failed to modify %settings, please verify the
file permissions.', array('%settings' => $settings_file)), 'error');
2910
    }
2920
  }
293
  else {
2940
    drupal_set_message(st('Failed to open %settings, please verify the file
permissions.', array('%settings' => $default_settings)), 'error');
295
  }
2960
}
297
298
/**
299
 * Get list of all .install files.
300
 *
301
 * @param $module_list
302
 *   An array of modules to search for their .install files.
303
 */
30488
function drupal_get_install_files($module_list = array()) {
3052
  $installs = array();
3062
  foreach ($module_list as $module) {
3072
    $installs = array_merge($installs, drupal_system_listing($module .
'.install$', 'modules'));
3082
  }
3092
  return $installs;
3100
}
311
312
/**
313
 * Verify a profile for installation.
314
 *
315
 * @param profile
316
 *   Name of profile to verify.
317
 * @param locale
318
 *   Name of locale used (if any).
319
 * @return
320
 *   The list of modules to install.
321
 */
32288
function drupal_verify_profile($profile, $locale) {
32362
  include_once './includes/file.inc';
32462
  include_once './includes/common.inc';
325
32662
  $profile_file = "./profiles/$profile/$profile.profile";
327
32862
  if (!isset($profile) || !file_exists($profile_file)) {
3290
    install_no_profile_error();
3300
  }
331
33262
  require_once($profile_file);
333
334
  // Get a list of modules required by this profile.
33562
  $function = $profile . '_profile_modules';
33662
  $module_list = array_merge(drupal_required_modules(), $function(),
($locale != 'en' ? array('locale') : array()));
337
338
  // Get a list of modules that exist in Drupal's assorted subdirectories.
33962
  $present_modules = array();
34062
  foreach (drupal_system_listing('\.module$', 'modules', 'name', 0) as
$present_module) {
34162
    $present_modules[] = $present_module->name;
34262
  }
343
344
  // Verify that all of the profile's required modules are present.
34562
  $missing_modules = array_diff($module_list, $present_modules);
34662
  if (count($missing_modules)) {
3470
    foreach ($missing_modules as $module) {
3480
      drupal_set_message(st('The %module module is required but was not
found. Please move it into the <em>modules</em> subdirectory.',
array('%module' => $module)), 'error');
3490
    }
3500
  }
351
  else {
35262
    return $module_list;
353
  }
3540
}
355
356
/**
357
 * Calls the install function and updates the system table for a given list
of
358
 * modules.
359
 *
360
 * @param module_list
361
 *   The modules to install.
362
 */
36388
function drupal_install_modules($module_list = array()) {
36464
  $files = module_rebuild_cache();
36564
  $module_list = array_flip(array_values($module_list));
366
  do {
36764
    $moved = FALSE;
36864
    foreach ($module_list as $module => $weight) {
36964
      $file = $files[$module];
37064
      if (isset($file->info['dependencies']) &&
is_array($file->info['dependencies'])) {
37164
        foreach ($file->info['dependencies'] as $dependency) {
3724
          if (isset($module_list[$dependency]) && $module_list[$module] <
$module_list[$dependency] +1) {
3731
            $module_list[$module] = $module_list[$dependency] +1;
3741
            $moved = TRUE;
3751
          }
3764
        }
37764
      }
37864
    }
3790
  } while ($moved);
38064
  asort($module_list);
38164
  $module_list = array_keys($module_list);
38264
  array_filter($module_list, '_drupal_install_module');
38364
  module_enable($module_list);
38464
}
385
386
/**
387
 * Callback to install an individual profile module.
388
 *
389
 * Used during installation to install modules one at a time and then
390
 * enable them, or to install a number of modules at one time
391
 * from admin/build/modules.
392
 */
39388
function _drupal_install_module($module) {
39464
  if (drupal_get_installed_schema_version($module, TRUE) ==
SCHEMA_UNINSTALLED) {
39564
    module_load_install($module);
39664
    module_invoke($module, 'install');
39764
    $versions = drupal_get_schema_versions($module);
39864
    drupal_set_installed_schema_version($module, $versions ? max($versions)
: SCHEMA_INSTALLED);
39964
    return TRUE;
4000
  }
40162
}
402
403
/**
404
 * Callback to install the system module.
405
 *
406
 * Separated from the installation of other modules so core system
407
 * functions can be made available while other modules are installed.
408
 */
40988
function drupal_install_system() {
41062
  $system_path = dirname(drupal_get_filename('module', 'system', NULL));
41162
  require_once './' . $system_path . '/system.install';
41262
  module_invoke('system', 'install');
41362
  $system_versions = drupal_get_schema_versions('system');
41462
  $system_version = $system_versions ? max($system_versions) :
SCHEMA_INSTALLED;
41562
  db_query("INSERT INTO {system} (filename, name, type, owner, status,
bootstrap, schema_version) VALUES('%s', '%s', '%s', '%s', %d, %d, %d)",
$system_path . '/system.module', 'system', 'module', '', 1, 0,
$system_version);
416
  // Now that we've installed things properly, bootstrap the full Drupal
environment
41762
  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
41862
  module_rebuild_cache();
41962
}
420
421
422
/**
423
 * Calls the uninstall function and updates the system table for a given
module.
424
 *
425
 * @param $module
426
 *   The module to uninstall.
427
 */
42888
function drupal_uninstall_module($module) {
429
  // First, retrieve all the module's menu paths from db.
4301
  drupal_load('module', $module);
4311
  $paths = module_invoke($module, 'menu');
432
433
  // Uninstall the module(s).
4341
  module_load_install($module);
4351
  module_invoke($module, 'uninstall');
436
437
  // Now remove the menu links for all paths declared by this module.
4381
  if (!empty($paths)) {
4391
    $paths = array_keys($paths);
440
    // Clean out the names of load functions.
4411
    foreach ($paths as $index => $path) {
4421
      $parts = explode('/', $path, MENU_MAX_PARTS);
4431
      foreach ($parts as $k => $part) {
4441
        if (preg_match('/^%[a-z_]*$/', $part)) {
4451
          $parts[$k] = '%';
4461
        }
4471
      }
4481
      $paths[$index] = implode('/', $parts);
4491
    }
4501
    $placeholders = implode(', ', array_fill(0, count($paths), "'%s'"));
451
4521
    $result = db_query('SELECT * FROM {menu_links} WHERE router_path IN ('
. $placeholders . ') AND external = 0 ORDER BY depth DESC', $paths);
453
    // Remove all such items. Starting from those with the greatest depth
will
454
    // minimize the amount of re-parenting done by menu_link_delete().
4551
    while ($item = db_fetch_array($result)) {
4560
      _menu_delete_item($item, TRUE);
4570
    }
4581
  }
459
4601
  drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED);
4611
}
462
463
/**
464
 * Verify the state of the specified file.
465
 *
466
 * @param $file
467
 *   The file to check for.
468
 * @param $mask
469
 *   An optional bitmask created from various FILE_* constants.
470
 * @param $type
471
 *   The type of file. Can be file (default), dir, or link.
472
 * @return
473
 *   TRUE on success or FALSE on failure. A message is set for the latter.
474
 */
47588
function drupal_verify_install_file($file, $mask = NULL, $type = 'file') {
4763
  $return = TRUE;
477
  // Check for files that shouldn't be there.
4783
  if (isset($mask) && ($mask & FILE_NOT_EXIST) && file_exists($file)) {
4790
    return FALSE;
4800
  }
481
  // Verify that the file is the type of file it is supposed to be.
4823
  if (isset($type) && file_exists($file)) {
4833
    $check = 'is_' . $type;
4843
    if (!function_exists($check) || !$check($file)) {
4850
      $return = FALSE;
4860
    }
4873
  }
488
489
  // Verify file permissions.
4903
  if (isset($mask)) {
4913
    $masks = array(FILE_EXIST, FILE_READABLE, FILE_WRITABLE,
FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE,
FILE_NOT_EXECUTABLE);
4923
    foreach ($masks as $current_mask) {
4933
      if ($mask & $current_mask) {
494
        switch ($current_mask) {
4953
          case FILE_EXIST:
4963
            if (!file_exists($file)) {
4970
              if ($type == 'dir') {
4980
                drupal_install_mkdir($file, $mask);
4990
              }
5000
              if (!file_exists($file)) {
5010
                $return = FALSE;
5020
              }
5030
            }
5043
            break;
5053
          case FILE_READABLE:
5063
            if (!is_readable($file) && !drupal_install_fix_file($file,
$mask)) {
5070
              $return = FALSE;
5080
            }
5093
            break;
5103
          case FILE_WRITABLE:
5110
            if (!is_writable($file) && !drupal_install_fix_file($file,
$mask)) {
5120
              $return = FALSE;
5130
            }
5140
            break;
5153
          case FILE_EXECUTABLE:
5160
            if (!is_executable($file) && !drupal_install_fix_file($file,
$mask)) {
5170
              $return = FALSE;
5180
            }
5190
            break;
5203
          case FILE_NOT_READABLE:
5210
            if (is_readable($file) && !drupal_install_fix_file($file,
$mask)) {
5220
              $return = FALSE;
5230
            }
5240
            break;
5253
          case FILE_NOT_WRITABLE:
5263
            if (is_writable($file) && !drupal_install_fix_file($file,
$mask)) {
5273
              $return = FALSE;
5283
            }
5293
            break;
5300
          case FILE_NOT_EXECUTABLE:
5310
            if (is_executable($file) && !drupal_install_fix_file($file,
$mask)) {
5320
              $return = FALSE;
5330
            }
5340
            break;
5350
        }
5363
      }
5373
    }
5383
  }
5393
  return $return;
5400
}
541
542
/**
543
 * Create a directory with specified permissions.
544
 *
545
 * @param file
546
 *  The name of the directory to create;
547
 * @param mask
548
 *  The permissions of the directory to create.
549
 * @param $message
550
 *  (optional) Whether to output messages. Defaults to TRUE.
551
 *
552
 * @return
553
 *  TRUE/FALSE whether or not the directory was successfully created.
554
 */
55588
function drupal_install_mkdir($file, $mask, $message = TRUE) {
5560
  $mod = 0;
5570
  $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE,
FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE);
5580
  foreach ($masks as $m) {
5590
    if ($mask & $m) {
560
      switch ($m) {
5610
        case FILE_READABLE:
5620
          $mod += 444;
5630
          break;
5640
        case FILE_WRITABLE:
5650
          $mod += 222;
5660
          break;
5670
        case FILE_EXECUTABLE:
5680
          $mod += 111;
5690
          break;
5700
      }
5710
    }
5720
  }
573
5740
  if (@mkdir($file, intval("0$mod", 8))) {
5750
    return TRUE;
5760
  }
577
  else {
5780
    return FALSE;
579
  }
5800
}
581
582
/**
583
 * Attempt to fix file permissions.
584
 *
585
 * The general approach here is that, because we do not know the security
586
 * setup of the webserver, we apply our permission changes to all three
587
 * digits of the file permission (i.e. user, group and all).
588
 *
589
 * To ensure that the values behave as expected (and numbers don't carry
590
 * from one digit to the next) we do the calculation on the octal value
591
 * using bitwise operations. This lets us remove, for example, 0222 from
592
 * 0700 and get the correct value of 0500.
593
 *
594
 * @param $file
595
 *  The name of the file with permissions to fix.
596
 * @param $mask
597
 *  The desired permissions for the file.
598
 * @param $message
599
 *  (optional) Whether to output messages. Defaults to TRUE.
600
 *
601
 * @return
602
 *  TRUE/FALSE whether or not we were able to fix the file's permissions.
603
 */
60488
function drupal_install_fix_file($file, $mask, $message = TRUE) {
6053
  $mod = fileperms($file) & 0777;
6063
  $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE,
FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE);
607
608
  // FILE_READABLE, FILE_WRITABLE, and FILE_EXECUTABLE permission strings
609
  // can theoretically be 0400, 0200, and 0100 respectively, but to be
safe
610
  // we set all three access types in case the administrator intends to
611
  // change the owner of settings.php after installation.
6123
  foreach ($masks as $m) {
6133
    if ($mask & $m) {
614
      switch ($m) {
6153
        case FILE_READABLE:
6163
          if (!is_readable($file)) {
6170
            $mod |= 0444;
6180
          }
6193
          break;
6203
        case FILE_WRITABLE:
6210
          if (!is_writable($file)) {
6220
            $mod |= 0222;
6230
          }
6240
          break;
6253
        case FILE_EXECUTABLE:
6260
          if (!is_executable($file)) {
6270
            $mod |= 0111;
6280
          }
6290
          break;
6303
        case FILE_NOT_READABLE:
6310
          if (is_readable($file)) {
6320
            $mod &= ~0444;
6330
          }
6340
          break;
6353
        case FILE_NOT_WRITABLE:
6363
          if (is_writable($file)) {
6373
            $mod &= ~0222;
6383
          }
6393
          break;
6400
        case FILE_NOT_EXECUTABLE:
6410
          if (is_executable($file)) {
6420
            $mod &= ~0111;
6430
          }
6440
          break;
6450
      }
6463
    }
6473
  }
648
649
  // chmod() will work if the web server is running as owner of the file.
650
  // If PHP safe_mode is enabled the currently executing script must also
651
  // have the same owner.
6523
  if (@chmod($file, $mod)) {
6530
    return TRUE;
6540
  }
655
  else {
6563
    return FALSE;
657
  }
6580
}
659
660
661
/**
662
 * Send the user to a different installer page. This issues an on-site
HTTP
663
 * redirect. Messages (and errors) are erased.
664
 *
665
 * @param $path
666
 *   An installer path.
667
 */
66888
function install_goto($path) {
6690
  global $base_url;
6700
  header('Location: ' . $base_url . '/' . $path);
6710
  header('Cache-Control: no-cache'); // Not a permanent redirect.
6720
  exit();
6730
}
674
675
/**
676
 * Hardcoded function for doing the equivalent of t() during
677
 * the install process, when database, theme, and localization
678
 * system is possibly not yet available.
679
 */
68088
function st($string, $args = array()) {
68162
  static $locale_strings = NULL;
68262
  global $profile, $install_locale;
683
68462
  if (!isset($locale_strings)) {
68562
    $locale_strings = array();
68662
    $filename = './profiles/' . $profile . '/translations/' .
$install_locale . '.po';
68762
    if (file_exists($filename)) {
6880
      require_once './includes/locale.inc';
6890
      $file = (object) array('filepath' => $filename);
6900
      _locale_import_read_po('mem-store', $file);
6910
      $locale_strings = _locale_import_one_string('mem-report');
6920
    }
69362
  }
694
69562
  require_once './includes/theme.inc';
696
  // Transform arguments before inserting them
69762
  foreach ($args as $key => $value) {
6980
    switch ($key[0]) {
699
      // Escaped only
7000
      case '@':
7010
        $args[$key] = check_plain($value);
7020
        break;
703
      // Escaped and placeholder
7040
      case '%':
7050
      default:
7060
        $args[$key] = '<em>' . check_plain($value) . '</em>';
7070
        break;
708
      // Pass-through
7090
      case '!':
7100
    }
7110
  }
71262
  return strtr((!empty($locale_strings[$string]) ? $locale_strings[$string]
: $string), $args);
7130
}
714
715
/**
716
 * Check a profile's requirements.
717
 *
718
 * @param profile
719
 *   Name of profile to check.
720
 */
72188
function drupal_check_profile($profile) {
7220
  include_once './includes/file.inc';
723
7240
  $profile_file = "./profiles/$profile/$profile.profile";
725
7260
  if (!isset($profile) || !file_exists($profile_file)) {
7270
    install_no_profile_error();
7280
  }
729
7300
  require_once($profile_file);
731
732
  // Get a list of modules required by this profile.
7330
  $function = $profile . '_profile_modules';
7340
  $module_list = array_unique(array_merge(drupal_required_modules(),
$function()));
735
736
  // Get a list of all .install files.
7370
  $installs = drupal_get_install_files($module_list);
738
739
  // Collect requirement testing results
7400
  $requirements = array();
7410
  foreach ($installs as $install) {
7420
    require_once $install->filename;
7430
    $function = $install->name. '_requirements';
7440
    if (function_exists($function)) {
7450
      $requirements = array_merge($requirements, $function('install'));
7460
    }
7470
  }
7480
  return $requirements;
7490
}
750
751
/**
752
 * Extract highest severity from requirements array.
753
 */
75488
function drupal_requirements_severity(&$requirements) {
7552
  $severity = REQUIREMENT_OK;
7562
  foreach ($requirements as $requirement) {
7572
    if (isset($requirement['severity'])) {
7582
      $severity = max($severity, $requirement['severity']);
7592
    }
7602
  }
7612
  return $severity;
7620
}
763
764
/**
765
 * Check a module's requirements.
766
 */
76788
function drupal_check_module($module) {
768
  // Include install file
7692
  $install = drupal_get_install_files(array($module));
7702
  if (isset($install[$module])) {
7712
    require_once $install[$module]->filename;
772
773
    // Check requirements
7742
    $requirements = module_invoke($module, 'requirements', 'install');
7752
    if (is_array($requirements) &&
drupal_requirements_severity($requirements) == REQUIREMENT_ERROR) {
776
      // Print any error messages
7770
      foreach ($requirements as $requirement) {
7780
        if (isset($requirement['severity']) && $requirement['severity'] ==
REQUIREMENT_ERROR) {
7790
          $message = $requirement['description'];
7800
          if (isset($requirement['value']) && $requirement['value']) {
7810
            $message .= ' (' . t('Currently using !item !version',
array('!item' => $requirement['title'], '!version' =>
$requirement['value'])) . ')';
7820
          }
7830
          drupal_set_message($message, 'error');
7840
        }
7850
      }
7860
      return FALSE;
7870
    }
7882
  }
7892
  return TRUE;
7900
}
79188