Skip to content
provision_drupal.module 9.18 KiB
Newer Older
<?php
/**
 * @file
 * Drupal specific functions for the provisioning framework.
 *
 * This module is responsible for the creation and maintenance of the drupal settings.php file, the sites directory structure
 * and all the install api code. 
 */

/**
 * @ingroup provisionui
 * @{
 */
 
/**
 * Implementation of hook_provision_service()
 */
function provision_drupal_provision_service() {
  return t("Drupal sites");
}

/**
 * Implentation of hook_provision_configure()
 */
function provision_drupal_provision_configure() {
Adrian Rossouw's avatar
Adrian Rossouw committed
  $template = _provision_drupal_default_template();
  $profiles = file_scan_directory('./profiles', '\.profile$', array('.', '..', 'CVS'), 0, TRUE, 'name', 0);
  // Don't need to choose profile if only one available.
  if (sizeof($profiles) == 1) {
    $profile = array_pop($profiles);
    $form['provision_default_profile'] = array('#type' => 'value', '#value' => $profile->name);
  }
  elseif (sizeof($profiles) > 1) {
    foreach ($profiles as $profile) {
      if ($_POST['profile'] == $profile->name) {
        $options[$profile->name] = $profile->name;
      }
    }
    $form['provision_default_profile'] = array(
      '#type' => 'radios',
      '#title' => t('Default install profile'),
      '#description' => t('New sites will be created with the following install profile'),
      '#options' => $options,
      '#default_value' => variable_get('provision_default_profile', 'default'),
    );
    
  }

  $form['provision_settings_template'] = array(
    '#type' => 'textarea',
    '#title' => t('Drupal settings template'),
    '#description' => t('The template for the generated settings.php file.'),
    '#default_value' => variable_get('provision_settings_template', $template),
    '#cols' => 60,
    '#rows' => 5,
  );
  
  return $form;
}

/**
 * @} End "ingroup provisionui"
*/

/**
 * Test to see if the site settings.php exists
 *
 * @param url
 *   The url of the site to check
 * @return
 *   If the file exists, return TRUE, else return FALSE.
 */
function _provision_drupal_site_exists($url) {
  return file_exists("sites/$url/settings.php");
}

/**
 * The default template to use while generating config files.
 *
 * @return
 *   The default template for the config file
 */
function _provision_drupal_default_template() {
  return <<<END
  <?php
    \$db_url = "[site-db-type]://[site-db-username]:[site-db-passwd]@[site-db-host]/[site-db-name]";
    \$profile = "[site-profile]";

    # Additional host wide configuration settings. Useful for safely specifying configuration settings.
    if (file_exists('includes/global.inc')) {
      include_once('includes/global.inc');
    }
  ?>
END;
}

/**
 * Generate a settings file for the site.
 *
 * @param url
 *   The url of the site being invoked.
 * @param data
 *   A reference to the associated array containing the data for the site. This needs to be a reference, 
 *   because the modules might provide additional information about the site.
 */
function _provision_drupal_create_settings_file($url, &$data) {
  $fp = fopen("sites/$url/settings.php", "w");
Adrian Rossouw's avatar
Adrian Rossouw committed
  $text = variable_get('provision_settings_template', _provision_drupal_default_template());
  fwrite($fp, token_replace($text, 'site', $data));
  fclose($fp);
  
  # Change the ownership of the file
  #chown($path, variable_get('provision_user', 'hosting'), variable_get('provision_group', 'apache'));
  
  # Change the permissions of the file
#  system("chmod 0550 sites/$url/settings.php");
  # TODO: add md5 of the file created to $data
}

/**
 * Create the directories needed to host a drupal site
 * 
 * Also maintains permissions on existing directories.
 */
function _provision_drupal_create_directories($url, $profile = null) {
  $paths = array(
    "sites/$url"                 => '0750',
    "sites/$url/files"           => '2750',
    "sites/$url/files/tmp"       => '2770',
    "sites/$url/files/images"    => '2770',
    "sites/$url/files/pictures"  => '2770',
    "sites/$url/themes"          => '2750',
    "sites/$url/modules"         => '2750',    
  );

  foreach ($paths as $path => $perm) {
    if (!is_dir($path)) {
      mkdir($path);
    }
    # Change the ownership of the files so that they are owned by the user the script is running as, and the
    # web server has access to them.
    # chown($path, variable_get('provision_user', 'hosting'), variable_get('provision_group', 'apache'));
    
    # Change the permissions to the optimal settings that were specified.
#    system("chmod $perm $path");

  }

}

/**
 * Switch the active database to the newly created database
 *
 * This function tricks Drupal into thinking that it's running on an uninstalled site,
 * so that it can cleanly install the database schema. It also handles switching back to the 
 * main provisioning site.
 */
function _provision_drupal_switch_active_site($url = null) {
  static $backups;
  if ($url) {
    /* Pretend to be the site being installed */
    
    // Fake the necessary HTTP headers that Drupal needs:
    $drupal_base_url = parse_url($url);
    $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
    $_SERVER['PHP_SELF'] = $drupal_base_url['path'].'/index.php';
    $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
    $_SERVER['REMOTE_ADDR'] = NULL;
    $_SERVER['REQUEST_METHOD'] = NULL;


    /**
     * This code is sourced from bootstrap.inc. I am trying to avoid patching core, but it might
     * be smarter to make a small patch to allow core to re-initialize itself more easily
     */

    // Export the following settings.php variables to the global namespace
    global $base_url, $base_path, $base_root;
    global $db_url, $db_prefix, $cookie_domain, $conf, $installed_profile, $active_db, $profile;
 
    # This is just for backup, to be able to restore to the old DRUSH system.
    $backups = compact("active_db", "base_url", "base_path", "db_url", "db_prefix", "cookie_domain", "conf", "installed_profile", "profile");
    
    $conf = array();
    include_once $_SERVER['DOCUMENT_ROOT'] .'sites/' . $url . '/settings.php';

    // Create base URL
     $base_root = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
     $base_url = $base_root .= '://'. preg_replace('/[^a-z0-9-:._]/i', '', $_SERVER['HTTP_HOST']);
     if ($dir = trim(dirname($_SERVER['SCRIPT_NAME']), '\,/')) {
       $base_path = "/$dir";
       $base_url .= $base_path;
       $base_path .= '/';
     }
     else {
       $base_path = '/';
     }
    
    unset($active_db);
    $db_url['new'] = $db_url;
    db_set_active('new'); 

  }
  else {
    /**
    * Restore everything to the way it was before we switched sites.
    */
    // Fake the necessary HTTP headers that Drupal needs:
    $drupal_base_url = parse_url(DRUSH_URI);
    $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
    $_SERVER['PHP_SELF'] = $drupal_base_url['path'].'/index.php';
    $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
    $_SERVER['REMOTE_ADDR'] = NULL;
    $_SERVER['REQUEST_METHOD'] = NULL;
    
    global $base_url, $base_path, $base_root;
     // Export the following settings.php variables to the global namespace
    global $db_url, $db_prefix, $cookie_domain, $conf, $installed_profile, $profile;

    # This is just for backup, to be able to restore to the old DRUSH system.
    extract($backups, EXTR_OVERWRITE);
    
  }
}

/**
 * Force drupal to load the modules it expects to find on an uninstalled site
 */
function _provision_drupal_force_load_modules($url = null) {
  static $backup_list;
  if ($url) {
    $backup_list = module_list();
    require_once './modules/system/system.install';
    require_once './includes/file.inc';
    require_once './includes/install.inc';
    // Load module basics (needed for hook invokes).
     include_once './includes/module.inc';
     $module_list['system']['filename'] = 'modules/system/system.module';
     $module_list['filter']['filename'] = 'modules/filter/filter.module';
     module_list(TRUE, FALSE, FALSE, $module_list);
     drupal_load('module', 'system');
     drupal_load('module', 'filter');
     #should i load all the other modules? i don't know .=\
  }
  else {
    module_list(TRUE, FALSE, FALSE, $backup_list);
  }
}

/**
 * Install the drupal schema and install profile
 */
function _provision_install_schema($profile) {
  // Load the profile.
  require_once "./profiles/$profile/$profile.profile";

  $requirements = drupal_check_profile($profile);
  $severity = drupal_requirements_severity($requirements);

  // If there are issues, report them.
  if ($severity == REQUIREMENT_ERROR) {
    foreach ($requirements as $requirement) {
      if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) {
        drupal_set_message($requirement['description'] .' ('. st('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) .')', 'error');
      }
    }

    return false;
  }

  // Verify existence of all required modules.
  $modules = drupal_verify_profile($profile, null);

  if (!$modules) {
    return false;
  }

  // Perform actual installation defined in the profile.
  drupal_install_profile($profile, $modules);

  // Show profile finalization info.
  $function = $profile .'_profile_final';
  if (function_exists($function)) {
    // More steps required
    $profile_message = $function();
  } 
}