provision.inc 8.68 KB
Newer Older
1
<?php
2
// $Id$
3

4
5
6
7
8
9
10
11
12
/**
 * @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
13
 * @see provisionvalues
14
15
 */

16
17
drush_errors_on();

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
 * @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.
 */

/**
 * Returns the aggregated site data from both the pre-existing site.php file, and the options passed to Drush
 *
 * This function merges the data from the command line parser, and the information already saved by previous invokations
 * of the api. This provides a single view of all data relating to the site.
 * This function also provides sensible defaults for some of the settings.
 *
 * @param url
 *   The url of the site being invoked.
 * @return
 *   An associated array containing the relevant settings for the site.
 */
function provision_get_site_data($url) {
  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
48
    $site_data['aliases'] = explode(",", $site_data['aliases']);
  }  
49
50
51
52
53
54
55
56
57
58
59
60
  return $site_data;
}

/**
 * Load site data stored in the site.php file for the specified site.
 *
 * @param url
 *   The url of the site being invoked
 * @return
 *   If the file was found, an associative array of the data that was loaded. Otherwise returns FALSE.
 */
function provision_load_site_data($url) {
61
  //Load the configuration data.
62
63
64

  //@TODO remove this, it is a temporary measure until all site.php files are placed by drushrc.php files

65
  $conf_file = "sites/$url/site.php";
66
67
  if (file_exists($conf_file)) {
    provision_path('chmod', $conf_file, 0400);
68
    require($conf_file);
69
70
71

    // The provision 0.1 config data might contain older data,
    // so any data in the new drushrc.php file would be newer.
72
    $site_context = drush_get_context('site');
73
74
    $site_context = array_merge($data, $site_context);
    drush_set_context('site', $site_context);
75
  }
76
  return FALSE;
77
78
79
80
81
}

/**
 * Save modified options to the site.php file
 */
82
83
function provision_save_site_data() {
  drush_save_config('site');
84
85
  // @TODO : remove site.php file after successful 
  // drushrc save.
86
87
88
89
90
91
92
}

/**
 * @} End of "defgroup sitedata".
 */


93
/**
94
95
96
97
98
 * Save the options for the platform to the drushrc.php in the root of
 * the platform. 
 *
 * @return 
 *   Boolean. The value returned by drush_save_config().
99
100
 */
function provision_save_platform_data() {
101
  return drush_save_config('drupal');
102
103
}

104
/**
105
 * @defgroup provisionvalues Value replacement support for the provisioning framework
106
107
108
 * @{
 */

109
110
111
112
/**
 * Generate the text for a config file using php
 */
function provision_render_config($template, $variables) {
113
  drush_errors_off();
114
115
  extract($variables, EXTR_SKIP);  // Extract the variables to a local namespace
  ob_start();                      // Start output buffering
116
  eval('?>'. $template);                 // Generate content
117
118
  $contents = ob_get_contents();   // Get the contents of the buffer
  ob_end_clean();                  // End buffering and discard
119
  drush_errors_on();
120
121
122
  return $contents;                // Return the contents
}

123
/**
124
 * @} End of "defgroup provisionvalues".
125
126
 */

127

128
129
130
131
/**
 * Remove files or directories, recursively
 *
 * This was taken from imagecache.module, with slight modifications:
132
 * - carry error codes along the way (returns TRUE only if all operations return TRUE)
133
134
135
136
137
138
 * - 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);
139
    while (($entry = $d->read()) !== FALSE) {
140
141
      if ($entry == '.' || $entry == '..') continue;
      $entry_path = $path .'/'. $entry;
142
      if (_provision_file_check_location($entry_path, $path)) {
143
        $ret = _provision_recursive_delete($entry_path);
144
145
      } 
      else {
146
147
148
149
        $ret = 0;
      }
    }

150
    $rm = provision_path('rmdir', $path, TRUE,
151
152
      dt('Deleting @path directory sucessful.', array('@path' => $path)),
      dt('Deleting @path directory failed.', array('@path' => $path)));
153
154
155
156

    $ret = $ret && $rm;
  }
  else {
157
    $rm = provision_path('unlink', $path, TRUE, NULL, 
158
      dt('Deleting @path file failed.', array('@path' => $path)));
159
160
161
162
163
    $ret = $ret && $rm;
  }
  return $ret;
}

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
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;
}

180
181
/**
 * Wrapper around drush_shell_exec to provide sprintf functionality with some more safety.
182
183
184
 *
 * @TODO: fix this so we can get error codes and the return values. drush_shell_exec is too
 *        limited
185
186
187
188
 */
function provision_shell_exec() {
  $args = func_get_args();
  
189
  //do not change the command itself, just the parameters.
190
191
192
  for ($x = 1; $x < sizeof($args); $x++) {
    $args[$x] = escapeshellcmd($args[$x]);
  }
193
  $command = call_user_func_array('sprintf', $args);
194
  drush_log($command); 
195
  return drush_shell_exec($command);
196
197
}

198
/**
199
 * Check whether a user is a member of a group.
200
 *
201
202
203
204
205
206
207
 * @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, 
208
 *   and FALSE if the user does not belong to the group, or either the user or group do not exist.
209
 */
210
211
212
213
214
215
216
217
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;
218
219
    }
  }
220
  return FALSE;
221
222
223
224
225
226
}

/**
 * Return the valid system username for $user.
 *
 * @return
227
 *   Returns the username if found, otherwise returns FALSE
228
229
230
 */
function provision_posix_username($user) {
  // TODO: make these singletons with static variables for caching.
231
  // we do this both ways, so that the function returns NULL if no such user was found.
232
233
234
235
  if (is_numeric($user)) {
    $info = posix_getpwuid($user);
    $user = $info['name'];
  }
236
  else {
237
238
239
240
241
242
243
244
245
246
    $info = posix_getpwnam($user);
    $user = $info['name'];
  }
  return $user;
}

/**
 * Return the valid system groupname for $group.
 *
 * @return
247
 *   Returns the groupname if found, otherwise returns FALSE
248
249
250
 */
function provision_posix_groupname($group) {
  // TODO: make these singletons with static variables for caching.
251
  // we do this both ways, so that the function returns NULL if no such user was found.
252
  if (is_numeric($group)) {
253
254
255
256
257
258
    $info = posix_getgrgid($group);
    $group = $info['name'];
  }
  else {
    $info = posix_getgrnam($group);
    $group = $info['name'];
259
  }
260
  return $group;
261
}
262

263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
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;
}
286

287
288
289
290
291
292
293
294
295
296
297
298
299
/**
 * 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);
}