/[drupal]/contributions/modules/drush/includes/sitealias.inc
ViewVC logotype

Contents of /contributions/modules/drush/includes/sitealias.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (show annotations) (download) (as text)
Wed Oct 28 11:57:56 2009 UTC (4 weeks, 4 days ago) by weitzman
Branch: MAIN
Changes since 1.2: +2 -2 lines
File MIME type: text/x-php
Minor coding standards fixes and one bug fix in includes/sitealias.inc
1 <?php
2 // $Id: sitealias.inc,v 1.2 2009/10/27 16:59:45 weitzman Exp $
3
4 /**
5 * Check to see if the first command-line arg or the
6 * -l option is a site alias; if it is, copy its record
7 * values to the 'alias' context.
8 *
9 * @return boolean
10 * TRUE if a site alias was found and processed.
11 */
12 function drush_sitealias_check_arg() {
13 $args = drush_get_arguments();
14
15 // Test to see if the first arg is a site specification
16 if (_drush_sitealias_set_context_by_name($args[0])) {
17 array_shift($args);
18 // We only need to expand the site specification
19 // once, then we are done. (Should we set a flag indicating
20 // that we already did this? Otherwise 'drush alias1 alias2 command'
21 // would behave strangely.)
22 drush_set_arguments($args);
23 return TRUE;
24 }
25
26 // Return false to indicate that no site alias was specified.
27 return FALSE;
28 }
29
30 /**
31 * Get a site alias record given an alias name or site specification.
32 *
33 * If it is the name of a site alias, return the alias record from
34 * the site aliases array.
35 *
36 * If it is the name of a folder in the 'sites' folder, construct
37 * an alias record from values stored in settings.php.
38 *
39 * If it is a site specification, construct an alias record from the
40 * values in the specification.
41 *
42 * Site specifications come in several forms:
43 *
44 * 1.) /path/to/drupal#sitename
45 * 2.) user@server/path/to/drupal#sitename
46 * 3.) user@server/path/to/drupal (sitename == server)
47 * 4.) user@server#sitename (only if $option['r'] set in some drushrc file on server)
48 * 5.) #sitename (only if $option['r'] already set, and 'sitename' is a folder in $option['r']/sites)
49 * 6.) sitename (only if $option['r'] already set, and 'sitename' is a folder in $option['r']/sites)
50 *
51 * Note that in the case of the first four forms, it is also possible
52 * to add additional site variable to the specification using uri query
53 * syntax. For example:
54 *
55 * user@server/path/to/drupal?db-url=...#sitename
56 *
57 * @param alias
58 * An alias name or site specification
59 * @param db_settings_needed
60 * 'true' if the caller needs the 'databases' record. We
61 * Will look it up the first time it is requested.
62 * @return array
63 * An alias record.
64 */
65 function drush_sitealias_get_record($alias, $db_settings_needed = false) {
66 // Sometimes getting an alias record involves loading settings.php or calling
67 // backend invoke. We'll cache all alias records fetched by this routine to
68 // insure that we never have to do anything like that twice.
69 $alias_record = drush_get_option('sitealias-' . $alias, array(), 'sitealias-cache');
70 if (empty($alias_record)) {
71 // Check to see if the provided parameter is in fact a defined alias.
72 $all_site_aliases = drush_get_option('site-aliases', array());
73 if (array_key_exists($alias, $all_site_aliases)) {
74 $alias_record = $all_site_aliases[$alias];
75 // If the alias record does not have a defined 'databases' entry,
76 // then we'll need to look one up
77 if ($db_settings_needed && !isset($alias_record['db-url']) && !isset($alias_record['databases'])) {
78 // Check to see if we've cached the databases record from a previous invocation of this function
79 $alias_record['databases'] = drush_get_option('databases-' . $alias, NULL, 'sitealias-cache');
80 if (!isset($alias_record['databases'])) {
81 // If the alias record is remote, then we'll use backend_invoke to fetch the
82 // database settings from the remote machine
83 if (array_key_exists('remote-host', $alias_record)) {
84 $data = array('root' => $alias_record['path-aliases']['!root'], 'uri' => $alias_record['uri'], 'all' => TRUE);
85 $args = array();
86 $values = drush_backend_invoke_args("sql conf", $args, $data, 'GET', FALSE, $alias_record['path-aliases']['!drush-script'], $alias_record['remote-host'], $alias_record['remote-user']);
87 $alias_record['databases'] = $values['object'];
88 }
89 // If the alias record is for a local machine, then look up and
90 // use the database settings from the appropriate settings.php file.
91 else {
92 $alias_record = array_merge(_drush_sitealias_build_record_from_settings($alias), $alias_record);
93 }
94 // Cache our result so we don't need to do IPC for successive calls to this function
95 drush_set_option('databases-' . $alias, $alias_record['databases'], 'sitealias-cache');
96 }
97 }
98 }
99 // If the parameter is not an alias, then it is some form of
100 // site specification (or it is nothing at all)
101 elseif (isset($alias)) {
102 // Cases 1.) - 4.):
103 // We will check for a site specification if the alias has at least
104 // two characters from the set '@', '/', '#'.
105 if ((strpos($alias, '@') === FALSE ? 0 : 1) + (strpos($alias, '/') === FALSE ? 0 : 1) + (strpos($alias, '#') === FALSE ? 0 : 1) >= 2) {
106 if ((substr($alias,0,7) != 'http://') && (substr($alias,0,1) != '/')) {
107 // Add on a scheme so that "user:pass@server" will always parse correctly
108 $parsed = parse_url('http://' . $alias);
109 }
110 else {
111 $parsed = parse_url($alias);
112 }
113 // Copy various parts of the parsed URL into the appropriate records of the alias record
114 foreach (array('user' => 'remote-user', 'pass' => 'remote-pass', 'host' => 'remote-host', 'fragment' => 'uri', 'path' => '!root') as $url_key => $option_key) {
115 if (array_key_exists($url_key, $parsed)) {
116 _drush_sitealias_set_record_element($alias_record, $option_key, $parsed[$url_key]);
117 }
118 }
119 // If the site specification has a query, also set the query items
120 // in the alias record. This allows passing db_url as part of the
121 // site specification, for example.
122 foreach (explode('&', $parsed['query']) as $query_arg) {
123 $query_components = explode('=', $query_arg);
124 _drush_sitealias_set_record_element($alias_record, urldecode($query_components[0]), urldecode($query_components[1]));
125 }
126
127 // Case 3.): If the URL contains a 'host' portion but no fragment, then set the uri to the host
128 // Note: We presume that 'server' is the best default for case 3; without this code, the default would
129 // be whatever is set in $options['l'] on the target machine's drushrc.php settings file.
130 if (array_key_exists('host', $parsed) && !array_key_exists('fragment', $parsed)) {
131 $alias_record['uri'] = $parsed['host'];
132 }
133 }
134 else {
135 // Case 5.) and 6.):
136 // If the alias is the name of a folder in the 'sites' directory,
137 // then use it as a local site specification.
138 $alias_record = _drush_sitealias_find_record_for_local_site($alias, $db_settings_needed);
139 }
140 }
141 _drush_sitealias_add_static_defaults($alias_record);
142 // Fail fast if database settings are not available and the caller
143 // said that they are required
144 if ($db_settings_needed && !isset($alias_record['databases'])) {
145 drush_print("Error: could not get database spec when it was required for " . $alias);
146 exit(1);
147 }
148 drush_set_option('sitealias-' . $alias, $alias_record, 'sitealias-cache');
149 }
150 return $alias_record;
151 }
152
153 /**
154 * Add "static" default values to the given alias record. The
155 * difference between a static default and a transient default is
156 * that static defaults -always- exist in the alias record, and
157 * they are cached, whereas transient defaults are only added
158 * if the given drush command explicitly adds them.
159 *
160 * @param alias_record
161 * An alias record with most values already filled in
162 */
163 function _drush_sitealias_add_static_defaults(&$alias_record) {
164 // If there is a 'db-url' entry but not 'databases' entry, then we will
165 // build 'databases' from 'db-url' so that drush commands that use aliases
166 // can always count on using a uniform 'databases' array.
167 if (isset($alias_record['db-url']) && !isset($alias_record['databases'])) {
168 $alias_record['databases'] = array('default' => array('default' => drush_convert_db_from_db_url($alias_record['db-url'])));
169 }
170 }
171
172 /**
173 * Add "transient" default values to the given alias record. The
174 * difference between a static default and a transient default is
175 * that static defaults -always- exist in the alias record,
176 * whereas transient defaults are only added if the given drush
177 * command explicitly calls this function. The other advantage
178 * of transient defaults is that it is possible to differentiate
179 * between a default value and an unspecified value, since the
180 * transient defaults are not added until requested.
181 *
182 * Since transient defaults are not cached, you should avoid doing
183 * expensive operations here. To be safe, drush commands should
184 * avoid calling this function more than once.
185 *
186 * @param alias_record
187 * An alias record with most values already filled in
188 */
189 function _drush_sitealias_add_transient_defaults(&$alias_record) {
190 if (isset($alias_record['path-aliases'])) {
191 if (!array_key_exists('!drush', $alias_record['path-aliases'])) {
192 $alias_record['path-aliases']['!drush'] = dirname(DRUSH_COMMAND);
193 }
194 }
195 }
196
197 /**
198 * Find a record in the site aliases list for a local site with
199 * the requested uri, if one exists. Otherwise, build one from
200 * the settings.php file for the specified site.
201 */
202 function _drush_sitealias_find_record_for_local_site($alias, $db_settings_needed = false) {
203 $alias_record = array();
204
205 // Clip off the leading '#' if it is there
206 if (substr($alias,0,1) == '#') {
207 $alias = substr($alias,1);
208 }
209
210 // This function may be called during the drush bootstrap
211 // (i.e., from drush_sitealias_check_arg()), when 'DRUSH_DRUPAL_ROOT'
212 // has not been set. It may also be called after bootstraping
213 // has finished (e.g. to process an argument from sync or sql sync)
214 // when it would be wasteful to call drush_locate_root again.
215 // If we find an alias or site specification during drush_sitealias_check_arg(),
216 // then we will set the 'root' option. If we do not, though,
217 // we will end up calling drush_locate_root every time this
218 // function is called.
219 // TODO: Would it be valid to use some other mechanism to test
220 // to see if the drupal root has already been cached? Maybe
221 // drush should just drush_set_option('root', $drupal_root) rather
222 // than setting a context and a bootstrap value?
223 //$drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT');
224 //$drupal_root = drush_bootstrap_value('drupal_root');
225 $drupal_root = drush_get_option(array('r', 'root'), drush_locate_root());
226
227 $all_site_aliases = drush_get_option('site-aliases', array());
228 foreach ($all_site_aliases as $one_alias_name => $one_alias_record) {
229 if (!isset($one_alias_record['remote-host']) && isset($one_alias_record['path-aliases']) && isset($one_alias_record['path-aliases']['!root']) && ($one_alias_record['uri'] == $alias) && ($one_alias_record['path-aliases']['!root'] == $drupal_root)) {
230 $alias_record = $one_alias_record;
231 }
232 }
233
234 if (empty($alias_record) || ($db_settings_needed && !isset($alias_record['db-url']) && !isset($alias_record['databases']) )) {
235 $alias_record = array_merge(_drush_sitealias_build_record_from_settings($alias, $drupal_root), $alias_record);
236 }
237
238 return $alias_record;
239 }
240
241 /**
242 * Use the information from a particular settings.php file
243 * to build an alias record.
244 *
245 * @param alias
246 * The name of the site in the 'sites' folder to convert
247 * @return array
248 * An alias record.
249 */
250 function _drush_sitealias_build_record_from_settings($alias, $drupal_root = null) {
251 $alias_record = array();
252
253 // Clip off the leading '#' if it is there
254 if (substr($alias,0,1) == '#') {
255 $alias = substr($alias,1);
256 }
257
258 if (!isset($drupal_root)) {
259 //$drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT');
260 $drupal_root = drush_get_option(array('r', 'root'), drush_locate_root());
261 }
262
263 // If we did not find an alias record that matches,
264 // then build one.
265 if (empty($alias_record)) {
266 $site_settings_file = $drupal_root . '/sites/' . $alias . '/settings.php';
267 if (isset($drupal_root) && file_exists($site_settings_file)) {
268 $alias_record['uri'] = $alias;
269 global $databases, $db_url;
270 require $site_settings_file;
271 if (isset($db_url)) {
272 $alias_record['db-url'] = $db_url;
273 }
274 else {
275 $alias_record['databases'] = $databases;
276 }
277 $alias_record['path-aliases'] = array(
278 '!root' => $drupal_root,
279 /*'!files' => '/path/to/file/storage', */
280 /*'!dump' => '/path/to/sql/dumpfile', */ );
281 }
282 }
283 return $alias_record;
284 }
285
286 /**
287 * Convert from an old-style database URL to an array of database settings
288 *
289 * @param db_url
290 * A Drupal 6 db-url string to convert.
291 * @return array
292 * An array of database values.
293 */
294 function drush_convert_db_from_db_url($db_url) {
295 $url = parse_url($db_url);
296 // Fill in defaults to prevent notices.
297 $url += array(
298 'driver' => NULL,
299 'user' => NULL,
300 'pass' => NULL,
301 'port' => NULL,
302 'database' => NULL,
303 );
304 $url = (object)$url;
305 return array(
306 'driver' => $url->scheme == 'mysqli' ? 'mysql' : $url->scheme,
307 'username' => urldecode($url->user),
308 'password' => urldecode($url->pass),
309 'port' => urldecode($url->port),
310 'host' => urldecode($url->host),
311 'database' => substr(urldecode($url->path), 1), // skip leading '/' character
312 );
313 }
314
315 /**
316 * Utility function used by drush_get_alias; keys that start with
317 * '!' are path aliases, the rest are entries in the alias record.
318 */
319 function _drush_sitealias_set_record_element(&$alias_record, $key, $value) {
320 if (substr($key,0,1) == '!') {
321 $alias_record['path-aliases'][$key] = $value;
322 }
323 elseif (!empty($key)) {
324 $alias_record[$key] = $value;
325 }
326 }
327
328 /**
329 * Looks up the specified alias record and calls through to
330 * drush_sitealias_set_alias_context, below.
331 *
332 * @param alias
333 * The name of the alias record
334 * @param prefix
335 * The prefix value to afix to the beginning of every
336 * key set.
337 * @return boolean
338 * TRUE is an alias was found and processed.
339 */
340 function _drush_sitealias_set_context_by_name($alias, $prefix = '') {
341 $site_alias_settings = drush_sitealias_get_record($alias);
342 if (!empty($site_alias_settings)) {
343 drush_sitealias_set_alias_context($site_alias_settings, $prefix);
344 return TRUE;
345 }
346 return FALSE;
347 }
348
349 /**
350 * Given a site alias record, copy selected fields from it
351 * into the drush 'alias' context. The 'alias' context has
352 * lower precedence than the 'options' context, so values
353 * set by an alias record can be overridden by command-line
354 * parameters.
355 *
356 * @param site_alias_settings
357 * An alias record
358 * @param prefix
359 * The prefix value to afix to the beginning of every
360 * key set. For example, if this function is called once with
361 * 'source-' and again with 'destination-' prefixes, then the
362 * source database records will be stored in 'source-databases',
363 * and the destination database records will be in
364 * 'destination-databases'.
365 */
366 function drush_sitealias_set_alias_context($site_alias_settings, $prefix) {
367 // Transfer all non-array options from the site alias to the drush options
368 // in the 'alias' context.
369 foreach ($site_alias_settings as $key => $value) {
370 if (!is_array($value) || ($key == "databases")) {
371 drush_set_option($prefix . $key, $value, 'alias');
372 }
373 }
374 // Transfer selected path aliases to the drush options.
375 if (array_key_exists('path-aliases', $site_alias_settings)) {
376 foreach (array('!root', '!drush', '!drush-script', '!dump', '!include') as $key) {
377 if (array_key_exists($key, $site_alias_settings['path-aliases'])) {
378 drush_set_option($prefix . substr($key, 1), $site_alias_settings['path-aliases'][$key], 'alias');
379 }
380 }
381 }
382 // If there are prefix-specific options (e.g. 'source-options' or 'target-options'),
383 // then transfer those values as well.
384 drush_sitealias_apply_special_alias_record_options($site_alias_settings, $prefix);
385 }
386
387 /**
388 * Looks up the specified alias record and then calls through
389 * to drush_sitealias_apply_special_alias_record_options, below.
390 *
391 * @param alias
392 * The name of the alias record.
393 * @param prefix
394 * The prefix value to afix to the beginning of every
395 * key set.
396 */
397 function drush_sitealias_apply_special_alias_options($alias, $prefix) {
398 if ($prefix != '') {
399 $site_alias_settings = drush_sitealias_get_record($alias);
400 if (!empty($site_alias_settings)) {
401 drush_sitealias_apply_special_alias_record_options($site_alias_settings, $prefix);
402 }
403 }
404 }
405
406 /**
407 * Site alias records can have special options sections,
408 * one for every kind of prefix used with 'drush_sitealias_set_alias_context.
409 * The options stored in this record are copied to the 'alias'
410 * context whenever that prefix is used.
411 *
412 * @param site_alias_settings
413 * The alias record.
414 * @param prefix
415 * The prefix value to afix to the beginning of every
416 * key set.
417 */
418 function drush_sitealias_apply_special_alias_record_options($site_alias_settings, $prefix) {
419 if ($prefix != '') {
420 if ((array_key_exists($prefix . 'options', $site_alias_settings))) {
421 foreach ($site_alias_settings[$prefix . 'options'] as $key => $value) {
422 drush_set_option($key, $value, 'alias');
423 }
424 }
425 }
426 }

  ViewVC Help
Powered by ViewVC 1.1.2