You are here

class VirtualFilesystem in X Autoload 7.5

Same name and namespace in other branches
  1. 7.4 tests/lib/Filesystem/VirtualFilesystem.php \Drupal\xautoload\Tests\Filesystem\VirtualFilesystem

Hierarchy

Expanded class hierarchy of VirtualFilesystem

5 files declare their use of VirtualFilesystem
AbstractExampleModules.php in tests/src/Example/AbstractExampleModules.php
ClassFinderAdapterTest.php in tests/src/ClassFinderAdapterTest.php
ClassLoaderTest.php in tests/src/ClassLoaderTest.php
ExampleModules.php in tests/src/Example/ExampleModules.php
HookTestExampleModules.php in tests/src/Example/HookTestExampleModules.php

File

tests/src/Filesystem/VirtualFilesystem.php, line 9

Namespace

Drupal\xautoload\Tests\Filesystem
View source
class VirtualFilesystem {

  /**
   * @var VirtualFilesystem[]
   */
  protected static $instances = array();

  /**
   * Called from generated PHP included over a stream wrapper.
   *
   * @param string $instance_key
   * @param string $file
   */
  static function reportFileIncluded($instance_key, $file) {
    self::$instances[$instance_key]->reportedOperations[] = $file . ' - include';
  }

  /**
   * @var string
   */
  protected $instanceKey;

  /**
   * @var string[]
   */
  protected $knownPaths = array();

  /**
   * @var string[]
   */
  protected $reportedOperations = array();
  const NOTHING = FALSE;
  const DIR = '(dir)';
  const FILE = '(file)';
  function __construct() {
    $this->instanceKey = Util::randomString();
    self::$instances[$this->instanceKey] = $this;
  }

  /**
   * @return array[]
   */
  function getReportedOperations() {
    return $this->reportedOperations;
  }

  /**
   * Delete all reported operations and start fresh.
   */
  function resetReportedOperations() {
    $this->reportedOperations = array();
  }

  /**
   * @param string $file
   * @param string $class
   * @throws \Exception
   */
  function addClass($file, $class) {
    $this
      ->addKnownFile($file);
    if (self::FILE !== ($existing = $this->knownPaths[$file])) {
      throw new \Exception("A non-empty file already exists at '{$file}'. Cannot overwrite with class '{$class}'.");
    }
    $this->knownPaths[$file] = $class;
  }

  /**
   * @param string $file
   * @param string $php
   *   File contents starting with '<?php'.
   * @param bool $overwrite
   *
   * @throws \Exception
   */
  function addPhpFile($file, $php, $overwrite = FALSE) {
    $this
      ->addKnownFile($file);
    if (!$overwrite && self::FILE !== ($existing = $this->knownPaths[$file])) {
      throw new \Exception("A non-empty file already exists at '{$file}'. Cannot overwrite with PHP code.");
    }
    if (0 !== strpos($php, '<?php')) {
      throw new \Exception("PHP files must begin with '<?php'.");
    }
    $this->knownPaths[$file] = $php;
  }

  /**
   * @param string[] $files
   */
  function addKnownFiles(array $files) {
    foreach ($files as $file) {
      $this
        ->addKnownFile($file);
    }
  }

  /**
   * @param string $file
   *
   * @throws \Exception
   */
  function addKnownFile($file) {
    if (!isset($this->knownPaths[$file])) {
      $this->knownPaths[$file] = self::FILE;
      $this
        ->addKnownDir(dirname($file));
    }
    elseif (self::DIR === $this->knownPaths[$file]) {
      throw new \Exception("A directory already exists at '{$file}', cannot overwrite with a file.");
    }
  }

  /**
   * @param string $dir
   */
  function addKnownDir($dir) {
    if (FALSE === strpos($dir, '://')) {
      return;
    }
    if (!isset($this->knownPaths[$dir])) {

      // Need to set parents first.
      $this
        ->addKnownDir(dirname($dir));
    }
    $this->knownPaths[$dir] = self::DIR;
  }

  /**
   * @param string $path
   * @return string|bool
   *   One of self::NOTHING, self::DIR, self::FILE, or a class name for a class
   *   that is supposed to be defined in the file.
   */
  function resolvePath($path) {
    if (isset($this->knownPaths[$path])) {
      return $this->knownPaths[$path];
    }
    else {
      return self::NOTHING;
    }
  }

  /**
   * @param string $dir
   * @return array|bool
   */
  function getDirContents($dir) {
    if (empty($this->knownPaths[$dir]) || self::DIR !== $this->knownPaths[$dir]) {
      return FALSE;
    }
    $pos = strlen($dir . '/');
    $contents = array(
      '.',
      '..',
    );
    foreach ($this->knownPaths as $path => $type) {
      if ($dir . '/' !== substr($path, 0, $pos)) {
        continue;
      }
      $name = substr($path, $pos);
      if (FALSE !== strpos($name, '/')) {

        // This is a deeper subdirectory.
        continue;
      }
      if ('' === $name) {
        continue;
      }
      $contents[] = $name;
    }
    return $contents;
  }

  /**
   * @param string $path
   * @param bool $report
   *
   * @return array
   */
  function getStat($path, $report = TRUE) {
    if ($report) {
      $this->reportedOperations[] = $path . ' - stat';
    }
    if (!isset($this->knownPaths[$path])) {

      // File does not exist.
      return FALSE;
    }
    elseif (self::DIR === $this->knownPaths[$path]) {
      return stat(__DIR__);
    }
    else {

      // Create a tmp file with the contents and get its stats.
      $contents = $this
        ->getFileContents($path);
      $resource = tmpfile();
      fwrite($resource, $contents);
      $stat = fstat($resource);
      fclose($resource);
      return $stat;
    }
  }

  /**
   * @param $path
   *   The file path.
   *
   * @return string
   *   The file contents.
   *
   * @throws \Exception
   *   Exception thrown if there is no file at $path.
   */
  function getFileContents($path) {
    if (!isset($this->knownPaths[$path])) {

      // File does not exist.
      throw new \Exception("Assumed file '{$path}' does not exist.");
    }
    elseif (self::DIR === $this->knownPaths[$path]) {
      throw new \Exception("Assumed file '{$path}' is a directory.");
    }
    $instance_key_export = var_export($this->instanceKey, TRUE);
    $path_export = var_export($path, TRUE);
    if (self::FILE === $this->knownPaths[$path]) {

      // Empty PHP file..
      return <<<EOT
<?php
Drupal\\xautoload\\Tests\\Filesystem\\VirtualFilesystem::reportFileIncluded({<span class="php-variable">$instance_key_export</span>}, {<span class="php-variable">$path_export</span>});

EOT;
    }
    if (0 === strpos($this->knownPaths[$path], '<?php')) {

      // PHP file.
      $php = substr($this->knownPaths[$path], 5);
      return <<<EOT
<?php
Drupal\\xautoload\\Tests\\Filesystem\\VirtualFilesystem::reportFileIncluded({<span class="php-variable">$instance_key_export</span>}, {<span class="php-variable">$path_export</span>});
{<span class="php-variable">$php</span>}
EOT;
    }
    if (preg_match('#\\s#', $this->knownPaths[$path])) {

      // File with arbitrary contents.
      return $this->knownPaths[$path];
    }

    // PHP file with class definition.
    $class = $this->knownPaths[$path];
    if (FALSE === ($pos = strrpos($class, '\\'))) {

      // Class without namespace.
      return <<<EOT
<?php
Drupal\\xautoload\\Tests\\Filesystem\\VirtualFilesystem::reportFileIncluded({<span class="php-variable">$instance_key_export</span>}, {<span class="php-variable">$path_export</span>});
class {<span class="php-variable">$class</span>} {}

EOT;
    }

    // Class without namespace.
    $namespace = substr($class, 0, $pos);
    $classname = substr($class, $pos + 1);
    return <<<EOT
<?php
namespace {<span class="php-variable">$namespace</span>};
\\Drupal\\xautoload\\Tests\\Filesystem\\VirtualFilesystem::reportFileIncluded({<span class="php-variable">$instance_key_export</span>}, {<span class="php-variable">$path_export</span>});
class {<span class="php-variable">$classname</span>} {}

EOT;
  }

}

Members