Mercurial > hg > isophonics-drupal-site
diff vendor/psy/psysh/src/CodeCleaner/UseStatementPass.php @ 13:5fb285c0d0e3
Update Drupal core to 8.4.7 via Composer. Security update; I *think* we've
been lucky to get away with this so far, as we don't support self-registration
which seems to be used by the so-called "drupalgeddon 2" attack that 8.4.5
was vulnerable to.
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:33:26 +0100 |
parents | |
children | 129ea1e6d783 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/src/CodeCleaner/UseStatementPass.php Mon Apr 23 09:33:26 2018 +0100 @@ -0,0 +1,126 @@ +<?php + +/* + * This file is part of Psy Shell. + * + * (c) 2012-2018 Justin Hileman + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Psy\CodeCleaner; + +use PhpParser\Node; +use PhpParser\Node\Name; +use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; +use PhpParser\Node\Stmt\GroupUse; +use PhpParser\Node\Stmt\Namespace_; +use PhpParser\Node\Stmt\Use_; +use PhpParser\NodeTraverser; + +/** + * Provide implicit use statements for subsequent execution. + * + * The use statement pass remembers the last use statement line encountered: + * + * use Foo\Bar as Baz; + * + * ... which it then applies implicitly to all future evaluated code, until the + * current namespace is replaced by another namespace. + */ +class UseStatementPass extends CodeCleanerPass +{ + private $aliases = []; + private $lastAliases = []; + private $lastNamespace = null; + + /** + * Re-load the last set of use statements on re-entering a namespace. + * + * This isn't how namespaces normally work, but because PsySH has to spin + * up a new namespace for every line of code, we do this to make things + * work like you'd expect. + * + * @param Node $node + */ + public function enterNode(Node $node) + { + if ($node instanceof Namespace_) { + // If this is the same namespace as last namespace, let's do ourselves + // a favor and reload all the aliases... + if (strtolower($node->name) === strtolower($this->lastNamespace)) { + $this->aliases = $this->lastAliases; + } + } + } + + /** + * If this statement is a namespace, forget all the aliases we had. + * + * If it's a use statement, remember the alias for later. Otherwise, apply + * remembered aliases to the code. + * + * @param Node $node + */ + public function leaveNode(Node $node) + { + if ($node instanceof Use_) { + // Store a reference to every "use" statement, because we'll need + // them in a bit. + foreach ($node->uses as $use) { + $alias = $use->alias ?: end($use->name->parts); + $this->aliases[strtolower($alias)] = $use->name; + } + + return NodeTraverser::REMOVE_NODE; + } elseif ($node instanceof GroupUse) { + // Expand every "use" statement in the group into a full, standalone + // "use" and store 'em with the others. + foreach ($node->uses as $use) { + $alias = $use->alias ?: end($use->name->parts); + $this->aliases[strtolower($alias)] = Name::concat($node->prefix, $use->name, [ + 'startLine' => $node->prefix->getAttribute('startLine'), + 'endLine' => $use->name->getAttribute('endLine'), + ]); + } + + return NodeTraverser::REMOVE_NODE; + } elseif ($node instanceof Namespace_) { + // Start fresh, since we're done with this namespace. + $this->lastNamespace = $node->name; + $this->lastAliases = $this->aliases; + $this->aliases = []; + } else { + foreach ($node as $name => $subNode) { + if ($subNode instanceof Name) { + // Implicitly thunk all aliases. + if ($replacement = $this->findAlias($subNode)) { + $node->$name = $replacement; + } + } + } + + return $node; + } + } + + /** + * Find class/namespace aliases. + * + * @param Name $name + * + * @return FullyQualifiedName|null + */ + private function findAlias(Name $name) + { + $that = strtolower($name); + foreach ($this->aliases as $alias => $prefix) { + if ($that === $alias) { + return new FullyQualifiedName($prefix->toString()); + } elseif (substr($that, 0, strlen($alias) + 1) === $alias . '\\') { + return new FullyQualifiedName($prefix->toString() . substr($name, strlen($alias))); + } + } + } +}