| 1 |
<?php
|
| 2 |
// $Id: provision.inc,v 1.76 2009/09/21 10:07:49 mig5 Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* The provisioning framework API.
|
| 7 |
*
|
| 8 |
* API functions that are used by the provisioning framework to provide structure to the provisioning modules.
|
| 9 |
*
|
| 10 |
* @see errorhandling
|
| 11 |
* @see logging
|
| 12 |
* @see sitedata
|
| 13 |
* @see provisionvalues
|
| 14 |
*/
|
| 15 |
|
| 16 |
drush_errors_on();
|
| 17 |
|
| 18 |
/**
|
| 19 |
* @defgroup sitedata Site data management utility functions.
|
| 20 |
* @{
|
| 21 |
* The provision framework maintains a site.php file in the sites directory, to maintain additional
|
| 22 |
* information from the front end, as well as providing a change history of setting changes.
|
| 23 |
*
|
| 24 |
* These functions load, save and manage changes made to the site data. This data has diagnostic and infrastructure
|
| 25 |
* values, that allow sites to be more easily moved between different provisioned platforms.
|
| 26 |
*/
|
| 27 |
|
| 28 |
/**
|
| 29 |
* Returns the aggregated site data from both the pre-existing site.php file, and the options passed to Drush
|
| 30 |
*
|
| 31 |
* This function merges the data from the command line parser, and the information already saved by previous invokations
|
| 32 |
* of the api. This provides a single view of all data relating to the site.
|
| 33 |
* This function also provides sensible defaults for some of the settings.
|
| 34 |
*
|
| 35 |
* @param url
|
| 36 |
* The url of the site being invoked.
|
| 37 |
* @return
|
| 38 |
* An associated array containing the relevant settings for the site.
|
| 39 |
*/
|
| 40 |
function provision_get_site_data($url) {
|
| 41 |
if ($old_data = provision_load_site_data($url)) {
|
| 42 |
//Merge previously saved data with the new data. This way, new parameters overwrite old ones.
|
| 43 |
$site_data = array_merge($old_data, $site_data);
|
| 44 |
}
|
| 45 |
|
| 46 |
if ($site_data['aliases'] && !is_array($site_data['aliases'])) {
|
| 47 |
$site_data['aliases'] = explode(",", $site_data['aliases']);
|
| 48 |
}
|
| 49 |
return $site_data;
|
| 50 |
}
|
| 51 |
|
| 52 |
/**
|
| 53 |
* Load site data stored in the site.php file for the specified site.
|
| 54 |
*
|
| 55 |
* @param url
|
| 56 |
* The url of the site being invoked
|
| 57 |
* @return
|
| 58 |
* If the file was found, an associative array of the data that was loaded. Otherwise returns FALSE.
|
| 59 |
*/
|
| 60 |
function provision_load_site_data($url) {
|
| 61 |
//Load the configuration data.
|
| 62 |
|
| 63 |
//@TODO remove this, it is a temporary measure until all site.php files are placed by drushrc.php files
|
| 64 |
|
| 65 |
$conf_file = "sites/$url/site.php";
|
| 66 |
if (file_exists($conf_file)) {
|
| 67 |
provision_path('chmod', $conf_file, 0400);
|
| 68 |
require($conf_file);
|
| 69 |
|
| 70 |
// The provision 0.1 config data might contain older data,
|
| 71 |
// so any data in the new drushrc.php file would be newer.
|
| 72 |
$site_context = drush_get_context('site');
|
| 73 |
$site_context = array_merge($data, $site_context);
|
| 74 |
drush_set_context('site', $site_context);
|
| 75 |
}
|
| 76 |
return FALSE;
|
| 77 |
}
|
| 78 |
|
| 79 |
/**
|
| 80 |
* Save modified options to the site.php file
|
| 81 |
*/
|
| 82 |
function provision_save_site_data() {
|
| 83 |
$context = 'site';
|
| 84 |
drush_save_config($site);
|
| 85 |
|
| 86 |
if (!drush_get_error()) {
|
| 87 |
// append the db settings in the _SERVER variable so normal drush commands can still read it.
|
| 88 |
$filename = _drush_config_file($context);
|
| 89 |
$cache = drush_get_context($context);
|
| 90 |
|
| 91 |
$fp = fopen($filename, "a+");
|
| 92 |
$fields = array('db_type', 'db_host', 'db_user', 'db_passwd', 'db_name');
|
| 93 |
|
| 94 |
foreach ($fields as $key) {
|
| 95 |
$line = "\n\$_SERVER['$key'] = ". var_export($cache[$key], TRUE) .';';
|
| 96 |
fwrite($fp, $line);
|
| 97 |
}
|
| 98 |
fwrite($fp, "\n");
|
| 99 |
fclose($fp);
|
| 100 |
}
|
| 101 |
}
|
| 102 |
|
| 103 |
/**
|
| 104 |
* @} End of "defgroup sitedata".
|
| 105 |
*/
|
| 106 |
|
| 107 |
|
| 108 |
/**
|
| 109 |
* Save the options for the platform to the drushrc.php in the root of
|
| 110 |
* the platform.
|
| 111 |
*
|
| 112 |
* @return
|
| 113 |
* Boolean. The value returned by drush_save_config().
|
| 114 |
*/
|
| 115 |
function provision_save_platform_data() {
|
| 116 |
return drush_save_config('drupal');
|
| 117 |
}
|
| 118 |
|
| 119 |
/**
|
| 120 |
* @defgroup provisionvalues Value replacement support for the provisioning framework
|
| 121 |
* @{
|
| 122 |
*/
|
| 123 |
|
| 124 |
/**
|
| 125 |
* Generate the text for a config file using php
|
| 126 |
*/
|
| 127 |
function provision_render_config($template, $variables) {
|
| 128 |
drush_errors_off();
|
| 129 |
extract($variables, EXTR_SKIP); // Extract the variables to a local namespace
|
| 130 |
ob_start(); // Start output buffering
|
| 131 |
eval('?>'. $template); // Generate content
|
| 132 |
$contents = ob_get_contents(); // Get the contents of the buffer
|
| 133 |
ob_end_clean(); // End buffering and discard
|
| 134 |
drush_errors_on();
|
| 135 |
return $contents; // Return the contents
|
| 136 |
}
|
| 137 |
|
| 138 |
/**
|
| 139 |
* @} End of "defgroup provisionvalues".
|
| 140 |
*/
|
| 141 |
|
| 142 |
|
| 143 |
/**
|
| 144 |
* Remove files or directories, recursively
|
| 145 |
*
|
| 146 |
* This was taken from imagecache.module, with slight modifications:
|
| 147 |
* - carry error codes along the way (returns TRUE only if all operations return TRUE)
|
| 148 |
* - remove any type of files encountered (not just links, files and dirs)
|
| 149 |
* - safety checking since we don't necessarly trust the removed files
|
| 150 |
*/
|
| 151 |
function _provision_recursive_delete($path) {
|
| 152 |
$ret = 1;
|
| 153 |
if (is_dir($path)) {
|
| 154 |
$d = dir($path);
|
| 155 |
while (($entry = $d->read()) !== FALSE) {
|
| 156 |
if ($entry == '.' || $entry == '..') continue;
|
| 157 |
$entry_path = $path .'/'. $entry;
|
| 158 |
if (_provision_file_check_location($entry_path, $path)) {
|
| 159 |
$ret = _provision_recursive_delete($entry_path);
|
| 160 |
}
|
| 161 |
else {
|
| 162 |
$ret = 0;
|
| 163 |
}
|
| 164 |
}
|
| 165 |
|
| 166 |
$rm = provision_path('rmdir', $path, TRUE,
|
| 167 |
dt('Deleting @path directory successful.', array('@path' => $path)),
|
| 168 |
dt('Deleting @path directory failed.', array('@path' => $path)));
|
| 169 |
|
| 170 |
$ret = $ret && $rm;
|
| 171 |
}
|
| 172 |
else {
|
| 173 |
$rm = provision_path('unlink', $path, TRUE, NULL,
|
| 174 |
dt('Deleting @path file failed.', array('@path' => $path)));
|
| 175 |
$ret = $ret && $rm;
|
| 176 |
}
|
| 177 |
return $ret;
|
| 178 |
}
|
| 179 |
|
| 180 |
function _provision_file_check_location($source, $directory = '') {
|
| 181 |
$check = realpath($source);
|
| 182 |
if ($check) {
|
| 183 |
$source = $check;
|
| 184 |
}
|
| 185 |
else {
|
| 186 |
// This file does not yet exist
|
| 187 |
$source = realpath(dirname($source)) .'/'. basename($source);
|
| 188 |
}
|
| 189 |
$directory = realpath($directory);
|
| 190 |
if ($directory && strpos($source, $directory) !== 0) {
|
| 191 |
return 0;
|
| 192 |
}
|
| 193 |
return $source;
|
| 194 |
}
|
| 195 |
|
| 196 |
/**
|
| 197 |
* Wrapper around drush_shell_exec to provide sprintf functionality with some more safety.
|
| 198 |
*
|
| 199 |
* @TODO: fix this so we can get error codes and the return values. drush_shell_exec is too
|
| 200 |
* limited
|
| 201 |
*/
|
| 202 |
function provision_shell_exec() {
|
| 203 |
$args = func_get_args();
|
| 204 |
|
| 205 |
//do not change the command itself, just the parameters.
|
| 206 |
for ($x = 1; $x < sizeof($args); $x++) {
|
| 207 |
$args[$x] = escapeshellcmd($args[$x]);
|
| 208 |
}
|
| 209 |
$command = call_user_func_array('sprintf', $args);
|
| 210 |
drush_log($command);
|
| 211 |
return drush_shell_exec($command);
|
| 212 |
}
|
| 213 |
|
| 214 |
/**
|
| 215 |
* Check whether a user is a member of a group.
|
| 216 |
*
|
| 217 |
* @param user
|
| 218 |
* username or user id of user.
|
| 219 |
* @param group
|
| 220 |
* groupname or group id of group.
|
| 221 |
*
|
| 222 |
* @return
|
| 223 |
* Boolean. True if user does belong to group,
|
| 224 |
* and FALSE if the user does not belong to the group, or either the user or group do not exist.
|
| 225 |
*/
|
| 226 |
function provision_user_in_group($user, $group) {
|
| 227 |
// TODO: make these singletons with static variables for caching.
|
| 228 |
$user = provision_posix_username($user);
|
| 229 |
$group = provision_posix_groupname($group);
|
| 230 |
if ($user && $group) {
|
| 231 |
$info = posix_getgrnam($group);
|
| 232 |
if (in_array($user, $info['members'])) {
|
| 233 |
return TRUE;
|
| 234 |
}
|
| 235 |
}
|
| 236 |
return FALSE;
|
| 237 |
}
|
| 238 |
|
| 239 |
/**
|
| 240 |
* Return the valid system username for $user.
|
| 241 |
*
|
| 242 |
* @return
|
| 243 |
* Returns the username if found, otherwise returns FALSE
|
| 244 |
*/
|
| 245 |
function provision_posix_username($user) {
|
| 246 |
// TODO: make these singletons with static variables for caching.
|
| 247 |
// we do this both ways, so that the function returns NULL if no such user was found.
|
| 248 |
if (is_numeric($user)) {
|
| 249 |
$info = posix_getpwuid($user);
|
| 250 |
$user = $info['name'];
|
| 251 |
}
|
| 252 |
else {
|
| 253 |
$info = posix_getpwnam($user);
|
| 254 |
$user = $info['name'];
|
| 255 |
}
|
| 256 |
return $user;
|
| 257 |
}
|
| 258 |
|
| 259 |
/**
|
| 260 |
* Return the valid system groupname for $group.
|
| 261 |
*
|
| 262 |
* @return
|
| 263 |
* Returns the groupname if found, otherwise returns FALSE
|
| 264 |
*/
|
| 265 |
function provision_posix_groupname($group) {
|
| 266 |
// TODO: make these singletons with static variables for caching.
|
| 267 |
// we do this both ways, so that the function returns NULL if no such user was found.
|
| 268 |
if (is_numeric($group)) {
|
| 269 |
$info = posix_getgrgid($group);
|
| 270 |
$group = $info['name'];
|
| 271 |
}
|
| 272 |
else {
|
| 273 |
$info = posix_getgrnam($group);
|
| 274 |
$group = $info['name'];
|
| 275 |
}
|
| 276 |
return $group;
|
| 277 |
}
|
| 278 |
|
| 279 |
function provision_password($length = 10) {
|
| 280 |
// This variable contains the list of allowable characters for the
|
| 281 |
// password. Note that the number 0 and the letter 'O' have been
|
| 282 |
// removed to avoid confusion between the two. The same is true
|
| 283 |
// of 'I', 1, and 'l'.
|
| 284 |
$allowable_characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
| 285 |
|
| 286 |
// Zero-based count of characters in the allowable list:
|
| 287 |
$len = strlen($allowable_characters) - 1;
|
| 288 |
|
| 289 |
// Declare the password as a blank string.
|
| 290 |
$pass = '';
|
| 291 |
|
| 292 |
// Loop the number of times specified by $length.
|
| 293 |
for ($i = 0; $i < $length; $i++) {
|
| 294 |
|
| 295 |
// Each iteration, pick a random character from the
|
| 296 |
// allowable string and append it to the password:
|
| 297 |
$pass .= $allowable_characters[mt_rand(0, $len)];
|
| 298 |
}
|
| 299 |
|
| 300 |
return $pass;
|
| 301 |
}
|
| 302 |
|
| 303 |
/**
|
| 304 |
* This is a helper function which changes deeply nested objects into arrays
|
| 305 |
*
|
| 306 |
* This helps get past the face that objects are not simple to work with, or
|
| 307 |
* save in context files.
|
| 308 |
*
|
| 309 |
* This function 'misuses' a side effect of the json_decode function's second
|
| 310 |
* parameter. As this is done in C, and the structures we are manipulating
|
| 311 |
* aren't that large, it should be performant enough.
|
| 312 |
*/
|
| 313 |
function _scrub_object($input) {
|
| 314 |
return json_decode(json_encode($input), TRUE);
|
| 315 |
}
|