More updates to stop using dev or alpha or beta versions.
[yaffs-website] / vendor / drush / drush / includes / context.inc
1 <?php
2 /**
3  * @file
4  * The Drush context API implementation.
5  *
6  * This API acts as a storage mechanism for all options, arguments and
7  * configuration settings that are loaded into drush.
8  *
9  * This API also acts as an IPC mechanism between the different drush commands,
10  * and provides protection from accidentally overriding settings that are
11  * needed by other parts of the system.
12  *
13  * It also avoids the necessity to pass references through the command chain
14  * and allows the scripts to keep track of whether any settings have changed
15  * since the previous execution.
16  *
17  * This API defines several contexts that are used by default.
18  *
19  * Argument contexts :
20  *   These contexts are used by Drush to store information on the command.
21  *   They have their own access functions in the forms of
22  *   drush_set_arguments(), drush_get_arguments(), drush_set_command(),
23  *   drush_get_command().
24  *
25  *     command : The drush command being executed.
26  *     arguments : Any additional arguments that were specified.
27  *
28  * Setting contexts :
29  *   These contexts store options that have been passed to the drush.php
30  *   script, either through the use of any of the config files, directly from
31  *   the command line through --option='value' or through a JSON encoded string
32  *   passed through the STDIN pipe.
33  *
34  *   These contexts are accessible through the drush_get_option() and
35  *   drush_set_option() functions.  See drush_context_names() for a description
36  *   of all of the contexts.
37  *
38  *   Drush commands may also choose to save settings for a specific context to
39  *   the matching configuration file through the drush_save_config() function.
40  */
41
42 use Drush\Drush;
43 use Drush\Log\LogLevel;
44
45
46 /**
47  * Return a list of the valid drush context names.
48  *
49  * These context names are carefully ordered from
50  * highest to lowest priority.
51  *
52  * These contexts are evaluated in a certain order, and the highest priority value
53  * is returned by default from drush_get_option. This allows scripts to check whether
54  * an option was different before the current execution.
55  *
56  *   Specified by the script itself :
57  *     process  : Generated in the current process.
58  *     cli      : Passed as --option=value to the command line.
59  *     stdin    : Passed as a JSON encoded string through stdin.
60  *     specific : Defined in a command-specific option record, and
61  *                set in the command context whenever that command is used.
62  *     alias    : Defined in an alias record, and set in the
63  *                alias context whenever that alias is used.
64  *
65  *   Specified by config files :
66  *     custom   : Loaded from the config file specified by --config or -c
67  *     site     : Loaded from the drushrc.php file in the Drupal site directory.
68  *     drupal   : Loaded from the drushrc.php file in the Drupal root directory.
69  *     user     : Loaded from the drushrc.php file in the user's home directory.
70  *     home.drush Loaded from the drushrc.php file in the $HOME/.drush directory.
71  *     system   : Loaded from the drushrc.php file in the system's $PREFIX/etc/drush directory.
72  *     drush    : Loaded from the drushrc.php file in the same directory as drush.php.
73  *
74  *   Specified by the script, but has the lowest priority :
75  *     default  : The script might provide some sensible defaults during init.
76  */
77 function drush_context_names() {
78   static $contexts = [
79     'process', 'cli', 'stdin', 'specific', 'alias',
80     'custom', 'site', 'drupal', 'user', 'home.drush', 'system',
81     'drush', 'default'
82   ];
83
84   return $contexts;
85 }
86
87 function drush_set_config_options($context, $options, $override = []) {
88   // Copy 'config-file' into 'context-path', converting to an array to hold multiple values if necessary
89   if (isset($options['config-file'])) {
90     if (isset($options['context-path'])) {
91       $options['context-path'] = array_merge([$options['config-file']], is_array($options['context-path']) ? $options['context-path'] : [$options['context-path']]);
92     }
93     else {
94       $options['context-path'] = $options['config-file'];
95     }
96   }
97
98   // Take out $aliases and $command_specific options
99   drush_set_config_special_contexts($options);
100
101   drush_set_context($context, $options);
102 }
103
104 /**
105  * For all global options with a short form, convert all options in the option
106  * array that use the short form into the long form.
107  */
108 function drush_expand_short_form_options(&$options) {
109   foreach (drush_get_global_options() as $name => $info) {
110     if (is_array($info)) {
111       // For any option with a short form, check to see if the short form was set in the
112       // options.  If it was, then rename it to its long form.
113       if (array_key_exists('short-form', $info) && array_key_exists($info['short-form'], $options)) {
114         if (!array_key_exists($name, $options) || !array_key_exists('merge-pathlist', $info)) {
115           $options[$name] = $options[$info['short-form']];
116         }
117         else {
118           $options[$name] = array_merge((array)$options[$name], (array)$options[$info['short-form']]);
119         }
120         unset($options[$info['short-form']]);
121       }
122     }
123   }
124 }
125
126 /**
127  * There are certain options such as 'site-aliases' and 'command-specific'
128  * that must be merged together if defined in multiple drush configuration
129  * files.  If we did not do this merge, then the last configuration file
130  * that defined any of these properties would overwrite all of the options
131  * that came before in previously-loaded configuration files.  We place
132  * all of them into their own context so that this does not happen.
133  */
134 function drush_set_config_special_contexts(&$options) {
135   if (isset($options) && is_array($options)) {
136     $has_command_specific = array_key_exists('command-specific', $options);
137     // Change the keys of the site aliases from 'alias' to '@alias'
138     if (array_key_exists('site-aliases', $options)) {
139       $user_aliases = $options['site-aliases'];
140       $options['site-aliases'] = [];
141       foreach ($user_aliases as $alias_name => $alias_value) {
142         if (substr($alias_name,0,1) != '@') {
143           $alias_name = "@$alias_name";
144         }
145         $options['site-aliases'][$alias_name] = $alias_value;
146       }
147     }
148     // Expand -s into --simulate, etc.
149     drush_expand_short_form_options($options);
150
151     foreach (drush_get_global_options() as $name => $info) {
152       if (is_array($info)) {
153         // For any global option with the 'merge-pathlist' or 'merge-associative' flag, set its
154         // value in the specified context.  The option is 'merged' because we
155         // load $options with the value from the context prior to including the
156         // configuration file.  If the configuration file sets $option['special'][] = 'value',
157         // then the configuration will be merged.  $option['special'] = array(...), on the
158         // other hand, will replace rather than merge the values together.
159         if ((array_key_exists($name, $options)) && (array_key_exists('merge', $info) || (array_key_exists('merge-pathlist', $info) || array_key_exists('merge-associative', $info)))) {
160           $context = array_key_exists('context', $info) ? $info['context'] : $name;
161           $cache =& drush_get_context($context);
162           $value = $options[$name];
163           if (!is_array($value) && array_key_exists('merge-pathlist', $info)) {
164             $value = explode(PATH_SEPARATOR, $value);
165           }
166           if (array_key_exists('merge-associative', $info)) {
167             foreach ($value as $subkey => $subvalue) {
168               $cache[$subkey] = array_merge(isset($cache[$subkey]) ? $cache[$subkey] : [], $subvalue);
169             }
170           }
171           else {
172             $cache = array_unique(array_merge($cache, $value));
173           }
174           // Once we have moved the option to its special context, we
175           // can remove it from its option context -- unless 'propagate-cli-value'
176           // is set, in which case we need to let it stick around in options
177           // in case it is needed in backend invoke.
178           if (!array_key_exists('propagate-cli-value', $info)) {
179             unset($options[$name]);
180           }
181         }
182       }
183     }
184
185     // If command-specific options were set and if we already have
186     // a command, then apply the command-specific options immediately.
187     if ($has_command_specific) {
188       drush_command_default_options();
189     }
190   }
191 }
192
193 /**
194  * Set a specific context.
195  *
196  * @param context
197  *   Any of the default defined contexts.
198  * @param value
199  *   The value to store in the context
200  *
201  * @return
202  *   An associative array of the settings specified in the request context.
203  */
204 function drush_set_context($context, $value) {
205   $cache =& drush_get_context($context);
206   $cache = $value;
207   return $value;
208 }
209
210
211 /**
212  * Return a specific context, or the whole context cache
213  *
214  * This function provides a storage mechanism for any information
215  * the currently running process might need to communicate.
216  *
217  * This avoids the use of globals, and constants.
218  *
219  * Functions that operate on the context cache, can retrieve a reference
220  * to the context cache using :
221  *     $cache = &drush_get_context($context);
222  *
223  * This is a private function, because it is meant as an internal
224  * generalized API for writing static cache functions, not as a general
225  * purpose function to be used inside commands.
226  *
227  * Code that modifies the reference directly might have unexpected consequences,
228  * such as modifying the arguments after they have already been parsed and dispatched
229  * to the callbacks.
230  *
231  * @param context
232  *   Optional. Any of the default defined contexts.
233  *
234  * @return
235  *   If context is not supplied, the entire context cache will be returned.
236  *   Otherwise only the requested context will be returned.
237  *   If the context does not exist yet, it will be initialized to an empty array.
238  */
239 function &drush_get_context($context = NULL, $default = NULL) {
240   static $cache = [];
241   if (isset($context)) {
242     if (!isset($cache[$context])) {
243       $default = !isset($default) ? [] : $default;
244       $cache[$context] = $default;
245     }
246     return $cache[$context];
247   }
248   return $cache;
249 }
250
251 /**
252  * Set the arguments passed to the drush.php script.
253  *
254  * This function will set the 'arguments' context of the current running script.
255  *
256  * When initially called by drush_parse_args, the entire list of arguments will
257  * be populated. Once the command is dispatched, this will be set to only the remaining
258  * arguments to the command (i.e. the command name is removed).
259  *
260  * @param arguments
261  *   Command line arguments, as an array.
262  */
263 function drush_set_arguments($arguments) {
264   drush_set_context('arguments', $arguments);
265 }
266
267 /**
268  * Gets the command line arguments passed to Drush.
269  *
270  * @return array
271  *   An indexed array of arguments. Until Drush has dispatched the command, the
272  *   array will include the command name as the first element. After that point
273  *   the array will not include the command name.
274  *
275  * @see drush_set_arguments()
276  */
277 function drush_get_arguments() {
278   return drush_get_context('arguments');
279 }
280
281 /**
282  * Set the command being executed.
283  *
284  * Drush_dispatch will set the correct command based on it's
285  * matching of the script arguments retrieved from drush_get_arguments
286  * to the implemented commands specified by drush_get_commands.
287  *
288  * @param
289  *   A numerically indexed array of command components.
290  */
291 function drush_set_command($command) {
292   drush_set_context('command', $command);
293 }
294
295 /**
296  * Return the command being executed.
297  */
298 function drush_get_command() {
299   return drush_get_context('command');
300 }
301
302 /**
303  * Get the value for an option.
304  *
305  * If the first argument is an array, then it checks whether one of the options
306  * exists and return the value of the first one found. Useful for allowing both
307  * -h and --host-name
308  *
309  * @param option
310  *   The name of the option to get
311  * @param default
312  *   Optional. The value to return if the option has not been set
313  * @param context
314  *   Optional. The context to check for the option. If this is set, only this context will be searched.
315  */
316 function drush_get_option($option, $default = NULL, $context = NULL) {
317   // Uncomment when fumigating.
318 //  $backtrace = debug_backtrace()[1];
319 //  if (!strpos($backtrace['file'], 'engines') && !strpos($backtrace['file'], 'preflight') && !strpos($backtrace['file'], 'backend')) {
320 //    drush_log('drush_get_option() has been deprecated and is unreliable. Called by '. $backtrace['function']. ' in '. $backtrace['file']. ':'. $backtrace['line'], LogLevel::WARNING);
321 //  }
322
323   $value = NULL;
324
325   if ($context) {
326     // We have a definite context to check for the presence of an option.
327     $value = _drush_get_option($option, drush_get_context($context));
328   }
329   else {
330     // We are not checking a specific context, so check them in a predefined order of precedence.
331     $contexts = drush_context_names();
332
333     foreach ($contexts as $context) {
334       $value = _drush_get_option($option, drush_get_context($context));
335
336       if ($value !== NULL) {
337         return $value;
338       }
339     }
340   }
341
342   if ($value !== NULL) {
343     return $value;
344   }
345
346   return $default;
347 }
348
349 /**
350  * Get the value for an option and return it as a list.  If the
351  * option in question is passed on the command line, its value should
352  * be a comma-separated list (e.g. --flag=1,2,3).  If the option
353  * was set in a drushrc.php file, then its value may be either a
354  * comma-separated list or an array of values (e.g. $option['flag'] = array('1', '2', '3')).
355  *
356  * @param option
357  *   The name of the option to get
358  * @param default
359  *   Optional. The value to return if the option has not been set
360  * @param context
361  *   Optional. The context to check for the option. If this is set, only this context will be searched.
362  */
363 function drush_get_option_list($option, $default = [], $context = NULL) {
364   $result = drush_get_option($option, $default, $context);
365
366   if (!is_array($result)) {
367     $result = array_map('trim', array_filter(explode(',', $result)));
368   }
369
370   return $result;
371 }
372
373 /**
374  * Get the value for an option, but first checks the provided option overrides.
375  *
376  * The feature of drush_get_option that allows a list of option names
377  * to be passed in an array is NOT supported.
378  *
379  * @param option_overrides
380  *   An array to check for values before calling drush_get_option.
381  * @param option
382  *   The name of the option to get.
383  * @param default
384  *   Optional. The value to return if the option has not been set.
385  * @param context
386  *   Optional. The context to check for the option. If this is set, only this context will be searched.
387  *
388  */
389 function drush_get_option_override($option_overrides, $option, $default = NULL, $context = NULL) {
390   return drush_sitealias_get_option($option_overrides, $option, $default, '', $context);
391 }
392
393 /**
394  * Get an option out of the specified alias.  If it has not been
395  * set in the alias, then get it via drush_get_option.
396  *
397  * @param site_alias_record
398  *   An array of options for an alias record.
399  * @param option
400  *   The name of the option to get.
401  * @param default
402  *   Optional. The value to return if the option does not exist in the site record and has not been set in a context.
403  * @param context
404  *   Optional. The context to check for the option. If this is set, only this context will be searched.
405  */
406 function drush_sitealias_get_option($site_alias_record, $option, $default = NULL, $prefix = '', $context = NULL) {
407   if (is_array($site_alias_record) && array_key_exists($option, $site_alias_record)) {
408     return $site_alias_record[$option];
409   }
410   else {
411     return drush_get_option($prefix . $option, $default, $context);
412   }
413 }
414
415 /**
416  * Get all of the values for an option in every context.
417  *
418  * @param option
419  *   The name of the option to get
420  * @return
421  *   An array whose key is the context name and value is
422  *   the specific value for the option in that context.
423  */
424 function drush_get_context_options($option, $flatten = FALSE) {
425   $result = [];
426
427   $contexts = drush_context_names();
428   foreach ($contexts as $context) {
429     $value = _drush_get_option($option, drush_get_context($context));
430
431     if ($value !== NULL) {
432       if ($flatten && is_array($value)) {
433         $result = array_merge($value, $result);
434       }
435       else {
436         $result[$context] = $value;
437       }
438     }
439   }
440
441   return $result;
442 }
443
444 /**
445  * Retrieves a collapsed list of all options.
446  */
447 function drush_get_merged_options() {
448   $contexts = drush_context_names();
449   $cache = drush_get_context();
450   $result = [];
451   foreach (array_reverse($contexts) as $context) {
452     if (array_key_exists($context, $cache)) {
453       $result = array_merge($result, $cache[$context]);
454     }
455   }
456
457   return $result;
458 }
459
460 /**
461  * Helper function to recurse through possible option names
462  */
463 function _drush_get_option($option, $context) {
464   if (is_array($option)) {
465     foreach ($option as $current) {
466       $current_value = _drush_get_option($current, $context);
467       if (isset($current_value)) {
468         return $current_value;
469       }
470     }
471   }
472   elseif (array_key_exists('no-' . $option, $context)) {
473     return FALSE;
474   }
475   elseif (array_key_exists($option, $context)) {
476     return $context[$option];
477   }
478
479   return NULL;
480 }
481
482 /**
483  * Set an option in one of the option contexts.
484  *
485  * @param option
486  *   The option to set.
487  * @param value
488  *   The value to set it to.
489  * @param context
490  *   Optional. Which context to set it in.
491  * @return
492  *   The value parameter. This allows for neater code such as
493  *     $myvalue = drush_set_option('http_host', $_SERVER['HTTP_HOST']);
494  *   Without having to constantly type out the value parameter.
495  */
496 function drush_set_option($option, $value, $context = 'process') {
497   $cache =& drush_get_context($context);
498   $cache[$option] = $value;
499   return $value;
500 }
501
502 /**
503  * A small helper function to set the value in the default context
504  */
505 function drush_set_default($option, $value) {
506   return drush_set_option($option, $value, 'default');
507 }
508
509 /**
510  * Remove a setting from a specific context.
511  *
512  * @param
513  *   Option to be unset
514  * @param
515  *   Context in which to unset the value in.
516  */
517 function drush_unset_option($option, $context = NULL) {
518   if ($context != NULL) {
519     $cache =& drush_get_context($context);
520     if (array_key_exists($option, $cache)) {
521       unset($cache[$option]);
522     }
523   }
524   else {
525     $contexts = drush_context_names();
526
527     foreach ($contexts as $context) {
528       drush_unset_option($option, $context);
529     }
530   }
531 }