123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597 |
- <?php
- /**
- * @file
- * The Drush context API implementation.
- *
- * This API acts as a storage mechanism for all options, arguments and
- * configuration settings that are loaded into drush.
- *
- * This API also acts as an IPC mechanism between the different drush commands,
- * and provides protection from accidentally overriding settings that are
- * needed by other parts of the system.
- *
- * It also avoids the necessity to pass references through the command chain
- * and allows the scripts to keep track of whether any settings have changed
- * since the previous execution.
- *
- * This API defines several contexts that are used by default.
- *
- * Argument contexts :
- * These contexts are used by Drush to store information on the command.
- * They have their own access functions in the forms of
- * drush_set_arguments(), drush_get_arguments(), drush_set_command(),
- * drush_get_command().
- *
- * command : The drush command being executed.
- * arguments : Any additional arguments that were specified.
- *
- * Setting contexts :
- * These contexts store options that have been passed to the drush.php
- * script, either through the use of any of the config files, directly from
- * the command line through --option='value' or through a JSON encoded string
- * passed through the STDIN pipe.
- *
- * These contexts are accessible through the drush_get_option() and
- * drush_set_option() functions. See drush_context_names() for a description
- * of all of the contexts.
- *
- * Drush commands may also choose to save settings for a specific context to
- * the matching configuration file through the drush_save_config() function.
- */
- /**
- * Return a list of the valid drush context names.
- *
- * These context names are carefully ordered from
- * highest to lowest priority.
- *
- * These contexts are evaluated in a certain order, and the highest priority value
- * is returned by default from drush_get_option. This allows scripts to check whether
- * an option was different before the current execution.
- *
- * Specified by the script itself :
- * process : Generated in the current process.
- * cli : Passed as --option=value to the command line.
- * stdin : Passed as a JSON encoded string through stdin.
- * specific : Defined in a command-specific option record, and
- * set in the command context whenever that command is used.
- * alias : Defined in an alias record, and set in the
- * alias context whenever that alias is used.
- *
- * Specified by config files :
- * custom : Loaded from the config file specified by --config or -c
- * site : Loaded from the drushrc.php file in the Drupal site directory.
- * drupal : Loaded from the drushrc.php file in the Drupal root directory.
- * user : Loaded from the drushrc.php file in the user's home directory.
- * home.drush Loaded from the drushrc.php file in the $HOME/.drush directory.
- * system : Loaded from the drushrc.php file in the system's $PREFIX/etc/drush directory.
- * drush : Loaded from the drushrc.php file in the same directory as drush.php.
- *
- * Specified by the script, but has the lowest priority :
- * default : The script might provide some sensible defaults during init.
- */
- function drush_context_names() {
- static $contexts = array(
- 'process', 'cli', 'stdin', 'specific', 'alias',
- 'custom', 'site', 'drupal', 'user', 'home.drush', 'system',
- 'drush', 'default');
- return $contexts;
- }
- /**
- * Return a list of possible drushrc file locations.
- *
- * @context
- * A valid drush context from drush_context_names().
- * @prefix
- * Optional. Specify a prefix to prepend to ".drushrc.php" when looking
- * for config files. Most likely used by contrib commands.
- * @return
- * An associative array containing possible config files to load
- * The keys are the 'context' of the files, the values are the file
- * system locations.
- */
- function _drush_config_file($context, $prefix = NULL) {
- $configs = array();
- $config_file = $prefix ? $prefix . '.' . 'drushrc.php' : 'drushrc.php';
- // Did the user explicitly specify a config file?
- if ($config = drush_get_option(array('c', 'config'))) {
- if (is_dir($config)) {
- $config = $config . '/drushrc.php';
- }
- $configs['custom'] = $config;
- }
- if ($site_path = drush_get_context('DRUSH_DRUPAL_SITE_ROOT')) {
- $configs['site'] = $site_path . "/" . $config_file;
- }
- if ($drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT')) {
- $configs['drupal'] = $drupal_root . '/' . $config_file;
- }
- // in the user home directory
- if (!is_null(drush_server_home())) {
- $configs['user'] = drush_server_home() . '/.' . $config_file;
- }
- // in $HOME/.drush directory
- if (!is_null(drush_server_home())) {
- $configs['home.drush'] = drush_server_home() . '/.drush/' . $config_file;
- }
- // In the system wide configuration folder.
- $configs['system'] = drush_get_context('ETC_PREFIX', '') . '/etc/drush/' . $config_file;
- // in the drush installation folder
- $configs['drush'] = dirname(__FILE__) . '/../' . $config_file;
- return empty($configs[$context]) ? '' : $configs[$context];
- }
- /**
- * Load drushrc files (if available) from several possible locations.
- */
- function drush_load_config($context) {
- drush_load_config_file($context, _drush_config_file($context));
- }
- function drush_load_config_file($context, $config) {
- if (file_exists($config)) {
- $options = $aliases = $command_specific = $override = array();
- drush_log(dt('Loading drushrc "!config" into "!context" scope.', array('!config' => realpath($config), '!context' => $context)), 'bootstrap');
- $ret = @include_once($config);
- if ($ret === FALSE) {
- drush_log(dt('Cannot open drushrc "!config", ignoring.', array('!config' => realpath($config))), 'warning');
- return FALSE;
- }
- if (!empty($options) || !empty($aliases) || !empty($command_specific)) {
- $options = array_merge(drush_get_context($context), $options);
- $options['config-file'] = realpath($config);
- //$options['site-aliases'] = array_merge(isset($aliases) ? $aliases : array(), isset($options['site-aliases']) ? $options['site-aliases'] : array());
- unset($options['site-aliases']);
- $options['command-specific'] = array_merge(isset($command_specific) ? $command_specific : array(), isset($options['command-specific']) ? $options['command-specific'] : array());
- drush_set_config_options($context, $options, $override);
- }
- }
- }
- function drush_set_config_options($context, $options, $override = array()) {
- global $drush_conf_override;
- // Only reset $drush_conf_override if the array is not set, otherwise keep old values and append new values to it.
- if (!isset($drush_conf_override)) {
- $drush_conf_override = array();
- }
- // Copy 'config-file' into 'context-path', converting to an array to hold multiple values if necessary
- if (isset($options['config-file'])) {
- if (isset($options['context-path'])) {
- $options['context-path'] = array_merge(array($options['config-file']), is_array($options['context-path']) ? $options['context-path'] : array($options['context-path']));
- }
- else {
- $options['context-path'] = $options['config-file'];
- }
- }
- // Take out $aliases and $command_specific options
- drush_set_config_special_contexts($options);
- drush_set_context($context, $options);
- // Instruct core not to store queries since we are not outputting them.
- // Don't run poormanscron during drush request (D7+).
- $defaults = array(
- 'dev_query' => FALSE,
- 'cron_safe_threshold' => 0,
- );
- foreach ($defaults as $key => $value) {
- // This can be overridden by a command or a drushrc file if needed.
- if (!isset($drush_conf_override[$key])) {
- $drush_conf_override[$key] = $value;
- }
- }
- /**
- * Allow the drushrc.php file to override $conf settings.
- * This is a separate variable because the $conf array gets
- * initialized to an empty array, in the drupal bootstrap process,
- * and changes in settings.php would wipe out the drushrc.php settings.
- */
- if (!empty($override)) {
- $drush_conf_override = array_merge($drush_conf_override, $override);
- }
- }
- /**
- * There are certain options such as 'site-aliases' and 'command-specific'
- * that must be merged together if defined in multiple drush configuration
- * files. If we did not do this merge, then the last configuration file
- * that defined any of these properties would overwrite all of the options
- * that came before in previously-loaded configuration files. We place
- * all of them into their own context so that this does not happen.
- */
- function drush_set_config_special_contexts(&$options) {
- if (isset($options)) {
- $has_command_specific = array_key_exists('command-specific', $options);
- // Change the keys of the site aliases from 'alias' to '@alias'
- if (array_key_exists('site-aliases', $options)) {
- $user_aliases = $options['site-aliases'];
- $options['site-aliases'] = array();
- foreach ($user_aliases as $alias_name => $alias_value) {
- if (substr($alias_name,0,1) != '@') {
- $alias_name = "@$alias_name";
- }
- $options['site-aliases'][$alias_name] = $alias_value;
- }
- }
- // Copy site aliases and command-specific options into their
- // appropriate caches.
- $special_contexts = drush_get_special_keys();
- foreach ($special_contexts as $option_name) {
- if (isset($options[$option_name])) {
- $cache =& drush_get_context($option_name);
- $cache = array_merge($cache, $options[$option_name]);
- unset($options[$option_name]);
- }
- }
- // If command-specific options were set and if we already have
- // a command, then apply the command-specific options immediately.
- if ($has_command_specific) {
- drush_command_default_options();
- }
- }
- }
- /**
- * Set a specific context.
- *
- * @param context
- * Any of the default defined contexts.
- * @param value
- * The value to store in the context
- *
- * @return
- * An associative array of the settings specified in the request context.
- */
- function drush_set_context($context, $value) {
- $cache =& drush_get_context($context);
- $cache = $value;
- return $value;
- }
- /**
- * Return a specific context, or the whole context cache
- *
- * This function provides a storage mechanism for any information
- * the currently running process might need to communicate.
- *
- * This avoids the use of globals, and constants.
- *
- * Functions that operate on the context cache, can retrieve a reference
- * to the context cache using :
- * $cache = &drush_get_context($context);
- *
- * This is a private function, because it is meant as an internal
- * generalized API for writing static cache functions, not as a general
- * purpose function to be used inside commands.
- *
- * Code that modifies the reference directly might have unexpected consequences,
- * such as modifying the arguments after they have already been parsed and dispatched
- * to the callbacks.
- *
- * @param context
- * Optional. Any of the default defined contexts.
- *
- * @return
- * If context is not supplied, the entire context cache will be returned.
- * Otherwise only the requested context will be returned.
- * If the context does not exist yet, it will be initialized to an empty array.
- */
- function &drush_get_context($context = NULL, $default = NULL) {
- static $cache = array();
- if (!is_null($context)) {
- if (!isset($cache[$context])) {
- $default = !is_null($default) ? $default : array();
- $cache[$context] = $default;
- }
- return $cache[$context];
- }
- return $cache;
- }
- /**
- * Set the arguments passed to the drush.php script.
- *
- * This function will set the 'arguments' context of the current running script.
- *
- * When initially called by drush_parse_args, the entire list of arguments will
- * be populated. Once the command is dispatched, this will be set to only the remaining
- * arguments to the command (i.e. the command name is removed).
- *
- * @param arguments
- * Command line arguments, as an array.
- */
- function drush_set_arguments($arguments) {
- drush_set_context('arguments', $arguments);
- }
- /**
- * Get the arguments passed to the drush.php script.
- *
- * When drush_set_arguments is initially called by drush_parse_args,
- * the entire list of arguments will be populated.
- * Once the command has been dispatched, this will be return only the remaining
- * arguments to the command.
- */
- function drush_get_arguments() {
- return drush_get_context('arguments');
- }
- /**
- * Set the command being executed.
- *
- * Drush_dispatch will set the correct command based on it's
- * matching of the script arguments retrieved from drush_get_arguments
- * to the implemented commands specified by drush_get_commands.
- *
- * @param
- * A numerically indexed array of command components.
- */
- function drush_set_command($command) {
- drush_set_context('command', $command);
- }
- /**
- * Return the command being executed.
- *
- *
- */
- function drush_get_command() {
- return drush_get_context('command');
- }
- /**
- * Get the value for an option.
- *
- * If the first argument is an array, then it checks whether one of the options
- * exists and return the value of the first one found. Useful for allowing both
- * -h and --host-name
- *
- * @param option
- * The name of the option to get
- * @param default
- * Optional. The value to return if the option has not been set
- * @param context
- * Optional. The context to check for the option. If this is set, only this context will be searched.
- */
- function drush_get_option($option, $default = NULL, $context = NULL) {
- $value = NULL;
- if ($context) {
- // We have a definite context to check for the presence of an option.
- $value = _drush_get_option($option, drush_get_context($context));
- }
- else {
- // We are not checking a specific context, so check them in a predefined order of precedence.
- $contexts = drush_context_names();
- foreach ($contexts as $context) {
- $value = _drush_get_option($option, drush_get_context($context));
- if ($value !== NULL) {
- return $value;
- }
- }
- }
- if ($value !== NULL) {
- return $value;
- }
- return $default;
- }
- /**
- * Get the value for an option and return it as a list. If the
- * option in question is passed on the command line, its value should
- * be a comma-separated list (e.g. --flag=1,2,3). If the option
- * was set in a drushrc.php file, then its value may be either a
- * comma-separated list or an array of values (e.g. $option['flag'] = array('1', '2', '3')).
- *
- * @param option
- * The name of the option to get
- * @param default
- * Optional. The value to return if the option has not been set
- * @param context
- * Optional. The context to check for the option. If this is set, only this context will be searched.
- */
- function drush_get_option_list($option, $default = array(), $context = NULL) {
- $result = drush_get_option($option, $default, $context);
- if (!is_array($result)) {
- $result = explode(',', $result);
- }
- return $result;
- }
- /**
- * Get the value for an option, but first checks the provided option overrides.
- *
- * The feature of drush_get_option that allows a list of option names
- * to be passed in an array is NOT supported.
- *
- * @param option_overrides
- * An array to check for values before calling drush_get_option.
- * @param option
- * The name of the option to get.
- * @param default
- * Optional. The value to return if the option has not been set.
- * @param context
- * Optional. The context to check for the option. If this is set, only this context will be searched.
- *
- */
- function drush_get_option_override($option_overrides, $option, $value = NULL, $context = NULL) {
- if (array_key_exists($option, $option_overrides)) {
- return $option_overrides[$option];
- }
- else {
- return drush_get_option($option, $value, $context);
- }
- }
- /**
- * Get all of the values for an option in every context.
- *
- * @param option
- * The name of the option to get
- * @return
- * An array whose key is the context name and value is
- * the specific value for the option in that context.
- */
- function drush_get_context_options($option, $flatten = FALSE) {
- $result = array();
- $contexts = drush_context_names();
- foreach ($contexts as $context) {
- $value = _drush_get_option($option, drush_get_context($context));
- if ($value !== NULL) {
- if ($flatten && is_array($value)) {
- $result = array_merge($value, $result);
- }
- else {
- $result[$context] = $value;
- }
- }
- }
- return $result;
- }
- /**
- * Retrieves a collapsed list of all options
- */
- function drush_get_merged_options() {
- $contexts = drush_context_names();
- $cache = drush_get_context();
- $result = array();
- foreach (array_reverse($contexts) as $context) {
- if (array_key_exists($context, $cache)) {
- $result = array_merge($result, $cache[$context]);
- }
- }
- return $result;
- }
- /**
- * Helper function to recurse through possible option names
- */
- function _drush_get_option($option, $context) {
- if (is_array($option)) {
- foreach ($option as $current) {
- if (array_key_exists($current, $context)) {
- return $context[$current];
- }
- }
- }
- elseif (array_key_exists($option, $context)) {
- return $context[$option];
- }
- return NULL;
- }
- /**
- * Set an option in one of the option contexts.
- *
- * @param option
- * The option to set.
- * @param value
- * The value to set it to.
- * @param context
- * Optional. Which context to set it in.
- * @return
- * The value parameter. This allows for neater code such as
- * $myvalue = drush_set_option('http_host', $_SERVER['HTTP_HOST']);
- * Without having to constantly type out the value parameter.
- */
- function drush_set_option($option, $value, $context = 'process') {
- $cache =& drush_get_context($context);
- $cache[$option] = $value;
- return $value;
- }
- /**
- * A small helper function to set the value in the default context
- */
- function drush_set_default($option, $value) {
- return drush_set_option($option, $value, 'default');
- }
- /**
- * Remove a setting from a specific context.
- *
- * @param
- * Option to be unset
- * @param
- * Context in which to unset the value in.
- */
- function drush_unset_option($option, $context = NULL) {
- if ($context != NULL) {
- $cache =& drush_get_context($context);
- if (array_key_exists($option, $cache)) {
- unset($cache[$option]);
- }
- }
- else {
- $contexts = drush_context_names();
- foreach ($contexts as $context) {
- drush_unset_option($option, $context);
- }
- }
- }
- /**
- * Save the settings in a specific context to the applicable configuration file
- * This is useful is you want certain settings to be available automatically the next time a command is executed.
- *
- * @param $context
- * The context to save
- */
- function drush_save_config($context) {
- $filename = _drush_config_file($context);
- if ($filename) {
- $cache = drush_get_context($context);
- $fp = fopen($filename, "w+");
- if (!$fp) {
- return drush_set_error('DRUSH_PERM_ERROR', dt('Drushrc (!filename) could not be written', array('!filename' => $filename)));
- }
- else {
- fwrite($fp, "<?php\n");
- $timestamp = mktime();
- foreach ($cache as $key => $value) {
- $line = "\n\$options['$key'] = ". var_export($value, TRUE) .';';
- fwrite($fp, $line);
- }
- fwrite($fp, "\n");
- fclose($fp);
- drush_log(dt('Drushrc file (!filename) was written successfully', array('!filename' => $filename)));
- return TRUE;
- }
- }
- return FALSE;
- }
|