Version 1
[yaffs-website] / vendor / drush / drush / includes / bootstrap.inc
diff --git a/vendor/drush/drush/includes/bootstrap.inc b/vendor/drush/drush/includes/bootstrap.inc
new file mode 100644 (file)
index 0000000..9b08db8
--- /dev/null
@@ -0,0 +1,614 @@
+<?php
+
+use Drush\Log\LogLevel;
+
+/**
+ * No bootstrap.
+ *
+ * Commands that only preflight, but do not bootstrap, should use
+ * a bootstrap level of DRUSH_BOOTSTRAP_NONE.
+ */
+define('DRUSH_BOOTSTRAP_NONE', -1);
+
+/**
+ * Use drush_bootstrap_max instead of drush_bootstrap_to_phase
+ *
+ * This constant is only usable as the value of the 'bootstrap'
+ * item of a command object, or as the parameter to
+ * drush_bootstrap_to_phase.  It is not a real bootstrap state.
+ */
+define('DRUSH_BOOTSTRAP_MAX', -2);
+
+/**
+ * @deprecated
+ *
+ * No longer used, but 0 remains reserved. Drush always runs preflight.
+ * Commands may alternatively use DRUSH_BOOTSTRAP_NONE.
+ */
+define('DRUSH_BOOTSTRAP_DRUSH', 0);
+
+// TODO: Move all of the constants below to a Drupal-specific file.
+// We can't do this until commands are declaring which CMS they work
+// with, because right now, commands that do not declare a 'bootstrap'
+// level default to DRUSH_BOOTSTRAP_DRUPAL_LOGIN, so we need this constant,
+// at least, available in non-Drupal contexts.
+
+/**
+ * Set up and test for a valid drupal root, either through the -r/--root options,
+ * or evaluated based on the current working directory.
+ *
+ * Any code that interacts with an entire Drupal installation, and not a specific
+ * site on the Drupal installation should use this bootstrap phase.
+ */
+define('DRUSH_BOOTSTRAP_DRUPAL_ROOT',  1);
+
+/**
+ * Set up a Drupal site directory and the correct environment variables to
+ * allow Drupal to find the configuration file.
+ *
+ * If no site is specified with the -l / --uri options, Drush will assume the
+ * site is 'default', which mimics Drupal's behaviour.
+ *
+ * If you want to avoid this behaviour, it is recommended that you use the
+ * DRUSH_BOOTSTRAP_DRUPAL_ROOT bootstrap phase instead.
+ *
+ * Any code that needs to modify or interact with a specific Drupal site's
+ * settings.php file should bootstrap to this phase.
+ */
+define('DRUSH_BOOTSTRAP_DRUPAL_SITE', 2);
+
+/**
+ * Load the settings from the Drupal sites directory.
+ *
+ * This phase is analagous to the DRUPAL_BOOTSTRAP_CONFIGURATION bootstrap phase in Drupal
+ * itself, and this is also the first step where Drupal specific code is included.
+ *
+ * This phase is commonly used for code that interacts with the Drupal install API,
+ * as both install.php and update.php start at this phase.
+ */
+define('DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION', 3);
+
+/**
+ * Connect to the Drupal database using the database credentials loaded
+ * during the previous bootstrap phase.
+ *
+ * This phase is analogous to the DRUPAL_BOOTSTRAP_DATABASE bootstrap phase in
+ * Drupal.
+ *
+ * Any code that needs to interact with the Drupal database API needs to
+ * be bootstrapped to at least this phase.
+ */
+define('DRUSH_BOOTSTRAP_DRUPAL_DATABASE', 4);
+
+/**
+ * Fully initialize Drupal.
+ *
+ * This is analogous to the DRUPAL_BOOTSTRAP_FULL bootstrap phase in
+ * Drupal.
+ *
+ * Any code that interacts with the general Drupal API should be
+ * bootstrapped to this phase.
+ */
+define('DRUSH_BOOTSTRAP_DRUPAL_FULL', 5);
+
+/**
+ * Log in to the initialiased Drupal site.
+ *
+ * This is the default bootstrap phase all commands will try to reach,
+ * unless otherwise specified.
+ *
+ * This bootstrap phase is used after the site has been
+ * fully bootstrapped.
+ *
+ * This phase will log you in to the drupal site with the username
+ * or user ID specified by the --user/ -u option.
+ *
+ * Use this bootstrap phase for your command if you need to have access
+ * to information for a specific user, such as listing nodes that might
+ * be different based on who is logged in.
+ */
+define('DRUSH_BOOTSTRAP_DRUPAL_LOGIN', 6);
+
+/**
+ * Return the list of bootstrap objects that are available for
+ * initializing a CMS with Drush.  We insure that any given candidate
+ * class is instantiated only once.
+ *
+ * @return \Drush\Boot\Boot[]
+ */
+function drush_get_bootstrap_candidates() {
+  $candidate_classes = drush_get_bootstrap_candidate_classnames();
+
+  $cache =& drush_get_context('DRUSH_BOOTSTRAP_CANDIDATE_OBJECTS');
+
+  $result = array();
+  foreach($candidate_classes as $candidate_class) {
+    if (array_key_exists($candidate_class, $cache)) {
+      $result[$candidate_class] = $cache[$candidate_class];
+    }
+    else {
+      $result[$candidate_class] = new $candidate_class;
+    }
+  }
+
+  $cache = $result;
+  return $result;
+}
+
+/**
+ * Find the list of bootstrap classnames available for initializing a
+ * CMS with Drush.
+ *
+ * @return array
+ */
+function drush_get_bootstrap_candidate_classnames() {
+  // Give all commandfiles a chance to return candidates.  They should
+  // return STRINGS with the class name of the bootstrap object they provide.
+  $candidates = drush_command_invoke_all('bootstrap_candidates');
+  // If a bootstrap class was specified on the command line, consider it first.
+  $bootstrap_class = drush_get_option('bootstrap_class', FALSE);
+  if ($bootstrap_class) {
+    array_unshift($candidates, $bootstrap_class);
+  }
+  // Add candidate bootstrap classes for Drupal
+  foreach (array('8', '7', '6') as $version) {
+    $drupal_bootstrap_class = 'Drush\Boot\DrupalBoot' . $version;
+    $candidates[] = $drupal_bootstrap_class;
+  }
+  // Always consider our default bootstrap class last.
+  $candidates[] = 'Drush\Boot\EmptyBoot';
+
+  return $candidates;
+}
+
+/**
+ * Look up the best bootstrap class for the given location
+ * from the set of available candidates.
+ */
+function drush_bootstrap_class_for_root($path) {
+  drush_load_bootstrap_commandfile_at_path($path);
+  $candidates = drush_get_bootstrap_candidates();
+  foreach ($candidates as $candidate) {
+    if ($candidate->valid_root($path)) {
+      return $candidate;
+    }
+  }
+  return NULL;
+}
+
+/**
+ * Check to see if there is a bootstrap class available
+ * at the specified location; if there is, load it.
+ */
+function drush_load_bootstrap_commandfile_at_path($path) {
+  static $paths = array();
+
+  if (!empty($path) && (!array_key_exists($path, $paths))) {
+    $paths[$path] = TRUE;
+    // Check to see if we have any bootstrap classes in this location.
+    $bootstrap_class_dir = $path . '/drush/bootstrap';
+    if (is_dir($bootstrap_class_dir)) {
+      _drush_add_commandfiles(array($bootstrap_class_dir), DRUSH_BOOTSTRAP_NONE);
+    }
+  }
+}
+
+/**
+ * Select the bootstrap class to use.  If this is called multiple
+ * times, the bootstrap class returned might change on subsequent
+ * calls, if the root directory changes.  Once the bootstrap object
+ * starts changing the state of the system, however, it will
+ * be 'latched', and further calls to drush_select_bootstrap_class()
+ * will always return the same object.
+ */
+function drush_select_bootstrap_class() {
+  $root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT');
+
+  // Once we have selected a Drupal root, we will reduce our bootstrap
+  // candidates down to just the one used to select this site root.
+  $bootstrap = drush_bootstrap_class_for_root($root);
+  // If we have not found a bootstrap class by this point,
+  // then take the last one and use it.  This should be our
+  // default bootstrap class.  The default bootstrap class
+  // should pass through all calls without doing anything that
+  // changes state in a CMS-specific way.
+  if ($bootstrap == NULL) {
+    $candidates = drush_get_bootstrap_candidates();
+    $bootstrap = array_pop($candidates);
+  }
+
+  return $bootstrap;
+}
+
+/**
+ * Don't allow the bootstrap object to change once we start bootstrapping
+ */
+function drush_latch_bootstrap_object($bootstrap) {
+  drush_set_context('DRUSH_BOOTSTRAP_OBJECT', $bootstrap);
+}
+
+/**
+ * Get the appropriate bootstrap object.  We'll search for a new
+ * bootstrap object every time someone asks for one until we start
+ * bootstrapping; then we'll returned the same cached one every time.
+ *
+ * @return \Drush\Boot\Boot
+ */
+function drush_get_bootstrap_object() {
+  $bootstrap = drush_get_context('DRUSH_BOOTSTRAP_OBJECT', FALSE);
+  if (!$bootstrap) {
+    $bootstrap = drush_select_bootstrap_class();
+  }
+  return $bootstrap;
+}
+
+/**
+ * Find the URI that has been selected by the cwd
+ * if it was not previously set via the --uri / -l option
+ */
+function _drush_bootstrap_selected_uri() {
+  $uri = drush_get_context('DRUSH_SELECTED_URI');
+  if (empty($uri)) {
+    $site_path = drush_site_path();
+    $elements = explode('/', $site_path);
+    $current = array_pop($elements);
+    if (!$current) {
+      $current = 'default';
+    }
+    $uri = 'http://'. $current;
+    $uri = drush_set_context('DRUSH_SELECTED_URI', $uri);
+    drush_sitealias_create_self_alias();
+  }
+
+  return $uri;
+}
+
+/**
+ * Helper function to store any context settings that are being validated.
+ */
+function drush_bootstrap_value($context, $value = null) {
+  $values =& drush_get_context('DRUSH_BOOTSTRAP_VALUES', array());
+
+  if (isset($value)) {
+    $values[$context] = $value;
+  }
+
+  if (array_key_exists($context, $values)) {
+    return $values[$context];
+  }
+
+  return null;
+}
+
+/**
+ * Returns an array that determines what bootstrap phases
+ * are necessary to bootstrap the CMS.
+ *
+ * @param bool $function_names
+ *   (optional) If TRUE, return an array of method names index by their
+ *   corresponding phase values. Otherwise return an array of phase values.
+ *
+ * @return array
+ *
+ * @see \Drush\Boot\Boot::bootstrap_phases()
+ */
+function _drush_bootstrap_phases($function_names = FALSE) {
+  $result = array();
+
+  if ($bootstrap = drush_get_bootstrap_object()) {
+    $result = $bootstrap->bootstrap_phases();
+    if (!$function_names) {
+      $result = array_keys($result);
+    }
+  }
+  return $result;
+}
+
+/**
+ * Bootstrap Drush to the desired phase.
+ *
+ * This function will sequentially bootstrap each
+ * lower phase up to the phase that has been requested.
+ *
+ * @param int $phase
+ *   The bootstrap phase to bootstrap to.
+ * @param int $phase_max
+ *   (optional) The maximum level to boot to. This does not have a use in this
+ *   function itself but can be useful for other code called from within this
+ *   function, to know if e.g. a caller is in the process of booting to the
+ *   specified level. If specified, it should never be lower than $phase.
+ *
+ * @return bool
+ *   TRUE if the specified bootstrap phase has completed.
+ *
+ * @see \Drush\Boot\Boot::bootstrap_phases()
+ */
+function drush_bootstrap($phase, $phase_max = FALSE) {
+  $bootstrap = drush_get_bootstrap_object();
+  $phases = _drush_bootstrap_phases(TRUE);
+  $result = TRUE;
+
+  // If the requested phase does not exist in the list of available
+  // phases, it means that the command requires bootstrap to a certain
+  // level, but no site root could be found.
+  if (!isset($phases[$phase])) {
+    $result = drush_bootstrap_error('DRUSH_NO_SITE', dt("We could not find an applicable site for that command."));
+  }
+
+  // Once we start bootstrapping past the DRUSH_BOOTSTRAP_DRUSH phase, we
+  // will latch the bootstrap object, and prevent it from changing.
+  if ($phase > DRUSH_BOOTSTRAP_DRUSH) {
+    drush_latch_bootstrap_object($bootstrap);
+  }
+
+  drush_set_context('DRUSH_BOOTSTRAPPING', TRUE);
+  foreach ($phases as $phase_index => $current_phase) {
+    $bootstrapped_phase = drush_get_context('DRUSH_BOOTSTRAP_PHASE', -1);
+    if ($phase_index > $phase) {
+      break;
+    }
+    if ($phase_index > $bootstrapped_phase) {
+      if ($result = drush_bootstrap_validate($phase_index)) {
+        if (method_exists($bootstrap, $current_phase) && !drush_get_error()) {
+          drush_log(dt("Drush bootstrap phase : !function()", array('!function' => $current_phase)), LogLevel::BOOTSTRAP);
+          $bootstrap->{$current_phase}();
+
+          // Reset commandfile cache and find any new command files that are available during this bootstrap phase.
+          drush_get_commands(TRUE);
+          _drush_find_commandfiles($phase_index, $phase_max);
+        }
+        drush_set_context('DRUSH_BOOTSTRAP_PHASE', $phase_index);
+      }
+    }
+  }
+  drush_set_context('DRUSH_BOOTSTRAPPING', FALSE);
+  if (!$result || drush_get_error()) {
+    $errors = drush_get_context('DRUSH_BOOTSTRAP_ERRORS', array());
+    foreach ($errors as $code => $message) {
+      drush_set_error($code, $message);
+    }
+  }
+  return !drush_get_error();
+}
+
+/**
+ * Determine whether a given bootstrap phase has been completed
+ *
+ * This function name has a typo which makes me laugh so we choose not to
+ * fix it. Take a deep breath, and smile. See
+ * http://en.wikipedia.org/wiki/HTTP_referer
+ *
+ *
+ * @param int $phase
+ *   The bootstrap phase to test
+ *
+ * @return bool
+ *   TRUE if the specified bootstrap phase has completed.
+ */
+function drush_has_boostrapped($phase) {
+  $phase_index = drush_get_context('DRUSH_BOOTSTRAP_PHASE');
+
+  return isset($phase_index) && ($phase_index >= $phase);
+}
+
+/**
+ * Validate whether a bootstrap phase can be reached.
+ *
+ * This function will validate the settings that will be used
+ * during the actual bootstrap process, and allow commands to
+ * progressively bootstrap to the highest level that can be reached.
+ *
+ * This function will only run the validation function once, and
+ * store the result from that execution in a local static. This avoids
+ * validating phases multiple times.
+ *
+ * @param int $phase
+ *   The bootstrap phase to validate to.
+ *
+ * @return bool
+ *   TRUE if bootstrap is possible, FALSE if the validation failed.
+ *
+ * @see \Drush\Boot\Boot::bootstrap_phases()
+ */
+function drush_bootstrap_validate($phase) {
+  $bootstrap = drush_get_bootstrap_object();
+  $phases = _drush_bootstrap_phases(TRUE);
+  static $result_cache = array();
+
+  if (!array_key_exists($phase, $result_cache)) {
+    drush_set_context('DRUSH_BOOTSTRAP_ERRORS', array());
+    drush_set_context('DRUSH_BOOTSTRAP_VALUES', array());
+
+    foreach ($phases as $phase_index => $current_phase) {
+      $validated_phase = drush_get_context('DRUSH_BOOTSTRAP_VALIDATION_PHASE', -1);
+      if ($phase_index > $phase) {
+        break;
+      }
+      if ($phase_index > $validated_phase) {
+        $current_phase .= '_validate';
+        if (method_exists($bootstrap, $current_phase)) {
+          $result_cache[$phase_index] = $bootstrap->{$current_phase}();
+        }
+        else {
+          $result_cache[$phase_index] = TRUE;
+        }
+        drush_set_context('DRUSH_BOOTSTRAP_VALIDATION_PHASE', $phase_index);
+      }
+    }
+  }
+  return $result_cache[$phase];
+}
+
+/**
+ * Bootstrap to the specified phase.
+ *
+ * @param int $max_phase_index
+ *   Only attempt bootstrap to the specified level.
+ *
+ * @return bool
+ *   TRUE if the specified bootstrap phase has completed.
+ */
+function drush_bootstrap_to_phase($max_phase_index) {
+  if ($max_phase_index == DRUSH_BOOTSTRAP_MAX) {
+    // Bootstrap as far as we can without throwing an error, but log for
+    // debugging purposes.
+    drush_log(dt("Trying to bootstrap as far as we can."), 'debug');
+    drush_bootstrap_max();
+    return TRUE;
+  }
+
+  drush_log(dt("Bootstrap to phase !phase.", array('!phase' => $max_phase_index)), LogLevel::BOOTSTRAP);
+  $phases = _drush_bootstrap_phases();
+  $result = TRUE;
+
+  // Try to bootstrap to the maximum possible level, without generating errors
+  foreach ($phases as $phase_index) {
+    if ($phase_index > $max_phase_index) {
+      // Stop trying, since we achieved what was specified.
+      break;
+    }
+
+    if (drush_bootstrap_validate($phase_index)) {
+      if ($phase_index > drush_get_context('DRUSH_BOOTSTRAP_PHASE', DRUSH_BOOTSTRAP_NONE)) {
+        $result = drush_bootstrap($phase_index, $max_phase_index);
+      }
+    }
+    else {
+      $result = FALSE;
+      break;
+    }
+  }
+
+  return $result;
+}
+
+/**
+ * Bootstrap to the highest level possible, without triggering any errors.
+ *
+ * @param int $max_phase_index
+ *   (optional) Only attempt bootstrap to the specified level.
+ *
+ * @return int
+ *   The maximum phase to which we bootstrapped.
+ */
+function drush_bootstrap_max($max_phase_index = FALSE) {
+  $phases = _drush_bootstrap_phases(TRUE);
+  if (!$max_phase_index) {
+    $max_phase_index = count($phases);
+  }
+
+  // Try to bootstrap to the maximum possible level, without generating errors.
+  foreach ($phases as $phase_index => $current_phase) {
+    if ($phase_index > $max_phase_index) {
+      // Stop trying, since we achieved what was specified.
+      break;
+    }
+
+    if (drush_bootstrap_validate($phase_index)) {
+      if ($phase_index > drush_get_context('DRUSH_BOOTSTRAP_PHASE')) {
+        drush_bootstrap($phase_index, $max_phase_index);
+      }
+    }
+    else {
+      // drush_bootstrap_validate() only logs successful validations. For us,
+      // knowing what failed can also be important.
+      $previous = drush_get_context('DRUSH_BOOTSTRAP_PHASE');
+      drush_log(dt("Bootstrap phase !function() failed to validate; continuing at !current().", array('!function' => $current_phase, '!current' => $phases[$previous])), 'debug');
+      break;
+    }
+  }
+
+  return drush_get_context('DRUSH_BOOTSTRAP_PHASE');
+}
+
+/**
+ * Bootstrap the specified site alias.  The site alias must
+ * be a valid alias to a local site.
+ *
+ * @param $site_record
+ *   The alias record for the given site alias.
+ *   @see drush_sitealias_get_record().
+ * @param $max_phase_index
+ *   Only attempt bootstrap to the specified level.
+ * @returns TRUE if attempted to bootstrap, or FALSE
+ *   if no bootstrap attempt was made.
+ */
+function drush_bootstrap_max_to_sitealias($site_record, $max_phase_index = NULL) {
+  if ((array_key_exists('root', $site_record) && !array_key_exists('remote-host', $site_record))) {
+    drush_sitealias_set_alias_context($site_record);
+    drush_bootstrap_max($max_phase_index);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Helper function to collect any errors that occur during the bootstrap process.
+ * Always returns FALSE, for convenience.
+ */
+function drush_bootstrap_error($code, $message = null) {
+  $errors = drush_get_context('DRUSH_BOOTSTRAP_ERRORS');
+  $errors[$code] = $message;
+  drush_set_context('DRUSH_BOOTSTRAP_ERRORS', $errors);
+  return FALSE;
+}
+
+function _drush_bootstrap_output_prepare() {
+  // Note that as soon as we set the DRUSH_BACKEND context, we change
+  // the behavior of drush_log().  It is therefore important that we
+  // should not set this context until immediately before we call ob_start
+  // (i.e., in this function).
+  $backend = drush_set_context('DRUSH_BACKEND', drush_get_option('backend'));
+  $quiet = drush_get_context('DRUSH_QUIET');
+
+  if ($backend) {
+    // Load options passed as a JSON encoded string through STDIN.
+    $stdin_options = _drush_backend_get_stdin();
+    if (is_array($stdin_options)) {
+      drush_set_context('stdin', $stdin_options);
+    }
+    // Add an output buffer handler to collect output/pass through backend
+    // packets. Using a chunksize of 2 ensures that each line is flushed
+    // straight away.
+    if ($quiet) {
+      // Pass through of backend packets, discard regular output.
+      ob_start('drush_backend_output_discard', 2);
+    }
+    else {
+      // Collect output.
+      ob_start('drush_backend_output_collect', 2);
+    }
+  }
+
+  // In non-backend quiet mode we start buffering and discards it on command
+  // completion.
+  if ($quiet && !$backend) {
+    ob_start();
+  }
+}
+
+/**
+ * Used by a Drush extension to request that its Composer autoload
+ * files be loaded by Drush, if they have not already been.
+ *
+ * Usage:
+ *
+ * function mycommandfile_drush_init() {
+ *   drush_autoload(__FILE__)
+ * }
+ *
+ */
+function drush_autoload($commandfile) {
+  $already_added = commandfiles_cache()->add($commandfile);
+
+  $dir = dirname($commandfile);
+  $candidates = array("vendor/autoload.php", "../../../vendor/autoload.php");
+  $drush_autoload_file = drush_get_context('DRUSH_VENDOR_PATH', '');
+
+  foreach ($candidates as $candidate) {
+    $autoload = $dir . '/' . $candidate;
+    if (file_exists($autoload) && (realpath($autoload) != $drush_autoload_file)) {
+      include $autoload;
+    }
+  }
+}