���� JFIF �� � ( %"1"%)+...383,7(-.-
![]() Server : Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.20 System : Linux st2.domain.com 3.10.0-1127.10.1.el7.x86_64 #1 SMP Wed Jun 3 14:28:03 UTC 2020 x86_64 User : apache ( 48) PHP Version : 7.4.20 Disable Function : NONE Directory : /usr/share/php/PhpMyAdmin/SqlParser5/Tools/ |
<?php declare(strict_types=1); namespace PhpMyAdmin\SqlParser\Tools; use Exception; use PhpMyAdmin\SqlParser\Context; use PhpMyAdmin\SqlParser\Lexer; use PhpMyAdmin\SqlParser\Parser; use function file_exists; use function file_get_contents; use function file_put_contents; use function in_array; use function is_dir; use function mkdir; use function print_r; use function scandir; use function serialize; use function sprintf; use function strpos; use function substr; /** * Used for test generation. */ class TestGenerator { /** * Generates a test's data. * * @param string $query the query to be analyzed * @param string $type test's type (may be `lexer` or `parser`) * * @return array */ public static function generate($query, $type = 'parser') { /** * Lexer used for tokenizing the query. * * @var Lexer */ $lexer = new Lexer($query); /** * Parsed used for analyzing the query. * A new instance of parser is generated only if the test requires. * * @var Parser */ $parser = $type === 'parser' ? new Parser($lexer->list) : null; /** * Lexer's errors. * * @var array */ $lexerErrors = []; /** * Parser's errors. * * @var array */ $parserErrors = []; // Both the lexer and the parser construct exception for errors. // Usually, exceptions contain a full stack trace and other details that // are not required. // The code below extracts only the relevant information. // Extracting lexer's errors. if (! empty($lexer->errors)) { foreach ($lexer->errors as $err) { $lexerErrors[] = [ $err->getMessage(), $err->ch, $err->pos, $err->getCode(), ]; } $lexer->errors = []; } // Extracting parser's errors. if (! empty($parser->errors)) { foreach ($parser->errors as $err) { $parserErrors[] = [ $err->getMessage(), $err->token, $err->getCode(), ]; } $parser->errors = []; } return [ 'query' => $query, 'lexer' => $lexer, 'parser' => $parser, 'errors' => [ 'lexer' => $lexerErrors, 'parser' => $parserErrors, ], ]; } /** * Builds a test. * * Reads the input file, generates the data and writes it back. * * @param string $type the type of this test * @param string $input the input file * @param string $output the output file * @param string $debug the debug file * @param bool $ansi activate quotes ANSI mode */ public static function build($type, $input, $output, $debug = null, $ansi = false) { // Support query types: `lexer` / `parser`. if (! in_array($type, ['lexer', 'parser'])) { throw new Exception('Unknown test type (expected `lexer` or `parser`).'); } /** * The query that is used to generate the test. * * @var string */ $query = file_get_contents($input); // There is no point in generating a test without a query. if (empty($query)) { throw new Exception('No input query specified.'); } if ($ansi === true) { // set ANSI_QUOTES for ansi tests Context::setMode('ANSI_QUOTES'); } $test = static::generate($query, $type); // unset mode, reset to default every time, to be sure Context::setMode(); // Writing test's data. file_put_contents($output, serialize($test)); // Dumping test's data in human readable format too (if required). if (! empty($debug)) { file_put_contents($debug, print_r($test, true)); } } /** * Generates recursively all tests preserving the directory structure. * * @param string $input the input directory * @param string $output the output directory * @param mixed|null $debug */ public static function buildAll($input, $output, $debug = null) { $files = scandir($input); foreach ($files as $file) { // Skipping current and parent directories. if (($file === '.') || ($file === '..')) { continue; } // Appending the filename to directories. $inputFile = $input . '/' . $file; $outputFile = $output . '/' . $file; $debugFile = $debug !== null ? $debug . '/' . $file : null; if (is_dir($inputFile)) { // Creating required directories to maintain the structure. // Ignoring errors if the folder structure exists already. if (! is_dir($outputFile)) { mkdir($outputFile); } if (($debug !== null) && (! is_dir($debugFile))) { mkdir($debugFile); } // Generating tests recursively. static::buildAll($inputFile, $outputFile, $debugFile); } elseif (substr($inputFile, -3) === '.in') { // Generating file names by replacing `.in` with `.out` and // `.debug`. $outputFile = substr($outputFile, 0, -3) . '.out'; if ($debug !== null) { $debugFile = substr($debugFile, 0, -3) . '.debug'; } // Building the test. if (! file_exists($outputFile)) { sprintf("Building test for %s...\n", $inputFile); static::build( strpos($inputFile, 'lex') !== false ? 'lexer' : 'parser', $inputFile, $outputFile, $debugFile, strpos($inputFile, 'ansi') !== false ); } else { sprintf("Test for %s already built!\n", $inputFile); } } } } }