Newer
Older
Adrian Rossouw
committed
<?php
Adrian Rossouw
committed
/**
* @file
* The provisioning framework API.
*
* API functions that are used by the provisioning framework to provide structure to the provisioning modules.
*
* @see errorhandling
* @see logging
* @see sitedata
* @see provisionvalues
Adrian Rossouw
committed
*/
Adrian Rossouw
committed
drush_errors_on();
Adrian Rossouw
committed
/**
* @defgroup sitedata Site data management utility functions.
* @{
* The provision framework maintains a site.php file in the sites directory, to maintain additional
* information from the front end, as well as providing a change history of setting changes.
*
* These functions load, save and manage changes made to the site data. This data has diagnostic and infrastructure
* values, that allow sites to be more easily moved between different provisioned platforms.
*/
Adrian Rossouw
committed
/**
* Make a determination whether or not the given
* host is local or not.
*
* We needed to fork this from drush core to handle the case sensitivity in host names.
*
* @param host
* A hostname, 'localhost' or '127.0.0.1'.
* @return
* True if the host is local.
*/
function provision_is_local_host($host) {
$host = strtolower($host);
// In order for this to work right, you must use 'localhost' or '127.0.0.1'
// or the machine returned by 'uname -n' for your 'remote-host' entry in
// your site alias. Note that sometimes 'uname -n' does not return the
// correct value. To fix it, put the correct hostname in /etc/hostname
// and then run 'hostname -F /etc/hostname'.
return ($host == 'localhost') || ($host == '127.0.0.1') || ($host == strtolower(php_uname('n')));
}
Adrian Rossouw
committed
/**
* Retrieve a base_url for the currently active site.
*
* TODO: when we actually support HTTPS, do this correctly.
*/
function provision_get_base_url() {
$base_url = 'http://' . d()->uri;
$http_port = d()->web_server->http_port;
if (!is_null($http_port) && ($http_port != 80)) {
$base_url .= ':' . $http_port;
}
return $base_url;
}
Adrian Rossouw
committed
/**
* Save modified options to the drushrc.php file
Adrian Rossouw
committed
*/
function provision_save_server_data() {
Adrian Rossouw
committed
if (!drush_get_error()) {
Adrian Rossouw
committed
$config = new provisionConfig_drushrc_server(d()->name);
$config->write();
Adrian Rossouw
committed
}
Adrian Rossouw
committed
}
Adrian Rossouw
committed
function provision_save_site_data() {
if (!drush_get_error()) {
$config = new provisionConfig_drushrc_site(d()->name);
$config->write();
Adrian Rossouw
committed
}
}
/**
* Save modified options to the drushrc.php file
*/
function provision_save_platform_data() {
if (!drush_get_error()) {
$config = new provisionConfig_drushrc_platform(d()->name);
$config->write();
Adrian Rossouw
committed
}
}
Adrian Rossouw
committed
/**
* @} End of "defgroup sitedata".
*/
/**
* Remove files or directories, recursively
*
* This was taken from imagecache.module, with slight modifications:
* - carry error codes along the way (returns TRUE only if all operations return TRUE)
* - remove any type of files encountered (not just links, files and dirs)
* - safety checking since we don't necessarly trust the removed files
*/
function _provision_recursive_delete($path) {
if (is_dir($path)) {
$d = dir($path);
while (($entry = $d->read()) !== FALSE) {
if ($entry == '.' || $entry == '..') continue;
$entry_path = $path .'/'. $entry;
if (_provision_file_check_location($entry_path, $path)) {
$ret = _provision_recursive_delete($entry_path);
$ret = 0;
}
}
$rm = provision_file()->rmdir($path)
->succeed('Deleting @path directory successful.')
->fail('Deleting @path directory failed.')
->status();
$ret = $ret && $rm;
}
else {
$rm = provision_file()->unlink($path)
->fail('Deleting @path file failed.')
->status();
}
return $ret;
}
function _provision_file_check_location($source, $directory = '') {
$check = realpath($source);
if ($check) {
$source = $check;
}
else {
// This file does not yet exist
$source = realpath(dirname($source)) .'/'. basename($source);
}
$directory = realpath($directory);
if ($directory && strpos($source, $directory) !== 0) {
return 0;
}
return $source;
}
/**
* Wrapper around drush_shell_exec to provide sprintf functionality with some more safety.
Adrian Rossouw
committed
*
* @TODO: fix this so we can get error codes and the return values. drush_shell_exec is too
* limited
*/
function provision_shell_exec() {
$args = func_get_args();
//do not change the command itself, just the parameters.
for ($x = 1; $x < sizeof($args); $x++) {
$args[$x] = escapeshellcmd($args[$x]);
}
$command = call_user_func_array('sprintf', $args);
Adrian Rossouw
committed
drush_log($command);
return drush_shell_exec($command);
Adrian Rossouw
committed
}
Adrian Rossouw
committed
/**
* Check whether a user is a member of a group.
Adrian Rossouw
committed
*
* @param user
* username or user id of user.
* @param group
* groupname or group id of group.
*
* @return
* Boolean. True if user does belong to group,
* and FALSE if the user does not belong to the group, or either the user or group do not exist.
Adrian Rossouw
committed
*/
function provision_user_in_group($user, $group) {
// TODO: make these singletons with static variables for caching.
$user = provision_posix_username($user);
$group = provision_posix_groupname($group);
if ($user && $group) {
$info = posix_getgrnam($group);
if (in_array($user, $info['members'])) {
return TRUE;
Adrian Rossouw
committed
}
}
}
/**
* Return the valid system username for $user.
*
* @return
* Returns the username if found, otherwise returns FALSE
*/
function provision_posix_username($user) {
// TODO: make these singletons with static variables for caching.
// we do this both ways, so that the function returns NULL if no such user was found.
if (is_numeric($user)) {
$info = posix_getpwuid($user);
$user = $info['name'];
}
Adrian Rossouw
committed
else {
$info = posix_getpwnam($user);
$user = $info['name'];
}
return $user;
}
/**
* Return the valid system groupname for $group.
*
* @return
* Returns the groupname if found, otherwise returns FALSE
*/
function provision_posix_groupname($group) {
// TODO: make these singletons with static variables for caching.
// we do this both ways, so that the function returns NULL if no such user was found.
if (is_numeric($group)) {
$info = posix_getgrgid($group);
$group = $info['name'];
}
else {
$info = posix_getgrnam($group);
$group = $info['name'];
Adrian Rossouw
committed
}
return $group;
Adrian Rossouw
committed
}
Adrian Rossouw
committed
function provision_password($length = 10) {
// This variable contains the list of allowable characters for the
// password. Note that the number 0 and the letter 'O' have been
// removed to avoid confusion between the two. The same is true
// of 'I', 1, and 'l'.
$allowable_characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
// Zero-based count of characters in the allowable list:
$len = strlen($allowable_characters) - 1;
// Declare the password as a blank string.
$pass = '';
// Loop the number of times specified by $length.
for ($i = 0; $i < $length; $i++) {
// Each iteration, pick a random character from the
// allowable string and append it to the password:
$pass .= $allowable_characters[mt_rand(0, $len)];
}
return $pass;
}
Adrian Rossouw
committed
Adrian Rossouw
committed
/**
* This is a helper function which changes deeply nested objects into arrays
*
* This helps get past the face that objects are not simple to work with, or
* save in context files.
*
* This function 'misuses' a side effect of the json_decode function's second
* parameter. As this is done in C, and the structures we are manipulating
* aren't that large, it should be performant enough.
*/
function _scrub_object($input) {
return json_decode(json_encode($input), TRUE);
}
Adrian Rossouw
committed
/**
* Execute a command against a specific context object.
*/
function provision_backend_invoke($target, $command, $arguments = array(), $options = array(), $mode = 'GET') {
return drush_backend_invoke_args('@' . ltrim($target, '@') . ' ' . $command, $arguments, $options + array('root' => null, 'uri' => null), $mode);
}
/**
* A base class for the service and file handling classes that implements
* chaining of methods.
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
*/
class provisionChainedState {
protected $last_status;
protected $tokens;
/**
* Clear internal state
*/
protected function _clear_state() {
$this->last_status = NULL;
$this->tokens = NULL;
}
/**
* Return the status of the last operation.
*
* @return
* TRUE or FALSE for success or failure; NULL if there was not a previous
* operation.
*/
function status() {
return $this->last_status;
}
/**
* Log a notice into the logging system, if the last operation completed
* succesfully.
*
* @param $message
* The message to log, a string.
*/
function succeed($message) {
if ($this->last_status === TRUE) {
drush_log(dt($message, $this->tokens), 'message');
}
return $this;
}
/**
* Log a notice into the logging system, if the last operation did not
* complete succesfully.
*
* @param $message
* Log this as a error to the logging system, if the $error_codes parameter
* has been set, otherwise, log this as a warning. If the operation
* specifies an additional reason for the operation failing, it will be
* appended to this message.
*
* @param error_codes
* Generate these system level errors using the provision error bitmasks.
*/
function fail($message, $error_codes = NULL) {
if (!empty($this->tokens['@reason'])) {
$message .= ' (@reason)';
}
if ($this->last_status === FALSE) {
if (is_null($error_codes)) {
// Trigger a warning
drush_log(dt($message, $this->tokens), 'warning');
}
else {
// Trigger a sysem halting error
drush_set_error($error_codes, dt($message, $this->tokens));
}
}
return $this;
}
}
Adrian Rossouw
committed
// Base class for provision exceptions.
class provisionException extends Exception {
}
/**
* Signal for parent to continue processing.
*
* The primary use for this class is for the config
* classes to be able to signal to it's caller, that
* the configuration file was not needed, and to
* continue on.
*/
class provisionException_continue extends provisionException {
}
include_once('provision.environment.inc');
include_once('provision.service.inc');
include_once('provision.file.inc');
include_once('provision.config.inc');