> * @psalm-var list */ private $data = []; public function __construct( ResponseRenderer $response, Template $template, SimulateDml $simulateDml ) { parent::__construct($response, $template); $this->simulateDml = $simulateDml; } public function __invoke(): void { /** @var string $sqlDelimiter */ $sqlDelimiter = $_POST['sql_delimiter']; $parser = $this->createParser($GLOBALS['sql_query'], $sqlDelimiter); $this->process($parser); if ($this->error) { $this->response->addJSON('message', Message::rawError($this->error)); $this->response->addJSON('sql_data', false); return; } $this->response->addJSON('sql_data', $this->data); } private function createParser(string $query, string $delimiter): Parser { $lexer = new Lexer($query, false, $delimiter); $list = new TokensList(array_values(array_filter( $lexer->list->tokens, static function ($token): bool { return $token->type !== Token::TYPE_COMMENT; } ))); return new Parser($list); } private function process(Parser $parser): void { foreach ($parser->statements as $statement) { if ( ! $statement instanceof UpdateStatement && ! $statement instanceof DeleteStatement || ! empty($statement->join) || count(Query::getTables($statement)) > 1 ) { $this->error = __('Only single-table UPDATE and DELETE queries can be simulated.'); break; } // Get the matched rows for the query. $result = $this->simulateDml->getMatchedRows($parser, $statement); $this->error = $this->simulateDml->getError(); if ($this->error !== '') { break; } $this->data[] = $result; } } }