Yaffs site version 1.1
[yaffs-website] / vendor / psy / psysh / src / Psy / Command / SudoCommand.php
diff --git a/vendor/psy/psysh/src/Psy/Command/SudoCommand.php b/vendor/psy/psysh/src/Psy/Command/SudoCommand.php
new file mode 100644 (file)
index 0000000..1a0a655
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+
+/*
+ * This file is part of Psy Shell.
+ *
+ * (c) 2012-2017 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Psy\Command;
+
+use PhpParser\NodeTraverser;
+use PhpParser\PrettyPrinter\Standard as Printer;
+use Psy\Input\CodeArgument;
+use Psy\ParserFactory;
+use Psy\Readline\Readline;
+use Psy\Sudo\SudoVisitor;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Evaluate PHP code, bypassing visibility restrictions.
+ */
+class SudoCommand extends Command
+{
+    private $readline;
+    private $parser;
+    private $traverser;
+    private $printer;
+
+    /**
+     * {@inheritdoc}
+     */
+    public function __construct($name = null)
+    {
+        $parserFactory = new ParserFactory();
+        $this->parser = $parserFactory->createParser();
+
+        $this->traverser = new NodeTraverser();
+        $this->traverser->addVisitor(new SudoVisitor());
+
+        $this->printer = new Printer();
+
+        parent::__construct($name);
+    }
+
+    /**
+     * Set the Shell's Readline service.
+     *
+     * @param Readline $readline
+     */
+    public function setReadline(Readline $readline)
+    {
+        $this->readline = $readline;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function configure()
+    {
+        $this
+            ->setName('sudo')
+            ->setDefinition(array(
+                new CodeArgument('code', InputArgument::REQUIRED, 'Code to execute.'),
+            ))
+            ->setDescription('Evaluate PHP code, bypassing visibility restrictions.')
+            ->setHelp(
+                <<<'HELP'
+Evaluate PHP code, bypassing visibility restrictions.
+
+e.g.
+<return>>>> $sekret->whisper("hi")</return>
+<return>PHP error:  Call to private method Sekret::whisper() from context '' on line 1</return>
+
+<return>>>> sudo $sekret->whisper("hi")</return>
+<return>=> "hi"</return>
+
+<return>>>> $sekret->word</return>
+<return>PHP error:  Cannot access private property Sekret::$word on line 1</return>
+
+<return>>>> sudo $sekret->word</return>
+<return>=> "hi"</return>
+
+<return>>>> $sekret->word = "please"</return>
+<return>PHP error:  Cannot access private property Sekret::$word on line 1</return>
+
+<return>>>> sudo $sekret->word = "please"</return>
+<return>=> "please"</return>
+HELP
+            );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $code = $input->getArgument('code');
+
+        // special case for !!
+        if ($code === '!!') {
+            $history = $this->readline->listHistory();
+            if (count($history) < 2) {
+                throw new \InvalidArgumentException('No previous command to replay');
+            }
+            $code = $history[count($history) - 2];
+        }
+
+        if (strpos('<?', $code) === false) {
+            $code = '<?php ' . $code;
+        }
+
+        $nodes = $this->traverser->traverse($this->parse($code));
+
+        $sudoCode = $this->printer->prettyPrint($nodes);
+        $this->getApplication()->addInput($sudoCode, true);
+    }
+
+    /**
+     * Lex and parse a string of code into statements.
+     *
+     * @param string $code
+     *
+     * @return array Statements
+     */
+    private function parse($code)
+    {
+        try {
+            return $this->parser->parse($code);
+        } catch (\PhpParser\Error $e) {
+            if (strpos($e->getMessage(), 'unexpected EOF') === false) {
+                throw $e;
+            }
+
+            // If we got an unexpected EOF, let's try it again with a semicolon.
+            return $this->parser->parse($code . ';');
+        }
+    }
+}