Further modules included.
[yaffs-website] / web / modules / contrib / drupalmoduleupgrader / src / Target.php
diff --git a/web/modules/contrib/drupalmoduleupgrader/src/Target.php b/web/modules/contrib/drupalmoduleupgrader/src/Target.php
new file mode 100644 (file)
index 0000000..30a6b26
--- /dev/null
@@ -0,0 +1,279 @@
+<?php
+
+namespace Drupal\drupalmoduleupgrader;
+
+use Doctrine\Common\Collections\ArrayCollection;
+use Drupal\Component\Utility\SafeMarkup;
+use Pharborist\Node;
+use Pharborist\Parser;
+use Pharborist\RootNode;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Finder\Finder;
+
+/**
+ * Default implementation of TargetInterface.
+ */
+class Target implements TargetInterface {
+
+  /**
+   * The target module's machine name.
+   *
+   * @var string
+   */
+  protected $id;
+
+  /**
+   * @var \Drupal\Component\Plugin\PluginManagerInterface
+   */
+  protected $indexerManager;
+
+  /**
+   * The target module's base path.
+   *
+   * @var string
+   */
+  protected $basePath;
+
+  /**
+   * @var IndexerInterface[]
+   */
+  protected $indexers = [];
+
+  /**
+   * @var \Doctrine\Common\Collections\ArrayCollection
+   */
+  protected $services;
+
+  /**
+   * All open documents.
+   *
+   * @var \Pharborist\RootNode[]
+   */
+  protected $documents = [];
+
+  /**
+   * Constructs a Target.
+   *
+   * @param string $path
+   *  The base path of the target module.
+   * @param ContainerInterface $container
+   *  The current container, to pull any dependencies out of.
+   */
+  public function __construct($path, ContainerInterface $container) {
+    $this->indexerManager = $container->get('plugin.manager.drupalmoduleupgrader.indexer');
+
+    if (is_dir($path)) {
+      $this->basePath = $path;
+    }
+    else {
+      throw new \RuntimeException(SafeMarkup::format('Invalid base path: @path', ['@path' => $path]));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function id() {
+    if (empty($this->id)) {
+      $dir = $this->getBasePath();
+      $info = (new Finder)->in($dir)->depth('== 0')->name('*.info')->getIterator();
+      $info->rewind();
+
+      if ($info_file = $info->current()) {
+        $this->id = subStr($info_file->getFilename(), 0, -5);
+      }
+      else {
+        throw new \RuntimeException(SafeMarkup::format('Could not find info file in @dir', ['@dir' => $dir]));
+      }
+    }
+    return $this->id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getBasePath() {
+    return $this->basePath;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPath($file) {
+    if ($file{0} == '.') {
+      $file = $this->id() . $file;
+    }
+    return $this->getBasePath() . '/' . ltrim($file, '/');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFinder() {
+      // We do NOT want to include submodules. We can detect one by the presence
+      // of an info file -- if there is one, its directory is a submodule.
+      $directories = (new Finder)
+        ->directories()
+        ->in($this->getBasePath())
+        ->filter(function(\SplFileInfo $dir) {
+          return (new Finder)->files()->in($dir->getPathname())->depth('== 0')->name('*.info')->count() === 0;
+        });
+
+      $directories = array_keys(iterator_to_array($directories));
+      $directories[] = $this->getBasePath();
+
+      return (new Finder)
+        ->files()
+        ->in($directories)
+        // We don't need to recurse, because we've already determined which
+        // directories to search.
+        ->depth('== 0')
+        ->name('*.module')
+        ->name('*.install')
+        ->name('*.inc')
+        ->name('*.php')
+        ->name('*.test');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIndexer($which) {
+    if (empty($this->indexers[$which])) {
+      /** @var IndexerInterface $indexer */
+      $indexer = $this->indexerManager->createInstance($which);
+      $indexer->bind($this);
+      $this->indexers[$which] = $indexer;
+    }
+    return $this->indexers[$which];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getServices() {
+    if (empty($this->services)) {
+      $this->services = new ArrayCollection();
+    }
+    return $this->services;
+  }
+
+  /**
+   * Runs all available indexers on this target.
+   */
+  public function buildIndex() {
+    $indexers = array_keys($this->indexerManager->getDefinitions());
+    foreach ($indexers as $id) {
+      $this->getIndexer($id)->build();
+    }
+    // Release syntax trees that were opened during indexing.
+    $this->flush();
+  }
+
+  /**
+   * Destroys all index data for this target.
+   */
+  public function destroyIndex() {
+    $indexers = array_keys($this->indexerManager->getDefinitions());
+    foreach ($indexers as $id) {
+      $this->getIndexer($id)->destroy();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function implementsHook($hook) {
+    return $this->getIndexer('function')->has('hook_' . $hook);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function executeHook($hook, array $arguments = []) {
+    if ($this->implementsHook($hook)) {
+      return $this->getIndexer('function')->execute('hook_' . $hook, $arguments);
+    }
+    else {
+      $variables = [
+        '@module' => $this->id(),
+        '@hook' => $hook,
+      ];
+      throw new \InvalidArgumentException(SafeMarkup::format('@module does not implement hook_@hook.', $variables));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function open($file) {
+    if (empty($this->documents[$file])) {
+      $this->documents[$file] = Parser::parseFile($file);
+    }
+    return $this->documents[$file];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save(Node $node = NULL) {
+    if ($node) {
+      $file = $this->getFileOf($node);
+      if ($file) {
+        $doc = $node instanceof RootNode ? $node : $node->parents()->get(0);
+
+        $victory = file_put_contents($file, $doc->getText());
+        if ($victory === FALSE) {
+          throw new IOException(SafeMarkup::format('Failed to save @file.', [ '@file' => $file ]));
+        }
+      }
+      else {
+        throw new IOException('Cannot save a node that is not attached to an open document.');
+      }
+    }
+    else {
+      array_walk($this->documents, [ $this, 'save' ]);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function create($file, $ns = NULL) {
+    $this->documents[$file] = RootNode::create($ns);
+    return $this->documents[$file];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function flush() {
+    $this->documents = [];
+  }
+
+  /**
+   * Determines which currently-open file a node belongs to, if any. Nodes
+   * which are not part of any open syntax tree will return NULL.
+   *
+   * @return string|NULL
+   */
+  public function getFileOf(Node $node) {
+    if ($node instanceof RootNode) {
+      $root = $node;
+    }
+    else {
+      $parents = $node->parents();
+      if ($parents->isEmpty()) {
+        return NULL;
+      }
+      $root = $parents->get(0);
+    }
+
+    foreach ($this->documents as $file => $doc) {
+      if ($root === $doc) {
+        return $file;
+      }
+    }
+  }
+
+}