Security update for permissions_by_term
[yaffs-website] / vendor / drupal / drupal-driver / src / Drupal / Driver / DrushDriver.php
diff --git a/vendor/drupal/drupal-driver/src/Drupal/Driver/DrushDriver.php b/vendor/drupal/drupal-driver/src/Drupal/Driver/DrushDriver.php
new file mode 100644 (file)
index 0000000..a51ec51
--- /dev/null
@@ -0,0 +1,354 @@
+<?php
+
+namespace Drupal\Driver;
+
+use Drupal\Component\Utility\Random;
+use Drupal\Driver\Exception\BootstrapException;
+
+use Symfony\Component\Process\Process;
+
+/**
+ * Implements DriverInterface.
+ */
+class DrushDriver extends BaseDriver {
+  /**
+   * Store a drush alias for tests requiring shell access.
+   *
+   * @var string
+   */
+  public $alias;
+
+  /**
+   * Stores the root path to a Drupal installation.
+   *
+   * This is an alternative to using drush aliases.
+   *
+   * @var string
+   */
+  public $root;
+
+  /**
+   * Store the path to drush binary.
+   *
+   * @var string
+   */
+  public $binary;
+
+  /**
+   * Track bootstrapping.
+   */
+  private $bootstrapped = FALSE;
+
+  /**
+   * Random generator.
+   *
+   * @var \Drupal\Component\Utility\Random
+   */
+  private $random;
+
+  /**
+   * Global arguments or options for drush commands.
+   *
+   * @var string
+   */
+  private $arguments = '';
+
+  /**
+   * Set drush alias or root path.
+   *
+   * @param string $alias
+   *   A drush alias.
+   * @param string $root_path
+   *   The root path of the Drupal install. This is an alternative to using
+   *   aliases.
+   * @param string $binary
+   *   The path to the drush binary.
+   * @param \Drupal\Component\Utility\Random $random
+   *   Random generator.
+   *
+   * @throws \Drupal\Driver\Exception\BootstrapException
+   *   Thrown when a required parameter is missing.
+   */
+  public function __construct($alias = NULL, $root_path = NULL, $binary = 'drush', Random $random = NULL) {
+    if (!empty($alias)) {
+      // Trim off the '@' symbol if it has been added.
+      $alias = ltrim($alias, '@');
+
+      $this->alias = $alias;
+    }
+    elseif (!empty($root_path)) {
+      $this->root = realpath($root_path);
+    }
+    else {
+      throw new BootstrapException('A drush alias or root path is required.');
+    }
+
+    $this->binary = $binary;
+
+    if (!isset($random)) {
+      $random = new Random();
+    }
+    $this->random = $random;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRandom() {
+    return $this->random;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function bootstrap() {
+    // Check that the given alias works.
+    // @todo check that this is a functioning alias.
+    // See http://drupal.org/node/1615450
+    if (!isset($this->alias) && !isset($this->root)) {
+      throw new BootstrapException('A drush alias or root path is required.');
+    }
+    $this->bootstrapped = TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isBootstrapped() {
+    return $this->bootstrapped;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function userCreate(\stdClass $user) {
+    $arguments = array(
+      sprintf('"%s"', $user->name),
+    );
+    $options = array(
+      'password' => $user->pass,
+      'mail' => $user->mail,
+    );
+    $this->drush('user-create', $arguments, $options);
+    if (isset($user->roles) && is_array($user->roles)) {
+      foreach ($user->roles as $role) {
+        $this->userAddRole($user, $role);
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function userDelete(\stdClass $user) {
+    $arguments = array(sprintf('"%s"', $user->name));
+    $options = array(
+      'yes' => NULL,
+      'delete-content' => NULL,
+    );
+    $this->drush('user-cancel', $arguments, $options);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function userAddRole(\stdClass $user, $role) {
+    $arguments = array(
+      sprintf('"%s"', $role),
+      sprintf('"%s"', $user->name),
+    );
+    $this->drush('user-add-role', $arguments);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fetchWatchdog($count = 10, $type = NULL, $severity = NULL) {
+    $options = array(
+      'count' => $count,
+      'type' => $type,
+      'severity' => $severity,
+    );
+    return $this->drush('watchdog-show', array(), $options);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function clearCache($type = 'all') {
+    $type = array($type);
+    return $this->drush('cache-clear', $type, array());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function clearStaticCaches() {
+    // The drush driver does each operation as a separate request;
+    // therefore, 'clearStaticCaches' can be a no-op.
+  }
+
+  /**
+   * Decodes JSON object returned by Drush.
+   *
+   * It will clean up any junk that may have appeared before or after the
+   * JSON object. This can happen with remote Drush aliases.
+   *
+   * @param string $output
+   *   The output from Drush.
+   * @return object
+   *   The decoded JSON object.
+   */
+  protected function decodeJsonObject($output) {
+    // Remove anything before the first '{'.
+    $output = preg_replace('/^[^\{]*/', '', $output);
+    // Remove anything after the last '}'.
+    $output = preg_replace('/[^\}]*$/s', '', $output);
+    return json_decode($output);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createNode($node) {
+    $result = $this->drush('behat', array('create-node', escapeshellarg(json_encode($node))), array());
+    return $this->decodeJsonObject($result);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function nodeDelete($node) {
+    $this->drush('behat', array('delete-node', escapeshellarg(json_encode($node))), array());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createTerm(\stdClass $term) {
+    $result = $this->drush('behat', array('create-term', escapeshellarg(json_encode($term))), array());
+    return $this->decodeJsonObject($result);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function termDelete(\stdClass $term) {
+    $this->drush('behat', array('delete-term', escapeshellarg(json_encode($term))), array());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isField($entity_type, $field_name) {
+    // If the Behat Drush Endpoint is not installed on the site-under-test,
+    // then the drush() method will throw an exception. In this instance, we
+    // want to treat all potential fields as non-fields.  This allows the
+    // Drush Driver to work with certain built-in Drush capabilities (e.g.
+    // creating users) even if the Behat Drush Endpoint is not available.
+    try {
+      $result = $this->drush('behat', array('is-field', escapeshellarg(json_encode(array($entity_type, $field_name)))), array());
+      return strpos($result, "true\n") !== FALSE;
+    }
+    catch (\Exception $e) {
+      return FALSE;
+    }
+  }
+
+  /**
+   * Sets common drush arguments or options.
+   *
+   * @param string $arguments
+   *   Global arguments to add to every drush command.
+   */
+  public function setArguments($arguments) {
+    $this->arguments = $arguments;
+  }
+
+  /**
+   * Get common drush arguments.
+   */
+  public function getArguments() {
+    return $this->arguments;
+  }
+
+  /**
+   * Parse arguments into a string.
+   *
+   * @param array $arguments
+   *   An array of argument/option names to values.
+   *
+   * @return string
+   *   The parsed arguments.
+   */
+  protected static function parseArguments(array $arguments) {
+    $string = '';
+    foreach ($arguments as $name => $value) {
+      if (is_null($value)) {
+        $string .= ' --' . $name;
+      }
+      else {
+        $string .= ' --' . $name . '=' . $value;
+      }
+    }
+    return $string;
+  }
+
+  /**
+   * Execute a drush command.
+   */
+  public function drush($command, array $arguments = array(), array $options = array()) {
+    $arguments = implode(' ', $arguments);
+
+    // Disable colored output from drush.
+    $options['nocolor'] = TRUE;
+    $string_options = $this->parseArguments($options);
+
+    $alias = isset($this->alias) ? "@{$this->alias}" : '--root=' . $this->root;
+
+    // Add any global arguments.
+    $global = $this->getArguments();
+
+    $process = new Process("{$this->binary} {$alias} {$string_options} {$global} {$command} {$arguments}");
+    $process->setTimeout(3600);
+    $process->run();
+
+    if (!$process->isSuccessful()) {
+      throw new \RuntimeException($process->getErrorOutput());
+    }
+
+    // Some drush commands write to standard error output (for example enable
+    // use drush_log which default to _drush_print_log) instead of returning a
+    // string (drush status use drush_print_pipe).
+    if (!$process->getOutput()) {
+      return $process->getErrorOutput();
+    }
+    else {
+      return $process->getOutput();
+    }
+
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function processBatch() {
+    // Do nothing. Drush should internally handle any needs for processing
+    // batch ops.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function runCron() {
+    $this->drush('cron');
+  }
+
+  /**
+   * Run Drush commands dynamically from a DrupalContext.
+   */
+  public function __call($name, $arguments) {
+    return $this->drush($name, $arguments);
+  }
+
+}