home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / CMS / drupal-6.0.exe / drupal-6.0 / includes / install.inc < prev    next >
Encoding:
Text File  |  2008-02-11  |  22.0 KB  |  737 lines

  1. <?php
  2. // $Id: install.inc,v 1.56.2.2 2008/02/11 15:10:26 goba Exp $
  3.  
  4. define('SCHEMA_UNINSTALLED', -1);
  5. define('SCHEMA_INSTALLED', 0);
  6.  
  7. define('REQUIREMENT_INFO', -1);
  8. define('REQUIREMENT_OK', 0);
  9. define('REQUIREMENT_WARNING', 1);
  10. define('REQUIREMENT_ERROR', 2);
  11.  
  12. define('FILE_EXIST',          1);
  13. define('FILE_READABLE',       2);
  14. define('FILE_WRITABLE',       4);
  15. define('FILE_EXECUTABLE',     8);
  16. define('FILE_NOT_EXIST',      16);
  17. define('FILE_NOT_READABLE',   32);
  18. define('FILE_NOT_WRITABLE',   64);
  19. define('FILE_NOT_EXECUTABLE', 128);
  20.  
  21. /**
  22.  * Initialize the update system by loading all installed module's .install files.
  23.  */
  24. function drupal_load_updates() {
  25.   foreach (drupal_get_installed_schema_version(NULL, FALSE, TRUE) as $module => $schema_version) {
  26.     if ($schema_version > -1) {
  27.       module_load_install($module);
  28.     }
  29.   }
  30. }
  31.  
  32. /**
  33.  * Returns an array of available schema versions for a module.
  34.  *
  35.  * @param $module
  36.  *   A module name.
  37.  * @return
  38.  *   If the module has updates, an array of available updates. Otherwise,
  39.  *   FALSE.
  40.  */
  41. function drupal_get_schema_versions($module) {
  42.   $updates = array();
  43.   $functions = get_defined_functions();
  44.   foreach ($functions['user'] as $function) {
  45.     if (strpos($function, $module .'_update_') === 0) {
  46.       $version = substr($function, strlen($module .'_update_'));
  47.       if (is_numeric($version)) {
  48.         $updates[] = $version;
  49.       }
  50.     }
  51.   }
  52.   if (count($updates) == 0) {
  53.     return FALSE;
  54.   }
  55.   return $updates;
  56. }
  57.  
  58. /**
  59.  * Returns the currently installed schema version for a module.
  60.  *
  61.  * @param $module
  62.  *   A module name.
  63.  * @param $reset
  64.  *   Set to TRUE after modifying the system table.
  65.  * @param $array
  66.  *   Set to TRUE if you want to get information about all modules in the
  67.  *   system.
  68.  * @return
  69.  *   The currently installed schema version.
  70.  */
  71. function drupal_get_installed_schema_version($module, $reset = FALSE, $array = FALSE) {
  72.   static $versions = array();
  73.  
  74.   if ($reset) {
  75.     $versions = array();
  76.   }
  77.  
  78.   if (!$versions) {
  79.     $versions = array();
  80.     $result = db_query("SELECT name, schema_version FROM {system} WHERE type = '%s'", 'module');
  81.     while ($row = db_fetch_object($result)) {
  82.       $versions[$row->name] = $row->schema_version;
  83.     }
  84.   }
  85.  
  86.   return $array ? $versions : $versions[$module];
  87. }
  88.  
  89. /**
  90.  * Update the installed version information for a module.
  91.  *
  92.  * @param $module
  93.  *   A module name.
  94.  * @param $version
  95.  *   The new schema version.
  96.  */
  97. function drupal_set_installed_schema_version($module, $version) {
  98.   db_query("UPDATE {system} SET schema_version = %d WHERE name = '%s'", $version, $module);
  99. }
  100.  
  101. /**
  102.  * Loads the profile definition, extracting the profile's defined name.
  103.  *
  104.  * @return
  105.  *   The name defined in the profile's _profile_details() hook.
  106.  */
  107. function drupal_install_profile_name() {
  108.   global $profile;
  109.   static $name = NULL;
  110.  
  111.   if (!isset($name)) {
  112.     // Load profile details.
  113.     $function = $profile .'_profile_details';
  114.     if (function_exists($function)) {
  115.       $details = $function();
  116.     }
  117.     $name = isset($details['name']) ? $details['name'] : 'Drupal';
  118.   }
  119.  
  120.   return $name;
  121. }
  122.  
  123. /**
  124.  * Auto detect the base_url with PHP predefined variables.
  125.  *
  126.  * @param $file
  127.  *   The name of the file calling this function so we can strip it out of
  128.  *   the URI when generating the base_url.
  129.  *
  130.  * @return
  131.  *   The auto-detected $base_url that should be configured in settings.php
  132.  */
  133. function drupal_detect_baseurl($file = 'install.php') {
  134.   global $profile;
  135.   $proto = $_SERVER['HTTPS'] ? 'https://' : 'http://';
  136.   $host = $_SERVER['SERVER_NAME'];
  137.   $port = ($_SERVER['SERVER_PORT'] == 80 ? '' : ':'. $_SERVER['SERVER_PORT']);
  138.   $uri = preg_replace("/\?.*/", '', $_SERVER['REQUEST_URI']);
  139.   $dir = str_replace("/$file", '', $uri);
  140.  
  141.   return "$proto$host$port$dir";
  142. }
  143.  
  144. /**
  145.  * Detect all databases supported by Drupal that are compiled into the current
  146.  * PHP installation.
  147.  *
  148.  * @return
  149.  *  An array of database types compiled into PHP.
  150.  */
  151. function drupal_detect_database_types() {
  152.   $databases = array();
  153.  
  154.   foreach (array('mysql', 'mysqli', 'pgsql') as $type) {
  155.     if (file_exists('./includes/install.'. $type .'.inc')) {
  156.       include_once './includes/install.'. $type .'.inc';
  157.       $function = $type .'_is_available';
  158.       if ($function()) {
  159.         $databases[$type] = $type;
  160.       }
  161.     }
  162.   }
  163.  
  164.   return $databases;
  165. }
  166.  
  167. /**
  168.  * Read settings.php into a buffer line by line, changing values specified in
  169.  * $settings array, then over-writing the old settings.php file.
  170.  *
  171.  * @param $settings
  172.  *   An array of settings that need to be updated.
  173.  */
  174. function drupal_rewrite_settings($settings = array(), $prefix = '') {
  175.   $default_settings = './sites/default/default.settings.php';
  176.   $settings_file = './'. conf_path(FALSE, TRUE) .'/'. $prefix .'settings.php';
  177.  
  178.   // Build list of setting names and insert the values into the global namespace.
  179.   $keys = array();
  180.   foreach ($settings as $setting => $data) {
  181.     $GLOBALS[$setting] = $data['value'];
  182.     $keys[] = $setting;
  183.   }
  184.  
  185.   $buffer = NULL;
  186.   $first = TRUE;
  187.   if ($fp = fopen($default_settings, 'r')) {
  188.     // Step line by line through settings.php.
  189.     while (!feof($fp)) {
  190.       $line = fgets($fp);
  191.       if ($first && substr($line, 0, 5) != '<?php') {
  192.         $buffer = "<?php\n\n";
  193.       }
  194.       $first = FALSE;
  195.       // Check for constants.
  196.       if (substr($line, 0, 7) == 'define(') {
  197.         preg_match('/define\(\s*[\'"]([A-Z_-]+)[\'"]\s*,(.*?)\);/', $line, $variable);
  198.         if (in_array($variable[1], $keys)) {
  199.           $setting = $settings[$variable[1]];
  200.           $buffer .= str_replace($variable[2], " '". $setting['value'] ."'", $line);
  201.           unset($settings[$variable[1]]);
  202.           unset($settings[$variable[2]]);
  203.         }
  204.         else {
  205.           $buffer .= $line;
  206.         }
  207.       }
  208.       // Check for variables.
  209.       elseif (substr($line, 0, 1) == '$') {
  210.         preg_match('/\$([^ ]*) /', $line, $variable);
  211.         if (in_array($variable[1], $keys)) {
  212.           // Write new value to settings.php in the following format:
  213.           //    $'setting' = 'value'; // 'comment'
  214.           $setting = $settings[$variable[1]];
  215.           $buffer .= '$'. $variable[1] ." = '". $setting['value'] ."';". (!empty($setting['comment']) ? ' // '. $setting['comment'] ."\n" : "\n");
  216.           unset($settings[$variable[1]]);
  217.         }
  218.         else {
  219.           $buffer .= $line;
  220.         }
  221.       }
  222.       else {
  223.         $buffer .= $line;
  224.       }
  225.     }
  226.     fclose($fp);
  227.  
  228.     // Add required settings that were missing from settings.php.
  229.     foreach ($settings as $setting => $data) {
  230.       if ($data['required']) {
  231.         $buffer .= "\$$setting = '". $data['value'] ."';\n";
  232.       }
  233.     }
  234.  
  235.     $fp = fopen($settings_file, 'w');
  236.     if ($fp && fwrite($fp, $buffer) === FALSE) {
  237.       drupal_set_message(st('Failed to modify %settings, please verify the file permissions.', array('%settings' => $settings_file)), 'error');
  238.     }
  239.   }
  240.   else {
  241.     drupal_set_message(st('Failed to open %settings, please verify the file permissions.', array('%settings' => $default_settings)), 'error');
  242.   }
  243. }
  244.  
  245. /**
  246.  * Get list of all .install files.
  247.  *
  248.  * @param $module_list
  249.  *   An array of modules to search for their .install files.
  250.  */
  251. function drupal_get_install_files($module_list = array()) {
  252.   $installs = array();
  253.   foreach ($module_list as $module) {
  254.     $installs = array_merge($installs, drupal_system_listing($module .'.install$', 'modules'));
  255.   }
  256.   return $installs;
  257. }
  258.  
  259. /**
  260.  * Verify a profile for installation.
  261.  *
  262.  * @param profile
  263.  *   Name of profile to verify.
  264.  * @param locale
  265.  *   Name of locale used (if any).
  266.  * @return
  267.  *   The list of modules to install.
  268.  */
  269. function drupal_verify_profile($profile, $locale) {
  270.   include_once './includes/file.inc';
  271.   include_once './includes/common.inc';
  272.  
  273.   $profile_file = "./profiles/$profile/$profile.profile";
  274.  
  275.   if (!isset($profile) || !file_exists($profile_file)) {
  276.     install_no_profile_error();
  277.   }
  278.  
  279.   require_once($profile_file);
  280.  
  281.   // Get a list of modules required by this profile.
  282.   $function = $profile .'_profile_modules';
  283.   $module_list = array_merge(drupal_required_modules(), $function(), ($locale != 'en' ? array('locale') : array()));
  284.  
  285.   // Get a list of modules that exist in Drupal's assorted subdirectories.
  286.   $present_modules = array();
  287.   foreach (drupal_system_listing('\.module$', 'modules', 'name', 0) as $present_module) {
  288.     $present_modules[] = $present_module->name;
  289.   }
  290.  
  291.   // Verify that all of the profile's required modules are present.
  292.   $missing_modules = array_diff($module_list, $present_modules);
  293.   if (count($missing_modules)) {
  294.     foreach ($missing_modules as $module) {
  295.       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');
  296.     }
  297.   }
  298.   else {
  299.     return $module_list;
  300.   }
  301. }
  302.  
  303. /**
  304.  * Calls the install function and updates the system table for a given list of
  305.  * modules.
  306.  *
  307.  * @param module_list
  308.  *   The modules to install.
  309.  */
  310. function drupal_install_modules($module_list = array()) {
  311.   $files = module_rebuild_cache();
  312.   $module_list = array_flip(array_values($module_list));
  313.   do {
  314.     $moved = FALSE;
  315.     foreach ($module_list as $module => $weight) {
  316.       $file = $files[$module];
  317.       if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) {
  318.         foreach ($file->info['dependencies'] as $dependency) {
  319.           if (isset($module_list[$dependency]) && $module_list[$module] < $module_list[$dependency] +1) {
  320.             $module_list[$module] = $module_list[$dependency] +1;
  321.             $moved = TRUE;
  322.           }
  323.         }
  324.       }
  325.     }
  326.   } while ($moved);
  327.   asort($module_list);
  328.   $module_list = array_keys($module_list);
  329.   array_filter($module_list, '_drupal_install_module');
  330.   module_enable($module_list);
  331. }
  332.  
  333. /**
  334.  * Callback to install an individual profile module.
  335.  *
  336.  * Used during installation to install modules one at a time and then
  337.  * enable them, or to install a number of modules at one time
  338.  * from admin/build/modules.
  339.  */
  340. function _drupal_install_module($module) {
  341.   if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) {
  342.     module_load_install($module);
  343.     module_invoke($module, 'install');
  344.     $versions = drupal_get_schema_versions($module);
  345.     drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED);
  346.     return TRUE;
  347.   }
  348. }
  349.  
  350. /**
  351.  * Callback to install the system module.
  352.  *
  353.  * Separated from the installation of other modules so core system
  354.  * functions can be made available while other modules are installed.
  355.  */
  356. function drupal_install_system() {
  357.   $system_path = dirname(drupal_get_filename('module', 'system', NULL));
  358.   require_once './'. $system_path .'/system.install';
  359.   module_invoke('system', 'install');
  360.   $system_versions = drupal_get_schema_versions('system');
  361.   $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED;
  362.   db_query("INSERT INTO {system} (filename, name, type, owner, status, throttle, bootstrap, schema_version) VALUES('%s', '%s', '%s', '%s', %d, %d, %d, %d)", $system_path .'/system.module', 'system', 'module', '', 1, 0, 0, $system_version);
  363.   // Now that we've installed things properly, bootstrap the full Drupal environment
  364.   drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
  365.   module_rebuild_cache();
  366. }
  367.  
  368.  
  369. /**
  370.  * Calls the uninstall function and updates the system table for a given module.
  371.  *
  372.  * @param $module
  373.  *   The module to uninstall.
  374.  */
  375. function drupal_uninstall_module($module) {
  376.   // First, retrieve all the module's menu paths from db.
  377.   drupal_load('module', $module);
  378.   $paths = module_invoke($module, 'menu');
  379.  
  380.   // Uninstall the module(s).
  381.   module_load_install($module);
  382.   module_invoke($module, 'uninstall');
  383.  
  384.   // Now remove the menu links for all paths declared by this module.
  385.   if (!empty($paths)) {
  386.     $paths = array_keys($paths);
  387.     // Clean out the names of load functions.
  388.     foreach ($paths as $index => $path) {
  389.       $parts = explode('/', $path, MENU_MAX_PARTS);
  390.       foreach ($parts as $k => $part) {
  391.         if (preg_match('/^%[a-z_]*$/', $part)) {
  392.           $parts[$k] = '%';
  393.         }
  394.       }
  395.       $paths[$index] = implode('/', $parts);
  396.     }
  397.     $placeholders = implode(', ', array_fill(0, count($paths), "'%s'"));
  398.  
  399.     $result = db_query('SELECT * FROM {menu_links} WHERE router_path IN ('. $placeholders .') AND external = 0 ORDER BY depth DESC', $paths);
  400.     // Remove all such items. Starting from those with the greatest depth will
  401.     // minimize the amount of re-parenting done by menu_link_delete().
  402.     while ($item = db_fetch_array($result)) {
  403.       _menu_delete_item($item, TRUE);
  404.     }
  405.   }
  406.  
  407.   drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED);
  408. }
  409.  
  410. /**
  411.  * Verify the state of the specified file.
  412.  *
  413.  * @param $file
  414.  *   The file to check for.
  415.  * @param $mask
  416.  *   An optional bitmask created from various FILE_* constants.
  417.  * @param $type
  418.  *   The type of file. Can be file (default), dir, or link.
  419.  * @return
  420.  *   TRUE on success or FALSE on failure. A message is set for the latter.
  421.  */
  422. function drupal_verify_install_file($file, $mask = NULL, $type = 'file') {
  423.   $return = TRUE;
  424.   // Check for files that shouldn't be there.
  425.   if (isset($mask) && ($mask & FILE_NOT_EXIST) && file_exists($file)) {
  426.     return FALSE;
  427.   }
  428.   // Verify that the file is the type of file it is supposed to be.
  429.   if (isset($type) && file_exists($file)) {
  430.     $check = 'is_'. $type;
  431.     if (!function_exists($check) || !$check($file)) {
  432.       $return = FALSE;
  433.     }
  434.   }
  435.  
  436.   // Verify file permissions.
  437.   if (isset($mask)) {
  438.     $masks = array(FILE_EXIST, FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE);
  439.     foreach ($masks as $current_mask) {
  440.       if ($mask & $current_mask) {
  441.         switch ($current_mask) {
  442.           case FILE_EXIST:
  443.             if (!file_exists($file)) {
  444.               if ($type == 'dir') {
  445.                 drupal_install_mkdir($file, $mask);
  446.               }
  447.               if (!file_exists($file)) {
  448.                 $return = FALSE;
  449.               }
  450.             }
  451.             break;
  452.           case FILE_READABLE:
  453.             if (!is_readable($file) && !drupal_install_fix_file($file, $mask)) {
  454.               $return = FALSE;
  455.             }
  456.             break;
  457.           case FILE_WRITABLE:
  458.             if (!is_writable($file) && !drupal_install_fix_file($file, $mask)) {
  459.               $return = FALSE;
  460.             }
  461.             break;
  462.           case FILE_EXECUTABLE:
  463.             if (!is_executable($file) && !drupal_install_fix_file($file, $mask)) {
  464.               $return = FALSE;
  465.             }
  466.             break;
  467.           case FILE_NOT_READABLE:
  468.             if (is_readable($file) && !drupal_install_fix_file($file, $mask)) {
  469.               $return = FALSE;
  470.             }
  471.             break;
  472.           case FILE_NOT_WRITABLE:
  473.             if (is_writable($file) && !drupal_install_fix_file($file, $mask)) {
  474.               $return = FALSE;
  475.             }
  476.             break;
  477.           case FILE_NOT_EXECUTABLE:
  478.             if (is_executable($file) && !drupal_install_fix_file($file, $mask)) {
  479.               $return = FALSE;
  480.             }
  481.             break;
  482.         }
  483.       }
  484.     }
  485.   }
  486.   return $return;
  487. }
  488.  
  489. /**
  490.  * Create a directory with specified permissions.
  491.  *
  492.  * @param file
  493.  *  The name of the directory to create;
  494.  * @param mask
  495.  *  The permissions of the directory to create.
  496.  * @param $message
  497.  *  (optional) Whether to output messages. Defaults to TRUE.
  498.  *
  499.  * @return
  500.  *  TRUE/FALSE whether or not the directory was successfully created.
  501.  */
  502. function drupal_install_mkdir($file, $mask, $message = TRUE) {
  503.   $mod = 0;
  504.   $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE);
  505.   foreach ($masks as $m) {
  506.     if ($mask & $m) {
  507.       switch ($m) {
  508.         case FILE_READABLE:
  509.           $mod += 444;
  510.           break;
  511.         case FILE_WRITABLE:
  512.           $mod += 222;
  513.           break;
  514.         case FILE_EXECUTABLE:
  515.           $mod += 111;
  516.           break;
  517.       }
  518.     }
  519.   }
  520.  
  521.   if (@mkdir($file, intval("0$mod", 8))) {
  522.     return TRUE;
  523.   }
  524.   else {
  525.     return FALSE;
  526.   }
  527. }
  528.  
  529. /**
  530.  * Attempt to fix file permissions.
  531.  *
  532.  * The general approach here is that, because we do not know the security
  533.  * setup of the webserver, we apply our permission changes to all three
  534.  * digits of the file permission (i.e. user, group and all).
  535.  *
  536.  * To ensure that the values behave as expected (and numbers don't carry
  537.  * from one digit to the next) we do the calculation on the octal value
  538.  * using bitwise operations. This lets us remove, for example, 0222 from
  539.  * 0700 and get the correct value of 0500.
  540.  *
  541.  * @param $file
  542.  *  The name of the file with permissions to fix.
  543.  * @param $mask
  544.  *  The desired permissions for the file.
  545.  * @param $message
  546.  *  (optional) Whether to output messages. Defaults to TRUE.
  547.  *
  548.  * @return
  549.  *  TRUE/FALSE whether or not we were able to fix the file's permissions.
  550.  */
  551. function drupal_install_fix_file($file, $mask, $message = TRUE) {
  552.   $mod = fileperms($file) & 0777;
  553.   $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE);
  554.  
  555.   // FILE_READABLE, FILE_WRITABLE, and FILE_EXECUTABLE permission strings
  556.   // can theoretically be 0400, 0200, and 0100 respectively, but to be safe
  557.   // we set all three access types in case the administrator intends to
  558.   // change the owner of settings.php after installation.
  559.   foreach ($masks as $m) {
  560.     if ($mask & $m) {
  561.       switch ($m) {
  562.         case FILE_READABLE:
  563.           if (!is_readable($file)) {
  564.             $mod |= 0444;
  565.           }
  566.           break;
  567.         case FILE_WRITABLE:
  568.           if (!is_writable($file)) {
  569.             $mod |= 0222;
  570.           }
  571.           break;
  572.         case FILE_EXECUTABLE:
  573.           if (!is_executable($file)) {
  574.             $mod |= 0111;
  575.           }
  576.           break;
  577.         case FILE_NOT_READABLE:
  578.           if (is_readable($file)) {
  579.             $mod &= ~0444;
  580.           }
  581.           break;
  582.         case FILE_NOT_WRITABLE:
  583.           if (is_writable($file)) {
  584.             $mod &= ~0222;
  585.           }
  586.           break;
  587.         case FILE_NOT_EXECUTABLE:
  588.           if (is_executable($file)) {
  589.             $mod &= ~0111;
  590.           }
  591.           break;
  592.       }
  593.     }
  594.   }
  595.  
  596.   // chmod() will work if the web server is running as owner of the file.
  597.   // If PHP safe_mode is enabled the currently executing script must also
  598.   // have the same owner.
  599.   if (@chmod($file, $mod)) {
  600.     return TRUE;
  601.   }
  602.   else {
  603.     return FALSE;
  604.   }
  605. }
  606.  
  607.  
  608. /**
  609.  * Send the user to a different installer page. This issues an on-site HTTP
  610.  * redirect. Messages (and errors) are erased.
  611.  *
  612.  * @param $path
  613.  *   An installer path.
  614.  */
  615. function install_goto($path) {
  616.   global $base_url;
  617.   header('Location: '. $base_url .'/'. $path);
  618.   header('Cache-Control: no-cache'); // Not a permanent redirect.
  619.   exit();
  620. }
  621.  
  622. /**
  623.  * Hardcoded function for doing the equivalent of t() during
  624.  * the install process, when database, theme, and localization
  625.  * system is possibly not yet available.
  626.  */
  627. function st($string, $args = array()) {
  628.   static $locale_strings = NULL;
  629.   global $profile, $install_locale;
  630.  
  631.   if (!isset($locale_strings)) {
  632.     $locale_strings = array();
  633.     $filename = './profiles/'. $profile .'/translations/'. $install_locale .'.po';
  634.     if (file_exists($filename)) {
  635.       require_once './includes/locale.inc';
  636.       $file = (object) array('filepath' => $filename);
  637.       _locale_import_read_po('mem-store', $file);
  638.       $locale_strings = _locale_import_one_string('mem-report');
  639.     }
  640.   }
  641.  
  642.   require_once './includes/theme.inc';
  643.   // Transform arguments before inserting them
  644.   foreach ($args as $key => $value) {
  645.     switch ($key[0]) {
  646.       // Escaped only
  647.       case '@':
  648.         $args[$key] = check_plain($value);
  649.         break;
  650.       // Escaped and placeholder
  651.       case '%':
  652.       default:
  653.         $args[$key] = '<em>'. check_plain($value) .'</em>';
  654.         break;
  655.       // Pass-through
  656.       case '!':
  657.     }
  658.   }
  659.   return strtr((!empty($locale_strings[$string]) ? $locale_strings[$string] : $string), $args);
  660. }
  661.  
  662. /**
  663.  * Check a profile's requirements.
  664.  *
  665.  * @param profile
  666.  *   Name of profile to check.
  667.  */
  668. function drupal_check_profile($profile) {
  669.   include_once './includes/file.inc';
  670.  
  671.   $profile_file = "./profiles/$profile/$profile.profile";
  672.  
  673.   if (!isset($profile) || !file_exists($profile_file)) {
  674.     install_no_profile_error();
  675.   }
  676.  
  677.   require_once($profile_file);
  678.  
  679.   // Get a list of modules required by this profile.
  680.   $function = $profile .'_profile_modules';
  681.   $module_list = array_unique(array_merge(drupal_required_modules(), $function()));
  682.  
  683.   // Get a list of all .install files.
  684.   $installs = drupal_get_install_files($module_list);
  685.  
  686.   // Collect requirement testing results
  687.   $requirements = array();
  688.   foreach ($installs as $install) {
  689.     require_once $install->filename;
  690.     if (module_hook($install->name, 'requirements')) {
  691.       $requirements = array_merge($requirements, module_invoke($install->name, 'requirements', 'install'));
  692.     }
  693.   }
  694.   return $requirements;
  695. }
  696.  
  697. /**
  698.  * Extract highest severity from requirements array.
  699.  */
  700. function drupal_requirements_severity(&$requirements) {
  701.   $severity = REQUIREMENT_OK;
  702.   foreach ($requirements as $requirement) {
  703.     if (isset($requirement['severity'])) {
  704.       $severity = max($severity, $requirement['severity']);
  705.     }
  706.   }
  707.   return $severity;
  708. }
  709.  
  710. /**
  711.  * Check a module's requirements.
  712.  */
  713. function drupal_check_module($module) {
  714.   // Include install file
  715.   $install = drupal_get_install_files(array($module));
  716.   if (isset($install[$module])) {
  717.     require_once $install[$module]->filename;
  718.  
  719.     // Check requirements
  720.     $requirements = module_invoke($module, 'requirements', 'install');
  721.     if (is_array($requirements) && drupal_requirements_severity($requirements) == REQUIREMENT_ERROR) {
  722.       // Print any error messages
  723.       foreach ($requirements as $requirement) {
  724.         if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) {
  725.           $message = $requirement['description'];
  726.           if (isset($requirement['value']) && $requirement['value']) {
  727.             $message .= ' ('. t('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) .')';
  728.           }
  729.           drupal_set_message($message, 'error');
  730.         }
  731.       }
  732.       return FALSE;
  733.     }
  734.   }
  735.   return TRUE;
  736. }
  737.