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('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: }