Chris@13: parser = $parserFactory->createParser();
Chris@13:
Chris@13: $this->traverser = new NodeTraverser();
Chris@13: $this->traverser->addVisitor(new SudoVisitor());
Chris@13:
Chris@13: $this->printer = new Printer();
Chris@13:
Chris@13: parent::__construct($name);
Chris@13: }
Chris@13:
Chris@13: /**
Chris@13: * Set the Shell's Readline service.
Chris@13: *
Chris@13: * @param Readline $readline
Chris@13: */
Chris@13: public function setReadline(Readline $readline)
Chris@13: {
Chris@13: $this->readline = $readline;
Chris@13: }
Chris@13:
Chris@13: /**
Chris@13: * {@inheritdoc}
Chris@13: */
Chris@13: protected function configure()
Chris@13: {
Chris@13: $this
Chris@13: ->setName('sudo')
Chris@13: ->setDefinition([
Chris@13: new CodeArgument('code', CodeArgument::REQUIRED, 'Code to execute.'),
Chris@13: ])
Chris@13: ->setDescription('Evaluate PHP code, bypassing visibility restrictions.')
Chris@13: ->setHelp(
Chris@13: <<<'HELP'
Chris@13: Evaluate PHP code, bypassing visibility restrictions.
Chris@13:
Chris@13: e.g.
Chris@13: >>> $sekret->whisper("hi")
Chris@13: PHP error: Call to private method Sekret::whisper() from context '' on line 1
Chris@13:
Chris@13: >>> sudo $sekret->whisper("hi")
Chris@13: => "hi"
Chris@13:
Chris@13: >>> $sekret->word
Chris@13: PHP error: Cannot access private property Sekret::$word on line 1
Chris@13:
Chris@13: >>> sudo $sekret->word
Chris@13: => "hi"
Chris@13:
Chris@13: >>> $sekret->word = "please"
Chris@13: PHP error: Cannot access private property Sekret::$word on line 1
Chris@13:
Chris@13: >>> sudo $sekret->word = "please"
Chris@13: => "please"
Chris@13: HELP
Chris@13: );
Chris@13: }
Chris@13:
Chris@13: /**
Chris@13: * {@inheritdoc}
Chris@13: */
Chris@13: protected function execute(InputInterface $input, OutputInterface $output)
Chris@13: {
Chris@13: $code = $input->getArgument('code');
Chris@13:
Chris@13: // special case for !!
Chris@13: if ($code === '!!') {
Chris@13: $history = $this->readline->listHistory();
Chris@17: if (\count($history) < 2) {
Chris@13: throw new \InvalidArgumentException('No previous command to replay');
Chris@13: }
Chris@17: $code = $history[\count($history) - 2];
Chris@13: }
Chris@13:
Chris@17: if (\strpos('', $code) === false) {
Chris@13: $code = 'traverser->traverse($this->parse($code));
Chris@13:
Chris@13: $sudoCode = $this->printer->prettyPrint($nodes);
Chris@13: $shell = $this->getApplication();
Chris@13: $shell->addCode($sudoCode, !$shell->hasCode());
Chris@13: }
Chris@13:
Chris@13: /**
Chris@13: * Lex and parse a string of code into statements.
Chris@13: *
Chris@13: * @param string $code
Chris@13: *
Chris@13: * @return array Statements
Chris@13: */
Chris@13: private function parse($code)
Chris@13: {
Chris@13: try {
Chris@13: return $this->parser->parse($code);
Chris@13: } catch (\PhpParser\Error $e) {
Chris@17: if (\strpos($e->getMessage(), 'unexpected EOF') === false) {
Chris@13: throw $e;
Chris@13: }
Chris@13:
Chris@13: // If we got an unexpected EOF, let's try it again with a semicolon.
Chris@13: return $this->parser->parse($code . ';');
Chris@13: }
Chris@13: }
Chris@13: }