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; } } } }