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